Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,19 +273,21 @@ public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedNa
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:")) {
int sourceReference = getSourceReference(source, context);
String clientPath = AdapterUtils.convertPath(uri, context.isDebuggerPathsAreUri(), context.isClientPathsAreUri());
return new Types.Source(sourceName, clientPath, sourceReference);
} else {
Types.Source sourceInSourcePaths = resolveSourceFromSourcePaths(sourceName, relativeSourcePath, context);
if (sourceInSourcePaths != null) {
return sourceInSourcePaths;
}

int sourceReference = getSourceReference(source, context);
// 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.
Expand All @@ -295,15 +297,25 @@ public static Types.Source convertDebuggerSourceToClient(String fullyQualifiedNa
}
} 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, sourceReference);
} else {
return null;
}
return resolveSourceFromSourcePaths(sourceName, relativeSourcePath, context);
}
}

private static int getSourceReference(Source source, IDebugAdapterContext context) {
return SourceType.REMOTE == source.getType() ? context.createSourceReference(source.getUri()) : 0;
}

private static Types.Source resolveSourceFromSourcePaths(String sourceName, String relativeSourcePath,
IDebugAdapterContext context) {
String absoluteSourcepath = AdapterUtils.sourceLookup(context.getSourcePaths(), relativeSourcePath);
if (absoluteSourcepath == null) {
return null;
}

String clientPath = AdapterUtils.convertPath(absoluteSourcepath, false, context.isClientPathsAreUri());
return new Types.Source(sourceName, clientPath, 0);
}

private String formatMethodName(String methodName, List<String> argumentTypeNames, String fqn, boolean showContextClass, boolean showParameter) {
StringBuilder formattedName = new StringBuilder();
if (showContextClass) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2026 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.handler;

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.easymock.EasyMockSupport;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import com.microsoft.java.debug.core.adapter.DebugAdapterContext;
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
import com.microsoft.java.debug.core.adapter.ProviderContext;
import com.microsoft.java.debug.core.adapter.Source;
import com.microsoft.java.debug.core.adapter.SourceType;
import com.microsoft.java.debug.core.protocol.Types;

public class StackTraceRequestHandlerTest extends EasyMockSupport {
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();

@Test
public void convertDebuggerSourceShouldPreferSourcePathsOverCachedJdtUri() throws Exception {
String fullyQualifiedName = "com.example.Foo";
String sourceName = "Foo.java";
String relativeSourcePath = Paths.get("com", "example", sourceName).toString();
String jdtUri = "jdt://contents/foo.jar/com.example/Foo.java?=handle";
Path sourceRoot = tempFolder.newFolder("sources").toPath();
Path sourceFile = sourceRoot.resolve(relativeSourcePath);
Files.createDirectories(sourceFile.getParent());
Files.write(sourceFile, "package com.example; class Foo {}\n".getBytes(StandardCharsets.UTF_8));

ISourceLookUpProvider sourceProvider = createMock(ISourceLookUpProvider.class);
expect(sourceProvider.getSource(fullyQualifiedName, relativeSourcePath))
.andReturn(new Source(jdtUri, SourceType.LOCAL))
.once();
replayAll();

ProviderContext providerContext = new ProviderContext();
providerContext.registerProvider(ISourceLookUpProvider.class, sourceProvider);
DebugAdapterContext context = new DebugAdapterContext(null, providerContext);
context.setSourcePaths(new String[0]);

Types.Source jdtSource = StackTraceRequestHandler.convertDebuggerSourceToClient(fullyQualifiedName, sourceName,
relativeSourcePath, context);
assertEquals(jdtUri, jdtSource.path);

context.setSourcePaths(new String[] { sourceRoot.toString() });
Types.Source localSource = StackTraceRequestHandler.convertDebuggerSourceToClient(fullyQualifiedName, sourceName,
relativeSourcePath, context);

assertEquals(sourceFile.toString(), localSource.path);
assertEquals(0, localSource.sourceReference);

context.setClientPathsAreUri(true);
Types.Source localUriSource = StackTraceRequestHandler.convertDebuggerSourceToClient(fullyQualifiedName,
sourceName, relativeSourcePath, context);

assertEquals(sourceFile.toUri().toString(), localUriSource.path);
verifyAll();
}

@Test
public void convertDebuggerSourceShouldHandleSourceWithNullType() throws Exception {
String fullyQualifiedName = "com.example.Bar";
String sourceName = "Bar.java";
Path sourceFile = tempFolder.newFile(sourceName).toPath();
String sourceUri = sourceFile.toUri().toString();

ISourceLookUpProvider sourceProvider = createMock(ISourceLookUpProvider.class);
expect(sourceProvider.getSource(fullyQualifiedName, sourceName))
.andReturn(new Source(sourceUri, null))
.once();
replayAll();

ProviderContext providerContext = new ProviderContext();
providerContext.registerProvider(ISourceLookUpProvider.class, sourceProvider);
DebugAdapterContext context = new DebugAdapterContext(null, providerContext);

Types.Source source = StackTraceRequestHandler.convertDebuggerSourceToClient(fullyQualifiedName, sourceName,
sourceName, context);

assertEquals(sourceFile.toString(), source.path);
assertEquals(0, source.sourceReference);
verifyAll();
}
}
Loading