SemanticRewritePlanContext.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer and others.
*
* 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.triggerpattern.api;
import java.util.Map;
import java.util.Objects;
/** Thread-confined semantic plan scope used while invoking the existing hint backend. */
public final class SemanticRewritePlanContext {
private record State(SemanticRewritePlan plan, Map<String, String> compilerOptions) {
State {
plan= Objects.requireNonNullElseGet(plan, SemanticRewritePlan::empty);
compilerOptions= Map.copyOf(compilerOptions == null ? Map.of() : compilerOptions);
}
}
private static final ThreadLocal<State> CURRENT=
ThreadLocal.withInitial(() -> new State(SemanticRewritePlan.empty(), Map.of()));
private SemanticRewritePlanContext() {
}
/** Returns the plan active for the current synchronous hint-processing call. */
public static SemanticRewritePlan current() {
return CURRENT.get().plan();
}
/** Returns the compiler options active in the current plan-aware scope. */
public static Map<String, String> currentCompilerOptions() {
return CURRENT.get().compilerOptions();
}
/** Installs a plan with no additional compiler options. */
public static Scope install(SemanticRewritePlan plan) {
return install(plan, Map.of());
}
/** Installs a plan and compiler options until the returned scope is closed. */
public static Scope install(SemanticRewritePlan plan, Map<String, String> compilerOptions) {
State previous= CURRENT.get();
CURRENT.set(new State(plan, compilerOptions));
return new Scope(previous);
}
/** Restores the previous scope exactly once. */
public static final class Scope implements AutoCloseable {
private final State previous;
private boolean closed;
private Scope(State previous) {
this.previous= previous;
}
@Override
public void close() {
if (!closed) {
CURRENT.set(previous);
closed= true;
}
}
}
}