diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java index b97847e70..339b0d17b 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java @@ -24,6 +24,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; + import com.microsoft.java.debug.core.adapter.Messages.Response; public class AdapterUtils { @@ -150,6 +152,19 @@ public static String toUri(String path) { } } + /** + * Check a string variable is an uri or not. + */ + public static boolean isUri(String uriString) { + try { + URI uri = new URI(uriString); + return StringUtils.isNotBlank(uri.getScheme()); + } catch (URISyntaxException | IllegalArgumentException | FileSystemNotFoundException + | SecurityException e) { + return false; + } + } + /** * Generate an error response with the given error message. * diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java index 8713beb3f..655126bce 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java @@ -61,12 +61,14 @@ public void handle(Command command, Arguments arguments, Response response, IDeb String sourcePath = clientPath; if (bpArguments.source.sourceReference != 0 && context.getSourceUri(bpArguments.source.sourceReference) != null) { sourcePath = context.getSourceUri(bpArguments.source.sourceReference); - } else { - sourcePath = AdapterUtils.convertPath(clientPath, context.isClientPathsAreUri(), context.isDebuggerPathsAreUri()); + } else if (StringUtils.isNotBlank(clientPath)) { + // See the bug https://github.com/Microsoft/vscode/issues/30996 + // Source.path in the SetBreakpointArguments could be a file system path or uri. + sourcePath = AdapterUtils.convertPath(clientPath, AdapterUtils.isUri(clientPath), context.isDebuggerPathsAreUri()); } // When breakpoint source path is null or an invalid file path, send an ErrorResponse back. - if (sourcePath == null) { + if (StringUtils.isBlank(sourcePath)) { AdapterUtils.setErrorResponse(response, ErrorCode.SET_BREAKPOINT_FAILURE, String.format("Failed to setBreakpoint. Reason: '%s' is an invalid path.", bpArguments.source.path)); return; diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java index 8d31dbcef..909179c3f 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java @@ -118,11 +118,17 @@ private Types.Source convertDebuggerSourceToClient(Location location, IDebugAdap }); if (!StringUtils.isBlank(uri)) { - String clientPath = AdapterUtils.convertPath(uri, context.isDebuggerPathsAreUri(), context.isClientPathsAreUri()); + // 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); } else { - return new Types.Source(sourceName, clientPath, context.createSourceReference(uri)); + // 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); } } else { // If the source lookup engine cannot find the source file, then lookup it in the source directories specified by user. diff --git a/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/JdtSourceLookUpProvider.java b/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/JdtSourceLookUpProvider.java index 614b1b295..002bc2c4f 100644 --- a/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/JdtSourceLookUpProvider.java +++ b/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/JdtSourceLookUpProvider.java @@ -41,7 +41,6 @@ import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.ToolFactory; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.CompilationUnit; @@ -52,7 +51,6 @@ import org.eclipse.jdt.core.search.SearchParticipant; import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.core.search.SearchRequestor; -import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; import org.eclipse.jdt.internal.debug.core.breakpoints.ValidBreakpointLocationLocator; import com.microsoft.java.debug.core.Configuration; @@ -65,9 +63,6 @@ public class JdtSourceLookUpProvider implements ISourceLookUpProvider { private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); private static final String JDT_SCHEME = "jdt"; private static final String PATH_SEPARATOR = "/"; - private static final String MISSING_SOURCES_HEADER = " // Failed to get sources. Instead, stub sources have been generated.\n" - + " // Implementation of methods is unavailable.\n"; - private static final String LF = "\n"; private HashMap context = new HashMap(); @@ -204,9 +199,6 @@ private String getContents(IClassFile cf) { if (buffer != null) { source = buffer.getContents(); } - if (source == null) { - source = disassemble(cf); - } } catch (JavaModelException e) { logger.log(Level.SEVERE, String.format("Failed to parse the source contents of the class file: %s", e.toString()), e); } @@ -282,7 +274,6 @@ private static String getFileURI(IClassFile classFile) { + PATH_SEPARATOR + classFile.getElementName(), classFile.getHandleIdentifier(), null) .toASCIIString(); } catch (URISyntaxException e) { - e.printStackTrace(); return null; } } @@ -315,19 +306,6 @@ private static IClassFile resolveClassFile(String uriString) { return null; } - private static String disassemble(IClassFile classFile) { - ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); - String disassembledByteCode = null; - try { - disassembledByteCode = disassembler.disassemble(classFile.getBytes(), LF, - ClassFileBytesDisassembler.WORKING_COPY); - disassembledByteCode = MISSING_SOURCES_HEADER + LF + disassembledByteCode; - } catch (Exception e) { - // ignore - } - return disassembledByteCode; - } - private static IJavaSearchScope createSearchScope(IJavaProject project) { if (project == null) { return SearchEngine.createWorkspaceScope();