Skip to content

Commit

Permalink
Allow ISourceLookUpProvider specify whether file is Local or Remote (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirMakaev authored Jan 8, 2024
1 parent 9bdd997 commit f8da9e2
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
public class DebugAdapterContext implements IDebugAdapterContext {
private static final int MAX_CACHE_ITEMS = 10000;
private final StepFilters defaultFilters = new StepFilters();
private Map<String, String> sourceMappingCache = Collections.synchronizedMap(new LRUCache<>(MAX_CACHE_ITEMS));
private Map<String, Source> sourceMappingCache = Collections.synchronizedMap(new LRUCache<>(MAX_CACHE_ITEMS));
private IProviderContext providerContext;
private IProtocolServer server;

Expand Down Expand Up @@ -212,7 +212,7 @@ public void setVariableFormatter(IVariableFormatter variableFormatter) {
}

@Override
public Map<String, String> getSourceLookupCache() {
public Map<String, Source> getSourceLookupCache() {
return sourceMappingCache;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public interface IDebugAdapterContext {

void setVariableFormatter(IVariableFormatter variableFormatter);

Map<String, String> getSourceLookupCache();
Map<String, Source> getSourceLookupCache();

void setDebuggeeEncoding(Charset encoding);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.java.debug.core.adapter;

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

/**
* Given a fully qualified class name and source file path, search the associated disk source file.
*
* @param fullyQualifiedName
* the fully qualified class name (e.g. com.microsoft.java.debug.core.adapter.ISourceLookUpProvider).
* @param sourcePath
* the qualified source file path (e.g. com\microsoft\java\debug\core\adapter\ISourceLookupProvider.java).
* @return the associated source file uri.
* Deprecated, please use {@link #getSource(String, String)} instead.
*/
@Deprecated
String getSourceFileURI(String fullyQualifiedName, String sourcePath);

String getSourceContents(String uri);

/**
* Retrieves a {@link Source} object representing the source code associated with the given fully qualified class name and source file path.
* The implementation of this interface can determine a source is "local" or "remote".
* In case of "remote" a follow up "source" request will be issued by the client
*
* @param fullyQualifiedName
* the fully qualified class name,
* e.g., "com.microsoft.java.debug.core.adapter.ISourceLookUpProvider".
* @param sourcePath
* the qualified source file path,
* e.g., "com/microsoft/java/debug/core/adapter/ISourceLookupProvider.java".
* @return A {@link Source} object encapsulating the source file URI obtained from
* {@link #getSourceFileURI(String, String)} and the source type as {@link SourceType#LOCAL}.
*/
default Source getSource(String fullyQualifiedName, String sourcePath) {
return new Source(getSourceFileURI(fullyQualifiedName, sourcePath), SourceType.LOCAL);
}

/**
* Returns the Java runtime that the specified project's build path used.
* @param projectName
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2017 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.java.debug.core.adapter;

public class Source {
public final String uri;
public final SourceType type;

public Source(String uri, SourceType type) {
this.uri = uri;
this.type = type;
}

public String getUri() {
return this.uri;
}

public SourceType getType() {
return this.type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*******************************************************************************
* Copyright (c) 2017 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/
package com.microsoft.java.debug.core.adapter;

public enum SourceType {
REMOTE,
LOCAL
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
import com.microsoft.java.debug.core.adapter.IDebugRequestHandler;
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
import com.microsoft.java.debug.core.adapter.Source;
import com.microsoft.java.debug.core.adapter.SourceType;
import com.microsoft.java.debug.core.adapter.formatter.SimpleTypeFormatter;
import com.microsoft.java.debug.core.adapter.variables.StackFrameReference;
import com.microsoft.java.debug.core.protocol.Messages.Response;
Expand Down Expand Up @@ -141,7 +143,7 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
}

private static List<StackFrameInfo> resolveStackFrameInfos(StackFrame[] frames, boolean async)
throws AbsentInformationException, IncompatibleThreadStateException {
throws AbsentInformationException, IncompatibleThreadStateException {
List<StackFrameInfo> jdiFrames = new ArrayList<>();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (StackFrame frame : frames) {
Expand Down Expand Up @@ -221,7 +223,7 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
clientSource = null;
}
} else if (DebugSettings.getCurrent().debugSupportOnDecompiledSource == Switch.ON
&& clientSource != null && clientSource.path != null) {
&& clientSource != null && clientSource.path != null) {
// Align the original line with the decompiled line.
int[] lineMappings = context.getProvider(ISourceLookUpProvider.class).getOriginalLineMappings(clientSource.path);
int[] renderLines = AdapterUtils.binarySearchMappedLines(lineMappings, clientLineNumber);
Expand All @@ -244,7 +246,7 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
});
if (match) {
clientColumnNumber = AdapterUtils.convertColumnNumber(breakpoint.getColumnNumber(),
context.isDebuggerColumnsStartAt1(), context.isClientColumnsStartAt1());
context.isDebuggerColumnsStartAt1(), context.isClientColumnsStartAt1());
}
}
}
Expand All @@ -256,33 +258,44 @@ private Types.StackFrame convertDebuggerStackFrameToClient(StackFrameInfo jdiFra
/**
* Find the source mapping for the specified source file name.
*/
public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedName, String sourceName, String relativeSourcePath,
public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedName, String sourceName,
String relativeSourcePath,
IDebugAdapterContext context) throws URISyntaxException {

// use a lru cache for better performance
String uri = context.getSourceLookupCache().computeIfAbsent(fullyQualifiedName, key -> {
String fromProvider = context.getProvider(ISourceLookUpProvider.class).getSourceFileURI(key, relativeSourcePath);
// avoid return null which will cause the compute function executed again
return StringUtils.isBlank(fromProvider) ? "" : fromProvider;
Source source = context.getSourceLookupCache().computeIfAbsent(fullyQualifiedName, key -> {
Source result = context.getProvider(ISourceLookUpProvider.class).getSource(key, relativeSourcePath);
if (result == null) {
return new Source("", SourceType.LOCAL);
}
return result;
});

Integer sourceReference = 0;
String uri = source.getUri();

if (source.getType().equals(SourceType.REMOTE)) {
sourceReference = context.createSourceReference(source.getUri());
}

if (!StringUtils.isBlank(uri)) {
// The Source.path could be a file system path or uri string.
if (uri.startsWith("file:")) {
String clientPath = AdapterUtils.convertPath(uri, context.isDebuggerPathsAreUri(), context.isClientPathsAreUri());
return new Types.Source(sourceName, clientPath, 0);
return new Types.Source(sourceName, clientPath, sourceReference);
} else {
// If the debugger returns uri in the Source.path for the StackTrace response, VSCode client will try to find a TextDocumentContentProvider
// to render the contents.
// Language Support for Java by Red Hat extension has already registered a jdt TextDocumentContentProvider to parse the jdt-based uri.
// 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/
// lib%5C/rt.jar%3Cjava.io(PrintStream.class'.
return new Types.Source(sourceName, uri, 0);
return new Types.Source(sourceName, uri, sourceReference);
}
} else {
// If the source lookup engine cannot find the source file, then lookup it in the source directories specified by user.
String absoluteSourcepath = AdapterUtils.sourceLookup(context.getSourcePaths(), relativeSourcePath);
if (absoluteSourcepath != null) {
return new Types.Source(sourceName, absoluteSourcepath, 0);
return new Types.Source(sourceName, absoluteSourcepath, sourceReference);
} else {
return null;
}
Expand Down

0 comments on commit f8da9e2

Please sign in to comment.