diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java index 7e68668203f..1935a184c6b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java @@ -370,5 +370,12 @@ public class BasicCompletionTest extends CompletionTestBase { checkCompletion(code, false, expected); checkCompletion(code, true, expected); } - + + // struct foo { int axx;}; + // struct foo bar = {.a + public void testCompletionInDesignatedInitializor_353281() throws Exception { + String code = getAboveComment(); + String[] expected= {"axx"}; + checkCompletion(code, false, expected); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDesignator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDesignator.java index 2e74509505f..567324b2ab7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDesignator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDesignator.java @@ -13,14 +13,16 @@ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTCompletionContext; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; /** * Implementation of field designators */ -public class CASTFieldDesignator extends ASTNode implements ICASTFieldDesignator { +public class CASTFieldDesignator extends ASTNode implements ICASTFieldDesignator, IASTCompletionContext { private IASTName name; @@ -74,4 +76,8 @@ public class CASTFieldDesignator extends ASTNode implements ICASTFieldDesignator return true; } + + public IBinding[] findBindings(IASTName n, boolean isPrefix) { + return CVisitor.findBindingsForContentAssist(n, isPrefix); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index 920ae596fd9..c3fb65a4489 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -607,25 +607,30 @@ public class CVisitor extends ASTQueries { } if (type != null && type instanceof ICompositeType) { + final ICompositeType ct = (ICompositeType) type; if (type instanceof IIndexBinding) { - type= ((CASTTranslationUnit) fieldReference.getTranslationUnit()).mapToASTType((ICompositeType) type); + type= ((CASTTranslationUnit) fieldReference.getTranslationUnit()).mapToASTType(ct); } if (prefix) { - IBinding[] result = null; char[] p = fieldReference.getFieldName().toCharArray(); - IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(p); - IField[] fields = ((ICompositeType) type).getFields(); - for (IField field : fields) { - if (matcher.match(field.getNameCharArray())) { - result = (IBinding[]) ArrayUtil.append(IBinding.class, result, field); - } - } - return ArrayUtil.trim(IBinding.class, result); + return findFieldsByPrefix(ct, p); } - return ((ICompositeType) type).findField(fieldReference.getFieldName().toString()); + return ct.findField(fieldReference.getFieldName().toString()); } return null; } + + public static IBinding[] findFieldsByPrefix(final ICompositeType ct, char[] p) { + IBinding[] result = null; + IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(p); + IField[] fields = ct.getFields(); + for (IField field : fields) { + if (matcher.match(field.getNameCharArray())) { + result = (IBinding[]) ArrayUtil.append(IBinding.class, result, field); + } + } + return (IBinding[]) ArrayUtil.trim(IBinding.class, result); + } static IType getPtrDiffType(IASTBinaryExpression expr) { IScope scope = getContainingScope(expr); @@ -1463,6 +1468,8 @@ public class CVisitor extends ASTQueries { if (prop == IASTFieldReference.FIELD_NAME) { result = (IBinding[]) findBinding((IASTFieldReference) name.getParent(), isPrefix); + } else if (prop == ICASTFieldDesignator.FIELD_NAME) { + result = findBindingForContentAssist((ICASTFieldDesignator) name.getParent(), isPrefix); } else { IScope scope= getContainingScope(name); try { @@ -1477,7 +1484,35 @@ public class CVisitor extends ASTQueries { return (IBinding[]) ArrayUtil.trim(IBinding.class, result); } - public static IBinding[] findBindings(IScope scope, String name) { + private static IBinding[] findBindingForContentAssist(ICASTFieldDesignator fd, boolean isPrefix) { + IASTNode blockItem = getContainingBlockItem(fd); + + IASTNode parent= blockItem; + while (parent != null && !(parent instanceof IASTSimpleDeclaration)) + parent= parent.getParent(); + + if (parent instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent; + IBinding struct= null; + if (simpleDecl.getDeclSpecifier() instanceof IASTNamedTypeSpecifier) { + struct = ((IASTNamedTypeSpecifier) simpleDecl.getDeclSpecifier()).getName().resolveBinding(); + } else if (simpleDecl.getDeclSpecifier() instanceof IASTElaboratedTypeSpecifier) { + struct = ((IASTElaboratedTypeSpecifier) simpleDecl.getDeclSpecifier()).getName().resolveBinding(); + } else if (simpleDecl.getDeclSpecifier() instanceof IASTCompositeTypeSpecifier) { + struct = ((IASTCompositeTypeSpecifier) simpleDecl.getDeclSpecifier()).getName().resolveBinding(); + } + if (struct instanceof IType) { + IType t= unwrapTypedefs((IType) struct); + + if (t instanceof ICompositeType) { + return findFieldsByPrefix((ICompositeType) t, fd.getName().toCharArray()); + } + } + } + return null; + } + + public static IBinding[] findBindings(IScope scope, String name) { CASTName astName = new CASTName(name.toCharArray()); // normal names diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 19c901da95a..cb269070476 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -177,18 +177,21 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { // in any way add the initializer such that the actual size can be tracked. result.addClause(clause); } else { - // Gnu extension: the assign operator is optional - if (LT(1) == IToken.tASSIGN) - consume(IToken.tASSIGN); - - IASTInitializerClause clause= initClause(false); - ICASTDesignatedInitializer desigInitializer = nodeFactory.newDesignatedInitializer(clause); + ICASTDesignatedInitializer desigInitializer = nodeFactory.newDesignatedInitializer((IASTInitializerClause) null); setRange(desigInitializer, designator.get(0)); - adjustLength(desigInitializer, clause); - for (ICASTDesignator d : designator) { desigInitializer.addDesignator(d); } + + if (LT(1) != IToken.tEOC) { + // Gnu extension: the assign operator is optional + if (LT(1) == IToken.tASSIGN) + consume(IToken.tASSIGN); + + IASTInitializerClause clause= initClause(false); + desigInitializer.setOperand(clause); + adjustLength(desigInitializer, clause); + } result.addClause(desigInitializer); }