ConcurrentCollectionDetector.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.jdt.internal.corext.fix.helper;
import java.util.Set;
import org.eclipse.jdt.core.dom.ITypeBinding;
/** Detects concurrent collection iteration semantics relevant to loop conversion. */
public final class ConcurrentCollectionDetector {
private static final Set<String> SNAPSHOT_COLLECTION_TYPES= Set.of(
"java.util.concurrent.CopyOnWriteArrayList", //$NON-NLS-1$
"java.util.concurrent.CopyOnWriteArraySet"); //$NON-NLS-1$
private static final Set<String> CONCURRENT_COLLECTION_TYPES= Set.of(
"java.util.concurrent.CopyOnWriteArrayList", //$NON-NLS-1$
"java.util.concurrent.CopyOnWriteArraySet", //$NON-NLS-1$
"java.util.concurrent.ConcurrentHashMap", //$NON-NLS-1$
"java.util.concurrent.ConcurrentSkipListMap", //$NON-NLS-1$
"java.util.concurrent.ConcurrentSkipListSet", //$NON-NLS-1$
"java.util.concurrent.ConcurrentLinkedQueue", //$NON-NLS-1$
"java.util.concurrent.ConcurrentLinkedDeque", //$NON-NLS-1$
"java.util.concurrent.LinkedBlockingQueue", //$NON-NLS-1$
"java.util.concurrent.LinkedBlockingDeque", //$NON-NLS-1$
"java.util.concurrent.ArrayBlockingQueue", //$NON-NLS-1$
"java.util.concurrent.PriorityBlockingQueue", //$NON-NLS-1$
"java.util.concurrent.DelayQueue", //$NON-NLS-1$
"java.util.concurrent.SynchronousQueue"); //$NON-NLS-1$
private ConcurrentCollectionDetector() {
// utility class
}
public static boolean isConcurrentCollection(ITypeBinding typeBinding) {
return typeBinding != null && isConcurrentCollection(typeBinding.getErasure().getQualifiedName());
}
public static boolean isConcurrentCollection(String qualifiedTypeName) {
return qualifiedTypeName != null && CONCURRENT_COLLECTION_TYPES.contains(qualifiedTypeName);
}
/**
* Copy-on-write iterators and spliterators traverse a stable array snapshot.
* Read-only sequential enhanced-for conversion can therefore retain their
* iteration semantics. Other concurrent collections remain conservatively
* blocked because their iterators are weakly consistent.
*/
public static boolean hasSnapshotIteration(ITypeBinding typeBinding) {
return typeBinding != null && hasSnapshotIteration(typeBinding.getErasure().getQualifiedName());
}
public static boolean hasSnapshotIteration(String qualifiedTypeName) {
return qualifiedTypeName != null && SNAPSHOT_COLLECTION_TYPES.contains(qualifiedTypeName);
}
}