From b73f4d0539cdfae2c19e41d3252fd3191501eb37 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 28 May 2010 08:53:04 +0000 Subject: [PATCH] Bug 103857: Content assist for fields declared below point of completion. --- .../internal/core/model/TranslationUnit.java | 9 ++++- .../core/dom/parser/ASTTranslationUnit.java | 10 ++++++ .../core/dom/parser/c/CNodeFactory.java | 6 +++- .../core/dom/parser/cpp/CPPNodeFactory.java | 4 +++ .../parser/cpp/semantics/CPPSemantics.java | 34 +++++++++++++++---- .../core/parser/scanner/CPreprocessor.java | 4 +++ .../internal/core/parser/scanner/Lexer.java | 6 +++- .../text/contentassist2/CompletionTests.java | 22 ++++++++++-- 8 files changed, 84 insertions(+), 11 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index edb4515f44e..99116f3cbd7 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -894,7 +894,14 @@ public class TranslationUnit extends Openable implements ITranslationUnit { fLanguageOfContext= language; if (language != null) { IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID()); - return language.getCompletionNode(fileContent, scanInfo, crf, index, ParserUtil.getParserLogService(), offset); + IASTCompletionNode result = language.getCompletionNode(fileContent, scanInfo, crf, index, ParserUtil.getParserLogService(), offset); + if (result != null) { + final IASTTranslationUnit ast = result.getTranslationUnit(); + if (ast != null) { + ast.setIsHeaderUnit(!isSourceUnit()); + } + } + return result; } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index 54f51d54750..30196c00ea0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -62,6 +62,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat private boolean fIsHeader= true; private IIndexFileSet fIndexFileSet; private INodeFactory fNodeFactory; + private boolean fForContentAssist; @Override @@ -339,6 +340,14 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat fIsHeader= headerUnit; } + public boolean isForContentAssist() { + return fForContentAssist; + } + + public final void setIsForContentAssist(boolean forContentAssist) { + fForContentAssist= forContentAssist; + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.scanner.ISkippedIndexedFilesListener#skippedFile(org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent) */ @@ -378,6 +387,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat copy.setIsHeaderUnit(fIsHeader); copy.setASTNodeFactory(fNodeFactory); copy.setLocationResolver(fLocationResolver); + copy.setIsForContentAssist(fForContentAssist); for(IASTDeclaration declaration : getDeclarations()) copy.addDeclaration(declaration == null ? null : declaration.copy()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java index ee633799221..36e1a5560ce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; import org.eclipse.cdt.core.dom.ast.IASTDoStatement; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; @@ -62,7 +63,6 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; -import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; @@ -80,6 +80,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator; import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.internal.core.dom.parser.NodeFactory; +import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; /** * Abstract factory implementation that creates AST nodes for C99. @@ -344,6 +345,9 @@ public class CNodeFactory extends NodeFactory implements ICNodeFactory { if (scanner != null) { tu.setLocationResolver(scanner.getLocationResolver()); + if (scanner instanceof CPreprocessor) { + tu.setIsForContentAssist(((CPreprocessor) scanner).isContentAssistMode()); + } } tu.setASTNodeFactory(this); return tu; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 4661f2afa41..50017fe4bc6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -109,6 +109,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember; import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.internal.core.dom.parser.NodeFactory; +import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; /** @@ -535,6 +536,9 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { if (scanner != null) { tu.setLocationResolver(scanner.getLocationResolver()); + if (scanner instanceof CPreprocessor) { + tu.setIsForContentAssist(((CPreprocessor) scanner).isContentAssistMode()); + } } tu.setASTNodeFactory(this); return tu; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index b1dfabbae6a..ac84b781b63 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -141,6 +141,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; +import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileSet; @@ -155,6 +156,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; +import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -1031,13 +1033,33 @@ public class CPPSemantics { } static IBinding[] getBindingsFromScope(ICPPScope scope, final IIndexFileSet fileSet, LookupData data) throws DOMException { - IBinding[] bindings; + // For internal scopes we need to check the point of declaration if (scope instanceof ICPPASTInternalScope) { - bindings= ((ICPPASTInternalScope) scope).getBindings(data.astName, true, data.prefixLookup, fileSet, data.checkPointOfDecl); - } else { - bindings= scope.getBindings(data.astName, true, data.prefixLookup, fileSet); - } - return bindings; + final IASTName astName = data.astName; + final ICPPASTInternalScope internalScope = (ICPPASTInternalScope) scope; + IBinding[] bindings= internalScope.getBindings(astName, true, data.prefixLookup, fileSet, data.checkPointOfDecl); + + // Bug 103857: Members declared after the point of completion cannot be + // found in the partial AST, we look them up in the index + if (data.checkWholeClassScope && scope instanceof ICPPClassScope) { + final IASTTranslationUnit tu = astName.getTranslationUnit(); + if (tu instanceof ASTTranslationUnit && ((ASTTranslationUnit) tu).isForContentAssist()) { + IIndex index = tu.getIndex(); + IASTNode node = internalScope.getPhysicalNode(); + if (index != null && node != null && node.contains(astName)) { + IBinding indexBinding= index.adaptBinding(((ICPPClassScope) scope).getClassType()); + if (indexBinding instanceof ICPPClassType) { + IScope scopeInIndex= ((ICPPClassType) indexBinding).getCompositeScope(); + bindings= ArrayUtil.addAll(bindings, scopeInIndex.getBindings(astName, true, data.prefixLookup, fileSet)); + } + } + } + } + return bindings; + } + + // For index scopes the point of declaration is ignored. + return scope.getBindings(data.astName, true, data.prefixLookup, fileSet); } static void removeObjects(final IBinding[] bindings) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 6b5df9223a0..0fa422443ee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -251,6 +251,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fContentAssistLimit= offset; fRootLexer.setContentAssistMode(offset); } + + public boolean isContentAssistMode() { + return fRootLexer.isContentAssistMode(); + } public void setProcessInactiveCode(boolean val) { fRootContext.setParseInactiveCode(val); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java index 5ad61e2a86f..56c05d56c1f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -135,6 +135,10 @@ final public class Lexer implements ITokenSequence { fOffset= fEndOffset= fStart; nextCharPhase3(); } + + public boolean isContentAssistMode() { + return fSupportContentAssist; + } /** * Call this before consuming the name-token in the include directive. It causes the header-file diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java index abd87e87b0a..81588cf6bb8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java @@ -789,14 +789,32 @@ public class CompletionTests extends AbstractContentAssistTest { // void blah(const vector3& v) { x += v./*cursor*/; } // float x; // }; - public void _testForwardMembersInInlineMethods_Bug185652() throws Exception { - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185652 + public void testForwardMembersInInlineMethods_Bug103857a() throws Exception { + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=103857 final String[] expected= { "x" }; assertMinimumCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_REP_STRINGS); } + // struct S { + // int mem; + // }; + // class X { + // void test() { + // T t; + // t.m/*cursor*/; + // } + // typedef S T; + // }; + public void testForwardMembersInInlineMethods_Bug103857b() throws Exception { + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185652 + final String[] expected= { + "mem" + }; + assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_REP_STRINGS); + } + // void Pri/*cursor*/ public void testMethodDefinitionClassName_Bug190296() throws Exception { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=190296