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);
            }
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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();
        }
Beispiel #5
0
        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);
                }
            }
        }