diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java index 290ad32497a..2152096b560 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java @@ -12,9 +12,15 @@ package org.eclipse.cdt.core.parser.util; import java.lang.reflect.Array; +import java.util.AbstractCollection; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.function.Consumer; /** * @author Doug Schaefer @@ -166,6 +172,32 @@ public class CharArrayObjectMap extends CharTable { return values; } + /** + * Returns a {@link Collection} view of the values contained in this map. + * The collection is backed by the map, so changes to the map are reflected + * in the collection, and vice-versa. + * + * @since 6.0 + */ + public Collection values() { + return new Values(); + } + + /** + * Checks if the map values contain the given object. + * + * @since 6.0 + */ + public boolean containsValue(Object v) { + int n = size(); + for (int i = 0; i < n; i++) { + if (Objects.equals(valueTable[i], v)) { + return true; + } + } + return false; + } + @Override public String toString() { StringBuilder buf = new StringBuilder(); @@ -183,4 +215,51 @@ public class CharArrayObjectMap extends CharTable { buf.append('}'); return buf.toString(); } + + private class Values extends AbstractCollection { + @Override + public final int size() { + return CharArrayObjectMap.this.size(); + } + + @Override + public final void clear() { + CharArrayObjectMap.this.clear(); + } + + @Override + public final boolean contains(Object v) { + return containsValue(v); + } + + @Override + public final Iterator iterator() { + return new ValueIterator(); + } + + @Override + @SuppressWarnings("unchecked") + public final void forEach(Consumer action) { + for (int i = 0; i < size(); i++) { + action.accept((T) valueTable[i]); + } + } + } + + private final class ValueIterator implements Iterator { + int index; + + @Override + public boolean hasNext() { + return index < size(); + } + + @Override + @SuppressWarnings("unchecked") + public T next() { + if (!hasNext()) + throw new NoSuchElementException(); + return (T) valueTable[index++]; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java index c7d758fc2b9..d6315cffc5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java @@ -40,7 +40,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.parser.Keywords; -import org.eclipse.cdt.core.parser.util.CharArrayMap; +import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; @@ -60,9 +60,9 @@ import org.eclipse.core.runtime.CoreException; */ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { private static final class PopulateMap implements IPDOMVisitor { - private final CharArrayMap> fResult; + private final CharArrayObjectMap> fResult; - private PopulateMap(CharArrayMap> result) { + private PopulateMap(CharArrayObjectMap> result) { fResult = result; } @@ -88,7 +88,8 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { public void leave(IPDOMNode node){} } - private static final IndexFilter CONVERSION_FILTER = new DeclaredBindingsFilter(ILinkage.CPP_LINKAGE_ID, true, false) { + private static final IndexFilter CONVERSION_FILTER = + new DeclaredBindingsFilter(ILinkage.CPP_LINKAGE_ID, true, false) { @Override public boolean acceptBinding(IBinding binding) throws CoreException { return binding instanceof ICPPMethod && @@ -189,7 +190,7 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { } public static IBinding[] getBindingsViaCache(IPDOMCPPClassType ct, final char[] name, IndexFilter filter) throws CoreException { - CharArrayMap> map = getBindingMap(ct); + CharArrayObjectMap> map = getBindingMap(ct); List cached= map.get(name); if (cached == null) return IBinding.EMPTY_BINDING_ARRAY; @@ -212,9 +213,10 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { /** * Visit bindings via the cache. */ - public static void acceptViaCache(IPDOMCPPClassType ct, IPDOMVisitor visitor, boolean includeNestedInAnonymous) throws CoreException { + public static void acceptViaCache(IPDOMCPPClassType ct, IPDOMVisitor visitor, + boolean includeNestedInAnonymous) throws CoreException { final long record= ct.getRecord(); - CharArrayMap> map= getBindingMap(ct); + CharArrayObjectMap> map= getBindingMap(ct); for (List list : map.values()) { for (PDOMBinding node : list) { if (includeNestedInAnonymous || node.getParentNodeRec() == record) { @@ -232,28 +234,30 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { final Long key= ct.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; final PDOM pdom = ct.getPDOM(); @SuppressWarnings("unchecked") - Reference>> cached= (Reference>>) pdom.getCachedResult(key); - CharArrayMap> map= cached == null ? null : cached.get(); + Reference>> cached= + (Reference>>) pdom.getCachedResult(key); + CharArrayObjectMap> map= cached == null ? null : cached.get(); if (map != null) { new PopulateMap(map).visit(member); } } } - public static CharArrayMap> getBindingMap(IPDOMCPPClassType ct) throws CoreException { + public static CharArrayObjectMap> getBindingMap(IPDOMCPPClassType ct) throws CoreException { final Long key= ct.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; final PDOM pdom = ct.getPDOM(); @SuppressWarnings("unchecked") - Reference>> cached= (Reference>>) pdom.getCachedResult(key); - CharArrayMap> map= cached == null ? null : cached.get(); + Reference>> cached= + (Reference>>) pdom.getCachedResult(key); + CharArrayObjectMap> map= cached == null ? null : cached.get(); if (map == null) { // There is no cache, build it: - map= new CharArrayMap<>(); + map= new CharArrayObjectMap<>(8); IPDOMVisitor visitor= new PopulateMap(map); visitor.visit(ct); ct.acceptUncached(visitor); - pdom.putCachedResult(key, new SoftReference>(map)); + pdom.putCachedResult(key, new SoftReference>(map)); } return map; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java index 6b2ca6497aa..ddce4e788e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java @@ -29,7 +29,7 @@ import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; -import org.eclipse.cdt.core.parser.util.CharArrayMap; +import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.IContentAssistMatcher; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.index.IIndexScope; @@ -66,7 +66,7 @@ class PDOMCPPEnumScope implements ICPPEnumScope, IIndexScope { @Override public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) { try { - CharArrayMap map= getBindingMap(fBinding); + CharArrayObjectMap map= getBindingMap(fBinding); return map.get(name.toCharArray()); } catch (CoreException e) { CCorePlugin.log(e); @@ -82,7 +82,7 @@ class PDOMCPPEnumScope implements ICPPEnumScope, IIndexScope { @Override public IBinding[] getBindings(ScopeLookupData lookup) { try { - CharArrayMap map= getBindingMap(fBinding); + CharArrayObjectMap map= getBindingMap(fBinding); if (lookup.isPrefixLookup()) { final List result= new ArrayList(); final char[] nc= lookup.getLookupKey(); @@ -141,22 +141,23 @@ class PDOMCPPEnumScope implements ICPPEnumScope, IIndexScope { return fBinding.hashCode(); } - private static CharArrayMap getBindingMap(IPDOMCPPEnumType enumeration) throws CoreException { + private static CharArrayObjectMap getBindingMap(IPDOMCPPEnumType enumeration) throws CoreException { final Long key= enumeration.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; final PDOM pdom = enumeration.getPDOM(); @SuppressWarnings("unchecked") - Reference> cached= (Reference>) pdom.getCachedResult(key); - CharArrayMap map= cached == null ? null : cached.get(); + Reference> cached= + (Reference>) pdom.getCachedResult(key); + CharArrayObjectMap map= cached == null ? null : cached.get(); if (map == null) { // there is no cache, build it: List enumerators = new ArrayList<>(); enumeration.loadEnumerators(enumerators); - map = new CharArrayMap(); + map = new CharArrayObjectMap(enumerators.size()); for (IPDOMCPPEnumerator enumerator : enumerators) { map.put(enumerator.getNameCharArray(), enumerator); } - pdom.putCachedResult(key, new SoftReference>(map)); + pdom.putCachedResult(key, new SoftReference>(map)); } return map; } @@ -165,8 +166,9 @@ class PDOMCPPEnumScope implements ICPPEnumScope, IIndexScope { final Long key= enumType.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; final PDOM pdom = enumType.getPDOM(); @SuppressWarnings("unchecked") - Reference> cached= (Reference>) pdom.getCachedResult(key); - CharArrayMap map= cached == null ? null : cached.get(); + Reference> cached= + (Reference>) pdom.getCachedResult(key); + CharArrayObjectMap map= cached == null ? null : cached.get(); if (map != null) { map.put(enumItem.getNameCharArray(), enumItem); } @@ -194,7 +196,7 @@ class PDOMCPPEnumScope implements ICPPEnumScope, IIndexScope { public static void acceptViaCache(IPDOMCPPEnumType enumType, IPDOMVisitor visitor) { try { - CharArrayMap map = getBindingMap(enumType); + CharArrayObjectMap map = getBindingMap(enumType); for (IPDOMCPPEnumerator enumItem : map.values()) { visitor.visit(enumItem); visitor.leave(enumItem);