Skip to content

Commit

Permalink
stronger types for different string types
Browse files Browse the repository at this point in the history
  • Loading branch information
softwareCobbler committed Dec 17, 2024
1 parent 5e2768f commit 3d88433
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 64 deletions.
12 changes: 6 additions & 6 deletions luceedebug/src/main/java/luceedebug/DapServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,11 @@ public CompletableFuture<VariablesResponse> variables(VariablesArguments args) {

@Override
public CompletableFuture<SetBreakpointsResponse> setBreakpoints(SetBreakpointsArguments args) {
final var path = new OriginalAndTransformedString(
args.getSource().getPath(),
applyPathTransformsIdeToCf(args.getSource().getPath())
);
logger.finest("bp for " + path.original + " -> " + path.transformed);
final var idePath = new StrongString.RawIdePath(args.getSource().getPath());
final var serverAbsPath = new StrongString.CanonicalServerAbsPath(applyPathTransformsIdeToCf(args.getSource().getPath()));

logger.finest("bp for " + idePath.v + " -> " + serverAbsPath.v);

final int size = args.getBreakpoints().length;
final int[] lines = new int[size];
final String[] exprs = new String[size];
Expand All @@ -390,7 +390,7 @@ public CompletableFuture<SetBreakpointsResponse> setBreakpoints(SetBreakpointsAr
}

var result = new ArrayList<Breakpoint>();
for (IBreakpoint bp : luceeVm_.bindBreakpoints(path, lines, exprs)) {
for (IBreakpoint bp : luceeVm_.bindBreakpoints(idePath, serverAbsPath, lines, exprs)) {
result.add(map_cfBreakpoint_to_lsp4jBreakpoint(bp));
}

Expand Down
5 changes: 4 additions & 1 deletion luceedebug/src/main/java/luceedebug/ILuceeVm.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

import com.sun.jdi.*;

import luceedebug.StrongString.CanonicalServerAbsPath;
import luceedebug.StrongString.RawIdePath;

public interface ILuceeVm {
public void registerStepEventCallback(Consumer</*threadID*/Long> cb);
public void registerBreakpointEventCallback(BiConsumer</*threadID*/Long, /*bpID*/Integer> cb);
Expand Down Expand Up @@ -37,7 +40,7 @@ public static BreakpointsChangedEvent justChanges(IBreakpoint[] changes) {
public IDebugEntity[] getNamedVariables(long ID);
public IDebugEntity[] getIndexedVariables(long ID);

public IBreakpoint[] bindBreakpoints(OriginalAndTransformedString absPath, int[] lines, String[] exprs);
public IBreakpoint[] bindBreakpoints(RawIdePath idePath, CanonicalServerAbsPath serverAbsPath, int[] lines, String[] exprs);

public void continue_(long jdwpThreadID);

Expand Down

This file was deleted.

30 changes: 30 additions & 0 deletions luceedebug/src/main/java/luceedebug/StrongString.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package luceedebug;

public class StrongString {
public final String v;
private StrongString(String v) {
this.v = v;
}

@Override
public int hashCode() {
return v.hashCode();
}

@Override
public boolean equals(Object other) {
return v.equals(other);
}

public static class RawIdePath extends StrongString {
public RawIdePath(String v) {
super(v);
}
}

public static class CanonicalServerAbsPath extends StrongString {
public CanonicalServerAbsPath(String v) {
super(v);
}
}
}
16 changes: 5 additions & 11 deletions luceedebug/src/main/java/luceedebug/coreinject/KlassMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
import java.util.HashMap;

import luceedebug.Config;
import luceedebug.OriginalAndTransformedString;
import luceedebug.StrongString.CanonicalServerAbsPath;

import com.sun.jdi.*;

class KlassMap {
/**
* original -> original
*
* transformed -> canonicalized as per fs config
*/
final public OriginalAndTransformedString sourceName;

final public CanonicalServerAbsPath sourceName;
final public HashMap<Integer, Location> lineMap;
private final ClassObjectReference objRef;

Expand All @@ -29,10 +25,8 @@ private KlassMap(Config config, ReferenceType refType) throws AbsentInformationE
lineMap.put(loc.lineNumber(), loc);
}

this.sourceName = new OriginalAndTransformedString(
sourceName,
Config.canonicalizeFileName(sourceName)
);
this.sourceName = new CanonicalServerAbsPath(Config.canonicalizeFileName(sourceName));

this.lineMap = lineMap;
this.refType = refType;
}
Expand Down
54 changes: 27 additions & 27 deletions luceedebug/src/main/java/luceedebug/coreinject/LuceeVm.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import static luceedebug.coreinject.Iife.iife;

import luceedebug.*;
import luceedebug.StrongString.CanonicalServerAbsPath;
import luceedebug.StrongString.RawIdePath;

public class LuceeVm implements ILuceeVm {
// This is a key into a map stored on breakpointRequest objects; the value should always be of Integer type
Expand Down Expand Up @@ -109,8 +111,8 @@ public void unregister(ThreadReference threadRef) {
}

private static class ReplayableCfBreakpointRequest {
final String ideAbsPath;
final String serverAbsPath;
final RawIdePath ideAbsPath;
final CanonicalServerAbsPath serverAbsPath;
final int line;
final int id;
/**
Expand Down Expand Up @@ -140,7 +142,7 @@ public boolean equals(Object vv) {
&& expr.equals(v.expr);
}

ReplayableCfBreakpointRequest(String ideAbsPath, String serverAbsPath, int line, int id, String expr) {
ReplayableCfBreakpointRequest(RawIdePath ideAbsPath, CanonicalServerAbsPath serverAbsPath, int line, int id, String expr) {
this.ideAbsPath = ideAbsPath;
this.serverAbsPath = serverAbsPath;
this.line = line;
Expand All @@ -149,7 +151,7 @@ public boolean equals(Object vv) {
this.maybeNull_jdwpBreakpointRequest = null;
}

ReplayableCfBreakpointRequest(String ideAbsPath, String serverAbsPath, int line, int id, String expr, BreakpointRequest jdwpBreakpointRequest) {
ReplayableCfBreakpointRequest(RawIdePath ideAbsPath, CanonicalServerAbsPath serverAbsPath, int line, int id, String expr, BreakpointRequest jdwpBreakpointRequest) {
this.ideAbsPath = ideAbsPath;
this.serverAbsPath = serverAbsPath;
this.line = line;
Expand All @@ -176,7 +178,7 @@ static BpLineAndId[] getLineInfo(Collection<ReplayableCfBreakpointRequest> vs) {

private final ThreadMap threadMap_ = new ThreadMap();
private final ExecutorService stepHandlerExecutor = Executors.newSingleThreadExecutor();
private final ConcurrentHashMap</*canonical sourceAbsPath*/ String, Set<ReplayableCfBreakpointRequest>> replayableBreakpointRequestsByAbsPath_ = new ConcurrentHashMap<>();
private final ConcurrentHashMap<CanonicalServerAbsPath, Set<ReplayableCfBreakpointRequest>> replayableBreakpointRequestsByAbsPath_ = new ConcurrentHashMap<>();

/**
* Mapping of "abspath on disk" -> "class file info"
Expand All @@ -185,7 +187,7 @@ static BpLineAndId[] getLineInfo(Collection<ReplayableCfBreakpointRequest> vs) {
* like "/app/foo.cfc" maps to "myapp.foo" as well as "someOtherMapping.foo", where each mapping
* is represented by a separate classfile.
*/
private final ConcurrentHashMap</*canonical absPath*/ String, Set<KlassMap>> klassMap_ = new ConcurrentHashMap<>();
private final ConcurrentHashMap<CanonicalServerAbsPath, Set<KlassMap>> klassMap_ = new ConcurrentHashMap<>();
private long JDWP_WORKER_CLASS_ID = 0;
private ThreadReference JDWP_WORKER_THREADREF = null;

Expand Down Expand Up @@ -595,14 +597,14 @@ private void trackClassRef(ReferenceType refType) {

final var klassMap = maybeNull_klassMap; // definitely non-null

Set<ReplayableCfBreakpointRequest> replayableBreakpointRequests = replayableBreakpointRequestsByAbsPath_.get(klassMap.sourceName.transformed);
Set<ReplayableCfBreakpointRequest> replayableBreakpointRequests = replayableBreakpointRequestsByAbsPath_.get(klassMap.sourceName);

klassMap_
.computeIfAbsent(klassMap.sourceName.transformed, _z -> new HashSet<>())
.computeIfAbsent(klassMap.sourceName, _z -> new HashSet<>())
.add(klassMap);

if (replayableBreakpointRequests != null) {
rebindBreakpoints(klassMap.sourceName.transformed, replayableBreakpointRequests);
rebindBreakpoints(klassMap.sourceName, replayableBreakpointRequests);
}
}
catch (Throwable e) {
Expand Down Expand Up @@ -724,7 +726,7 @@ private int nextBreakpointID() {
return breakpointID.incrementAndGet();
}

public void rebindBreakpoints(String serverAbsPath, Collection<ReplayableCfBreakpointRequest> cfBpRequests) {
public void rebindBreakpoints(CanonicalServerAbsPath serverAbsPath, Collection<ReplayableCfBreakpointRequest> cfBpRequests) {
var changedBreakpoints = __internal__bindBreakpoints(serverAbsPath, ReplayableCfBreakpointRequest.getLineInfo(cfBpRequests));

if (breakpointsChangedCallback != null) {
Expand All @@ -733,30 +735,29 @@ public void rebindBreakpoints(String serverAbsPath, Collection<ReplayableCfBreak
}

static class BpLineAndId {
final String ideAbsPath;
final String serverAbsPath;
final RawIdePath ideAbsPath;
final CanonicalServerAbsPath serverAbsPath;
final int line;
final int id;
final String expr;

public BpLineAndId(String ideAbsPath, String serverAbsPath, int line, int id, String expr) {
public BpLineAndId(RawIdePath ideAbsPath, CanonicalServerAbsPath serverAbsPath, int line, int id, String expr) {
this.ideAbsPath = ideAbsPath;
this.serverAbsPath = serverAbsPath;
this.line = line;
this.id = id;
this.expr = expr;
}

}

private BpLineAndId[] freshBpLineAndIdRecordsFromLines(OriginalAndTransformedString absPath, int[] lines, String[] exprs) {
private BpLineAndId[] freshBpLineAndIdRecordsFromLines(RawIdePath idePath, CanonicalServerAbsPath serverPath, int[] lines, String[] exprs) {
if (lines.length != exprs.length) { // really this should be some kind of aggregate
throw new AssertionError("lines.length != exprs.length");
}

var result = new BpLineAndId[lines.length];

Set<ReplayableCfBreakpointRequest> bpInfo = replayableBreakpointRequestsByAbsPath_.get(absPath.transformed);
Set<ReplayableCfBreakpointRequest> bpInfo = replayableBreakpointRequestsByAbsPath_.get(serverPath);

for (var i = 0; i < lines.length; ++i) {
final int line = lines[i];
Expand All @@ -773,20 +774,20 @@ private BpLineAndId[] freshBpLineAndIdRecordsFromLines(OriginalAndTransformedStr
return nextBreakpointID();
});

result[i] = new BpLineAndId(absPath.original, absPath.transformed, line, id, exprs[i]);
result[i] = new BpLineAndId(idePath, serverPath, line, id, exprs[i]);
}
return result;
}

public IBreakpoint[] bindBreakpoints(OriginalAndTransformedString absPath, int[] lines, String[] exprs) {
return __internal__bindBreakpoints(absPath.transformed, freshBpLineAndIdRecordsFromLines(absPath, lines, exprs));
public IBreakpoint[] bindBreakpoints(RawIdePath idePath, CanonicalServerAbsPath serverPath, int[] lines, String[] exprs) {
return __internal__bindBreakpoints(serverPath, freshBpLineAndIdRecordsFromLines(idePath, serverPath, lines, exprs));
}

/**
* caller is responsible for transforming the source path into a cf path,
* i.e. the IDE might say "/foo/bar/baz.cfc" but we are only aware of "/app-host-container/foo/bar/baz.cfc" or etc.
*/
private IBreakpoint[] __internal__bindBreakpoints(String serverAbsPath, BpLineAndId[] lineInfo) {
private IBreakpoint[] __internal__bindBreakpoints(CanonicalServerAbsPath serverAbsPath, BpLineAndId[] lineInfo) {
final Set<KlassMap> klassMapSet = klassMap_.get(serverAbsPath);

if (klassMapSet == null) {
Expand Down Expand Up @@ -830,10 +831,9 @@ private IBreakpoint[] __internal__bindBreakpoints(String serverAbsPath, BpLineAn
}

garbageCollectedKlassMaps.forEach(klassMap -> {
Set<ReplayableCfBreakpointRequest> z = replayableBreakpointRequestsByAbsPath_.get(klassMap.sourceName.transformed);
Set<ReplayableCfBreakpointRequest> z = replayableBreakpointRequestsByAbsPath_.get(klassMap.sourceName);
if (z != null) {
// TODO: stronger types WRT "transformed" and "non-transformed" paths, they shouldn't both be String they should be some distinct wrapper type
z.removeIf(bpReq -> bpReq.serverAbsPath.equals(klassMap.sourceName.transformed));
z.removeIf(bpReq -> bpReq.serverAbsPath.equals(klassMap.sourceName));
}

klassMapSet.remove(klassMap);
Expand All @@ -849,7 +849,7 @@ private IBreakpoint[] __internal__bindBreakpoints(String serverAbsPath, BpLineAn
* Seems we're not allowed to inspect the jdwp-native id, but we can attach our own
*/
private IBreakpoint[] __internal__idempotentBindBreakpoints(KlassMap klassMap, BpLineAndId[] lineInfo) {
final var replayable = replayableBreakpointRequestsByAbsPath_.computeIfAbsent(klassMap.sourceName.transformed, _z -> new HashSet<>());
final var replayable = replayableBreakpointRequestsByAbsPath_.computeIfAbsent(klassMap.sourceName, _z -> new HashSet<>());
final var result = new ArrayList<IBreakpoint>();

for (int i = 0; i < lineInfo.length; ++i) {
Expand Down Expand Up @@ -879,15 +879,15 @@ private IBreakpoint[] __internal__idempotentBindBreakpoints(KlassMap klassMap, B
}
}

replayableBreakpointRequestsByAbsPath_.put(klassMap.sourceName.transformed, replayable);
replayableBreakpointRequestsByAbsPath_.put(klassMap.sourceName, replayable);

return result.toArray(size -> new IBreakpoint[size]);
}

/**
* returns an array of the line numbers the old breakpoints were bound to
*/
private void clearExistingBreakpoints(String absPath) {
private void clearExistingBreakpoints(CanonicalServerAbsPath absPath) {
Set<ReplayableCfBreakpointRequest> replayable = replayableBreakpointRequestsByAbsPath_.get(absPath);

// "just do it" in all cases
Expand Down Expand Up @@ -1055,7 +1055,7 @@ public String[] getTrackedCanonicalFileNames() {
final var result = new ArrayList<String>();
for (var klassMap : klassMap_.values()) {
for (var mapping : klassMap) {
result.add(mapping.sourceName.transformed);
result.add(mapping.sourceName.v);
}
}
return result.toArray(size -> new String[size]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void a(LuceeAndDockerInfo dockerInfo) throws Throwable {
.buildOrGetImage(dockerClient, dockerInfo.dockerFile)
.getImageID();

System.out.println("container ID is ....");
final String containerID = DockerUtils
.getFreshDefaultContainer(
dockerClient,
Expand All @@ -45,14 +46,19 @@ void a(LuceeAndDockerInfo dockerInfo) throws Throwable {
)
.getContainerID();

System.out.println(" ...." + containerID);

dockerClient
.startContainerCmd(containerID)
.exec();

System.out.println("started...");
HostPortBindings portBindings = DockerUtils.getPublishedHostPortBindings(dockerClient, containerID);
System.out.println("pbs..." + portBindings.dap + "," + portBindings.http);

try {
LuceeUtils.pollForServerIsActive("http://localhost:" + portBindings.http + "/heartbeat.cfm");
System.out.println("poll OK");

final var dapClient = new DapUtils.MockClient();

Expand Down

0 comments on commit 3d88433

Please sign in to comment.