1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-20 15:35:24 +02:00
Fixed bug 48909 - Wrong completion node after a . or an ->
	Fixed bug 49702 - Wrong completion kind sent in const/dest and code blocks
	Added new CompletionKind - STATEMENT_START to indicate the beginning of a statement line.  

TESTS
	Updated ContextualParseTest to accommodate bugfixes 48909 & 49702.  

UI
	Updated CompletionEngine to handle IASTCompletionKind.CompletionKind.STATEMENT_START
This commit is contained in:
John Camelon 2004-01-13 17:07:02 +00:00
parent cfa54903d5
commit 2c18a23f89
10 changed files with 524 additions and 166 deletions

View file

@ -1,3 +1,6 @@
2004-01-13 John Camelon
Updated ContextualParseTest to accommodate bugfixes 48909 & 49702.
2004-01-08 Andrew Niefer
Added CompleteParseASTTest.testBug43110_XRef
Added ParserSymbolTableTest.testBug43110_Ellipses

View file

@ -8,6 +8,7 @@ package org.eclipse.cdt.core.parser.tests;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Iterator;
import org.eclipse.cdt.core.parser.IParser;
@ -25,6 +26,7 @@ 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.LookupResult;
import org.eclipse.cdt.internal.core.parser.ParserLogService;
@ -126,16 +128,19 @@ public class ContextualParseTest extends CompleteParseBaseTest {
writer.write( "} " );
String code = writer.toString();
int index = code.indexOf( " a " );
IASTCompletionNode node = parse( code, index + 2 );
for( int i = 0; i < 2; ++i )
{
int index = ( i == 0 ? code.indexOf( " a " ) + 2 : code.indexOf( " a ") + 1 );
IASTCompletionNode node = parse( code, index );
assertNotNull( node );
String prefix = node.getCompletionPrefix();
assertNotNull( prefix );
assertTrue( node.getCompletionScope() instanceof IASTFunction );
assertEquals( prefix, "a" );
assertEquals( node.getCompletionKind(), IASTCompletionNode.CompletionKind.SINGLE_NAME_REFERENCE );
assertEquals( prefix, i == 0 ? "a" :"" );
assertEquals( node.getCompletionKind(), IASTCompletionNode.CompletionKind.STATEMENT_START );
IASTNode.LookupKind[] kinds = new IASTNode.LookupKind[1];
kinds[0] = IASTNode.LookupKind.ALL;
@ -145,12 +150,18 @@ public class ContextualParseTest extends CompleteParseBaseTest {
Iterator iter = result.getNodes();
IASTVariable anotherVar = (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" );
assertEquals( aVar.getName(), "aVar" );
}
}
public void testCompletionLookup_Qualified() throws Exception
{
@ -206,6 +217,63 @@ public class ContextualParseTest extends CompleteParseBaseTest {
assertEquals( aField.getName(), "aField" );
}
public void testMemberCompletion_Arrow() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "class A {" );
writer.write( " public: void aPublicBaseMethod();" );
writer.write( " private: void aPrivateBaseMethod();" );
writer.write( "};" );
writer.write( "class B : public A {" );
writer.write( " public: void aMethod();" );
writer.write( "};" );
writer.write( "void foo(){" );
writer.write( " B * b = new B();" );
writer.write( " b-> \n" );
String code = writer.toString();
int index = code.indexOf( "b->" );
IASTCompletionNode node = parse( code, index + 3 );
assertNotNull(node);
assertEquals( node.getCompletionPrefix(), "" );
assertEquals(node.getCompletionKind(), IASTCompletionNode.CompletionKind.MEMBER_REFERENCE);
assertTrue(node.getCompletionScope() instanceof IASTFunction );
assertEquals( ((IASTFunction)node.getCompletionScope()).getName(), "foo" );
assertTrue(node.getCompletionContext() instanceof IASTClassSpecifier );
assertEquals( ((IASTClassSpecifier)node.getCompletionContext()).getName(), "B" );
}
public void testMemberCompletion_Dot() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "class A {" );
writer.write( " public: void aPublicBaseMethod();" );
writer.write( " private: void aPrivateBaseMethod();" );
writer.write( "};" );
writer.write( "class B : public A {" );
writer.write( " public: void aMethod();" );
writer.write( "};" );
writer.write( "void foo(){" );
writer.write( " B b;" );
writer.write( " b. \n" );
String code = writer.toString();
int index = code.indexOf( "b." );
IASTCompletionNode node = parse( code, index + 2 );
assertNotNull(node);
assertEquals( node.getCompletionPrefix(), "" );
assertEquals(node.getCompletionKind(), IASTCompletionNode.CompletionKind.MEMBER_REFERENCE);
assertTrue(node.getCompletionScope() instanceof IASTFunction );
assertEquals( ((IASTFunction)node.getCompletionScope()).getName(), "foo" );
assertTrue(node.getCompletionContext() instanceof IASTClassSpecifier );
assertEquals( ((IASTClassSpecifier)node.getCompletionContext()).getName(), "B" );
}
public void testCompletionLookup_Pointer() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "class A {" );
@ -219,15 +287,20 @@ public class ContextualParseTest extends CompleteParseBaseTest {
writer.write( " B * b = new B();" );
writer.write( " b->a \n" );
for( int i = 0; i < 2; ++i )
{
String code = writer.toString();
int index = code.indexOf( "b->a" );
IASTCompletionNode node = parse( code, index + 4 );
int index;
index = (i == 0 )? (code.indexOf( "b->a" )+4) :(code.indexOf( "b->") + 3);
IASTCompletionNode node = parse( code, index);
assertNotNull( node );
String prefix = node.getCompletionPrefix();
assertEquals( prefix, "a" );
assertEquals( prefix, ( i == 0 ) ? "a" :"");
assertTrue( node.getCompletionScope() instanceof IASTFunction );
assertEquals( node.getCompletionKind(), IASTCompletionNode.CompletionKind.MEMBER_REFERENCE );
@ -248,6 +321,7 @@ public class ContextualParseTest extends CompleteParseBaseTest {
assertEquals( method.getName(), "aMethod" );
assertEquals( baseMethod.getName(), "aPublicBaseMethod" );
}
}
public void testCompletionLookup_FriendClass_1() throws Exception{
StringWriter writer = new StringWriter();
@ -334,6 +408,7 @@ public class ContextualParseTest extends CompleteParseBaseTest {
assertEquals( method.getName(), "aPrivateMethod" );
}
public void testCompletionLookup_ParametersAsLocalVariables() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "int foo( int aParameter ){" );
@ -353,7 +428,7 @@ public class ContextualParseTest extends CompleteParseBaseTest {
assertEquals( prefix, "a" );
assertTrue( node.getCompletionScope() instanceof IASTCodeScope );
assertEquals( node.getCompletionKind(), IASTCompletionNode.CompletionKind.SINGLE_NAME_REFERENCE );
assertEquals( node.getCompletionKind(), IASTCompletionNode.CompletionKind.STATEMENT_START );
assertNull( node.getCompletionContext() );
LookupResult result = node.getCompletionScope().lookup( prefix, new IASTNode.LookupKind [] { IASTNode.LookupKind.LOCAL_VARIABLES }, node.getCompletionContext() );
@ -421,4 +496,70 @@ public class ContextualParseTest extends CompleteParseBaseTest {
assertFalse( iter.hasNext() );
assertEquals( method.getName(), "aMethod" );
}
public void testCompletionInConstructor() throws Exception
{
Writer writer = new StringWriter();
writer.write("class SimpleTest{");
writer.write(" public:");
writer.write("SimpleTest();");
writer.write("~SimpleTest();");
writer.write("int a, b, c, aa, bb, cc, abc;");
writer.write("};");
writer.write("SimpleTest::~SimpleTest()");
writer.write("{}");
writer.write("SimpleTest::SimpleTest()");
writer.write("{");
writer.write("/**/a");
writer.write("}");
IASTCompletionNode node = parse( writer.toString(), writer.toString().indexOf("/**/a") + 5 );
assertNotNull(node);
assertEquals(node.getCompletionPrefix(), "a");
assertTrue(node.getCompletionScope() instanceof IASTMethod);
IASTMethod inquestion = (IASTMethod)node.getCompletionScope();
assertEquals( inquestion.getName(), "SimpleTest");
assertTrue(inquestion.isConstructor());
assertEquals(node.getCompletionKind(), IASTCompletionNode.CompletionKind.STATEMENT_START );
assertNull(node.getCompletionContext());
LookupKind[] kinds = new LookupKind[ 1 ];
kinds[0] = LookupKind.FIELDS;
LookupResult result = inquestion.lookup( "a", kinds, null );
assertEquals(result.getResultsSize(), 3 );
}
public void testCompletionInDestructor() throws Exception
{
Writer writer = new StringWriter();
writer.write("class SimpleTest{");
writer.write(" public:");
writer.write("SimpleTest();");
writer.write("~SimpleTest();");
writer.write("int a, b, c, aa, bb, cc, abc;");
writer.write("};");
writer.write("SimpleTest::SimpleTest()");
writer.write("{}");
writer.write("SimpleTest::~SimpleTest()");
writer.write("{");
writer.write("/**/a");
writer.write("}");
IASTCompletionNode node = parse( writer.toString(), writer.toString().indexOf("/**/a") + 5 );
assertNotNull(node);
assertEquals(node.getCompletionPrefix(), "a");
assertTrue(node.getCompletionScope() instanceof IASTMethod);
IASTMethod inquestion = (IASTMethod)node.getCompletionScope();
assertEquals( inquestion.getName(), "~SimpleTest");
assertTrue(inquestion.isDestructor());
assertEquals(node.getCompletionKind(), IASTCompletionNode.CompletionKind.STATEMENT_START );
assertNull(node.getCompletionContext());
LookupKind[] kinds = new LookupKind[ 1 ];
kinds[0] = LookupKind.FIELDS;
LookupResult result = inquestion.lookup( "a", kinds, null );
assertEquals(result.getResultsSize(), 3 );
}
}

View file

@ -1,3 +1,9 @@
2004-01-12 John Camelon
Fixed bug 48909 - Wrong completion node after a . or an ->
Fixed bug 49702 - Wrong completion kind sent in const/dest and code blocks
Added new CompletionKind - STATEMENT_START to indicate the beginning of a statement line.
2004-01-08 Andrew Niefer
fixing bug 43110 - Parser support needed for functions with ellipses
Added IParameterizedSymbol.setHasVariableArgs() & hasVariableArgs()

View file

@ -24,6 +24,7 @@ public interface IASTCompletionNode {
{
// x.[ ] x->[ ]
public static final CompletionKind MEMBER_REFERENCE = new CompletionKind( 0 );
// x::[ ]
public static final CompletionKind SCOPED_REFERENCE = new CompletionKind( 1 );
@ -69,6 +70,9 @@ public interface IASTCompletionNode {
// any place where a type or variable name is expected to be introduced
public static final CompletionKind USER_SPECIFIED_NAME = new CompletionKind( 15 );
// the beginning of a statement
public static final CompletionKind STATEMENT_START = new CompletionKind( 16 );
// error condition -- a place in the grammar where there is nothing to lookup
public static final CompletionKind NO_SUCH_KIND = new CompletionKind( 200 );
/**

View file

@ -60,6 +60,13 @@ public interface IASTNode {
public int getResultsSize();
}
/**
* @param prefix
* @param kind
* @param context
* @return
* @throws LookupException
*/
public LookupResult lookup( String prefix, LookupKind[] kind, IASTNode context) throws LookupException;
}

View file

@ -42,6 +42,7 @@ public class ContextualParser extends Parser implements IParser {
protected IASTNode context;
protected IToken finalToken;
private Set keywordSet;
private int boundaryOffset;
/**
* @param scanner
@ -60,6 +61,7 @@ public class ContextualParser extends Parser implements IParser {
*/
public IASTCompletionNode parse(int offset) throws ParserNotImplementedException {
scanner.setOffsetBoundary(offset);
boundaryOffset = offset;
translationUnit();
return new ASTCompletionNode( getCompletionKind(), getCompletionScope(), getCompletionContext(), getCompletionPrefix(), reconcileKeywords( getKeywordSet(), getCompletionPrefix() ) );
}
@ -164,15 +166,29 @@ public class ContextualParser extends Parser implements IParser {
* @see org.eclipse.cdt.internal.core.parser.Parser#handleOffsetLimitException()
*/
protected void handleOffsetLimitException(OffsetLimitReachedException exception) throws EndOfFileException, OffsetLimitReachedException {
finalToken = exception.getFinalToken();
setCompletionToken( exception.getFinalToken() );
if( (finalToken!= null )&& (finalToken.getEndOffset() != boundaryOffset ))
setCompletionToken(null);
throw exception;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.Parser#setCompletionKeywords(java.lang.String[])
*/
protected void setCompletionKeywords(Set keywords) {
this.keywordSet = keywords;
protected void setCompletionKeywords(KeywordSets.Key key) {
this.keywordSet = KeywordSets.getKeywords( key, language );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.Parser#setCompletionToken(org.eclipse.cdt.core.parser.IToken)
*/
protected void setCompletionToken(IToken token) {
finalToken = token;
}
protected IToken getCompletionToken()
{
return finalToken;
}
}

View file

@ -29,6 +29,8 @@ public class KeywordSets {
{
public static final Key EMPTY = new Key( 0 );
public static final Key DECL_SPECIFIER_SEQUENCE = new Key( 1 );
public static final Key DECLARATION = new Key( 2 );
public static final Key STATEMENT = new Key(3);
/**
* @param enumValue
*/
@ -44,6 +46,10 @@ public class KeywordSets {
return EMPTY;
if( kind == Key.DECL_SPECIFIER_SEQUENCE )
return (Set) DECL_SPECIFIER_SEQUENCE.get( language );
if( kind == Key.DECLARATION )
return (Set) DECLARATION.get( language );
if( kind == Key.STATEMENT )
return (Set) STATEMENT.get( language );
//TODO finish this
return null;
@ -109,4 +115,53 @@ public class KeywordSets {
DECL_SPECIFIER_SEQUENCE.put( ParserLanguage.C, DECL_SPECIFIER_SEQUENCE_C );
}
private static final Set DECLARATION_CPP;
static
{
DECLARATION_CPP = new TreeSet();
DECLARATION_CPP.addAll( DECL_SPECIFIER_SEQUENCE_CPP );
DECLARATION_CPP.add( Keywords.ASM );
// more to come
}
private static final Set DECLARATION_C;
static
{
DECLARATION_C = new TreeSet();
DECLARATION_C.addAll(DECL_SPECIFIER_SEQUENCE_C );
DECLARATION_C.add(Keywords.ASM );
// more to come
}
private static final Hashtable DECLARATION;
static
{
DECLARATION = new Hashtable();
DECLARATION.put( ParserLanguage.CPP, DECLARATION_CPP );
DECLARATION.put( ParserLanguage.C, DECLARATION_C );
}
private static final Set STATEMENT_C;
static
{
STATEMENT_C= new TreeSet();
STATEMENT_C.addAll( DECLARATION_C );
STATEMENT_C.add( Keywords.FOR );
// more to come
}
private static final Set STATEMENT_CPP;
static
{
STATEMENT_CPP = new TreeSet( STATEMENT_C );
STATEMENT_CPP.add( Keywords.TRY );
}
private static final Hashtable STATEMENT;
static
{
STATEMENT = new Hashtable();
STATEMENT.put( ParserLanguage.CPP, STATEMENT_CPP);
STATEMENT.put( ParserLanguage.C, STATEMENT_C );
}
}

View file

@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.core.parser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.eclipse.cdt.core.parser.BacktrackException;
@ -48,7 +47,6 @@ import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
import org.eclipse.cdt.core.parser.ast.IASTNode;
import org.eclipse.cdt.core.parser.ast.IASTOffsetableElement;
import org.eclipse.cdt.core.parser.ast.IASTScope;
import org.eclipse.cdt.core.parser.ast.IASTScopedElement;
import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTTemplate;
import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
@ -62,6 +60,7 @@ import org.eclipse.cdt.core.parser.ast.IASTUsingDirective;
import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier.ClassNameType;
import org.eclipse.cdt.core.parser.ast.IASTCompletionNode.CompletionKind;
import org.eclipse.cdt.core.parser.ast.IASTExpression.Kind;
import org.eclipse.cdt.internal.core.parser.KeywordSets.Key;
/**
* This is our first implementation of the IParser interface, serving as a parser for
@ -708,10 +707,12 @@ public abstract class Parser implements IParser
throws EndOfFileException, BacktrackException
{
setCurrentScope(scope);
setCompletionKeywords( Key.DECLARATION );
switch (LT(1))
{
case IToken.t_asm :
IToken first = consume(IToken.t_asm);
setCompletionKind( CompletionKind.NO_SUCH_KIND );
consume(IToken.tLPAREN);
String assembly = consume(IToken.tSTRING).getImage();
consume(IToken.tRPAREN);
@ -753,10 +754,9 @@ public abstract class Parser implements IParser
default :
simpleDeclarationStrategyUnion(scope, ownerTemplate);
}
if( scope instanceof IASTScopedElement )
setCurrentScope( ((IASTScopedElement)scope).getOwnerScope() );
else
setCurrentScope( null );
setCurrentScope(scope);
setCompletionKeywords( Key.DECLARATION );
}
protected void simpleDeclarationStrategyUnion(
IASTScope scope,
@ -920,7 +920,6 @@ public abstract class Parser implements IParser
*
* @param container IParserCallback object which serves as the owner scope for this declaration.
* @param tryConstructor true == take strategy1 (constructor ) : false == take strategy 2 ( pointer to function)
* @param forKR Is this for K&R-style parameter declaration (true) or simple declaration (false)
* @throws BacktrackException request a backtrack
*/
protected void simpleDeclaration(
@ -933,8 +932,8 @@ public abstract class Parser implements IParser
DeclarationWrapper sdw =
new DeclarationWrapper(scope, firstToken.getOffset(), ownerTemplate);
setCompletionKeywords( KeywordSets.getKeywords( KeywordSets.Key.DECL_SPECIFIER_SEQUENCE, language ) );
declSpecifierSeq(false, strategy == SimpleDeclarationStrategy.TRY_CONSTRUCTOR, sdw );
setCompletionKeywords( Key.DECL_SPECIFIER_SEQUENCE );
declSpecifierSeq(sdw, false, strategy == SimpleDeclarationStrategy.TRY_CONSTRUCTOR );
if (sdw.getTypeSpecifier() == null && sdw.getSimpleType() != IASTSimpleTypeSpecifier.Type.UNSPECIFIED )
try
{
@ -1162,7 +1161,7 @@ public abstract class Parser implements IParser
DeclarationWrapper sdw =
new DeclarationWrapper(scope, current.getOffset(), null);
declSpecifierSeq(true, false, sdw);
declSpecifierSeq(sdw, true, false);
if (sdw.getTypeSpecifier() == null
&& sdw.getSimpleType()
!= IASTSimpleTypeSpecifier.Type.UNSPECIFIED)
@ -1357,9 +1356,9 @@ public abstract class Parser implements IParser
* @throws BacktrackException request a backtrack
*/
protected void declSpecifierSeq(
DeclarationWrapper sdw,
boolean parm,
boolean tryConstructor,
DeclarationWrapper sdw )
boolean tryConstructor )
throws BacktrackException, EndOfFileException
{
Flags flags = new Flags(parm, tryConstructor);
@ -1783,6 +1782,8 @@ public abstract class Parser implements IParser
IToken last = null;
IToken mark = mark();
try
{
if (LT(1) == IToken.tCOLONCOLON)
last = consume( IToken.tCOLONCOLON );
// TODO - whacky way to deal with destructors, please revisit
@ -1792,7 +1793,15 @@ public abstract class Parser implements IParser
{
case IToken.tIDENTIFIER :
last = consume(IToken.tIDENTIFIER);
IToken secondMark = mark();
IToken secondMark = null;
try
{
secondMark = mark();
}
catch( OffsetLimitReachedException olre )
{
return new TokenDuple(last, last);
}
try
{
last = consumeTemplateParameters(last);
@ -1824,6 +1833,11 @@ public abstract class Parser implements IParser
}
return new TokenDuple(first, last);
} catch( OffsetLimitReachedException olre )
{
backup(mark);
throw backtrack;
}
}
/**
* Parse a const-volatile qualifier.
@ -2689,7 +2703,7 @@ public abstract class Parser implements IParser
ITokenDuple duple = null;
setCompletionKind( CompletionKind.USER_SPECIFIED_NAME );
setCompletionKeywords( KeywordSets.getKeywords( KeywordSets.Key.EMPTY, language ) );
setCompletionKeywords( Key.EMPTY );
// class name
if (LT(1) == IToken.tIDENTIFIER)
duple = className();
@ -2896,6 +2910,9 @@ public abstract class Parser implements IParser
{
setCurrentScope(scope);
setCompletionKind( CompletionKind.STATEMENT_START );
setCompletionKeywords( Key.STATEMENT );
switch (LT(1))
{
case IToken.t_case :
@ -3007,6 +3024,9 @@ public abstract class Parser implements IParser
default :
// can be many things:
// label
try
{
if (LT(1) == IToken.tIDENTIFIER && LT(2) == IToken.tCOLON)
{
consume(IToken.tIDENTIFIER);
@ -3014,6 +3034,10 @@ public abstract class Parser implements IParser
statement(scope);
return;
}
}catch( OffsetLimitReachedException olre )
{
// ok
}
// expressionStatement
// Note: the function style cast ambiguity is handled in expression
// Since it only happens when we are in a statement
@ -3021,7 +3045,10 @@ public abstract class Parser implements IParser
try
{
IASTExpression thisExpression = expression(scope);
if( queryLookaheadCapability() )
consume(IToken.tSEMI);
else
throw new EndOfFileException();
thisExpression.acceptElement( requestor );
return;
}
@ -3029,14 +3056,15 @@ public abstract class Parser implements IParser
{
backup( mark );
}
catch( OffsetLimitReachedException olre )
{
backup(mark);
}
// declarationStatement
declaration(scope, null);
}
if( scope instanceof IASTScopedElement )
setCurrentScope( ((IASTScopedElement)scope).getOwnerScope() );
else
setCurrentScope( null );
}
protected void catchHandlerSequence(IASTScope scope)
throws EndOfFileException, BacktrackException
@ -3136,9 +3164,12 @@ public abstract class Parser implements IParser
newScope.enterScope( requestor );
}
IToken checkToken = null;
while (LT(1) != IToken.tRBRACE)
setCurrentScope(createNewScope ? newScope : scope);
setCompletionKind( CompletionKind.STATEMENT_START );
while (queryLookaheadCapability() && LT(1) != IToken.tRBRACE)
{
checkToken = LA(1);
setCurrentScope(createNewScope ? newScope : scope);
try
{
statement(createNewScope ? newScope : scope );
@ -3149,9 +3180,14 @@ public abstract class Parser implements IParser
if( LA(1) == checkToken )
errorHandling();
}
setCurrentScope(createNewScope ? newScope : scope);
setCompletionKind( CompletionKind.STATEMENT_START );
setCompletionKeywords( Key.STATEMENT );
}
consume(IToken.tRBRACE);
if( queryLookaheadCapability() ) consume(IToken.tRBRACE);
else throw new EndOfFileException();
if( createNewScope )
newScope.exitScope( requestor );
}
@ -3170,6 +3206,7 @@ public abstract class Parser implements IParser
public IASTExpression expression(IASTScope scope) throws BacktrackException, EndOfFileException
{
IASTExpression assignmentExpression = assignmentExpression(scope);
if( !queryLookaheadCapability() ) return assignmentExpression;
while (LT(1) == IToken.tCOMMA)
{
consume();
@ -3211,6 +3248,7 @@ public abstract class Parser implements IParser
&& conditionalExpression.getExpressionKind()
== IASTExpression.Kind.CONDITIONALEXPRESSION)
return conditionalExpression;
if( !queryLookaheadCapability() ) return conditionalExpression;
switch (LT(1)) {
case IToken.tASSIGN :
return assignmentOperatorExpression(
@ -3341,6 +3379,7 @@ public abstract class Parser implements IParser
throws BacktrackException, EndOfFileException
{
IASTExpression firstExpression = logicalOrExpression(scope);
if( !queryLookaheadCapability() ) return firstExpression;
if (LT(1) == IToken.tQUESTION)
{
consume();
@ -3377,6 +3416,7 @@ public abstract class Parser implements IParser
throws BacktrackException, EndOfFileException
{
IASTExpression firstExpression = logicalAndExpression(scope);
if( !queryLookaheadCapability() ) return firstExpression;
while (LT(1) == IToken.tOR)
{
consume();
@ -3412,6 +3452,7 @@ public abstract class Parser implements IParser
throws BacktrackException, EndOfFileException
{
IASTExpression firstExpression = inclusiveOrExpression( scope );
if( !queryLookaheadCapability() ) return firstExpression;
while (LT(1) == IToken.tAND)
{
consume();
@ -3446,6 +3487,7 @@ public abstract class Parser implements IParser
throws BacktrackException, EndOfFileException
{
IASTExpression firstExpression = exclusiveOrExpression(scope);
if( !queryLookaheadCapability() ) return firstExpression;
while (LT(1) == IToken.tBITOR)
{
consume();
@ -3481,6 +3523,7 @@ public abstract class Parser implements IParser
throws BacktrackException, EndOfFileException
{
IASTExpression firstExpression = andExpression( scope );
if( !queryLookaheadCapability() ) return firstExpression;
while (LT(1) == IToken.tXOR)
{
consume();
@ -3516,6 +3559,7 @@ public abstract class Parser implements IParser
protected IASTExpression andExpression(IASTScope scope) throws EndOfFileException, BacktrackException
{
IASTExpression firstExpression = equalityExpression(scope);
if( !queryLookaheadCapability() ) return firstExpression;
while (LT(1) == IToken.tAMPER)
{
consume();
@ -3553,6 +3597,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = relationalExpression(scope);
for (;;)
{
if( !queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tEQUAL :
@ -3598,6 +3643,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = shiftExpression(scope);
for (;;)
{
if( !queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tGT :
@ -3677,6 +3723,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = additiveExpression(scope);
for (;;)
{
if( !queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tSHIFTL :
@ -3721,6 +3768,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = multiplicativeExpression( scope );
for (;;)
{
if( !queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tPLUS :
@ -3765,6 +3813,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = pmExpression(scope);
for (;;)
{
if( !queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tSTAR :
@ -3819,6 +3868,7 @@ public abstract class Parser implements IParser
IASTExpression firstExpression = castExpression(scope);
for (;;)
{
if( ! queryLookaheadCapability() ) return firstExpression;
switch (LT(1))
{
case IToken.tDOTSTAR :
@ -3861,6 +3911,7 @@ public abstract class Parser implements IParser
protected IASTExpression castExpression( IASTScope scope ) throws EndOfFileException, BacktrackException
{
// TO DO: we need proper symbol checkint to ensure type name
if( ! queryLookaheadCapability() ) return unaryExpression(scope);
if (LT(1) == IToken.tLPAREN)
{
IToken mark = mark();
@ -4341,6 +4392,7 @@ public abstract class Parser implements IParser
protected IASTExpression unaryExpression( IASTScope scope )
throws EndOfFileException, BacktrackException
{
if( ! queryLookaheadCapability() ) return postfixExpression( scope );
switch (LT(1))
{
case IToken.tSTAR :
@ -4465,6 +4517,8 @@ public abstract class Parser implements IParser
{
IASTExpression firstExpression = null;
boolean isTemplate = false;
if( ! queryLookaheadCapability() ) return primaryExpression(scope);
switch (LT(1))
{
case IToken.t_typename :
@ -4625,6 +4679,7 @@ public abstract class Parser implements IParser
IASTExpression secondExpression = null;
for (;;)
{
if( ! queryLookaheadCapability() )return firstExpression;
switch (LT(1))
{
case IToken.tLBRACKET :
@ -4729,11 +4784,17 @@ public abstract class Parser implements IParser
// member access
consume(IToken.tDOT);
try
{
if (LT(1) == IToken.t_template)
{
consume(IToken.t_template);
isTemplate = true;
}
} catch( OffsetLimitReachedException olre )
{
setCompletionToken( null );
}
IASTNode context = astFactory.getCompletionContext( (isTemplate
? IASTExpression.Kind.POSTFIX_DOT_TEMPL_IDEXPRESS
@ -4760,23 +4821,30 @@ public abstract class Parser implements IParser
catch (ASTSemanticException e5)
{
failParse();
setCompletionContext( null );
throw backtrack;
} catch (Exception e)
{
throw backtrack;
} finally
{
setCompletionContext( null );
throw backtrack;
}
break;
case IToken.tARROW :
// member access
consume(IToken.tARROW);
try
{
if (LT(1) == IToken.t_template)
{
consume(IToken.t_template);
isTemplate = true;
}
} catch( OffsetLimitReachedException olre )
{
setCompletionToken( null );
}
context = astFactory.getCompletionContext( (isTemplate
? IASTExpression.Kind.POSTFIX_ARROW_TEMPL_IDEXP
@ -4803,13 +4871,12 @@ public abstract class Parser implements IParser
catch (ASTSemanticException e)
{
failParse();
setCompletionContext( null );
throw backtrack;
} catch (Exception e)
{
throw backtrack;
}finally
{
setCompletionContext( null );
throw backtrack;
}
break;
default :
@ -4820,6 +4887,23 @@ public abstract class Parser implements IParser
/**
* @return
* @throws EndOfFileException
*/
protected boolean queryLookaheadCapability() throws EndOfFileException {
//make sure we can look ahead one before doing this
boolean result = true;
try
{
LA(1);
}
catch( OffsetLimitReachedException olre )
{
result = false;
}
return result;
}
protected IASTExpression specialCastExpression( IASTScope scope,
IASTExpression.Kind kind)
throws EndOfFileException, BacktrackException
@ -4886,6 +4970,21 @@ public abstract class Parser implements IParser
throws EndOfFileException, BacktrackException
{
IToken t = null;
IASTExpression emptyExpression = null;
try {
emptyExpression = astFactory.createExpression(
scope,
IASTExpression.Kind.PRIMARY_EMPTY,
null,
null,
null,
null,
null, "", null);
} catch (ASTSemanticException e9) {
// TODO Auto-generated catch block
e9.printStackTrace();
}
if( !queryLookaheadCapability() ) return emptyExpression;
switch (LT(1))
{
// TO DO: we need more literals...
@ -5036,7 +5135,7 @@ public abstract class Parser implements IParser
case IToken.t_operator :
ITokenDuple duple = null;
IToken mark = mark();
try
{
duple = name();
@ -5045,7 +5144,6 @@ public abstract class Parser implements IParser
{
Declarator d = new Declarator( new DeclarationWrapper(scope, 0, null) );
IToken mark = mark();
if (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER)
{
IToken start = consume();
@ -5071,6 +5169,11 @@ public abstract class Parser implements IParser
duple = d.getNameDuple();
}
catch(OffsetLimitReachedException olre )
{
backup(mark);
throw backtrack;
}
try
@ -5092,24 +5195,7 @@ public abstract class Parser implements IParser
throw backtrack;
}
default :
try
{
return astFactory.createExpression(
scope,
IASTExpression.Kind.PRIMARY_EMPTY,
null,
null,
null,
null,
null, "", null);
}
catch (ASTSemanticException e)
{
throw backtrack;
} catch (Exception e)
{
throw backtrack;
}
return emptyExpression;
}
}
/**
@ -5165,6 +5251,7 @@ public abstract class Parser implements IParser
protected IScanner scanner;
protected IToken currToken, // current token we plan to consume next
lastToken; // last token we consumed
private boolean limitReached = false;
protected void setCurrentScope( IASTScope scope )
{
@ -5178,12 +5265,15 @@ public abstract class Parser implements IParser
*/
protected IToken fetchToken() throws EndOfFileException
{
if(limitReached) throw new OffsetLimitReachedException(getCompletionToken());
try
{
return scanner.nextToken();
}
catch( OffsetLimitReachedException olre )
{
limitReached = true;
handleOffsetLimitException(olre);
return null;
}
@ -5315,8 +5405,16 @@ public abstract class Parser implements IParser
{
}
protected void setCompletionKeywords( Set keywords )
protected void setCompletionKeywords(KeywordSets.Key key )
{
}
protected void setCompletionToken( IToken token )
{
}
protected IToken getCompletionToken()
{
return null;
}
}

View file

@ -1,3 +1,6 @@
2004-01-13 John Camelon
Updated CompletionEngine to handle IASTCompletionKind.CompletionKind.STATEMENT_START
2004-01-08 Hoda Amer
Added Content assist log cpabilities

View file

@ -17,7 +17,6 @@ import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICLogConstants;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.parser.IParser;
@ -411,6 +410,24 @@ public class CompletionEngine implements RelevanceConstants{
addToCompletions (result);
}
private void completionOnStatementStart( IASTCompletionNode completionNode )
{
IASTScope searchNode = completionNode.getCompletionScope();
LookupResult result = null;
// lookup fields and methods with the right visibility
IASTNode.LookupKind[] kinds = new IASTNode.LookupKind[7];
kinds[0] = IASTNode.LookupKind.FIELDS;
kinds[1] = IASTNode.LookupKind.METHODS;
kinds[2] = IASTNode.LookupKind.VARIABLES;
kinds[3] = IASTNode.LookupKind.STRUCTURES;
kinds[4] = IASTNode.LookupKind.ENUMERATIONS;
kinds[5] = IASTNode.LookupKind.NAMESPACES;
kinds[6] = IASTNode.LookupKind.FUNCTIONS;
result = lookup (searchNode, completionNode.getCompletionPrefix(), kinds, completionNode.getCompletionContext());
addToCompletions (result);
}
private void completionOnScopedReference(IASTCompletionNode completionNode){
// 1. Get the search scope node
// the search node is the name before the qualification
@ -630,6 +647,10 @@ public class CompletionEngine implements RelevanceConstants{
// CompletionOnKeyword
completionOnKeyword(completionNode);
}
else if(kind == IASTCompletionNode.CompletionKind.STATEMENT_START )
{
completionOnStatementStart(completionNode);
}
addKeywordsToCompletions( completionNode.getKeywords());
return completionNode;
@ -705,6 +726,10 @@ public class CompletionEngine implements RelevanceConstants{
kindStr = "USER_SPECIFIED_NAME";
break;
case 16:
kindStr = "STATEMENT_START";
break;
case 200:
kindStr = "NO_SUCH_KIND";
break;