1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-10 09:45:39 +02:00

fixed bug with content assist not working on top level named type specifier

This commit is contained in:
Mike Kucera 2008-05-05 18:13:05 +00:00
parent 1a60090ab9
commit 17931aa374
5 changed files with 79 additions and 62 deletions

View file

@ -23,34 +23,33 @@ public class BasicCompletionTest extends CompletionTestBase {
private void testVar(IASTCompletionNode node) throws Exception { private void testVar(IASTCompletionNode node) throws Exception {
IASTName[] names = node.getNames(); IASTName[] names = node.getNames();
assertEquals(1, names.length); assertEquals(1, names.length);
IBinding[] bindings = names[0].getCompletionContext().findBindings( IBinding[] bindings = names[0].getCompletionContext().findBindings(names[0], true);
names[0], true);
assertEquals(1, bindings.length); assertEquals(1, bindings.length);
IVariable var = (IVariable)bindings[0]; IVariable var = (IVariable)bindings[0];
assertEquals("blah", var.getName()); assertEquals("blah", var.getName());
} }
public void testVar() throws Exception { public void testVar() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("int blah = 4;"); "int blah = 4;" +
code.append("int two = bl"); "int two = bl";
testVar(getGPPCompletionNode(code.toString()));
testVar(getGCCCompletionNode(code.toString())); testVar(getGPPCompletionNode(code));
testVar(getGCCCompletionNode(code));
} }
public void testFunction() throws Exception { public void testFunction() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("void func(int x) { }"); "void func(int x) { }" +
code.append("void func2() { fu"); "void func2() { fu";
// C++ // C++
IASTCompletionNode node = getGPPCompletionNode(code.toString()); IASTCompletionNode node = getGPPCompletionNode(code);
IASTName[] names = node.getNames(); IASTName[] names = node.getNames();
// There are three names, one as an expression, one that isn't connected, one as a declaration // There are three names, one as an expression, one that isn't connected, one as a declaration
assertEquals(3, names.length); assertEquals(3, names.length);
// The expression points to our functions // The expression points to our functions
IBinding[] bindings = names[0].getCompletionContext().findBindings( IBinding[] bindings = names[0].getCompletionContext().findBindings(names[0], true);
names[0], true);
// There should be two since they both start with fu // There should be two since they both start with fu
assertEquals(2, bindings.length); assertEquals(2, bindings.length);
assertEquals("func", ((IFunction)bindings[0]).getName()); assertEquals("func", ((IFunction)bindings[0]).getName());
@ -61,13 +60,12 @@ public class BasicCompletionTest extends CompletionTestBase {
assertNull(names[2].getTranslationUnit()); assertNull(names[2].getTranslationUnit());
// C // C
node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
names = node.getNames(); names = node.getNames();
// There are two names, one as an expression, one as a declaration // There are two names, one as an expression, one as a declaration
assertEquals(2, names.length); assertEquals(2, names.length);
// The expression points to our functions // The expression points to our functions
bindings = sortBindings(names[0].getCompletionContext().findBindings( bindings = sortBindings(names[0].getCompletionContext().findBindings(names[0], true));
names[0], true));
// There should be two since they both start with fu // There should be two since they both start with fu
assertEquals(2, bindings.length); assertEquals(2, bindings.length);
assertEquals("func", ((IFunction)bindings[0]).getName()); assertEquals("func", ((IFunction)bindings[0]).getName());
@ -77,22 +75,21 @@ public class BasicCompletionTest extends CompletionTestBase {
} }
public void testTypedef() throws Exception { public void testTypedef() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("typedef int blah;"); "typedef int blah;" +
code.append("bl"); "bl";
// C++ // C++
IASTCompletionNode node = getGPPCompletionNode(code.toString()); IASTCompletionNode node = getGPPCompletionNode(code);
IASTName[] names = node.getNames(); IASTName[] names = node.getNames();
assertEquals(2, names.length); assertEquals(2, names.length);
assertNull(names[0].getTranslationUnit()); assertNull(names[0].getTranslationUnit());
IBinding[] bindings = names[1].getCompletionContext().findBindings( IBinding[] bindings = names[1].getCompletionContext().findBindings(names[1], true);
names[1], true);
assertEquals(1, bindings.length); assertEquals(1, bindings.length);
assertEquals("blah", ((ITypedef)bindings[0]).getName()); assertEquals("blah", ((ITypedef)bindings[0]).getName());
// C // C
node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
names = node.getNames(); names = node.getNames();
assertEquals(1, names.length); assertEquals(1, names.length);
bindings = names[0].getCompletionContext().findBindings(names[0], true); bindings = names[0].getCompletionContext().findBindings(names[0], true);
@ -101,28 +98,28 @@ public class BasicCompletionTest extends CompletionTestBase {
} }
public void testBug181624() throws Exception { public void testBug181624() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("void foo() {"); "void foo() {" +
code.append(" switch ("); " switch (";
// C++ // C++
IASTCompletionNode node = getGPPCompletionNode(code.toString()); IASTCompletionNode node = getGPPCompletionNode(code);
assertNotNull(node); assertNotNull(node);
// C // C
node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
assertNotNull(node); assertNotNull(node);
code = new StringBuffer(); code =
code.append("void foo() {"); "void foo() {" +
code.append(" while ("); " while (";
// C++ // C++
node = getGPPCompletionNode(code.toString()); node = getGPPCompletionNode(code);
assertNotNull(node); assertNotNull(node);
// C // C
node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
assertNotNull(node); assertNotNull(node);
} }
} }

View file

@ -13,7 +13,6 @@ package org.eclipse.cdt.core.lrparser.tests;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
@ -24,7 +23,7 @@ import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.tests.prefix.BasicCompletionTest; import org.eclipse.cdt.core.parser.tests.prefix.BasicCompletionTest;
import org.eclipse.cdt.internal.core.parser.ParserException; import org.eclipse.cdt.internal.core.parser.ParserException;
@SuppressWarnings("restriction") @SuppressWarnings({"restriction", "nls"})
public class LRCompletionBasicTest extends BasicCompletionTest { public class LRCompletionBasicTest extends BasicCompletionTest {
public static TestSuite suite() { public static TestSuite suite() {
@ -52,41 +51,52 @@ public class LRCompletionBasicTest extends BasicCompletionTest {
protected ILanguage getCPPLanguage() { protected ILanguage getCPPLanguage() {
return ISOCPPLanguage.getDefault(); return ISOCPPLanguage.getDefault();
} }
@Override @Override
public void testFunction() throws Exception { public void testFunction() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("void func(int x) { }");//$NON-NLS-1$ "void func(int x) { }" +
code.append("void func2() { fu");//$NON-NLS-1$ "void func2() { fu";
// C++
IASTCompletionNode node = getGPPCompletionNode(code);
IBinding[] bindings = LRCompletionParseTest.getBindings(node.getNames());
assertEquals(2, bindings.length);
assertEquals("func", ((IFunction)bindings[0]).getName());
assertEquals("func2", ((IFunction)bindings[1]).getName());
// C // C
IASTCompletionNode node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
IASTName[] names = node.getNames(); bindings = LRCompletionParseTest.getBindings(node.getNames());
// There is only one name, for now
assertEquals(2, names.length);
// The expression points to our functions
IBinding[] bindings = sortBindings(names[1].getCompletionContext().findBindings(names[1], true));
// There should be two since they both start with fu
assertEquals(2, bindings.length); assertEquals(2, bindings.length);
assertEquals("func", ((IFunction)bindings[0]).getName());//$NON-NLS-1$ assertEquals("func", ((IFunction)bindings[0]).getName());
assertEquals("func2", ((IFunction)bindings[1]).getName());//$NON-NLS-1$ assertEquals("func2", ((IFunction)bindings[1]).getName());
} }
@Override @Override
public void testTypedef() throws Exception { public void testTypedef() throws Exception {
StringBuffer code = new StringBuffer(); String code =
code.append("typedef int blah;");//$NON-NLS-1$ "typedef int blah;" +
code.append("bl");//$NON-NLS-1$ "bl";
// C++
IASTCompletionNode node = getGPPCompletionNode(code);
IBinding[] bindings = LRCompletionParseTest.getBindings(node.getNames());
assertEquals(1, bindings.length);
assertEquals("blah", ((ITypedef)bindings[0]).getName());
// C // C
IASTCompletionNode node = getGCCCompletionNode(code.toString()); node = getGCCCompletionNode(code);
IASTName[] names = node.getNames(); bindings = LRCompletionParseTest.getBindings(node.getNames());
assertEquals(1, names.length);
IBinding[] bindings = names[0].getCompletionContext().findBindings(names[0], true);
assertEquals(1, bindings.length); assertEquals(1, bindings.length);
assertEquals("blah", ((ITypedef)bindings[0]).getName());//$NON-NLS-1$ assertEquals("blah", ((ITypedef)bindings[0]).getName());
} }
} }

View file

@ -56,7 +56,7 @@ public class LRCompletionParseTest extends TestCase {
}; };
protected IBinding[] getBindings(IASTName[] names) { public static IBinding[] getBindings(IASTName[] names) {
List<IBinding> bindings = new ArrayList<IBinding>(); List<IBinding> bindings = new ArrayList<IBinding>();
for(IASTName name : names) for(IASTName name : names)

View file

@ -28,7 +28,6 @@ public class CPPASTAmbiguousDeclarator extends CPPASTAmbiguity implements IASTDe
public CPPASTAmbiguousDeclarator(IASTDeclarator ... ds) { public CPPASTAmbiguousDeclarator(IASTDeclarator ... ds) {
System.out.println("CPPASTAmbiguousDeclarator created");
for(IASTDeclarator declarator : ds) for(IASTDeclarator declarator : ds)
addDeclarator(declarator); addDeclarator(declarator);
} }

View file

@ -1198,21 +1198,32 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
List<Object> declarators = hasDeclaratorList ? astStack.closeScope() : Collections.emptyList(); List<Object> declarators = hasDeclaratorList ? astStack.closeScope() : Collections.emptyList();
IASTDeclSpecifier declSpecifier = (IASTDeclSpecifier) astStack.pop(); // may be null IASTDeclSpecifier declSpecifier = (IASTDeclSpecifier) astStack.pop(); // may be null
List<IToken> ruleTokens = parser.getRuleTokens(); List<IToken> ruleTokens = parser.getRuleTokens();
IToken nameToken = null;
// do not generate nodes for extra EOC tokens // do not generate nodes for extra EOC tokens
if(matchTokens(ruleTokens, tokenMap, TK_EndOfCompletion)) { if(matchTokens(ruleTokens, tokenMap, TK_EndOfCompletion)) {
return; return;
} }
if(declSpecifier == null) { // can happen if implicit int is used
// In the case that a single completion token is parsed then it needs
// to be interpreted as a named type specifier for content assist to work.
else if(matchTokens(ruleTokens, tokenMap, TK_Completion, TK_EndOfCompletion)) {
IASTName name = createName(parser.getLeftIToken());
declSpecifier = nodeFactory.newCPPNamedTypeSpecifier(name, false);
setOffsetAndLength(declSpecifier, offset(name), length(name));
declarators = Collections.emptyList(); // throw away the bogus declarator
}
// can happen if implicit int is used
else if(declSpecifier == null) {
declSpecifier = nodeFactory.newSimpleDeclSpecifier(); declSpecifier = nodeFactory.newSimpleDeclSpecifier();
setOffsetAndLength(declSpecifier, parser.getLeftIToken().getStartOffset(), 0); setOffsetAndLength(declSpecifier, parser.getLeftIToken().getStartOffset(), 0);
} }
// bug 80171, check for situation similar to: static var; // bug 80171, check for situation similar to: static var;
// this will get parsed wrong, the following is a hack to rebuild the AST as it should have been parsed // this will get parsed wrong, the following is a hack to rebuild the AST as it should have been parsed
IToken nameToken = null; else if(declarators.isEmpty() &&
if(declarators.isEmpty() &&
declSpecifier instanceof ICPPASTNamedTypeSpecifier && declSpecifier instanceof ICPPASTNamedTypeSpecifier &&
ruleTokens.size() >= 2 && ruleTokens.size() >= 2 &&
baseKind(nameToken = ruleTokens.get(ruleTokens.size() - 2)) == TK_identifier) { baseKind(nameToken = ruleTokens.get(ruleTokens.size() - 2)) == TK_identifier) {