diff --git a/core/org.eclipse.cdt.core.tests/build.properties b/core/org.eclipse.cdt.core.tests/build.properties index 70b17f8d270..8a325d26564 100644 --- a/core/org.eclipse.cdt.core.tests/build.properties +++ b/core/org.eclipse.cdt.core.tests/build.properties @@ -17,7 +17,8 @@ bin.includes = plugin.xml,\ parser/org/eclipse/cdt/internal/index/tests/,\ parser/org/eclipse/cdt/internal/pdom/tests/,\ parser/org/eclipse/cdt/core/parser/tests/ast2/,\ - parser/org/eclipse/cdt/core/parser/tests/scanner/ + parser/org/eclipse/cdt/core/parser/tests/scanner/,\ + parser/org/eclipse/cdt/core/parser/tests/prefix/ output.. = bin/ source.. = model/,\ 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 268ca5e9a51..1df2d70188f 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2009 IBM Corporation 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 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.prefix; +import java.util.List; + import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -124,4 +126,22 @@ public class BasicCompletionTest extends CompletionTestBase { node = getGCCCompletionNode(code); assertNotNull(node); } + + // template class CT {}; + // template class B: public A { + // public: + // void doit(){} + // }; + // int main() { + // B b; + // b. + public void testBug267911() throws Exception { + String code = getAboveComment(); + IASTCompletionNode node = getGPPCompletionNode(code); + assertNotNull(node); + List bindings= proposeBindings(node); + String[] names= getSortedNames(bindings); + assertEquals("B", names[0]); + assertEquals("doit", names[1]); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/CompletionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/CompletionTestBase.java index 6385b84b377..4705080a62a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/CompletionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/CompletionTestBase.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2004, 2007 IBM Corporation and others. + * Copyright (c) 2004, 2009 IBM Corporation 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 @@ -7,15 +7,22 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.prefix; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.Iterator; +import java.util.List; -import junit.framework.TestCase; +import junit.framework.AssertionFailedError; +import org.eclipse.cdt.core.dom.ast.IASTCompletionContext; 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.parser.ISourceCodeParser; import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; @@ -32,11 +39,14 @@ import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.core.parser.tests.ast2.AST2BaseTest; +import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; import org.eclipse.cdt.internal.core.parser.ParserException; -public class CompletionTestBase extends TestCase { +public class CompletionTestBase extends BaseTestCase { private static final IParserLogService NULL_LOG = new NullLogService(); @@ -97,4 +107,47 @@ public class CompletionTestBase extends TestCase { Arrays.sort(bindings, bindingsComparator); return bindings; } + + protected String getAboveComment() throws IOException { + return getContents(1)[0].toString(); + } + + protected StringBuffer[] getContents(int sections) throws IOException { + CTestPlugin plugin = CTestPlugin.getDefault(); + if (plugin == null) + throw new AssertionFailedError("This test must be run as a JUnit plugin test"); + return TestSourceReader.getContentsForTest(plugin.getBundle(), "parser", getClass(), getName(), sections); + } + + protected List proposeBindings(IASTCompletionNode completionNode) { + List proposals = new ArrayList(); + boolean handleMacros= false; + IASTName[] names = completionNode.getNames(); + + for (int i = 0; i < names.length; ++i) { + if (names[i].getTranslationUnit() == null) + // The node isn't properly hooked up, must have backtracked out of this node + continue; + + IASTCompletionContext astContext = names[i].getCompletionContext(); + if (astContext == null) { + continue; + } + IBinding[] bindings = astContext.findBindings(names[i], true); + if (bindings != null) + for (int j = 0; j < bindings.length; ++j) + proposals.add(bindings[j]); + } + return proposals; + } + + protected String[] getSortedNames(List bindings) { + String[] result= new String[bindings.size()]; + Iterator it= bindings.iterator(); + for (int i = 0; i < result.length; i++) { + result[i]= it.next().getName(); + } + Arrays.sort(result); + return result; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java index 4fcdc2730ea..9410007f34d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java @@ -89,22 +89,6 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat public IBinding[] getBindings(IASTName name, boolean forceResolve, boolean prefixLookup, IIndexFileSet fileSet, boolean checkPointOfDecl) throws DOMException { - char[] c = name.getLookupKey(); - - if ((!prefixLookup && CharArrayUtils.equals(c, specialClass.getNameCharArray())) || - (prefixLookup && CharArrayUtils.equals(specialClass.getNameCharArray(), 0, c.length, c, true))) { - IBinding[] result= new IBinding[] {specialClass}; - if (CPPClassScope.isConstructorReference(name)) { - result = (IBinding[]) ArrayUtil.addAll(IBinding.class, result, specialClass.getConstructors()); - } - result= (IBinding[]) ArrayUtil.trim(IBinding.class, result); - // specialize all but first - for (int i = 1; i < result.length; i++) { - result[i]= specialClass.specializeMember(result[i]); - } - return result; - } - ICPPClassType specialized = specialClass.getSpecializedBinding(); IScope classScope = specialized.getCompositeScope(); if (classScope == null) @@ -118,7 +102,11 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat } IBinding[] result= null; for (IBinding binding : bindings) { - binding= specialClass.specializeMember(binding); + if (binding == specialized) { + binding= specialClass; + } else { + binding= specialClass.specializeMember(binding); + } result = (IBinding[]) ArrayUtil.append(IBinding.class, result, binding); } return (IBinding[]) ArrayUtil.trim(IBinding.class, result); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java index d2b4049d8d1..0f8d8a3fb21 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2009 IBM Corporation 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 @@ -83,9 +83,9 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase { if (b instanceof ICPPClassType || b instanceof ICPPTemplateParameter) { baseClass = b; } else if (b instanceof IProblemBinding) { - baseClass = new CPPClassType.CPPClassTypeProblem(base.getName(), ((IProblemBinding) b).getID(), base.getName().toCharArray()); + baseClass = new CPPClassType.CPPClassTypeProblem(base.getName(), ((IProblemBinding) b).getID()); } else { - baseClass = new CPPClassType.CPPClassTypeProblem(base.getName(), IProblemBinding.SEMANTIC_NAME_NOT_FOUND, base.getName().toCharArray()); + baseClass = new CPPClassType.CPPClassTypeProblem(base.getName(), IProblemBinding.SEMANTIC_NAME_NOT_FOUND); } } return baseClass; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 752e88b9aba..f829e8079dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -64,7 +65,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; * Base implementation for c++ scopes. */ public class CPPClassScope extends CPPScope implements ICPPClassScope { - private static final char[] CONSTRUCTOR_KEY = "!!!CTOR!!!".toCharArray(); //$NON-NLS-1$ private ICPPMethod[] implicits = null; public CPPClassScope(ICPPASTCompositeTypeSpecifier physicalNode) { @@ -349,6 +349,8 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) return true; return false; + } else if (node instanceof IASTFieldReference) { + return false; } return true; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index df45a1b7aaa..030f6ba95d7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -62,6 +62,9 @@ import org.eclipse.core.runtime.PlatformObject; public class CPPClassType extends PlatformObject implements ICPPInternalClassTypeMixinHost { public static class CPPClassTypeProblem extends ProblemBinding implements ICPPClassType { + public CPPClassTypeProblem(IASTName name, int id) { + super(name, id); + } public CPPClassTypeProblem(IASTNode node, int id, char[] arg) { super(node, id, arg); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index 16c4852f7de..74eec0910c3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -51,6 +51,7 @@ import org.eclipse.core.runtime.NullProgressMonitor; * Base class for c++-scopes of the ast. */ abstract public class CPPScope implements ICPPScope, ICPPASTInternalScope { + protected static final char[] CONSTRUCTOR_KEY = "!!!CTOR!!!".toCharArray(); //$NON-NLS-1$ private static final IProgressMonitor NPM = new NullProgressMonitor(); private IASTNode physicalNode; private boolean isCached = false; @@ -240,7 +241,7 @@ abstract public class CPPScope implements ICPPScope, ICPPASTInternalScope { ObjectSet all= new ObjectSet(16); for (int i = 0; i < keys.length; i++) { final char[] key = (char[]) keys[i]; - if (CharArrayUtils.equals(key, 0, c.length, c, true)) { + if (key != CONSTRUCTOR_KEY && CharArrayUtils.equals(key, 0, c.length, c, true)) { obj= bindings.get(key); if (obj instanceof ObjectSet) { all.addAll((ObjectSet) obj);