mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Rolled back fix for bug 172305 to reimplement it separately from name lookup.
This commit is contained in:
parent
07339a8260
commit
29f917fa8f
15 changed files with 266 additions and 496 deletions
|
@ -651,22 +651,6 @@ public class ASTTypeUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a type is present in an array of types.
|
|
||||||
* @param type a type.
|
|
||||||
* @param array an array of types
|
|
||||||
* @return offset of the first occurrence of type in the array, or -1 if not found.
|
|
||||||
* @since 5.2
|
|
||||||
*/
|
|
||||||
public static int findType(IType type, IType[] array) {
|
|
||||||
for (int i = 0; i < array.length; i++) {
|
|
||||||
if (type.isSameType(array[i])) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] getQualifiedNameForAnonymous(ICPPBinding binding, boolean normalize) throws DOMException {
|
private static String[] getQualifiedNameForAnonymous(ICPPBinding binding, boolean normalize) throws DOMException {
|
||||||
LinkedList<String> result= new LinkedList<String>();
|
LinkedList<String> result= new LinkedList<String>();
|
||||||
result.addFirst(getNameForAnonymous(binding));
|
result.addFirst(getNameForAnonymous(binding));
|
||||||
|
@ -737,6 +721,7 @@ public class ASTTypeUtil {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int findFileNameStart(char[] fname) {
|
private static int findFileNameStart(char[] fname) {
|
||||||
for (int i= fname.length - 2; i >= 0; i--) {
|
for (int i= fname.length - 2; i >= 0; i--) {
|
||||||
switch (fname[i]) {
|
switch (fname[i]) {
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Sergey Prigogin (Google)
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser;
|
package org.eclipse.cdt.internal.core.dom.parser;
|
||||||
|
|
||||||
|
|
|
@ -1643,7 +1643,7 @@ public class CVisitor extends ASTQueries {
|
||||||
* Searches for the function enclosing the given node. May return <code>null</code>.
|
* Searches for the function enclosing the given node. May return <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public static IBinding findEnclosingFunction(IASTNode node) {
|
public static IBinding findEnclosingFunction(IASTNode node) {
|
||||||
while (node != null && !(node instanceof IASTFunctionDefinition)) {
|
while(node != null && node instanceof IASTFunctionDefinition == false) {
|
||||||
node= node.getParent();
|
node= node.getParent();
|
||||||
}
|
}
|
||||||
if (node == null)
|
if (node == null)
|
||||||
|
|
|
@ -50,8 +50,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
|
@ -67,7 +65,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType.CPPClassTypeProblem;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType.CPPClassTypeProblem;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,41 +122,6 @@ public class ClassTypeHelper {
|
||||||
return resultSet.keyArray(IBinding.class);
|
return resultSet.keyArray(IBinding.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a binding is a friend of a class. Only classes and functions can be friends of a class.
|
|
||||||
* A class is considered a friend of itself.
|
|
||||||
* @param binding a binding.
|
|
||||||
* @param classType a class.
|
|
||||||
* @return <code>true</code> if <code>binding</code> is a friend of <code>classType</code>.
|
|
||||||
* @throws DOMException
|
|
||||||
*/
|
|
||||||
public static boolean isFriend(IBinding binding, ICPPClassType classType) throws DOMException {
|
|
||||||
IType type;
|
|
||||||
if (binding instanceof ICPPClassType) {
|
|
||||||
type = (IType) binding;
|
|
||||||
if (type.isSameType(classType)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (IBinding friend : classType.getFriends()) {
|
|
||||||
if (friend instanceof ICPPClassType && type.isSameType((IType) friend)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (binding instanceof ICPPFunction) {
|
|
||||||
type = ((ICPPFunction) binding).getType();
|
|
||||||
char[] name = binding.getNameCharArray();
|
|
||||||
for (IBinding friend : classType.getFriends()) {
|
|
||||||
if (friend instanceof ICPPFunction &&
|
|
||||||
CharArrayUtils.equals(name, friend.getNameCharArray()) &&
|
|
||||||
SemanticUtil.isSameOwner(binding.getOwner(), friend.getOwner()) &&
|
|
||||||
type.isSameType(((ICPPFunction) friend).getType())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A host maybe backed up with a definition from the index.
|
* A host maybe backed up with a definition from the index.
|
||||||
* @throws DOMException
|
* @throws DOMException
|
||||||
|
@ -245,39 +207,22 @@ public class ClassTypeHelper {
|
||||||
return (ICPPField[]) ArrayUtil.trim(ICPPField.class, result);
|
return (ICPPField[]) ArrayUtil.trim(ICPPField.class, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPClassType[] getAllBases(ICPPClassType classType) throws DOMException {
|
public static ICPPClassType[] getAllBases(ICPPClassType ct) throws DOMException {
|
||||||
return getAllBases(classType, ICPPBase.v_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all direct and indirect base classes that have at least a given visibility level.
|
|
||||||
* @param classType a class
|
|
||||||
* @param minVisibility one of <code>ICPPBase.v_private</code>, <code>ICPPBase.v_protected</code>,
|
|
||||||
* or <code>ICPPBase.v_public</code>. All base classes are returned if
|
|
||||||
* <code>minVisibility == ICPPBase.v_private</code> since it is the lowest visibility level.
|
|
||||||
* @return An array of visible base classes in arbitrary order.
|
|
||||||
* @throws DOMException
|
|
||||||
*/
|
|
||||||
public static ICPPClassType[] getAllBases(ICPPClassType classType, int minVisibility) throws DOMException {
|
|
||||||
HashSet<ICPPClassType> result= new HashSet<ICPPClassType>();
|
HashSet<ICPPClassType> result= new HashSet<ICPPClassType>();
|
||||||
result.add(classType);
|
result.add(ct);
|
||||||
getAllBases(classType, minVisibility, result);
|
getAllBases(ct, result);
|
||||||
result.remove(classType);
|
result.remove(ct);
|
||||||
return result.toArray(new ICPPClassType[result.size()]);
|
return result.toArray(new ICPPClassType[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getAllBases(ICPPClassType classType, int minVisibility, HashSet<ICPPClassType> result) throws DOMException {
|
private static void getAllBases(ICPPClassType ct, HashSet<ICPPClassType> result) throws DOMException {
|
||||||
ICPPBase[] bases= classType.getBases();
|
ICPPBase[] bases= ct.getBases();
|
||||||
for (ICPPBase base : bases) {
|
for (ICPPBase base : bases) {
|
||||||
// Note that numeric visibility values are ordered backwards:
|
|
||||||
// ICPPBase.v_public < ICPPBase.v_protected < ICPPBase.v_private.
|
|
||||||
if (base.getVisibility() <= minVisibility) {
|
|
||||||
IBinding b= base.getBaseClass();
|
IBinding b= base.getBaseClass();
|
||||||
if (b instanceof ICPPClassType) {
|
if (b instanceof ICPPClassType) {
|
||||||
final ICPPClassType baseClass = (ICPPClassType) b;
|
final ICPPClassType ctbase = (ICPPClassType) b;
|
||||||
if (result.add(baseClass)) {
|
if (result.add(ctbase)) {
|
||||||
getAllBases(baseClass, minVisibility, result);
|
getAllBases(ctbase, result);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +230,7 @@ public class ClassTypeHelper {
|
||||||
|
|
||||||
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) throws DOMException {
|
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) throws DOMException {
|
||||||
ICPPMethod[] methods= ct.getDeclaredMethods();
|
ICPPMethod[] methods= ct.getDeclaredMethods();
|
||||||
ICPPClassType[] bases= getAllBases(ct, ICPPBase.v_private);
|
ICPPClassType[] bases= getAllBases(ct);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
methods = (ICPPMethod[]) ArrayUtil.addAll(ICPPMethod.class, methods, base.getDeclaredMethods());
|
methods = (ICPPMethod[]) ArrayUtil.addAll(ICPPMethod.class, methods, base.getDeclaredMethods());
|
||||||
}
|
}
|
||||||
|
@ -298,7 +243,7 @@ public class ClassTypeHelper {
|
||||||
ICPPClassScope scope= (ICPPClassScope) ct.getCompositeScope();
|
ICPPClassScope scope= (ICPPClassScope) ct.getCompositeScope();
|
||||||
set.addAll(scope.getImplicitMethods());
|
set.addAll(scope.getImplicitMethods());
|
||||||
|
|
||||||
ICPPClassType[] bases= getAllBases(ct, ICPPBase.v_private);
|
ICPPClassType[] bases= getAllBases(ct);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
set.addAll(base.getDeclaredMethods());
|
set.addAll(base.getDeclaredMethods());
|
||||||
final IScope compositeScope = base.getCompositeScope();
|
final IScope compositeScope = base.getCompositeScope();
|
||||||
|
@ -419,7 +364,7 @@ public class ClassTypeHelper {
|
||||||
|
|
||||||
public static IField[] getFields(ICPPClassType ct) throws DOMException {
|
public static IField[] getFields(ICPPClassType ct) throws DOMException {
|
||||||
IField[] fields = ct.getDeclaredFields();
|
IField[] fields = ct.getDeclaredFields();
|
||||||
ICPPClassType[] bases = getAllBases(ct, ICPPBase.v_private);
|
ICPPClassType[] bases = getAllBases(ct);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
fields = (IField[]) ArrayUtil.addAll(IField.class, fields, base.getFields());
|
fields = (IField[]) ArrayUtil.addAll(IField.class, fields, base.getFields());
|
||||||
}
|
}
|
||||||
|
@ -487,7 +432,7 @@ public class ClassTypeHelper {
|
||||||
if (sourceClass == null || targetClass == null)
|
if (sourceClass == null || targetClass == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ICPPClassType[] bases= getAllBases(sourceClass, ICPPBase.v_private);
|
ICPPClassType[] bases= getAllBases(sourceClass);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
if (base.isSameType(targetClass))
|
if (base.isSameType(targetClass))
|
||||||
return true;
|
return true;
|
||||||
|
@ -657,7 +602,7 @@ public class ClassTypeHelper {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<IType> inheritedTypeids = new ArrayList<IType>();
|
List<IType> inheritedTypeids = new ArrayList<IType>();
|
||||||
ICPPClassType[] bases= getAllBases(owner, ICPPBase.v_private);
|
ICPPClassType[] bases= getAllBases(owner);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
if (!(base instanceof ICPPDeferredClassInstance)) {
|
if (!(base instanceof ICPPDeferredClassInstance)) {
|
||||||
ICPPMethod baseMethod= getMethodInClass(base, kind);
|
ICPPMethod baseMethod= getMethodInClass(base, kind);
|
||||||
|
@ -749,54 +694,4 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two visibility values. ICPPBase.v_public is the highest visibility, ICPPBase.v_private is
|
|
||||||
* the lowest.
|
|
||||||
* @param visibility1 one of: ICPPBase.v_public, ICPPBase.v_protected, ICPPBase.v_private.
|
|
||||||
* @param visibility2 one of: ICPPBase.v_public, ICPPBase.v_protected, ICPPBase.v_private.
|
|
||||||
* @return <code>true</code> if <code>visibility1</code> is less than <code>visibility2</code>.
|
|
||||||
*/
|
|
||||||
public static boolean isLessVisibility(int visibility1, int visibility2) {
|
|
||||||
// Note that numeric visibility values are ordered backwards:
|
|
||||||
// ICPPBase.v_public < ICPPBase.v_protected < ICPPBase.v_private.
|
|
||||||
return visibility1 > visibility2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes bindings that are not visible at the given visibility level.
|
|
||||||
* @param bindings bindings to be filtered.
|
|
||||||
* @param minVisibility one of: ICPPMember.v_public, ICPPMember.v_protected, ICPPMember.v_private.
|
|
||||||
*/
|
|
||||||
public static void filterByVisibility(IBinding[] bindings, int minVisibility) {
|
|
||||||
final int length = bindings.length;
|
|
||||||
int pos = 0;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
final IBinding binding= bindings[i];
|
|
||||||
if (binding != null && isVisible(binding, minVisibility)) {
|
|
||||||
bindings[pos++]= binding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (pos < length) {
|
|
||||||
bindings[pos++]= null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a binding is visible at the given visibility level.
|
|
||||||
* @param binding a binding.
|
|
||||||
* @param minVisibility one of: ICPPMember.v_public, ICPPMember.v_protected, ICPPMember.v_private.
|
|
||||||
* @return <code>true</code> if visibility of the binding is not less than <code>minVisibility</code>.
|
|
||||||
*/
|
|
||||||
public static boolean isVisible(IBinding binding, int minVisibility) {
|
|
||||||
try {
|
|
||||||
if (binding instanceof ICPPMember) {
|
|
||||||
return !isLessVisibility(((ICPPMember) binding).getVisibility(), minVisibility);
|
|
||||||
}
|
|
||||||
// TODO(sprigogin): Handle visibility of nested types
|
|
||||||
} catch (DOMException e) {
|
|
||||||
// Presume visibility if anything goes wrong.
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Markus Schorn - initial API and implementation
|
* Markus Schorn - initial API and implementation
|
||||||
* Sergey Prigogin (Google)
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
@ -31,15 +30,13 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for performing the base class lookup. First a directed graph without loops is computed
|
* Helper class for performing the base class lookup. First a directed graph without loops is computed to represent the base
|
||||||
* to represent the base class hierarchy up to those bases for which the lookup finds matches. Next, from
|
* class hierarchy up to those bases for which the lookup finds matches. Next, from these leaves we search for virtual bases
|
||||||
* these leaves we search for virtual bases that are hidden. With this information the matches are extracted
|
* that are hidden. With this information the matches are extracted from the graph.
|
||||||
* from the graph.
|
|
||||||
*/
|
*/
|
||||||
class BaseClassLookup {
|
class BaseClassLookup {
|
||||||
public static void lookupInBaseClasses(LookupData data, ICPPClassScope classScope, IIndexFileSet fileSet) {
|
public static void lookupInBaseClasses(LookupData data, ICPPClassScope classScope, IIndexFileSet fileSet) {
|
||||||
|
@ -51,8 +48,7 @@ class BaseClassLookup {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final HashMap<IScope, BaseClassLookup> infoMap = new HashMap<IScope, BaseClassLookup>();
|
final HashMap<IScope, BaseClassLookup> infoMap = new HashMap<IScope, BaseClassLookup>();
|
||||||
BaseClassLookup rootInfo= lookupInBaseClass(data, null, false, classType, ICPPMember.v_public,
|
BaseClassLookup rootInfo= lookupInBaseClass(data, null, false, classType, fileSet, infoMap, 0);
|
||||||
fileSet, infoMap, 0);
|
|
||||||
if (data.contentAssist) {
|
if (data.contentAssist) {
|
||||||
rootInfo.collectResultForContentAssist(data);
|
rootInfo.collectResultForContentAssist(data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,7 +71,6 @@ class BaseClassLookup {
|
||||||
private BaseClassLookup(ICPPClassType type) {
|
private BaseClassLookup(ICPPClassType type) {
|
||||||
fClassType= type;
|
fClassType= type;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICPPClassType getClassType() {
|
ICPPClassType getClassType() {
|
||||||
return fClassType;
|
return fClassType;
|
||||||
}
|
}
|
||||||
|
@ -83,11 +78,9 @@ class BaseClassLookup {
|
||||||
IBinding[] getResult() {
|
IBinding[] getResult() {
|
||||||
return fBindings;
|
return fBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean containsVirtualBase() {
|
boolean containsVirtualBase() {
|
||||||
return fVirtual != null && fVirtual.nextSetBit(0) >= 0;
|
return (fVirtual != null && fVirtual.nextSetBit(0) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasMatches() {
|
boolean hasMatches() {
|
||||||
return fBindings != null && fBindings.length > 0 && fBindings[0] != null;
|
return fBindings != null && fBindings.length > 0 && fBindings[0] != null;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +104,6 @@ class BaseClassLookup {
|
||||||
public void setHiddenAsVirtualBase() {
|
public void setHiddenAsVirtualBase() {
|
||||||
fHiddenAsVirtualBase= true;
|
fHiddenAsVirtualBase= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void propagateHiddenAsVirtual() {
|
public void propagateHiddenAsVirtual() {
|
||||||
if (fPropagationDone)
|
if (fPropagationDone)
|
||||||
return;
|
return;
|
||||||
|
@ -141,27 +133,16 @@ class BaseClassLookup {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BaseClassLookup lookupInBaseClass(LookupData data, ICPPClassScope baseClassScope,
|
static BaseClassLookup lookupInBaseClass(LookupData data, ICPPClassScope baseClassScope, boolean isVirtual, ICPPClassType root, IIndexFileSet fileSet, HashMap<IScope, BaseClassLookup> infoMap, int depth) {
|
||||||
boolean isVirtual, ICPPClassType root, int minVisibility, IIndexFileSet fileSet,
|
|
||||||
HashMap<IScope, BaseClassLookup> infoMap, int depth) {
|
|
||||||
if (depth++ > CPPSemantics.MAX_INHERITANCE_DEPTH)
|
if (depth++ > CPPSemantics.MAX_INHERITANCE_DEPTH)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (data.filterByVisibility) {
|
|
||||||
ICPPClassType classType = baseClassScope != null ? baseClassScope.getClassType() : root;
|
|
||||||
int baseVisibility = CPPSemantics.getClassVisibility(classType, data.getVisibilityContext());
|
|
||||||
if (ClassTypeHelper.isLessVisibility(baseVisibility, minVisibility)) {
|
|
||||||
minVisibility = baseVisibility;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseClassScope != null) {
|
if (baseClassScope != null) {
|
||||||
BaseClassLookup info= infoMap.get(baseClassScope);
|
BaseClassLookup info= infoMap.get(baseClassScope);
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
// avoid loops
|
// avoid loops
|
||||||
if (info.getResult() == null) {
|
if (info.getResult() == null) {
|
||||||
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE,
|
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, root.getNameCharArray());
|
||||||
root.getNameCharArray());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
|
@ -186,10 +167,6 @@ class BaseClassLookup {
|
||||||
if (data.typesOnly) {
|
if (data.typesOnly) {
|
||||||
CPPSemantics.removeObjects(members);
|
CPPSemantics.removeObjects(members);
|
||||||
}
|
}
|
||||||
if (data.filterByVisibility) {
|
|
||||||
ClassTypeHelper.filterByVisibility(members, minVisibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (members != null && members.length > 0 && members[0] != null) {
|
if (members != null && members.length > 0 && members[0] != null) {
|
||||||
if (data.prefixLookup) {
|
if (data.prefixLookup) {
|
||||||
matches= members;
|
matches= members;
|
||||||
|
@ -203,8 +180,7 @@ class BaseClassLookup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is no result in the baseClass itself or we do content assist, we have to examine its
|
// there is no result in the baseClass itself or we do content assist, we have to examine its base-classes
|
||||||
// base-classes
|
|
||||||
ICPPClassType baseClass= result.getClassType();
|
ICPPClassType baseClass= result.getClassType();
|
||||||
if (baseClass != null) {
|
if (baseClass != null) {
|
||||||
ICPPBase[] grandBases= null;
|
ICPPBase[] grandBases= null;
|
||||||
|
@ -218,12 +194,8 @@ class BaseClassLookup {
|
||||||
for (ICPPBase grandBase : grandBases) {
|
for (ICPPBase grandBase : grandBases) {
|
||||||
if (grandBase instanceof IProblemBinding)
|
if (grandBase instanceof IProblemBinding)
|
||||||
continue;
|
continue;
|
||||||
try {
|
|
||||||
if (data.filterByVisibility &&
|
|
||||||
ClassTypeHelper.isLessVisibility(grandBase.getVisibility(), minVisibility)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
IBinding grandBaseBinding = grandBase.getBaseClass();
|
IBinding grandBaseBinding = grandBase.getBaseClass();
|
||||||
if (!(grandBaseBinding instanceof ICPPClassType)) {
|
if (!(grandBaseBinding instanceof ICPPClassType)) {
|
||||||
// 14.6.2.3 scope is not examined
|
// 14.6.2.3 scope is not examined
|
||||||
|
@ -248,10 +220,7 @@ class BaseClassLookup {
|
||||||
if (!(grandBaseScope instanceof ICPPClassScope))
|
if (!(grandBaseScope instanceof ICPPClassScope))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BaseClassLookup baseInfo= lookupInBaseClass(data, (ICPPClassScope) grandBaseScope,
|
BaseClassLookup baseInfo= lookupInBaseClass(data, (ICPPClassScope) grandBaseScope, grandBase.isVirtual(), root, fileSet, infoMap, depth);
|
||||||
grandBase.isVirtual(), root,
|
|
||||||
minVisibility == ICPPMember.v_private ? ICPPMember.v_protected : minVisibility,
|
|
||||||
fileSet, infoMap, depth);
|
|
||||||
if (baseInfo != null)
|
if (baseInfo != null)
|
||||||
result.addBase(grandBase.isVirtual(), baseInfo);
|
result.addBase(grandBase.isVirtual(), baseInfo);
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
|
@ -327,14 +296,14 @@ class BaseClassLookup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectResultForContentAssist(LookupData data) {
|
public void collectResultForContentAssist(LookupData data) {
|
||||||
if (fCollected)
|
if (fCollected)
|
||||||
return;
|
return;
|
||||||
fCollected= true;
|
fCollected= true;
|
||||||
|
|
||||||
data.foundItems = CPPSemantics.mergePrefixResults((CharArrayObjectMap) data.foundItems, fBindings, true);
|
data.foundItems = CPPSemantics.mergePrefixResults((CharArrayObjectMap) data.foundItems, fBindings, true);
|
||||||
for (BaseClassLookup child : fChildren) {
|
for (int i=0; i<fChildren.size(); i++) {
|
||||||
|
BaseClassLookup child = fChildren.get(i);
|
||||||
child.collectResultForContentAssist(data);
|
child.collectResultForContentAssist(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.EScopeKind;
|
import org.eclipse.cdt.core.dom.ast.EScopeKind;
|
||||||
|
@ -174,7 +173,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
||||||
|
@ -816,11 +814,6 @@ public class CPPSemantics {
|
||||||
if (data.typesOnly) {
|
if (data.typesOnly) {
|
||||||
removeObjects(bindings);
|
removeObjects(bindings);
|
||||||
}
|
}
|
||||||
if (data.filterByVisibility && scope instanceof ICPPClassScope) {
|
|
||||||
int visibility = getClassVisibility(((ICPPClassScope) scope).getClassType(),
|
|
||||||
data.getVisibilityContext());
|
|
||||||
ClassTypeHelper.filterByVisibility(bindings, visibility);
|
|
||||||
}
|
|
||||||
mergeResults(data, bindings, true);
|
mergeResults(data, bindings, true);
|
||||||
|
|
||||||
// store using-directives found in this block or namespace for later use.
|
// store using-directives found in this block or namespace for later use.
|
||||||
|
@ -1007,41 +1000,6 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns visibility of a class in a given context.
|
|
||||||
* @param classType a class
|
|
||||||
* @param visibilityContext @see LookupData.visibilityContext
|
|
||||||
* @return One of: ICPPMember.v_public, ICPPMember.v_protected, ICPPMember.v_private.
|
|
||||||
*/
|
|
||||||
static int getClassVisibility(ICPPClassType classType, IBinding[] visibilityContext) {
|
|
||||||
int visibility = ICPPMember.v_public;
|
|
||||||
try {
|
|
||||||
for (IBinding context : visibilityContext) {
|
|
||||||
if (ClassTypeHelper.isFriend(context, classType)) {
|
|
||||||
return ICPPMember.v_private;
|
|
||||||
}
|
|
||||||
if (visibility == ICPPMember.v_public && context instanceof ICPPClassType) {
|
|
||||||
ICPPClassType contextClass = (ICPPClassType) context;
|
|
||||||
ICPPBase[] bases = contextClass.getBases();
|
|
||||||
for (ICPPBase base : bases) {
|
|
||||||
IBinding baseClass = base.getBaseClass();
|
|
||||||
if (baseClass instanceof ICPPClassType) {
|
|
||||||
ICPPClassType[] baseClasses =
|
|
||||||
ClassTypeHelper.getAllBases((ICPPClassType) baseClass, ICPPMember.v_protected);
|
|
||||||
if (ASTTypeUtil.findType(classType, baseClasses) >= 0) {
|
|
||||||
visibility = ICPPMember.v_protected;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
|
||||||
visibility = ICPPMember.v_private; // Presume complete visibility if anything goes wrong.
|
|
||||||
}
|
|
||||||
return visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ICPPTemplateScope enclosingTemplateScope(IASTNode node) {
|
private static ICPPTemplateScope enclosingTemplateScope(IASTNode node) {
|
||||||
IASTNode parent= node.getParent();
|
IASTNode parent= node.getParent();
|
||||||
if (parent instanceof IASTName) {
|
if (parent instanceof IASTName) {
|
||||||
|
@ -2872,7 +2830,6 @@ public class CPPSemantics {
|
||||||
LookupData data = createLookupData(name, true);
|
LookupData data = createLookupData(name, true);
|
||||||
data.contentAssist = true;
|
data.contentAssist = true;
|
||||||
data.prefixLookup = prefixLookup;
|
data.prefixLookup = prefixLookup;
|
||||||
data.filterByVisibility = true;
|
|
||||||
data.foundItems = new CharArrayObjectMap(2);
|
data.foundItems = new CharArrayObjectMap(2);
|
||||||
|
|
||||||
return contentAssistLookup(data, name);
|
return contentAssistLookup(data, name);
|
||||||
|
@ -2884,7 +2841,7 @@ public class CPPSemantics {
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
}
|
}
|
||||||
CharArrayObjectMap map = (CharArrayObjectMap) data.foundItems;
|
CharArrayObjectMap map = (CharArrayObjectMap) data.foundItems;
|
||||||
IBinding[] result = IBinding.EMPTY_BINDING_ARRAY;
|
IBinding[] result = null;
|
||||||
if (!map.isEmpty()) {
|
if (!map.isEmpty()) {
|
||||||
char[] key = null;
|
char[] key = null;
|
||||||
Object obj = null;
|
Object obj = null;
|
||||||
|
@ -2893,28 +2850,28 @@ public class CPPSemantics {
|
||||||
key = map.keyAt(i);
|
key = map.keyAt(i);
|
||||||
obj = map.get(key);
|
obj = map.get(key);
|
||||||
if (obj instanceof IBinding) {
|
if (obj instanceof IBinding) {
|
||||||
result = ArrayUtil.append(result, (IBinding) obj);
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, obj);
|
||||||
} else if (obj instanceof IASTName) {
|
} else if (obj instanceof IASTName) {
|
||||||
IBinding binding = ((IASTName) obj).resolveBinding();
|
IBinding binding = ((IASTName) obj).resolveBinding();
|
||||||
if (binding != null && !(binding instanceof IProblemBinding))
|
if (binding != null && !(binding instanceof IProblemBinding))
|
||||||
result = ArrayUtil.append(result, binding);
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, binding);
|
||||||
} else if (obj instanceof Object[]) {
|
} else if (obj instanceof Object[]) {
|
||||||
Object[] objs = (Object[]) obj;
|
Object[] objs = (Object[]) obj;
|
||||||
for (int j = 0; j < objs.length && objs[j] != null; j++) {
|
for (int j = 0; j < objs.length && objs[j] != null; j++) {
|
||||||
Object item = objs[j];
|
Object item = objs[j];
|
||||||
if (item instanceof IBinding) {
|
if (item instanceof IBinding) {
|
||||||
result = ArrayUtil.append(result, (IBinding) item);
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, item);
|
||||||
} else if (item instanceof IASTName) {
|
} else if (item instanceof IASTName) {
|
||||||
IBinding binding = ((IASTName) item).resolveBinding();
|
IBinding binding = ((IASTName) item).resolveBinding();
|
||||||
if (binding != null && !(binding instanceof IProblemBinding))
|
if (binding != null && !(binding instanceof IProblemBinding))
|
||||||
result = ArrayUtil.append(result, binding);
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ArrayUtil.trim(result);
|
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBinding[] standardLookup(LookupData data, Object start) {
|
private static IBinding[] standardLookup(LookupData data, Object start) {
|
||||||
|
@ -2977,7 +2934,7 @@ public class CPPSemantics {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static IBinding resolveUnknownName(IScope scope, ICPPUnknownBinding unknown) {
|
static protected IBinding resolveUnknownName(IScope scope, ICPPUnknownBinding unknown) {
|
||||||
final IASTName unknownName = unknown.getUnknownName();
|
final IASTName unknownName = unknown.getUnknownName();
|
||||||
LookupData data = new LookupData(unknownName);
|
LookupData data = new LookupData(unknownName);
|
||||||
data.checkPointOfDecl= false;
|
data.checkPointOfDecl= false;
|
||||||
|
|
|
@ -872,8 +872,8 @@ public class CPPVisitor extends ASTQueries {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns enclosing function definition, or <code>null</code> if the given node
|
* Searches for an enclosing function definition or declaration, returns
|
||||||
* is not part of a function definition.
|
* the name of the function. If you pass the name of a function, it will be returned.
|
||||||
*/
|
*/
|
||||||
public static ICPPASTFunctionDefinition findEnclosingFunctionDefinition(IASTNode node) {
|
public static ICPPASTFunctionDefinition findEnclosingFunctionDefinition(IASTNode node) {
|
||||||
while (node != null) {
|
while (node != null) {
|
||||||
|
@ -1872,10 +1872,8 @@ public class CPPVisitor extends ASTQueries {
|
||||||
break;
|
break;
|
||||||
if (owner instanceof ICPPFunction)
|
if (owner instanceof ICPPFunction)
|
||||||
break;
|
break;
|
||||||
if (owner instanceof ICPPNamespace && n.length() == 0) {
|
if (owner instanceof ICPPNamespace && n.length() == 0)
|
||||||
// TODO(sprigogin): Do not ignore anonymous namespaces.
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
ns = (String[]) ArrayUtil.append(String.class, ns, n);
|
ns = (String[]) ArrayUtil.append(String.class, ns, n);
|
||||||
}
|
}
|
||||||
|
@ -1990,30 +1988,6 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches for the function or class enclosing the given node. May return <code>null</code>.
|
|
||||||
*/
|
|
||||||
public static IBinding findEnclosingFunctionOrClass(IASTNode node) {
|
|
||||||
IASTName name = null;
|
|
||||||
for (; node != null; node= node.getParent()) {
|
|
||||||
if (node instanceof IASTFunctionDefinition) {
|
|
||||||
IASTDeclarator dtor= findInnermostDeclarator(((IASTFunctionDefinition) node).getDeclarator());
|
|
||||||
if (dtor != null) {
|
|
||||||
name= dtor.getName();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (node instanceof IASTCompositeTypeSpecifier) {
|
|
||||||
name= ((IASTCompositeTypeSpecifier) node).getName();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return name.resolveBinding();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IBinding findNameOwner(IASTName name, boolean allowFunction) {
|
public static IBinding findNameOwner(IASTName name, boolean allowFunction) {
|
||||||
IASTNode node= name;
|
IASTNode node= name;
|
||||||
while (node instanceof IASTName) {
|
while (node instanceof IASTName) {
|
||||||
|
@ -2036,10 +2010,9 @@ public class CPPVisitor extends ASTQueries {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for the first class, namespace, or function, if <code>allowFunction</code>
|
* Searches for the first function, class or namespace enclosing the declaration the provided
|
||||||
* is <code>true</code>, enclosing the declaration the provided node belongs to and returns
|
* node belongs to and returns the binding for it. Returns <code>null</code>, if the declaration
|
||||||
* the binding for it. Returns <code>null</code>, if the declaration is not enclosed by any
|
* is not enclosed by any of the above constructs.
|
||||||
* of the above constructs.
|
|
||||||
*/
|
*/
|
||||||
public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) {
|
public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) {
|
||||||
// Search for declaration
|
// Search for declaration
|
||||||
|
|
|
@ -18,7 +18,6 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||||
|
@ -42,7 +41,6 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
||||||
|
@ -66,7 +64,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
|
@ -86,9 +83,12 @@ public class LookupData {
|
||||||
protected CPPASTTranslationUnit tu;
|
protected CPPASTTranslationUnit tu;
|
||||||
public Map<ICPPNamespaceScope, List<ICPPNamespaceScope>> usingDirectives= Collections.emptyMap();
|
public Map<ICPPNamespaceScope, List<ICPPNamespaceScope>> usingDirectives= Collections.emptyMap();
|
||||||
|
|
||||||
/** Used to ensure we don't visit things more than once. */
|
/*
|
||||||
|
* Used to ensure we don't visit things more than once
|
||||||
|
*/
|
||||||
public ObjectSet<IScope> visited= new ObjectSet<IScope>(1);
|
public ObjectSet<IScope> visited= new ObjectSet<IScope>(1);
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ObjectSet<IScope> associated = ObjectSet.EMPTY_SET;
|
public ObjectSet<IScope> associated = ObjectSet.EMPTY_SET;
|
||||||
|
|
||||||
|
@ -99,23 +99,17 @@ public class LookupData {
|
||||||
public boolean forAssociatedScopes = false;
|
public boolean forAssociatedScopes = false;
|
||||||
public boolean contentAssist = false;
|
public boolean contentAssist = false;
|
||||||
public boolean prefixLookup = false;
|
public boolean prefixLookup = false;
|
||||||
/** Don't return private/protected members that are not visible. */
|
|
||||||
public boolean filterByVisibility = false;
|
|
||||||
public boolean typesOnly = false;
|
public boolean typesOnly = false;
|
||||||
public boolean considerConstructors = false;
|
public boolean considerConstructors = false;
|
||||||
/** For lookup of unknown bindings the point of declaration can be reversed. */
|
public boolean checkPointOfDecl= true; // for lookup of unknown bindings the point of declaration can be reversed.
|
||||||
public boolean checkPointOfDecl= true;
|
public boolean usesEnclosingScope= true; // for field references or qualified names, enclosing template declarations are ignored.
|
||||||
/** For field references or qualified names, enclosing template declarations are ignored. */
|
public boolean firstArgIsImpliedMethodArg = false; // when computing the cost of a method call treat the first argument as the implied method argument
|
||||||
public boolean usesEnclosingScope= true;
|
|
||||||
/** When computing the cost of a method call, treat the first argument as the implied method argument. */
|
|
||||||
public boolean firstArgIsImpliedMethodArg = false;
|
|
||||||
public boolean ignoreMembers = false;
|
public boolean ignoreMembers = false;
|
||||||
|
|
||||||
public ICPPClassType skippedScope;
|
public ICPPClassType skippedScope;
|
||||||
public Object foundItems = null;
|
public Object foundItems = null;
|
||||||
private Object[] functionArgs;
|
private Object[] functionArgs;
|
||||||
private IType[] functionArgTypes;
|
private IType[] functionArgTypes;
|
||||||
private IBinding[] visibilityContext;
|
|
||||||
public ProblemBinding problem;
|
public ProblemBinding problem;
|
||||||
|
|
||||||
public LookupData(IASTName n) {
|
public LookupData(IASTName n) {
|
||||||
|
@ -664,39 +658,4 @@ public class LookupData {
|
||||||
}
|
}
|
||||||
return IBinding.EMPTY_BINDING_ARRAY;
|
return IBinding.EMPTY_BINDING_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Visibility context is a class or/and a function that determine visibility of private/protected
|
|
||||||
* members by participating in friendship or class inheritance relationships. If both, a class and
|
|
||||||
* a function are present in the context, the class has to be local to the function.
|
|
||||||
*/
|
|
||||||
public IBinding[] getVisibilityContext() {
|
|
||||||
if (visibilityContext == null) {
|
|
||||||
visibilityContext = IBinding.EMPTY_BINDING_ARRAY;
|
|
||||||
try {
|
|
||||||
IBinding previous = null;
|
|
||||||
for (IBinding binding = CPPVisitor.findEnclosingFunctionOrClass(astName);
|
|
||||||
binding != null; binding = binding.getOwner()) {
|
|
||||||
if (binding instanceof ICPPMethod ||
|
|
||||||
// Definition of an undeclared method.
|
|
||||||
binding instanceof IProblemBinding &&
|
|
||||||
((IProblemBinding) binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (binding instanceof ICPPClassType && previous instanceof ICPPClassType) {
|
|
||||||
// Only the innermost class participates in the visibility context.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (binding instanceof ICPPFunction || binding instanceof ICPPClassType) {
|
|
||||||
visibilityContext = ArrayUtil.append(visibilityContext, binding);
|
|
||||||
previous = binding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
|
||||||
CCorePlugin.log(e);
|
|
||||||
}
|
|
||||||
visibilityContext = ArrayUtil.trim(visibilityContext);
|
|
||||||
}
|
|
||||||
return visibilityContext;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
@ -27,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
|
@ -291,6 +289,7 @@ public class SemanticUtil {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static IType[] getSimplifiedTypes(IType[] types) {
|
public static IType[] getSimplifiedTypes(IType[] types) {
|
||||||
// Don't create a new array until it's really needed.
|
// Don't create a new array until it's really needed.
|
||||||
IType[] result = types;
|
IType[] result = types;
|
||||||
|
@ -393,38 +392,4 @@ public class SemanticUtil {
|
||||||
}
|
}
|
||||||
return baseType;
|
return baseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns <code>true</code> if two bindings have the same owner.
|
|
||||||
*/
|
|
||||||
public static boolean isSameOwner(IBinding owner1, IBinding owner2) {
|
|
||||||
try {
|
|
||||||
// Ignore anonymous namespaces
|
|
||||||
while (owner1 instanceof ICPPNamespace && owner1.getNameCharArray().length == 0)
|
|
||||||
owner1= owner1.getOwner();
|
|
||||||
// Ignore anonymous namespaces
|
|
||||||
while (owner2 instanceof ICPPNamespace && owner2.getNameCharArray().length == 0)
|
|
||||||
owner2= owner2.getOwner();
|
|
||||||
|
|
||||||
if (owner1 == null)
|
|
||||||
return owner2 == null;
|
|
||||||
if (owner2 == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (owner1 instanceof IType) {
|
|
||||||
if (owner2 instanceof IType) {
|
|
||||||
return ((IType) owner1).isSameType((IType) owner2);
|
|
||||||
}
|
|
||||||
} else if (owner1 instanceof ICPPNamespace) {
|
|
||||||
if (owner2 instanceof ICPPNamespace) {
|
|
||||||
if (!CharArrayUtils.equals(owner1.getNameCharArray(), owner2.getNameCharArray()))
|
|
||||||
return false;
|
|
||||||
return isSameOwner(owner1.getOwner(), owner2.getOwner());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
|
||||||
CCorePlugin.log(e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,12 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||||
|
@ -27,7 +31,7 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
/**
|
/**
|
||||||
* Mirrors type-hierarchy from DOM interfaces
|
* Mirrors type-hierarchy from DOM interfaces
|
||||||
*/
|
*/
|
||||||
public abstract class PDOMCPPBinding extends PDOMBinding implements ICPPBinding {
|
abstract class PDOMCPPBinding extends PDOMBinding implements ICPPBinding {
|
||||||
|
|
||||||
@SuppressWarnings("hiding")
|
@SuppressWarnings("hiding")
|
||||||
protected static final int RECORD_SIZE= PDOMBinding.RECORD_SIZE + 0;
|
protected static final int RECORD_SIZE= PDOMBinding.RECORD_SIZE + 0;
|
||||||
|
@ -35,11 +39,44 @@ public abstract class PDOMCPPBinding extends PDOMBinding implements ICPPBinding
|
||||||
public PDOMCPPBinding(PDOMLinkage linkage, long record) {
|
public PDOMCPPBinding(PDOMLinkage linkage, long record) {
|
||||||
super(linkage, record);
|
super(linkage, record);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PDOMCPPBinding(PDOMLinkage linkage, PDOMNode parent, char[] name) throws CoreException {
|
public PDOMCPPBinding(PDOMLinkage linkage, PDOMNode parent, char[] name) throws CoreException {
|
||||||
super(linkage, parent, name);
|
super(linkage, parent, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isSameOwner(IBinding owner1, IBinding owner2) {
|
||||||
|
try {
|
||||||
|
// ignore unnamed namespaces
|
||||||
|
while(owner1 instanceof ICPPNamespace && owner1.getNameCharArray().length == 0)
|
||||||
|
owner1= owner1.getOwner();
|
||||||
|
// ignore unnamed namespaces
|
||||||
|
while(owner2 instanceof ICPPNamespace && owner2.getNameCharArray().length == 0)
|
||||||
|
owner2= owner2.getOwner();
|
||||||
|
|
||||||
|
if (owner1 == null)
|
||||||
|
return owner2 == null;
|
||||||
|
if (owner2 == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (owner1 instanceof IType) {
|
||||||
|
if (owner2 instanceof IType) {
|
||||||
|
return ((IType) owner1).isSameType((IType) owner2);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (owner1 instanceof ICPPNamespace) {
|
||||||
|
if (owner2 instanceof ICPPNamespace) {
|
||||||
|
if (!CharArrayUtils.equals(owner1.getNameCharArray(), owner2.getNameCharArray()))
|
||||||
|
return false;
|
||||||
|
return isSameOwner(owner1.getOwner(), owner2.getOwner());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
CCorePlugin.log(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final public char[][] getQualifiedNameCharArray() throws DOMException {
|
final public char[][] getQualifiedNameCharArray() throws DOMException {
|
||||||
List<char[]> result = new ArrayList<char[]>();
|
List<char[]> result = new ArrayList<char[]>();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -37,7 +37,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredClassInstance;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
||||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
||||||
|
@ -261,7 +260,7 @@ public class PDOMCPPClassTemplate extends PDOMCPPClassType
|
||||||
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return SemanticUtil.isSameOwner(getOwner(), ctype.getOwner());
|
return isSameOwner(getOwner(), ctype.getOwner());
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.Util;
|
import org.eclipse.cdt.internal.core.Util;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
||||||
import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList;
|
import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
|
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
|
||||||
|
@ -269,7 +268,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
|
||||||
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return SemanticUtil.isSameOwner(getOwner(), ctype.getOwner());
|
return isSameOwner(getOwner(), ctype.getOwner());
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexType;
|
import org.eclipse.cdt.internal.core.index.IIndexType;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||||
|
@ -119,7 +118,7 @@ class PDOMCPPEnumeration extends PDOMCPPBinding implements IEnumeration, IIndexT
|
||||||
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
if (nchars == null || !CharArrayUtils.equals(nchars, getNameCharArray()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return SemanticUtil.isSameOwner(getOwner(), etype.getOwner());
|
return isSameOwner(getOwner(), etype.getOwner());
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that anonymous types are not returned as possibilities.
|
* Test that anonymous types are not returned as possibilites
|
||||||
*/
|
*/
|
||||||
public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{
|
public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{
|
||||||
private final String fileName = "CompletionTestStart40.cpp";
|
private final String fileName = "CompletionTestStart40.cpp";
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* IBM Corporation
|
* IBM Corporation
|
||||||
* Sergey Prigogin (Google)
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.ui.tests.text.contentassist2;
|
package org.eclipse.cdt.ui.tests.text.contentassist2;
|
||||||
|
|
||||||
|
@ -36,6 +35,7 @@ import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class CompletionTests extends AbstractContentAssistTest {
|
public class CompletionTests extends AbstractContentAssistTest {
|
||||||
|
|
||||||
private static final String HEADER_FILE_NAME = "CompletionTest.h";
|
private static final String HEADER_FILE_NAME = "CompletionTest.h";
|
||||||
private static final String SOURCE_FILE_NAME = "CompletionTest.cpp";
|
private static final String SOURCE_FILE_NAME = "CompletionTest.cpp";
|
||||||
private static final String CURSOR_LOCATION_TAG = "/*cursor*/";
|
private static final String CURSOR_LOCATION_TAG = "/*cursor*/";
|
||||||
|
@ -86,8 +86,6 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
// C1* m12();
|
// C1* m12();
|
||||||
// C1* m13();
|
// C1* m13();
|
||||||
//
|
//
|
||||||
//protected:
|
|
||||||
// void m1protected();
|
|
||||||
//private:
|
//private:
|
||||||
// void m1private();
|
// void m1private();
|
||||||
//};
|
//};
|
||||||
|
@ -104,12 +102,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
// C2* m23();
|
// C2* m23();
|
||||||
// C1* operator()(int x);
|
// C1* operator()(int x);
|
||||||
//
|
//
|
||||||
//protected:
|
|
||||||
// void m2protected();
|
|
||||||
//private:
|
//private:
|
||||||
// void m2private();
|
// void m2private();
|
||||||
// friend void _friend_function(C3* x);
|
|
||||||
// friend class _friend_class;
|
|
||||||
//};
|
//};
|
||||||
//typedef C2 T2;
|
//typedef C2 T2;
|
||||||
//
|
//
|
||||||
|
@ -123,8 +117,6 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
// C3* m13();
|
// C3* m13();
|
||||||
//
|
//
|
||||||
// template<typename T> T tConvert();
|
// template<typename T> T tConvert();
|
||||||
//protected:
|
|
||||||
// void m3protected();
|
|
||||||
//private:
|
//private:
|
||||||
// void m3private();
|
// void m3private();
|
||||||
//};
|
//};
|
||||||
|
@ -223,67 +215,87 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {C1 v; v.m/*cursor*/
|
//void gfunc() {C1 v; v.m/*cursor*/
|
||||||
public void testLocalVariable() throws Exception {
|
public void _testLocalVariable() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {C1 v; v.fMySelf->m/*cursor*/
|
//void gfunc() {C1 v; v.fMySelf.m/*cursor*/
|
||||||
public void testLocalVariable_MemberVariable() throws Exception {
|
public void _testLocalVariable_MemberVariable() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {C1 v; v.m12()->m/*cursor*/
|
//void gfunc() {C1 v; v.m12().m/*cursor*/
|
||||||
public void testLocalVariable_MemberFunction() throws Exception {
|
public void _testLocalVariable_MemberFunction() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {gfC1()->m/*cursor*/
|
//void gfunc() {gfC1().m/*cursor*/
|
||||||
public void testGlobalFunction() throws Exception {
|
public void _testGlobalFunction() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C1::self() {m/*cursor*/
|
//void C1::self() {m/*cursor*/
|
||||||
public void testOwnMember() throws Exception {
|
public void testOwnMember() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m1private(void)", "m1protected(void)"
|
"m123(void)", "m12(void)", "m13(void)", "m1private(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C1::self() {this->m/*cursor*/
|
//void C1::self() {this->m/*cursor*/
|
||||||
public void testOwnMemberViaThis() throws Exception {
|
public void testOwnMemberViaThis() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m1private(void)", "m1protected(void)"
|
"m123(void)", "m12(void)", "m13(void)", "m1private(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {try{int bla;}catch(C1 v) {v.fMySelf->m/*cursor*/
|
//void gfunc() {try{int bla;}catch(C1 v) {v.fMySelf.m/*cursor*/
|
||||||
public void testCatchBlock1() throws Exception {
|
public void _testCatchBlock1() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc() {try{int bla;}catch(C2 c){} catch(C1 v) {v.fMySelf->m/*cursor*/
|
//void gfunc() {try{int bla;}catch(C2 c){} catch(C1 v) {v.fMySelf.m/*cursor*/
|
||||||
public void testCatchBlock2() throws Exception {
|
public void _testCatchBlock2() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {gC/*cursor*/
|
//void f() {gC/*cursor*/
|
||||||
|
@ -291,7 +303,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"gC1", "gC2"
|
"gC1", "gC2"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C1::f() {gC/*cursor*/
|
//void C1::f() {gC/*cursor*/
|
||||||
|
@ -299,7 +312,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"gC1", "gC2"
|
"gC1", "gC2"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C2* cLocal1; while(true) {C1* cLocal2; cL/*cursor*/
|
//void f() {C2* cLocal1; while(true) {C1* cLocal2; cL/*cursor*/
|
||||||
|
@ -307,7 +321,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"cLocal1", "cLocal2"
|
"cLocal1", "cLocal2"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C2::f() {C2* cLocal1; while(true) {C1* cLocal2; cL/*cursor*/
|
//void C2::f() {C2* cLocal1; while(true) {C1* cLocal2; cL/*cursor*/
|
||||||
|
@ -315,7 +330,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"cLocal1", "cLocal2"
|
"cLocal1", "cLocal2"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C2* cLocal1; cLocal1->f/*cursor*/
|
//void f() {C2* cLocal1; cLocal1->f/*cursor*/
|
||||||
|
@ -323,7 +339,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"fMySelf"
|
"fMySelf"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C2::f() {while(true) {f/*cursor*/
|
//void C2::f() {while(true) {f/*cursor*/
|
||||||
|
@ -331,7 +348,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"fMySelf"
|
"fMySelf"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {gf/*cursor*/
|
//void f() {gf/*cursor*/
|
||||||
|
@ -339,7 +357,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"gfC1(void)", "gfC2(void)"
|
"gfC1(void)", "gfC2(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C3::f() {gf/*cursor*/
|
//void C3::f() {gf/*cursor*/
|
||||||
|
@ -347,24 +366,30 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"gfC1(void)", "gfC2(void)"
|
"gfC1(void)", "gfC2(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1* l1; l1->m/*cursor*/
|
//void f() {C1* l1; l1.m/*cursor*/
|
||||||
public void testMethods_GlobalScope() throws Exception {
|
public void _testMethods_GlobalScope() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)"
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C3::f() {m/*cursor*/
|
//void C3::f() {m/*cursor*/
|
||||||
public void testMethods_MethodScope() throws Exception {
|
public void _testMethods_MethodScope() throws Exception {
|
||||||
|
// fails because of additional m1private(void)
|
||||||
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172305
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m23(void)", "m1protected(void)",
|
"m123(void)", "m12(void)", "m13(void)"
|
||||||
"m2protected(void)", "m3private(void)", "m3protected(void)"
|
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C/*cursor*/
|
//void f() {C/*cursor*/
|
||||||
|
@ -372,41 +397,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"C1", "C2", "C3"
|
"C1", "C2", "C3"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
}
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
|
|
||||||
//class _friend_class { C3* x; void m() {x->m/*cursor*/
|
|
||||||
public void testTypes_FriendClass() throws Exception {
|
|
||||||
final String[] expected= {
|
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m23(void)", "m1protected(void)",
|
|
||||||
"m2protected(void)", "m2private(void)"
|
|
||||||
};
|
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//namespace ns { class _friend_class { C3* x; void m() {x->m/*cursor*/ // Not a friend due to namespace
|
|
||||||
public void testTypes_FakeFriendClass() throws Exception {
|
|
||||||
final String[] expected= {
|
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m23(void)"
|
|
||||||
};
|
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//void _friend_function(C3* x) { x->m/*cursor*/
|
|
||||||
public void testTypes_FriendFunction() throws Exception {
|
|
||||||
final String[] expected= {
|
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m23(void)", "m1protected(void)",
|
|
||||||
"m2protected(void)", "m2private(void)"
|
|
||||||
};
|
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//void _friend_function(C2* x) { x->m/*cursor*/ // Not a friend due to parameter type mismatch
|
|
||||||
public void testTypes_FakeFriendFunction() throws Exception {
|
|
||||||
final String[] expected= {
|
|
||||||
"m123(void)", "m12(void)", "m13(void)", "m23(void)"
|
|
||||||
};
|
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C2::f() {T/*cursor*/
|
//void C2::f() {T/*cursor*/
|
||||||
|
@ -414,7 +406,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"T1", "T2", "T3", "TClass"
|
"T1", "T2", "T3", "TClass"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//namespace ns {void nsfunc(){C/*cursor*/
|
//namespace ns {void nsfunc(){C/*cursor*/
|
||||||
|
@ -422,7 +415,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"C1", "C2", "C3", "CNS"
|
"C1", "C2", "C3", "CNS"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//namespace ns {void gfunc(){::C/*cursor*/
|
//namespace ns {void gfunc(){::C/*cursor*/
|
||||||
|
@ -430,7 +424,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"C1", "C2", "C3"
|
"C1", "C2", "C3"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {e/*cursor*/
|
//void f() {e/*cursor*/
|
||||||
|
@ -438,7 +433,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"e11", "e12", "E1"
|
"e11", "e12", "E1"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void C3::f() {e/*cursor*/
|
//void C3::f() {e/*cursor*/
|
||||||
|
@ -446,7 +442,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"e11", "e12", "e21", "e22", "E1", "E2"
|
"e11", "e12", "e21", "e22", "E1", "E2"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->C/*cursor*/
|
//void f() {C3* l1; l1->C/*cursor*/
|
||||||
|
@ -455,7 +452,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"C3", "C2", "C1"
|
"C3", "C2", "C1"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C2* l1; l1->C/*cursor*/
|
//void f() {C2* l1; l1->C/*cursor*/
|
||||||
|
@ -464,7 +462,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"C2", "C1"
|
"C2", "C1"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->C3::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->C3::fMySelf->iam/*cursor*/
|
||||||
|
@ -473,7 +472,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam3(void)", "iam2(void)", "iam1(void)"
|
"iam3(void)", "iam2(void)", "iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->C2::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->C2::fMySelf->iam/*cursor*/
|
||||||
|
@ -482,7 +482,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam2(void)", "iam1(void)"
|
"iam2(void)", "iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->C1::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->C1::fMySelf->iam/*cursor*/
|
||||||
|
@ -490,7 +491,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->T3::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->T3::fMySelf->iam/*cursor*/
|
||||||
|
@ -499,7 +501,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam3(void)", "iam2(void)", "iam1(void)"
|
"iam3(void)", "iam2(void)", "iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->T2::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->T2::fMySelf->iam/*cursor*/
|
||||||
|
@ -508,7 +511,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam2(void)", "iam1(void)"
|
"iam2(void)", "iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C3* l1; l1->T1::fMySelf->iam/*cursor*/
|
//void f() {C3* l1; l1->T1::fMySelf->iam/*cursor*/
|
||||||
|
@ -516,7 +520,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1().iam/*cursor*/
|
//void f() {C1().iam/*cursor*/
|
||||||
|
@ -524,7 +529,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1 c; (&c)->iam/*cursor*/
|
//void f() {C1 c; (&c)->iam/*cursor*/
|
||||||
|
@ -532,7 +538,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1* c; (*c).iam/*cursor*/
|
//void f() {C1* c; (*c).iam/*cursor*/
|
||||||
|
@ -540,7 +547,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1** c; (**c).iam/*cursor*/
|
//void f() {C1** c; (**c).iam/*cursor*/
|
||||||
|
@ -548,14 +556,16 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1** c; (*c)->iam/*cursor*/
|
//void f() {C1** c; (*c)->iam/*cursor*/
|
||||||
public void testDereferencingOperator3() throws Exception {
|
public void testDereferencingOperator3() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1* c; c[0].iam/*cursor*/
|
//void f() {C1* c; c[0].iam/*cursor*/
|
||||||
|
@ -563,28 +573,32 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1** c; c[0][1].iam/*cursor*/
|
//void f() {C1** c; c[0][1].iam/*cursor*/
|
||||||
public void testArrayAccessOperator2() throws Exception {
|
public void testArrayAccessOperator2() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1** c; c[0]->iam/*cursor*/
|
//void f() {C1** c; c[0]->iam/*cursor*/
|
||||||
public void testArrayAccessOperator3() throws Exception {
|
public void testArrayAccessOperator3() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1* c; (&c[0])->iam/*cursor*/
|
//void f() {C1* c; (&c[0])->iam/*cursor*/
|
||||||
public void testArrayAccessOperator4() throws Exception {
|
public void testArrayAccessOperator4() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {void* c; ((C1*)c)->iam/*cursor*/
|
//void f() {void* c; ((C1*)c)->iam/*cursor*/
|
||||||
|
@ -592,14 +606,16 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void g(int a) {}; void f() {void* c; g(((C1*)c)->iam/*cursor*/
|
//void g(int a) {}; void f() {void* c; g(((C1*)c)->iam/*cursor*/
|
||||||
public void testCasts2() throws Exception {
|
public void testCasts2() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {C1* c; c++->iam/*cursor*/
|
//void f() {C1* c; c++->iam/*cursor*/
|
||||||
|
@ -607,35 +623,40 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1* c; (*++c).iam/*cursor*/
|
//void f() {C1* c; (*++c).iam/*cursor*/
|
||||||
public void testPointerArithmetic2() throws Exception {
|
public void testPointerArithmetic2() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1* c; c--->iam/*cursor*/
|
//void f() {C1* c; c--->iam/*cursor*/
|
||||||
public void testPointerArithmetic3() throws Exception {
|
public void testPointerArithmetic3() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1 c; (&c+1)->iam/*cursor*/
|
//void f() {C1 c; (&c+1)->iam/*cursor*/
|
||||||
public void testPointerArithmetic4() throws Exception {
|
public void testPointerArithmetic4() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void f() {C1 c; (&c-1)->iam/*cursor*/
|
//void f() {C1 c; (&c-1)->iam/*cursor*/
|
||||||
public void testPointerArithmetic5() throws Exception {
|
public void testPointerArithmetic5() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"iam1(void)"
|
"iam1(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void f() {int localVar=0; if (*cond && somefunc(&local/*cursor*/
|
//void f() {int localVar=0; if (*cond && somefunc(&local/*cursor*/
|
||||||
|
@ -643,7 +664,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"localVar"
|
"localVar"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//int a[] = {1,2}; void f(int _0306_b) {_0306_b/*cursor*/
|
//int a[] = {1,2}; void f(int _0306_b) {_0306_b/*cursor*/
|
||||||
|
@ -651,14 +673,16 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"_0306_b"
|
"_0306_b"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//int a[] = {1,2}; void f(int b) {int _0306_b[] = {2,3}; _0306_b/*cursor*/
|
//int a[] = {1,2}; void f(int b) {int _0306_b[] = {2,3}; _0306_b/*cursor*/
|
||||||
public void testCuttingInput2() throws Exception {
|
public void testCuttingInput2() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"_0306_b"
|
"_0306_b"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//enum EnumType function() {int _031209_v; _031209/*cursor*/
|
//enum EnumType function() {int _031209_v; _031209/*cursor*/
|
||||||
|
@ -666,7 +690,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"_031209_v"
|
"_031209_v"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//namespace ns {void x() {NSCO/*cursor*/
|
//namespace ns {void x() {NSCO/*cursor*/
|
||||||
|
@ -674,14 +699,16 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"NSCONST"
|
"NSCONST"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
//void ns::CNS::mcns(){NSCO/*cursor*/
|
//void ns::CNS::mcns(){NSCO/*cursor*/
|
||||||
public void testAccessToNamespaceFromClassMember2() throws Exception {
|
public void testAccessToNamespaceFromClassMember2() throws Exception {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"NSCONST"
|
"NSCONST"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#i/*cursor*/
|
//#i/*cursor*/
|
||||||
|
@ -689,7 +716,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"#if", "#ifdef", "#ifndef", "#include"
|
"#if", "#ifdef", "#ifndef", "#include"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//# d/*cursor*/
|
//# d/*cursor*/
|
||||||
|
@ -706,7 +734,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"defined"
|
"defined"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc(){TClass<int> t(0); t.a/*cursor*/
|
//void gfunc(){TClass<int> t(0); t.a/*cursor*/
|
||||||
|
@ -715,7 +744,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"add(int)"
|
"add(int)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc(){C3 c3; c3.t/*cursor*/
|
//void gfunc(){C3 c3; c3.t/*cursor*/
|
||||||
|
@ -724,7 +754,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"tConvert(void)"
|
"tConvert(void)"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//using namespace ns;void gfunc(){NSC/*cursor*/
|
//using namespace ns;void gfunc(){NSC/*cursor*/
|
||||||
|
@ -732,7 +763,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"NSCONST"
|
"NSCONST"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void gfunc(){n/*cursor*/
|
//void gfunc(){n/*cursor*/
|
||||||
|
@ -740,7 +772,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"ns::"
|
"ns::"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_REP_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_REP_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//using namespace /*cursor*/
|
//using namespace /*cursor*/
|
||||||
|
@ -748,7 +781,8 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected= {
|
final String[] expected= {
|
||||||
"ns"
|
"ns"
|
||||||
};
|
};
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_REP_STRINGS);
|
assertCompletionResults(fCursorOffset, expected,
|
||||||
|
AbstractContentAssistTest.COMPARE_REP_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//// to_be_replaced_
|
//// to_be_replaced_
|
||||||
|
|
Loading…
Add table
Reference in a new issue