Skip to content

Commit f8da9e2

Browse files
Allow ISourceLookUpProvider specify whether file is Local or Remote (#515)
1 parent 9bdd997 commit f8da9e2

File tree

6 files changed

+93
-22
lines changed

6 files changed

+93
-22
lines changed

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapterContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
public class DebugAdapterContext implements IDebugAdapterContext {
3333
private static final int MAX_CACHE_ITEMS = 10000;
3434
private final StepFilters defaultFilters = new StepFilters();
35-
private Map<String, String> sourceMappingCache = Collections.synchronizedMap(new LRUCache<>(MAX_CACHE_ITEMS));
35+
private Map<String, Source> sourceMappingCache = Collections.synchronizedMap(new LRUCache<>(MAX_CACHE_ITEMS));
3636
private IProviderContext providerContext;
3737
private IProtocolServer server;
3838

@@ -212,7 +212,7 @@ public void setVariableFormatter(IVariableFormatter variableFormatter) {
212212
}
213213

214214
@Override
215-
public Map<String, String> getSourceLookupCache() {
215+
public Map<String, Source> getSourceLookupCache() {
216216
return sourceMappingCache;
217217
}
218218

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/IDebugAdapterContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public interface IDebugAdapterContext {
8585

8686
void setVariableFormatter(IVariableFormatter variableFormatter);
8787

88-
Map<String, String> getSourceLookupCache();
88+
Map<String, Source> getSourceLookupCache();
8989

9090
void setDebuggeeEncoding(Charset encoding);
9191

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ISourceLookUpProvider.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
* Contributors:
99
* Microsoft Corporation - initial API and implementation
1010
*******************************************************************************/
11-
1211
package com.microsoft.java.debug.core.adapter;
1312

1413
import java.util.List;
@@ -42,18 +41,31 @@ public interface ISourceLookUpProvider extends IProvider {
4241
JavaBreakpointLocation[] getBreakpointLocations(String sourceUri, SourceBreakpoint[] sourceBreakpoints) throws DebugException;
4342

4443
/**
45-
* Given a fully qualified class name and source file path, search the associated disk source file.
46-
*
47-
* @param fullyQualifiedName
48-
* the fully qualified class name (e.g. com.microsoft.java.debug.core.adapter.ISourceLookUpProvider).
49-
* @param sourcePath
50-
* the qualified source file path (e.g. com\microsoft\java\debug\core\adapter\ISourceLookupProvider.java).
51-
* @return the associated source file uri.
44+
* Deprecated, please use {@link #getSource(String, String)} instead.
5245
*/
46+
@Deprecated
5347
String getSourceFileURI(String fullyQualifiedName, String sourcePath);
5448

5549
String getSourceContents(String uri);
5650

51+
/**
52+
* Retrieves a {@link Source} object representing the source code associated with the given fully qualified class name and source file path.
53+
* The implementation of this interface can determine a source is "local" or "remote".
54+
* In case of "remote" a follow up "source" request will be issued by the client
55+
*
56+
* @param fullyQualifiedName
57+
* the fully qualified class name,
58+
* e.g., "com.microsoft.java.debug.core.adapter.ISourceLookUpProvider".
59+
* @param sourcePath
60+
* the qualified source file path,
61+
* e.g., "com/microsoft/java/debug/core/adapter/ISourceLookupProvider.java".
62+
* @return A {@link Source} object encapsulating the source file URI obtained from
63+
* {@link #getSourceFileURI(String, String)} and the source type as {@link SourceType#LOCAL}.
64+
*/
65+
default Source getSource(String fullyQualifiedName, String sourcePath) {
66+
return new Source(getSourceFileURI(fullyQualifiedName, sourcePath), SourceType.LOCAL);
67+
}
68+
5769
/**
5870
* Returns the Java runtime that the specified project's build path used.
5971
* @param projectName
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2017 Microsoft Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Microsoft Corporation - initial API and implementation
10+
*******************************************************************************/
11+
12+
package com.microsoft.java.debug.core.adapter;
13+
14+
public class Source {
15+
public final String uri;
16+
public final SourceType type;
17+
18+
public Source(String uri, SourceType type) {
19+
this.uri = uri;
20+
this.type = type;
21+
}
22+
23+
public String getUri() {
24+
return this.uri;
25+
}
26+
27+
public SourceType getType() {
28+
return this.type;
29+
}
30+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2017 Microsoft Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Microsoft Corporation - initial API and implementation
10+
*******************************************************************************/
11+
package com.microsoft.java.debug.core.adapter;
12+
13+
public enum SourceType {
14+
REMOTE,
15+
LOCAL
16+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
3737
import com.microsoft.java.debug.core.adapter.IDebugRequestHandler;
3838
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
39+
import com.microsoft.java.debug.core.adapter.Source;
40+
import com.microsoft.java.debug.core.adapter.SourceType;
3941
import com.microsoft.java.debug.core.adapter.formatter.SimpleTypeFormatter;
4042
import com.microsoft.java.debug.core.adapter.variables.StackFrameReference;
4143
import com.microsoft.java.debug.core.protocol.Messages.Response;
@@ -141,7 +143,7 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
141143
}
142144

143145
private static List<StackFrameInfo> resolveStackFrameInfos(StackFrame[] frames, boolean async)
144-
throws AbsentInformationException, IncompatibleThreadStateException {
146+
throws AbsentInformationException, IncompatibleThreadStateException {
145147
List<StackFrameInfo> jdiFrames = new ArrayList<>();
146148
List<CompletableFuture<Void>> futures = new ArrayList<>();
147149
for (StackFrame frame : frames) {
@@ -221,7 +223,7 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
221223
clientSource = null;
222224
}
223225
} else if (DebugSettings.getCurrent().debugSupportOnDecompiledSource == Switch.ON
224-
&& clientSource != null && clientSource.path != null) {
226+
&& clientSource != null && clientSource.path != null) {
225227
// Align the original line with the decompiled line.
226228
int[] lineMappings = context.getProvider(ISourceLookUpProvider.class).getOriginalLineMappings(clientSource.path);
227229
int[] renderLines = AdapterUtils.binarySearchMappedLines(lineMappings, clientLineNumber);
@@ -244,7 +246,7 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
244246
});
245247
if (match) {
246248
clientColumnNumber = AdapterUtils.convertColumnNumber(breakpoint.getColumnNumber(),
247-
context.isDebuggerColumnsStartAt1(), context.isClientColumnsStartAt1());
249+
context.isDebuggerColumnsStartAt1(), context.isClientColumnsStartAt1());
248250
}
249251
}
250252
}
@@ -256,33 +258,44 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
256258
/**
257259
* Find the source mapping for the specified source file name.
258260
*/
259-
public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedName, String sourceName, String relativeSourcePath,
261+
public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedName, String sourceName,
262+
String relativeSourcePath,
260263
IDebugAdapterContext context) throws URISyntaxException {
264+
261265
// use a lru cache for better performance
262-
String uri = context.getSourceLookupCache().computeIfAbsent(fullyQualifiedName, key -> {
263-
String fromProvider = context.getProvider(ISourceLookUpProvider.class).getSourceFileURI(key, relativeSourcePath);
264-
// avoid return null which will cause the compute function executed again
265-
return StringUtils.isBlank(fromProvider) ? "" : fromProvider;
266+
Source source = context.getSourceLookupCache().computeIfAbsent(fullyQualifiedName, key -> {
267+
Source result = context.getProvider(ISourceLookUpProvider.class).getSource(key, relativeSourcePath);
268+
if (result == null) {
269+
return new Source("", SourceType.LOCAL);
270+
}
271+
return result;
266272
});
267273

274+
Integer sourceReference = 0;
275+
String uri = source.getUri();
276+
277+
if (source.getType().equals(SourceType.REMOTE)) {
278+
sourceReference = context.createSourceReference(source.getUri());
279+
}
280+
268281
if (!StringUtils.isBlank(uri)) {
269282
// The Source.path could be a file system path or uri string.
270283
if (uri.startsWith("file:")) {
271284
String clientPath = AdapterUtils.convertPath(uri, context.isDebuggerPathsAreUri(), context.isClientPathsAreUri());
272-
return new Types.Source(sourceName, clientPath, 0);
285+
return new Types.Source(sourceName, clientPath, sourceReference);
273286
} else {
274287
// If the debugger returns uri in the Source.path for the StackTrace response, VSCode client will try to find a TextDocumentContentProvider
275288
// to render the contents.
276289
// Language Support for Java by Red Hat extension has already registered a jdt TextDocumentContentProvider to parse the jdt-based uri.
277290
// The jdt uri looks like 'jdt://contents/rt.jar/java.io/PrintStream.class?=1.helloworld/%5C/usr%5C/lib%5C/jvm%5C/java-8-oracle%5C/jre%5C/
278291
// lib%5C/rt.jar%3Cjava.io(PrintStream.class'.
279-
return new Types.Source(sourceName, uri, 0);
292+
return new Types.Source(sourceName, uri, sourceReference);
280293
}
281294
} else {
282295
// If the source lookup engine cannot find the source file, then lookup it in the source directories specified by user.
283296
String absoluteSourcepath = AdapterUtils.sourceLookup(context.getSourcePaths(), relativeSourcePath);
284297
if (absoluteSourcepath != null) {
285-
return new Types.Source(sourceName, absoluteSourcepath, 0);
298+
return new Types.Source(sourceName, absoluteSourcepath, sourceReference);
286299
} else {
287300
return null;
288301
}

0 commit comments

Comments
 (0)