|
9 | 9 | using System.Text;
|
10 | 10 | using System.Threading;
|
11 | 11 | using System.Threading.Tasks;
|
12 |
| - using CodeGeneration.Roslyn.Engine; |
13 |
| - using global::CodeGeneration.Roslyn; |
14 | 12 | using ImmutableObjectGraph.Generation.Roslyn;
|
15 | 13 | using Microsoft.CodeAnalysis;
|
16 | 14 | using Microsoft.CodeAnalysis.CSharp;
|
@@ -38,7 +36,6 @@ public CodeGenTests(ITestOutputHelper logger)
|
38 | 36 | .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
|
39 | 37 | .AddMetadataReferences(GetNetStandard20References())
|
40 | 38 | .AddMetadataReference(MetadataReference.CreateFromFile(typeof(GenerateImmutableAttribute).Assembly.Location))
|
41 |
| - .AddMetadataReference(MetadataReference.CreateFromFile(typeof(CodeGenerationAttributeAttribute).Assembly.Location)) |
42 | 39 | .AddMetadataReference(MetadataReference.CreateFromFile(typeof(Optional).Assembly.Location))
|
43 | 40 | .AddMetadataReference(MetadataReference.CreateFromFile(typeof(ImmutableArray).Assembly.Location));
|
44 | 41 | var inputDocument = project.AddDocument("input.cs", string.Empty);
|
@@ -265,40 +262,51 @@ protected async Task<GenerationResult> GenerateAsync(SourceText inputSource)
|
265 | 262 | {
|
266 | 263 | var solution = this.solution.WithDocumentText(this.inputDocumentId, inputSource);
|
267 | 264 | var inputDocument = solution.GetDocument(this.inputDocumentId);
|
268 |
| - var generatorDiagnostics = new List<Diagnostic>(); |
269 |
| - var progress = new SynchronousProgress<Diagnostic>(generatorDiagnostics.Add); |
270 | 265 | var inputCompilation = (CSharpCompilation)await inputDocument.Project.GetCompilationAsync();
|
271 | 266 | var inputSyntaxTree = await inputDocument.GetSyntaxTreeAsync();
|
272 |
| - var outputSyntaxTree = await DocumentTransform.TransformAsync(inputCompilation, inputSyntaxTree, null, Assembly.Load, progress); |
273 |
| - var outputDocument = inputDocument.Project |
274 |
| - .AddDocument("output.cs", outputSyntaxTree.GetRoot()); |
275 |
| - |
276 |
| - // Make sure the result compiles without errors or warnings. |
277 |
| - var compilation = await outputDocument.Project.GetCompilationAsync(); |
278 |
| - var compilationDiagnostics = compilation.GetDiagnostics(); |
| 267 | + var driver = CSharpGeneratorDriver.Create(new CodeGenerator()); |
| 268 | + var runResult = driver.RunGenerators(inputCompilation).GetRunResult(); |
| 269 | + var outputSyntaxTree = runResult.GeneratedTrees[0]; |
| 270 | + var generatorDiagnostics = runResult.Diagnostics; |
| 271 | + var project = inputDocument.Project; |
| 272 | + |
| 273 | + var i = 0; |
| 274 | + var syntaxTrees = ImmutableArray.CreateBuilder<SyntaxTree>(); |
| 275 | + foreach (var t in runResult.GeneratedTrees) |
| 276 | + { |
| 277 | + var document = project.AddDocument($"output{i++}.cs", t.GetRoot()); |
279 | 278 |
|
280 |
| - SourceText outputDocumentText = await outputDocument.GetTextAsync(); |
281 |
| - this.logger.WriteLine("{0}", outputDocumentText); |
| 279 | + SourceText outputDocumentText = await document.GetTextAsync(); |
| 280 | + this.logger.WriteLine("{0}", outputDocumentText); |
282 | 281 |
|
283 |
| - // Verify all line endings are consistent (otherwise VS can bug the heck out of the user if they have the generated file open). |
284 |
| - string firstLineEnding = null; |
285 |
| - foreach (var line in outputDocumentText.Lines) |
286 |
| - { |
287 |
| - string actualNewLine = line.Text.GetSubText(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)).ToString(); |
288 |
| - if (firstLineEnding == null) |
289 |
| - { |
290 |
| - firstLineEnding = actualNewLine; |
291 |
| - } |
292 |
| - else if (actualNewLine != firstLineEnding && actualNewLine.Length > 0) |
| 282 | + // Verify all line endings are consistent (otherwise VS can bug the heck out of the user if they have the generated file open). |
| 283 | + string firstLineEnding = null; |
| 284 | + foreach (var line in outputDocumentText.Lines) |
293 | 285 | {
|
294 |
| - string expected = EscapeLineEndingCharacters(firstLineEnding); |
295 |
| - string actual = EscapeLineEndingCharacters(actualNewLine); |
296 |
| - Assert.True(false, $"Expected line ending characters '{expected}' but found '{actual}' on line {line.LineNumber + 1}.\nContent: {line}"); |
| 286 | + string actualNewLine = line.Text.GetSubText(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)).ToString(); |
| 287 | + if (firstLineEnding == null) |
| 288 | + { |
| 289 | + firstLineEnding = actualNewLine; |
| 290 | + } |
| 291 | + else if (actualNewLine != firstLineEnding && actualNewLine.Length > 0) |
| 292 | + { |
| 293 | + string expected = EscapeLineEndingCharacters(firstLineEnding); |
| 294 | + string actual = EscapeLineEndingCharacters(actualNewLine); |
| 295 | + Assert.True(false, $"Expected line ending characters '{expected}' but found '{actual}' on line {line.LineNumber + 1}.\nContent: {line}"); |
| 296 | + } |
297 | 297 | }
|
| 298 | + |
| 299 | + var syntaxTree = await document.GetSyntaxTreeAsync(); |
| 300 | + syntaxTrees.Add(syntaxTree); |
| 301 | + |
| 302 | + project = document.Project; |
298 | 303 | }
|
299 | 304 |
|
300 |
| - var semanticModel = await outputDocument.GetSemanticModelAsync(); |
301 |
| - var result = new GenerationResult(outputDocument, semanticModel, generatorDiagnostics, compilationDiagnostics); |
| 305 | + // Make sure the result compiles without errors or warnings. |
| 306 | + var compilation = await project.GetCompilationAsync(); |
| 307 | + var compilationDiagnostics = compilation.GetDiagnostics(); |
| 308 | + |
| 309 | + var result = new GenerationResult(compilation, syntaxTrees.ToImmutable(), generatorDiagnostics, compilationDiagnostics); |
302 | 310 |
|
303 | 311 | foreach (var diagnostic in generatorDiagnostics)
|
304 | 312 | {
|
@@ -338,32 +346,39 @@ private static string EscapeLineEndingCharacters(string whitespace)
|
338 | 346 |
|
339 | 347 | private static IEnumerable<MetadataReference> GetNetStandard20References()
|
340 | 348 | {
|
341 |
| - string nugetPackageRoot = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\.nuget\packages"); |
342 |
| - string netstandardRoot = Path.Combine(nugetPackageRoot, @"netstandard.library\2.0.3\build\netstandard2.0\ref"); |
343 |
| - foreach (string assembly in Directory.GetFiles(netstandardRoot, "*.dll")) |
| 349 | + var nugetPackageRoot = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\.nuget\packages"); |
| 350 | + foreach (var dir in Directory.GetDirectories(Path.Combine(nugetPackageRoot, "netstandard.library"), "2.*")) |
344 | 351 | {
|
345 |
| - yield return MetadataReference.CreateFromFile(assembly); |
| 352 | + var netstandardRoot = Path.Combine(dir, @"build\netstandard2.0\ref"); |
| 353 | + foreach (string assembly in Directory.GetFiles(netstandardRoot, "*.dll")) |
| 354 | + { |
| 355 | + yield return MetadataReference.CreateFromFile(assembly); |
| 356 | + } |
| 357 | + break; |
346 | 358 | }
|
347 | 359 | }
|
348 | 360 |
|
349 | 361 | protected class GenerationResult
|
350 | 362 | {
|
351 | 363 | public GenerationResult(
|
352 |
| - Document document, |
353 |
| - SemanticModel semanticModel, |
| 364 | + Compilation compilation, |
| 365 | + ImmutableArray<SyntaxTree> syntaxTrees, |
354 | 366 | IReadOnlyList<Diagnostic> generatorDiagnostics,
|
355 | 367 | IReadOnlyList<Diagnostic> compilationDiagnostics)
|
356 | 368 | {
|
357 |
| - this.Document = document; |
358 |
| - this.SemanticModel = semanticModel; |
359 |
| - this.Declarations = CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None); |
| 369 | + this.Compilation = compilation; |
| 370 | + this.SyntaxTrees = syntaxTrees; |
| 371 | + this.SemanticModels = syntaxTrees.Select(s => compilation.GetSemanticModel(s)).ToImmutableArray(); |
| 372 | + this.Declarations = SemanticModels.SelectMany(semanticModel => CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None)).ToImmutableArray(); |
360 | 373 | this.GeneratorDiagnostics = generatorDiagnostics;
|
361 | 374 | this.CompilationDiagnostics = compilationDiagnostics;
|
362 | 375 | }
|
363 | 376 |
|
364 |
| - public Document Document { get; private set; } |
| 377 | + public Compilation Compilation { get; } |
| 378 | + |
| 379 | + public ImmutableArray<SemanticModel> SemanticModels { get; private set; } |
365 | 380 |
|
366 |
| - public SemanticModel SemanticModel { get; private set; } |
| 381 | + public ImmutableArray<SyntaxTree> SyntaxTrees { get; } |
367 | 382 |
|
368 | 383 | internal ImmutableArray<DeclarationInfo> Declarations { get; private set; }
|
369 | 384 |
|
|
0 commit comments