@@ -31,7 +31,8 @@ private static void VerifyCompilationOptions(
31
31
Compilation compilation ,
32
32
EmitOptions emitOptions ,
33
33
BlobReader compilationOptionsBlobReader ,
34
- string langVersion )
34
+ string langVersion ,
35
+ int sourceFileCount )
35
36
{
36
37
var pdbOptions = DeterministicBuildCompilationTestHelpers . ParseCompilationOptions ( compilationOptionsBlobReader ) ;
37
38
@@ -43,12 +44,19 @@ private static void VerifyCompilationOptions(
43
44
pdbOptions . VerifyPdbOption ( "unsafe" , originalOptions . AllowUnsafe ) ;
44
45
45
46
Assert . Equal ( langVersion , pdbOptions [ "language-version" ] ) ;
47
+ Assert . Equal ( sourceFileCount . ToString ( ) , pdbOptions [ "source-file-count" ] ) ;
46
48
47
49
var firstSyntaxTree = ( CSharpSyntaxTree ) compilation . SyntaxTrees . FirstOrDefault ( ) ;
48
50
pdbOptions . VerifyPdbOption ( "define" , firstSyntaxTree . Options . PreprocessorSymbolNames , isDefault : v => v . IsEmpty ( ) , toString : v => string . Join ( "," , v ) ) ;
49
51
}
50
52
51
- private static void TestDeterministicCompilationCSharp ( string langVersion , SyntaxTree [ ] syntaxTrees , CSharpCompilationOptions compilationOptions , EmitOptions emitOptions , params TestMetadataReferenceInfo [ ] metadataReferences )
53
+ private static void TestDeterministicCompilationCSharp (
54
+ string langVersion ,
55
+ SyntaxTree [ ] syntaxTrees ,
56
+ CSharpCompilationOptions compilationOptions ,
57
+ EmitOptions emitOptions ,
58
+ TestMetadataReferenceInfo [ ] metadataReferences ,
59
+ int ? debugDocumentsCount = null )
52
60
{
53
61
var originalCompilation = CreateCompilation (
54
62
syntaxTrees ,
@@ -74,11 +82,12 @@ private static void TestDeterministicCompilationCSharp(string langVersion, Synta
74
82
using ( var embeddedPdb = peReader . ReadEmbeddedPortablePdbDebugDirectoryData ( embedded ) )
75
83
{
76
84
var pdbReader = embeddedPdb . GetMetadataReader ( ) ;
77
-
78
85
var metadataReferenceReader = DeterministicBuildCompilationTestHelpers . GetSingleBlob ( PortableCustomDebugInfoKinds . CompilationMetadataReferences , pdbReader ) ;
79
86
var compilationOptionsReader = DeterministicBuildCompilationTestHelpers . GetSingleBlob ( PortableCustomDebugInfoKinds . CompilationOptions , pdbReader ) ;
80
87
81
- VerifyCompilationOptions ( compilationOptions , originalCompilation , emitOptions , compilationOptionsReader , langVersion ) ;
88
+ Assert . Equal ( debugDocumentsCount ?? syntaxTrees . Length , pdbReader . Documents . Count ) ;
89
+
90
+ VerifyCompilationOptions ( compilationOptions , originalCompilation , emitOptions , compilationOptionsReader , langVersion , syntaxTrees . Length ) ;
82
91
DeterministicBuildCompilationTestHelpers . VerifyReferenceInfo ( metadataReferences , metadataReferenceReader ) ;
83
92
}
84
93
}
@@ -98,17 +107,77 @@ public static void Main()
98
107
Console.WriteLine();
99
108
}
100
109
}
101
- " , options : parseOptions , encoding : Encoding . UTF8 ) ;
110
+ " , filename : "a.cs" , options : parseOptions , encoding : Encoding . UTF8 ) ;
111
+
112
+ var sourceTwo = Parse ( @"
113
+ class TypeTwo
114
+ {
115
+ }" , filename : "b.cs" , options : parseOptions , encoding : new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
116
+
117
+ var sourceThree = Parse ( @"
118
+ class TypeThree
119
+ {
120
+ }" , filename : "c.cs" , options : parseOptions , encoding : Encoding . Unicode ) ;
121
+
122
+ var referenceOneCompilation = CreateCompilation (
123
+ @"public struct StructWithReference
124
+ {
125
+ string PrivateData;
126
+ }
127
+ public struct StructWithValue
128
+ {
129
+ int PrivateData;
130
+ }" , options : TestOptions . DebugDll ) ;
131
+
132
+ var referenceTwoCompilation = CreateCompilation (
133
+ @"public class ReferenceTwo
134
+ {
135
+ }" , options : TestOptions . DebugDll ) ;
136
+
137
+ using var referenceOne = TestMetadataReferenceInfo . Create (
138
+ referenceOneCompilation ,
139
+ fullPath : "abcd.dll" ,
140
+ emitOptions : emitOptions ) ;
141
+
142
+ using var referenceTwo = TestMetadataReferenceInfo . Create (
143
+ referenceTwoCompilation ,
144
+ fullPath : "efgh.dll" ,
145
+ emitOptions : emitOptions ) ;
146
+
147
+ var testSource = new [ ] { sourceOne , sourceTwo , sourceThree } ;
148
+ TestDeterministicCompilationCSharp (
149
+ parseOptions . LanguageVersion . MapSpecifiedToEffectiveVersion ( ) . ToDisplayString ( ) ,
150
+ testSource ,
151
+ compilationOptions ,
152
+ emitOptions ,
153
+ new [ ] { referenceOne , referenceTwo } ) ;
154
+ }
155
+
156
+ [ Theory ]
157
+ [ ClassData ( typeof ( CSharpDeterministicBuildCompilationTests ) ) ]
158
+ public void PortablePdb_DeterministicCompilation_DuplicateFilePaths ( CSharpCompilationOptions compilationOptions , EmitOptions emitOptions , CSharpParseOptions parseOptions )
159
+ {
160
+ var sourceOne = Parse ( @"
161
+ using System;
162
+
163
+ class MainType
164
+ {
165
+ public static void Main()
166
+ {
167
+ Console.WriteLine();
168
+ }
169
+ }
170
+ " , filename : "a.cs" , options : parseOptions , encoding : Encoding . UTF8 ) ;
102
171
103
172
var sourceTwo = Parse ( @"
104
173
class TypeTwo
105
174
{
106
- }" , options : parseOptions , encoding : new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
175
+ }" , filename : "b.cs" , options : parseOptions , encoding : new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
107
176
108
177
var sourceThree = Parse ( @"
109
178
class TypeThree
110
179
{
111
- }" , options : parseOptions , encoding : Encoding . Unicode ) ;
180
+ }" , filename : "a.cs" , options : parseOptions , encoding : Encoding . Unicode ) ;
112
181
113
182
var referenceOneCompilation = CreateCompilation (
114
183
@"public struct StructWithReference
@@ -136,7 +205,16 @@ public struct StructWithValue
136
205
emitOptions : emitOptions ) ;
137
206
138
207
var testSource = new [ ] { sourceOne , sourceTwo , sourceThree } ;
139
- TestDeterministicCompilationCSharp ( parseOptions . LanguageVersion . MapSpecifiedToEffectiveVersion ( ) . ToDisplayString ( ) , testSource , compilationOptions , emitOptions , referenceOne , referenceTwo ) ;
208
+
209
+ // Note that only one debug document can be present for each distinct source path.
210
+ // So if more than one syntax tree has the same file path, it won't be possible to do a rebuild from the DLL+PDB.
211
+ TestDeterministicCompilationCSharp (
212
+ parseOptions . LanguageVersion . MapSpecifiedToEffectiveVersion ( ) . ToDisplayString ( ) ,
213
+ testSource ,
214
+ compilationOptions ,
215
+ emitOptions ,
216
+ new [ ] { referenceOne , referenceTwo } ,
217
+ debugDocumentsCount : 2 ) ;
140
218
}
141
219
142
220
[ ConditionalTheory ( typeof ( DesktopOnly ) ) ]
@@ -153,17 +231,17 @@ public static void Main()
153
231
Console.WriteLine();
154
232
}
155
233
}
156
- " , options : parseOptions , encoding : Encoding . UTF8 ) ;
234
+ " , filename : "a.cs" , options : parseOptions , encoding : Encoding . UTF8 ) ;
157
235
158
236
var sourceTwo = Parse ( @"
159
237
class TypeTwo
160
238
{
161
- }" , options : parseOptions , encoding : new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
239
+ }" , filename : "b.cs" , options : parseOptions , encoding : new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
162
240
163
241
var sourceThree = Parse ( @"
164
242
class TypeThree
165
243
{
166
- }" , options : parseOptions , encoding : Encoding . GetEncoding ( 932 ) ) ; // SJIS encoding
244
+ }" , filename : "c.cs" , options : parseOptions , encoding : Encoding . GetEncoding ( 932 ) ) ; // SJIS encoding
167
245
168
246
var referenceOneCompilation = CreateCompilation (
169
247
@"public struct StructWithReference
@@ -191,7 +269,12 @@ public struct StructWithValue
191
269
emitOptions : emitOptions ) ;
192
270
193
271
var testSource = new [ ] { sourceOne , sourceTwo , sourceThree } ;
194
- TestDeterministicCompilationCSharp ( parseOptions . LanguageVersion . MapSpecifiedToEffectiveVersion ( ) . ToDisplayString ( ) , testSource , compilationOptions , emitOptions , referenceOne , referenceTwo ) ;
272
+ TestDeterministicCompilationCSharp (
273
+ parseOptions . LanguageVersion . MapSpecifiedToEffectiveVersion ( ) . ToDisplayString ( ) ,
274
+ testSource ,
275
+ compilationOptions ,
276
+ emitOptions ,
277
+ new [ ] { referenceOne , referenceTwo } ) ;
195
278
}
196
279
197
280
public IEnumerator < object [ ] > GetEnumerator ( ) => GetTestParameters ( ) . GetEnumerator ( ) ;
0 commit comments