WIP - embed source files into PDB · noahfalk/roslyn@e4e20bf (original) (raw)

8 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -160,7 +160,14 @@ private SyntaxTree ParseFile(
160 160 }
161 161 else
162 162 {
163 -return ParseFile(parseOptions, scriptParseOptions, content, file);
163 +SyntaxTree tree = ParseFile(parseOptions, scriptParseOptions, content, file);
164 +if(Arguments.EmbedSourceInPdb)
165 +{
166 +SyntaxNode root = tree.GetRoot();
167 +root = root.WithAdditionalAnnotations(new SyntaxAnnotation("EmbedSourceInPdb"));
168 +tree = tree.WithRootAndOptions(root, tree.Options);
169 +}
170 +return tree;
164 171 }
165 172 }
166 173
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
58 58 bool concurrentBuild = true;
59 59 bool emitPdb = false;
60 60 string pdbPath = null;
61 +bool embedSourceInPdb = false;
61 62 bool noStdLib = false;
62 63 string outputDirectory = baseDirectory;
63 64 string outputFileName = null;
@@ -971,6 +972,9 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
971 972
972 973 additionalFiles.AddRange(ParseAdditionalFileArgument(value, baseDirectory, diagnostics));
973 974 continue;
975 +case "embedSource":
976 +embedSourceInPdb = true;
977 +continue;
974 978 }
975 979 }
976 980
@@ -1102,6 +1106,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
1102 1106 OutputFileName = outputFileName,
1103 1107 PdbPath = pdbPath,
1104 1108 EmitPdb = emitPdb,
1109 +EmbedSourceInPdb = embedSourceInPdb,
1105 1110 OutputDirectory = outputDirectory,
1106 1111 DocumentationPath = documentationPath,
1107 1112 ErrorLogPath = errorLogPath,
Original file line number Diff line number Diff line change
@@ -2612,9 +2612,20 @@ private static ImmutableArray MakeChecksumBytes(string bytesText)
2612 2612 return builder.ToImmutableAndFree();
2613 2613 }
2614 2614
2615 +private static bool IsSyntaxTreePdbEmbedded(SyntaxTree tree)
2616 +{
2617 +return tree.GetRoot().GetAnnotations().Any(a => a.Kind == "EmbedSourceInPdb");
2618 +}
2619 +
2615 2620 private static Cci.DebugSourceDocument MakeDebugSourceDocumentForTree(string normalizedPath, SyntaxTree tree)
2616 2621 {
2617 -return new Cci.DebugSourceDocument(normalizedPath, Cci.DebugSourceDocument.CorSymLanguageTypeCSharp, () => tree.GetChecksumAndAlgorithm());
2622 +byte[] pdbEmbeddedSourceBytes = null;
2623 +if(IsSyntaxTreePdbEmbedded(tree))
2624 +{
2625 +SourceText text = tree.GetText();
2626 +pdbEmbeddedSourceBytes = text.Encoding.GetBytes(text.ToString());
2627 +}
2628 +return new Cci.DebugSourceDocument(normalizedPath, Cci.DebugSourceDocument.CorSymLanguageTypeCSharp, () => tree.GetChecksumAndAlgorithm(), pdbEmbeddedSourceBytes);
2618 2629 }
2619 2630
2620 2631 private void SetupWin32Resources(PEModuleBuilder moduleBeingBuilt, Stream win32Resources, DiagnosticBag diagnostics)
Original file line number Diff line number Diff line change
@@ -74,6 +74,11 @@ public abstract class CommandLineArguments
74 74 ///
75 75 public bool EmitPdb { get; internal set; }
76 76
77 +///
78 +/// True to embed source files in the PDB.
79 +///
80 +public bool EmbedSourceInPdb { get; internal set; }
81 +
77 82 ///
78 83 /// Absolute path of the output directory.
79 84 ///
Original file line number Diff line number Diff line change
@@ -132,7 +132,8 @@ internal enum PdbWriterOperation : byte
132 132 DefineKickoffMethod,
133 133 OpenMapTokensToSourceSpans,
134 134 MapTokenToSourceSpan,
135 -CloseMapTokensToSourceSpans
135 +CloseMapTokensToSourceSpans,
136 +SetSource
136 137 }
137 138
138 139 public bool LogOperation(PdbWriterOperation op)
@@ -949,6 +950,16 @@ private ISymUnmanagedDocumentWriter GetDocumentWriter(DebugSourceDocument docume
949 950 _callLogger.LogArgument(vendor.ToByteArray());
950 951 _callLogger.LogArgument(type.ToByteArray());
951 952 }
953 +if(document.EmbeddedSource != null)
954 +{
955 +writer.SetSource((uint)document.EmbeddedSource.Length, document.EmbeddedSource);
956 +if (_callLogger.LogOperation(OP.SetSource))
957 +{
958 +//logging length is irrelevant, it has no additional entropy
959 +//for performance it might be better to log ChecksumAndAlgorithm instead?
960 +_callLogger.LogArgument(document.EmbeddedSource);
961 +}
962 +}
952 963 }
953 964 catch (Exception ex)
954 965 {
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ internal sealed class DebugSourceDocument
19 19 private readonly string _location;
20 20 private readonly Guid _language;
21 21 private readonly bool _isComputedChecksum;
22 +private readonly byte[] _embeddedSource;
22 23
23 24 private readonly Task<ValueTuple<ImmutableArray<byte>, Guid>> _checksumAndAlgorithm;
24 25
@@ -33,11 +34,12 @@ public DebugSourceDocument(string location, Guid language)
33 34 ///
34 35 /// Use to create a document when checksum is computed based on actual source stream.
35 36 ///
36 -public DebugSourceDocument(string location, Guid language, Func<ValueTuple<ImmutableArray<byte>, Guid>> checksumAndAlgorithm)
37 +public DebugSourceDocument(string location, Guid language, Func<ValueTuple<ImmutableArray<byte>, Guid>> checksumAndAlgorithm, byte[] embeddedSource = null)
37 38 : this(location, language)
38 39 {
39 40 _checksumAndAlgorithm = Task.Run(checksumAndAlgorithm);
40 41 _isComputedChecksum = true;
42 +_embeddedSource = embeddedSource;
41 43 }
42 44
43 45 ///
@@ -108,6 +110,14 @@ public ValueTuple<ImmutableArray, Guid> ChecksumAndAlgorithm
108 110 }
109 111 }
110 112
113 +public byte[] EmbeddedSource
114 +{
115 +get
116 +{
117 +return _embeddedSource;
118 +}
119 +}
120 +
111 121 ///
112 122 /// returns true when checksum was computed base on an actual source stream
113 123 /// as opposed to be suggested via a checksum directive/pragma
@@ -119,5 +129,7 @@ internal bool IsComputedChecksum
119 129 return _isComputedChecksum;
120 130 }
121 131 }
132 +
133 +
122 134 }
123 135 }
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
1 1 *REMOVED*static Microsoft.CodeAnalysis.SyntaxNodeExtensions.NormalizeWhitespace(this TNode node, string indentation = " ", bool elasticTrivia = false) -> TNode
2 +Microsoft.CodeAnalysis.CommandLineArguments.EmbedSourceInPdb.get -> bool
2 3 Microsoft.CodeAnalysis.CommandLineArguments.ScriptArguments.get -> System.Collections.Immutable.ImmutableArray
3 4 Microsoft.CodeAnalysis.CommandLineParser.IsInteractive.get -> bool
4 5 Microsoft.CodeAnalysis.Compilation.GetSubmissionResultType(out bool hasValue) -> Microsoft.CodeAnalysis.ITypeSymbol