private async Task <SourceFileInfo?> TryGetSourceLinkFileAsync(SourceDocument sourceDocument, Encoding encoding, TelemetryMessage telemetry, bool useExtendedTimeout, CancellationToken cancellationToken) { if (sourceDocument.SourceLinkUrl is null || _sourceLinkService is null) { return(null); } var timeout = useExtendedTimeout ? ExtendedSourceLinkTimeout : SourceLinkTimeout; // This should ideally be the repo-relative path to the file, and come from SourceLink: https://github.com/dotnet/sourcelink/pull/699 var relativePath = Path.GetFileName(sourceDocument.FilePath); var delay = Task.Delay(timeout, cancellationToken); var sourceFileTask = _sourceLinkService.Value.GetSourceFilePathAsync(sourceDocument.SourceLinkUrl, relativePath, cancellationToken); var winner = await Task.WhenAny(sourceFileTask, delay).ConfigureAwait(false); if (winner == sourceFileTask) { var sourceFile = await sourceFileTask.ConfigureAwait(false); if (sourceFile is not null) { // TODO: Don't ignore the checksum here: https://github.com/dotnet/roslyn/issues/55834 var result = LoadSourceFile(sourceFile.SourceFilePath, sourceDocument, encoding, "SourceLink", ignoreChecksum: true, fromRemoteLocation: true); if (result is not null) { telemetry.SetSourceFileSource("sourcelink"); _logger?.Log(FeaturesResources._0_found_via_SourceLink, sourceDocument.FilePath); } else { _logger?.Log(FeaturesResources._0_found_via_SourceLink_but_couldnt_read_file, sourceDocument.FilePath); } return(result); } else { telemetry.SetSourceFileSource("timeout"); _logger?.Log(FeaturesResources.Timeout_SourceLink); } } return(null); }
private SourceFileInfo?TryGetOriginalFile(SourceDocument sourceDocument, Encoding encoding, TelemetryMessage telemetry) { if (File.Exists(sourceDocument.FilePath)) { var result = LoadSourceFile(sourceDocument.FilePath, sourceDocument, encoding, FeaturesResources.external, ignoreChecksum: false); if (result is not null) { telemetry.SetSourceFileSource("ondisk"); _logger?.Log(FeaturesResources._0_found_in_original_location, sourceDocument.FilePath); } else { _logger?.Log(FeaturesResources._0_found_in_original_location_but_checksum_failed, sourceDocument.FilePath); } return(result); } return(null); }
private SourceFileInfo?TryGetEmbeddedSourceFile(string tempFilePath, SourceDocument sourceDocument, Encoding encoding, TelemetryMessage telemetry) { if (sourceDocument.EmbeddedTextBytes is null) { return(null); } var filePath = Path.Combine(tempFilePath, Path.GetFileName(sourceDocument.FilePath)); // We might have already navigated to this file before, so it might exist, but // we still need to re-validate the checksum and make sure its not the wrong file if (File.Exists(filePath) && LoadSourceFile(filePath, sourceDocument, encoding, FeaturesResources.embedded, ignoreChecksum: false) is { } existing) { telemetry.SetSourceFileSource("embedded"); _logger?.Log(FeaturesResources._0_found_in_embedded_PDB_cached_source_file, sourceDocument.FilePath); return(existing); } var embeddedTextBytes = sourceDocument.EmbeddedTextBytes; var uncompressedSize = BitConverter.ToInt32(embeddedTextBytes, 0); var stream = new MemoryStream(embeddedTextBytes, sizeof(int), embeddedTextBytes.Length - sizeof(int)); if (uncompressedSize != 0) { var decompressed = new MemoryStream(uncompressedSize); using (var deflater = new DeflateStream(stream, CompressionMode.Decompress)) { deflater.CopyTo(decompressed); } if (decompressed.Length != uncompressedSize) { return(null); } stream = decompressed; } if (stream is not null) { // Even though Roslyn supports loading SourceTexts from a stream, Visual Studio requires // a file to exist on disk so we have to write embedded source to a temp file. using (stream) { try { stream.Position = 0; using (var file = File.OpenWrite(filePath)) { stream.CopyTo(file); } new FileInfo(filePath).IsReadOnly = true; } catch (IOException ex) { _logger?.Log(FeaturesResources._0_found_in_embedded_PDB_but_could_not_write_file_1, sourceDocument.FilePath, ex.Message); return(null); } } var result = LoadSourceFile(filePath, sourceDocument, encoding, FeaturesResources.embedded, ignoreChecksum: false); if (result is not null) { telemetry.SetSourceFileSource("embedded"); _logger?.Log(FeaturesResources._0_found_in_embedded_PDB, sourceDocument.FilePath); } else { _logger?.Log(FeaturesResources._0_found_in_embedded_PDB_but_checksum_failed, sourceDocument.FilePath); } return(result); } return(null); }