UniqueSequenceContractInferrer.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
*******************************************************************************/
package org.sandbox.jdt.container.analysis;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.sandbox.jdt.container.api.ContainerRecommendation;
import org.sandbox.jdt.container.api.ContainerRecommendation.AutomationLevel;
import org.sandbox.jdt.container.api.ContainerRecommendation.Confidence;
import org.sandbox.jdt.container.api.ContainerRecommendation.ContractAssessment;
import org.sandbox.jdt.container.api.ContainerRecommendation.ContractProperty;
import org.sandbox.jdt.container.api.ContainerRecommendation.Preservation;
import org.sandbox.jdt.container.api.ContainerShape;
import org.sandbox.jdt.container.api.ContainerUsageProfile;
import org.sandbox.jdt.container.api.ContainerUsageProfile.AliasingContract;
import org.sandbox.jdt.container.api.ContainerUsageProfile.AnalysisCompleteness;
import org.sandbox.jdt.container.api.ContainerUsageProfile.ElementDomain;
import org.sandbox.jdt.container.api.ContainerUsageProfile.EscapeLevel;
import org.sandbox.jdt.container.api.ContainerUsageProfile.OrderRequirement;
import org.sandbox.jdt.container.api.ContainerUsageProfile.ThreadExposure;
import org.sandbox.jdt.container.api.ContainerUsageProfile.UniquenessRequirement;
import org.sandbox.jdt.container.api.TargetContainerContract;
import org.sandbox.jdt.container.api.TargetContainerContract.Mutability;
import org.sandbox.jdt.container.api.UsageEvidence.Kind;
/** Infers the first manually-unique sequence to ordered-set contract. */
public final class UniqueSequenceContractInferrer {
/** Returns an explainable report-only recommendation for a proven local profile. */
public Optional<ContainerRecommendation> infer(ContainerUsageProfile profile) {
Objects.requireNonNull(profile, "profile"); //$NON-NLS-1$
if (!eligible(profile)) {
return Optional.empty();
}
TargetContainerContract target= new TargetContainerContract(
ContainerShape.SET,
OrderRequirement.ENCOUNTER,
UniquenessRequirement.REQUIRED,
Mutability.MUTABLE,
profile.nullContract(),
"Use an encounter-ordered mutable set for a sequence whose insertions already suppress duplicates."); //$NON-NLS-1$
return Optional.of(new ContainerRecommendation(
profile,
target,
ContainerRuleRegistry.uniqueSequenceSet(),
Confidence.HIGH,
AutomationLevel.REPORT_ONLY,
List.of(
assessment(
ContractProperty.ORDER,
"LinkedHashSet preserves the observed encounter order."), //$NON-NLS-1$
assessment(
ContractProperty.UNIQUENESS,
"Every insertion suppresses duplicates and the element type has stable equality and hash semantics."), //$NON-NLS-1$
assessment(
ContractProperty.MUTABILITY,
"The target remains mutable during the same local use phase."), //$NON-NLS-1$
assessment(
ContractProperty.NULLS,
"ArrayList and LinkedHashSet both permit one null element; an unknown application policy remains unknown."), //$NON-NLS-1$
assessment(
ContractProperty.ALIASING,
"Every local use was classified and no alias or publication was found."), //$NON-NLS-1$
assessment(
ContractProperty.SIGNATURES,
"The represented value is local, so no signature changes are required."), //$NON-NLS-1$
assessment(
ContractProperty.CONCURRENCY,
"The value is proven thread-confined and is not captured.")))); //$NON-NLS-1$
}
private static boolean eligible(ContainerUsageProfile profile) {
return profile.completeness() == AnalysisCompleteness.LOCAL_USAGE_COMPLETE
&& profile.currentShape() == ContainerShape.LIST
&& (profile.elementDomain() == ElementDomain.REFERENCE
|| profile.elementDomain() == ElementDomain.ENUM)
&& profile.access().append()
&& profile.access().membershipQuery()
&& !profile.access().hasPositionalSemantics()
&& profile.orderRequirement() == OrderRequirement.ENCOUNTER
&& profile.uniquenessRequirement() == UniquenessRequirement.REQUIRED
&& profile.escapeLevel() == EscapeLevel.LOCAL
&& profile.aliasingContract() == AliasingContract.NO_OBSERVED_ALIAS
&& profile.concurrency().exposure() == ThreadExposure.THREAD_CONFINED
&& hasEvidence(profile, Kind.DUPLICATE_SUPPRESSION)
&& hasEvidence(profile, Kind.HASH_STABLE_COMPONENT);
}
private static boolean hasEvidence(ContainerUsageProfile profile, Kind kind) {
return profile.evidence().stream().anyMatch(evidence -> evidence.kind() == kind);
}
private static ContractAssessment assessment(
ContractProperty property,
String explanation) {
return new ContractAssessment(
property, Preservation.PRESERVED, explanation);
}
}