cleanup: notnull, add mutation annotations, optimize list copying, deduplicate

GitOrigin-RevId: 16dc54f0e3b3b666caad8377f0769a22b1e1623b
This commit is contained in:
Alexey Kudravtsev
2025-10-30 22:23:10 +00:00
committed by intellij-monorepo-bot
parent c8e750adf1
commit ffa0186613
5 changed files with 56 additions and 100 deletions
@@ -22,8 +22,8 @@ import java.util.*;
final class CachingConstructorInjectionComponentAdapter implements ComponentAdapter {
private static final ThreadLocal<Set<Class<?>>> ourGuard = new ThreadLocal<>();
private final PicoContainer container;
private final Object key;
private final Class<?> componentImplementation;
private final @NotNull Object key;
private final @NotNull Class<?> componentImplementation;
private Object myInstance;
CachingConstructorInjectionComponentAdapter(@NotNull PicoContainer container,
@@ -35,12 +35,12 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
}
@Override
public Object getComponentKey() {
public @NotNull Object getComponentKey() {
return key;
}
@Override
public Class<?> getComponentImplementation() {
public @NotNull Class<?> getComponentImplementation() {
return componentImplementation;
}
@@ -50,7 +50,7 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
}
@Override
public Object getComponentInstance() {
public @NotNull Object getComponentInstance() {
Object instance = myInstance;
if (instance == null) {
instance = instantiateGuarded(this, container, getComponentImplementation());
@@ -59,9 +59,9 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
return instance;
}
public static @NotNull Object instantiateGuarded(@Nullable CachingConstructorInjectionComponentAdapter adapter,
@NotNull PicoContainer container,
@NotNull Class<?> componentImplementation) {
private static @NotNull Object instantiateGuarded(@Nullable CachingConstructorInjectionComponentAdapter adapter,
@NotNull PicoContainer container,
@NotNull Class<?> componentImplementation) {
Set<Class<?>> currentStack = ourGuard.get();
if (currentStack == null) {
currentStack = Collections.newSetFromMap(new IdentityHashMap<>(1));
@@ -91,7 +91,7 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
return container.getComponentAdapter(expectedType);
}
ComponentAdapter result = getTargetAdapter(container, expectedType, excludeAdapter.getComponentKey());
ComponentAdapter result = container.getComponentAdapterOfType(expectedType, excludeAdapter.getComponentKey());
return result == null ? null : expectedType.isAssignableFrom(result.getComponentImplementation()) ? result : null;
}
@@ -142,8 +142,7 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
private static @NotNull Constructor<?> getGreediestSatisfiableConstructor(@Nullable ComponentAdapter adapter,
@NotNull DefaultPicoContainer container,
@NotNull Class<?> componentImplementation) throws
PicoIntrospectionException {
@NotNull Class<?> componentImplementation) throws PicoIntrospectionException {
Set<Constructor<?>> conflicts = new HashSet<>();
Set<Class<?>[]> unsatisfiableDependencyTypes = new HashSet<>();
// filter out all constructors that will definitely not match
@@ -221,35 +220,4 @@ final class CachingConstructorInjectionComponentAdapter implements ComponentAdap
}
return false;
}
private static ComponentAdapter getTargetAdapter(@NotNull DefaultPicoContainer container,
Class<?> expectedType,
@NotNull Object excludeKey) {
ComponentAdapter byKey = container.getComponentAdapter(expectedType);
if (byKey != null && !excludeKey.equals(byKey.getComponentKey())) {
return byKey;
}
List<ComponentAdapter> found = container.getComponentAdaptersOfType(expectedType);
ComponentAdapter exclude = null;
for (ComponentAdapter work : found) {
if (work.getComponentKey().equals(excludeKey)) {
exclude = work;
}
}
found.remove(exclude);
if (found.isEmpty()) {
return container.getParent() == null ? null : container.getParent().getComponentAdapterOfType(expectedType);
}
else if (found.size() == 1) {
return found.get(0);
}
else {
Class<?>[] foundClasses = new Class[found.size()];
for (int i = 0; i < foundClasses.length; i++) {
foundClasses[i] = found.get(i).getComponentImplementation();
}
throw new AmbiguousComponentResolutionException(expectedType, foundClasses);
}
}
}
@@ -1,9 +1,7 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.pico;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.*;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
@@ -25,7 +23,7 @@ public class DefaultPicoContainer implements MutablePicoContainer {
this(null);
}
public final @NotNull Collection<ComponentAdapter> getComponentAdapters() {
public final @NotNull @Unmodifiable Collection<ComponentAdapter> getComponentAdapters() {
return componentAdapters.getImmutableSet();
}
@@ -38,11 +36,6 @@ public class DefaultPicoContainer implements MutablePicoContainer {
return adapter;
}
public final void release() {
componentKeyToAdapter.clear();
componentAdapters.clear();
}
private @Nullable ComponentAdapter getFromCache(@NotNull Object componentKey) {
ComponentAdapter adapter = componentKeyToAdapter.get(componentKey);
if (adapter != null) {
@@ -51,20 +44,20 @@ public class DefaultPicoContainer implements MutablePicoContainer {
return componentKey instanceof Class ? componentKeyToAdapter.get(((Class<?>)componentKey).getName()) : null;
}
public final @Nullable ComponentAdapter getComponentAdapterOfType(@NotNull Class<?> componentType) {
final @Nullable ComponentAdapter getComponentAdapterOfType(@NotNull Class<?> componentType, @Nullable Object excludeKey) {
// See http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-115
ComponentAdapter adapterByKey = getComponentAdapter(componentType);
if (adapterByKey != null) {
if (adapterByKey != null && (excludeKey == null || !excludeKey.equals(adapterByKey.getComponentKey()))) {
return adapterByKey;
}
List<ComponentAdapter> found = getComponentAdaptersOfType(componentType);
List<ComponentAdapter> found = getComponentAdaptersOfType(componentType, excludeKey);
if (found.isEmpty()) {
return parent == null ? null : parent.getComponentAdapterOfType(componentType, excludeKey);
}
if (found.size() == 1) {
return found.get(0);
}
if (found.isEmpty()) {
return parent == null ? null : parent.getComponentAdapterOfType(componentType);
}
Class<?>[] foundClasses = new Class[found.size()];
for (int i = 0; i < foundClasses.length; i++) {
@@ -73,7 +66,8 @@ public class DefaultPicoContainer implements MutablePicoContainer {
throw new AmbiguousComponentResolutionException(componentType, foundClasses);
}
public final @NotNull List<ComponentAdapter> getComponentAdaptersOfType(@NotNull Class<?> componentType) {
private @NotNull @Unmodifiable List<ComponentAdapter> getComponentAdaptersOfType(@NotNull Class<?> componentType,
@Nullable Object excludeKey) {
if (componentType == String.class) {
return Collections.emptyList();
}
@@ -87,7 +81,8 @@ public class DefaultPicoContainer implements MutablePicoContainer {
for (ComponentAdapter adapter : componentKeyToAdapter.values()) {
// exclude services
if (adapter.getComponentKey() instanceof String) {
Object componentKey = adapter.getComponentKey();
if (componentKey instanceof String || excludeKey != null && excludeKey.equals(componentKey)) {
continue;
}
@@ -99,7 +94,7 @@ public class DefaultPicoContainer implements MutablePicoContainer {
return result;
}
public final ComponentAdapter registerComponent(@NotNull ComponentAdapter componentAdapter) {
private @NotNull ComponentAdapter registerComponent(@NotNull ComponentAdapter componentAdapter) {
if (componentKeyToAdapter.putIfAbsent(componentAdapter.getComponentKey(), componentAdapter) != null) {
@NotNull String message = "Key " + componentAdapter.getComponentKey() + " duplicated";
throw new PicoException(message);
@@ -140,7 +135,7 @@ public class DefaultPicoContainer implements MutablePicoContainer {
@Override
public final @Nullable Object getComponentInstanceOfType(@NotNull Class<?> componentType) {
ComponentAdapter componentAdapter = getComponentAdapterOfType(componentType);
ComponentAdapter componentAdapter = getComponentAdapterOfType(componentType, null);
return componentAdapter == null ? null : getInstance(componentAdapter);
}
@@ -165,19 +160,15 @@ public class DefaultPicoContainer implements MutablePicoContainer {
return registerComponent(new CachingConstructorInjectionComponentAdapter(this, componentKey, componentImplementation));
}
public final DefaultPicoContainer getParent() {
return parent;
}
/**
* A linked hash set that's copied on write operations.
*/
private static final class LinkedHashSetWrapper<T> {
private final Object lock = new Object();
private volatile Set<T> immutableSet;
private LinkedHashSet<T> synchronizedSet = new LinkedHashSet<>();
private volatile @Unmodifiable Set<T> immutableSet;
private Set<T> synchronizedSet = new LinkedHashSet<>();
public void add(@NotNull T element) {
void add(@NotNull T element) {
synchronized (lock) {
if (!synchronizedSet.contains(element)) {
copySyncSetIfExposedAsImmutable().add(element);
@@ -185,7 +176,7 @@ public class DefaultPicoContainer implements MutablePicoContainer {
}
}
private LinkedHashSet<T> copySyncSetIfExposedAsImmutable() {
private Set<T> copySyncSetIfExposedAsImmutable() {
if (immutableSet != null) {
immutableSet = null;
synchronizedSet = new LinkedHashSet<>(synchronizedSet);
@@ -193,22 +184,13 @@ public class DefaultPicoContainer implements MutablePicoContainer {
return synchronizedSet;
}
public void remove(@Nullable T element) {
void remove(@Nullable T element) {
synchronized (lock) {
copySyncSetIfExposedAsImmutable().remove(element);
}
}
public void clear() {
synchronized (lock) {
if (immutableSet != null) {
immutableSet = null;
}
synchronizedSet = new LinkedHashSet<>();
}
}
public @NotNull Set<T> getImmutableSet() {
@NotNull @Unmodifiable Set<T> getImmutableSet() {
Set<T> result = immutableSet;
if (result == null) {
synchronized (lock) {
@@ -232,8 +214,8 @@ public class DefaultPicoContainer implements MutablePicoContainer {
}
static final class InstanceComponentAdapter implements ComponentAdapter {
private final Object componentKey;
private final Object componentInstance;
private final @NotNull Object componentKey;
private final @NotNull Object componentInstance;
InstanceComponentAdapter(@NotNull Object componentKey, @NotNull Object componentInstance) {
this.componentKey = componentKey;
@@ -241,17 +223,17 @@ public class DefaultPicoContainer implements MutablePicoContainer {
}
@Override
public Object getComponentInstance() {
public @NotNull Object getComponentInstance() {
return componentInstance;
}
@Override
public Object getComponentKey() {
public @NotNull Object getComponentKey() {
return componentKey;
}
@Override
public Class<?> getComponentImplementation() {
public @NotNull Class<?> getComponentImplementation() {
return componentInstance.getClass();
}
@@ -7,6 +7,8 @@
*/
package org.picocontainer;
import org.jetbrains.annotations.NotNull;
/**
* A component adapter is responsible for providing a specific component instance. An instance of an implementation of
* this interface is used inside a {@link PicoContainer} for every registered component or instance. Each
@@ -24,6 +26,7 @@ public interface ComponentAdapter {
* @return the component's key. Should either be a class type (normally an interface) or an identifier that is
* unique (within the scope of the current PicoContainer).
*/
@NotNull
Object getComponentKey();
/**
@@ -32,7 +35,9 @@ public interface ComponentAdapter {
* @return the component's implementation class. Should normally be a concrete class (ie, a class that can be
* instantiated).
*/
@NotNull
Class<?> getComponentImplementation();
@NotNull
Object getComponentInstance();
}
@@ -24,7 +24,7 @@ internal class ComponentManagerResolver(
return !constructor.isAnnotationPresent(NonInjectable::class.java) && !constructor.isAnnotationPresent(Deprecated::class.java)
}
override fun isInjectable(parameterType: Class<*>): Boolean = !isNotApplicableClass(parameterType)
override fun isInjectable(parameterType: Class<*>): Boolean = isApplicableClass(parameterType)
override fun resolveDependency(parameterType: Class<*>, instanceClass: Class<*>, round: Int): ArgumentSupplier? {
if (ComponentManager::class.java === parameterType) {
@@ -103,19 +103,20 @@ internal fun <T> instantiateUsingPicoContainer(aClass: Class<*>,
}
}
internal fun isNotApplicableClass(type: Class<*>): Boolean {
return type.isPrimitive ||
type.isAnnotation ||
type.isSynthetic ||
type.isEnum ||
type.isArray ||
type === java.lang.String::class.java ||
type === Class::class.java ||
type === File::class.java ||
type === Path::class.java ||
java.lang.Number::class.java.isAssignableFrom(type) ||
java.util.Collection::class.java.isAssignableFrom(type) ||
java.util.Map::class.java.isAssignableFrom(type)
internal fun isApplicableClass(type: Class<*>): Boolean {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
return !type.isPrimitive &&
!type.isAnnotation &&
!type.isSynthetic &&
!type.isEnum &&
!type.isArray &&
type !== java.lang.String::class.java &&
type !== Class::class.java &&
type !== File::class.java &&
type !== Path::class.java &&
!java.lang.Number::class.java.isAssignableFrom(type) &&
!java.util.Collection::class.java.isAssignableFrom(type) &&
!java.util.Map::class.java.isAssignableFrom(type)
}
private fun getGreediestSatisfiableConstructor(aClass: Class<*>,
@@ -147,7 +148,7 @@ private fun getGreediestSatisfiableConstructor(aClass: Class<*>,
}
// first, perform fast check to ensure that assert about getComponentAdapterOfType is thrown only if the constructor is applicable
if (parameterTypes.any(::isNotApplicableClass)) {
if (!parameterTypes.all(::isApplicableClass)) {
continue
}