public async Task TestCodeGeneration(string resourceBaseName, Language language) { var inputResourceName = "BrightstarDB.CodeGeneration.Tests.GeneratorTestsResources." + resourceBaseName + "Input_" + language.ToString() + ".txt"; var outputResourceName = "BrightstarDB.CodeGeneration.Tests.GeneratorTestsResources." + resourceBaseName + "Output_" + language.ToString() + ".txt"; using (var inputStream = this.GetType().Assembly.GetManifestResourceStream(inputResourceName)) using (var outputStream = this.GetType().Assembly.GetManifestResourceStream(outputResourceName)) using (var outputStreamReader = new StreamReader(outputStream)) { var workspace = new AdhocWorkspace(); var projectId = ProjectId.CreateNewId(); var versionStamp = VersionStamp.Create(); var projectInfo = ProjectInfo.Create( projectId, versionStamp, "AdhocProject", "AdhocProject", language.ToSyntaxGeneratorLanguageName(), metadataReferences: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Uri).Assembly.Location), MetadataReference.CreateFromFile(typeof(BrightstarException).Assembly.Location) }); var project = workspace.AddProject(projectInfo); workspace.AddDocument(projectId, "Source.cs", SourceText.From(inputStream)); var solution = workspace.CurrentSolution; var results = await Generator .GenerateAsync( language, solution, "BrightstarDB.CodeGeneration.Tests", interfacePredicate: x => true); var result = results .Aggregate( new StringBuilder(), (current, next) => current.AppendLine(next.ToString()), x => x.ToString()); var expectedCode = outputStreamReader.ReadToEnd(); // make sure version changes don't break the tests expectedCode = expectedCode.Replace("$VERSION$", typeof(BrightstarException).Assembly.GetName().Version.ToString()); //// useful when converting generated code to something that can be pasted into an expectation file //var sanitisedResult = result.Replace("1.10.0.0", "$VERSION$"); //System.Diagnostics.Debug.WriteLine(sanitisedResult); Assert.AreEqual(expectedCode, result); } }
// TODO: VB is totally borked - calls to syntaxGenerator.WithStatements don't seem to add the statements! Will need to look into this at a later date //[InlineData("SimpleInterface", Language.VisualBasic)] //[InlineData("InterfaceWithGenericMethods", Language.VisualBasic)] //[InlineData("GenericInterface", Language.VisualBasic)] //[InlineData("InterfaceWithNonMockableMembers", Language.VisualBasic)] //[InlineData("PartialInterface", Language.VisualBasic)] //[InlineData("InheritingInterface", Language.VisualBasic)] public async Task can_generate_simple_mock(string resourceBaseName, Language language) { var inputResourceName = "PCLMock.UnitTests.CodeGeneration.GeneratorFixtureResources." + resourceBaseName + "Input_" + language.ToString() + ".txt"; var outputResourceName = "PCLMock.UnitTests.CodeGeneration.GeneratorFixtureResources." + resourceBaseName + "Output_" + language.ToString() + ".txt"; using (var inputStream = this.GetType().Assembly.GetManifestResourceStream(inputResourceName)) using (var outputStream = this.GetType().Assembly.GetManifestResourceStream(outputResourceName)) using (var outputStreamReader = new StreamReader(outputStream)) { var workspace = new AdhocWorkspace(); var projectId = ProjectId.CreateNewId(); var versionStamp = VersionStamp.Create(); var projectInfo = ProjectInfo.Create( projectId, versionStamp, "AdhocProject", "AdhocProject", language.ToSyntaxGeneratorLanguageName(), metadataReferences: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Uri).Assembly.Location), MetadataReference.CreateFromFile(typeof(MockBase<>).Assembly.Location) }); var project = workspace.AddProject(projectInfo); workspace.AddDocument(projectId, "Source.cs", SourceText.From(inputStream)); var solution = workspace.CurrentSolution; var results = (await Generator.GenerateMocksAsync( language, solution, x => true, x => "The.Namespace", x => "Mock")); var result = results .Single() .ToString(); var expectedCode = outputStreamReader.ReadToEnd(); // make sure version changes don't break the tests expectedCode = expectedCode.Replace("$VERSION$", typeof(MockBase<>).Assembly.GetName().Version.ToString()); // useful when converting generated code to something that can be pasted into an expectation file var sanitisedResult = result.Replace(typeof(MockBase<>).Assembly.GetName().Version.ToString(), "$VERSION$"); Assert.Equal(expectedCode, result); } }
public async static Task<IImmutableList<SyntaxNode>> GenerateMocksAsync( Language language, Solution solution, Func<INamedTypeSymbol, bool> interfacePredicate, Func<INamedTypeSymbol, string> mockNamespaceSelector, Func<INamedTypeSymbol, string> mockNameSelector) { var syntaxGenerator = SyntaxGenerator.GetGenerator(solution.Workspace, language.ToSyntaxGeneratorLanguageName()); var compilations = await Task.WhenAll( solution .Projects .Select(async x => { var compilation = await x.GetCompilationAsync(); // make sure the compilation has a reference to PCLMock return compilation.AddReferences(MetadataReference.CreateFromFile(typeof(MockBase<>).Assembly.Location)); })); return compilations .SelectMany(x => x .SyntaxTrees .Select(y => new { Compilation = x, SyntaxTree = y, SemanticModel = x.GetSemanticModel(y) })) .SelectMany( x => x .SyntaxTree .GetRoot() .DescendantNodes() .Where(y => y is InterfaceDeclarationSyntax || y is VB.InterfaceBlockSyntax) .Select(y => new { Compilation = x.Compilation, SyntaxTree = x.SyntaxTree, SemanticModel = x.SemanticModel, InterfaceSymbol = (INamedTypeSymbol)x.SemanticModel.GetDeclaredSymbol(y) })) .Where(x => interfacePredicate == null || interfacePredicate(x.InterfaceSymbol)) .Distinct() .Select(x => GenerateMock(language, syntaxGenerator, x.SemanticModel, x.InterfaceSymbol, mockNamespaceSelector(x.InterfaceSymbol), mockNameSelector(x.InterfaceSymbol))) .Select((x, i) => i == 0 ? syntaxGenerator.WithLeadingComments(x, headerComment, language) : x) .ToImmutableList(); }
private static SyntaxNode GenerateEntity( Language language, Solution solution, Compilation compilation, IImmutableList<INamedTypeSymbol> interfaceSymbols, Func<INamedTypeSymbol, string> entityNamespaceSelector, Func<INamedTypeSymbol, string> entityNameSelector, Func<INamedTypeSymbol, Accessibility> entityAccessibilitySelector, INamedTypeSymbol interfaceSymbol) { var syntaxGenerator = SyntaxGenerator.GetGenerator(solution.Workspace, language.ToSyntaxGeneratorLanguageName()); var generator = new EntityGenerator( language, syntaxGenerator, solution, compilation, interfaceSymbols, entityNamespaceSelector, entityNameSelector, entityAccessibilitySelector, interfaceSymbol); return generator .Generate() .NormalizeWhitespace(); }
private static SyntaxNode GenerateContext( Language language, Solution solution, string @namespace, string name, IImmutableList<INamedTypeSymbol> interfaceSymbols, Func<INamedTypeSymbol, string> entityNamespaceSelector, Func<INamedTypeSymbol, string> entityNameSelector) { Compilation compilation; var brightstarAssemblyPath = GetBrightstarAssemblyLocation(solution); var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(brightstarAssemblyPath) }; // we create our own compilation with which to generate the entity context switch (language) { case Language.CSharp: compilation = CSharpCompilation.Create("Ignore", references: references); break; case Language.VisualBasic: compilation = VB.VisualBasicCompilation.Create("Ignore", references: references); break; default: throw new NotSupportedException(); } var syntaxGenerator = SyntaxGenerator.GetGenerator(solution.Workspace, language.ToSyntaxGeneratorLanguageName()); var generator = new EntityContextGenerator( language, syntaxGenerator, solution, compilation, @namespace, name, interfaceSymbols, entityNamespaceSelector, entityNameSelector); var context = generator .Generate(); context = syntaxGenerator.WithLeadingComments(context, headerComment, language); return context .NormalizeWhitespace(); }
public async Task TestErrorConditions(string resourceBaseName, Language language, string expectedErrorMessage) { var inputResourceName = "BrightstarDB.CodeGeneration.Tests.GeneratorTestsResources." + resourceBaseName + "Input_" + language.ToString() + ".txt"; using (var inputStream = this.GetType().Assembly.GetManifestResourceStream(inputResourceName)) { var workspace = new AdhocWorkspace(); var projectId = ProjectId.CreateNewId(); var versionStamp = VersionStamp.Create(); var projectInfo = ProjectInfo.Create( projectId, versionStamp, "AdhocProject", "AdhocProject", language.ToSyntaxGeneratorLanguageName(), metadataReferences: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Uri).Assembly.Location), MetadataReference.CreateFromFile(typeof(BrightstarException).Assembly.Location) }); var project = workspace.AddProject(projectInfo); workspace.AddDocument(projectId, "Source.cs", SourceText.From(inputStream)); var solution = workspace.CurrentSolution; try { var results = await Generator .GenerateAsync( language, solution, "BrightstarDB.CodeGeneration.Tests", interfacePredicate: x => true); Assert.Fail("No exception was thrown during code generation."); } catch (Exception ex) { Assert.AreEqual(expectedErrorMessage, ex.Message); } } }