Beispiel #1
0
        private static void AddTargetAssets(IUnitTestGeneratorOptions options, KeyValuePair <Project, Tuple <HashSet <TargetAsset>, HashSet <IReferencedAssembly> > > pair)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            foreach (var targetAsset in pair.Value.Item1)
            {
                var asset = AssetFactory.Create(targetAsset);
                if (asset != null)
                {
                    var targetProjectFileName = pair.Key.FileName;
                    var targetProjectPath     = Path.GetDirectoryName(targetProjectFileName);

                    if (string.IsNullOrWhiteSpace(targetProjectPath))
                    {
                        continue;
                    }

#pragma warning disable VSTHRD010
                    if (!pair.Key.ProjectItems.OfType <ProjectItem>().Any(x => string.Equals(x.Name, asset.AssetFileName, StringComparison.OrdinalIgnoreCase)))
#pragma warning restore VSTHRD010
                    {
                        var nameSpace = VsProjectHelper.GetProjectRootNamespace(pair.Key);
                        var fileName  = Path.Combine(targetProjectPath, asset.AssetFileName);
                        File.WriteAllText(fileName, asset.Content(nameSpace, options.GenerationOptions.FrameworkType));
                        pair.Key.ProjectItems.AddFromFile(fileName);
                    }
                }
            }
        }
        public static IFrameworkSet Create(IUnitTestGeneratorOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var context = new GenerationContext();

            return(new FrameworkSet(Create(options.GenerationOptions.FrameworkType), Create(options.GenerationOptions.MockingFrameworkType, context), context, options.GenerationOptions.TestTypeNaming));
        }
Beispiel #3
0
        private static async Task GenerateItemAsync(bool withRegeneration, IUnitTestGeneratorOptions options, Solution solution, GenerationItem generationItem)
        {
            var targetProject = solution.Projects.FirstOrDefault(x => string.Equals(x.Name, generationItem.Source.SourceProjectName, StringComparison.Ordinal));
            var documents     = solution.GetDocumentIdsWithFilePath(generationItem.Source.FilePath);
            var documentId    = documents.FirstOrDefault(x => x.ProjectId == targetProject?.Id) ?? documents.FirstOrDefault();

            if (documentId == null)
            {
                throw new InvalidOperationException("Could not find document in solution with file path '" + generationItem.Source.FilePath + "'");
            }

            var document = solution.GetDocument(documentId);

            var semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(true);

            var tree = await semanticModel.SyntaxTree.GetRootAsync().ConfigureAwait(true);

            if (!tree.DescendantNodes().OfType <ClassDeclarationSyntax>().Any() && !tree.DescendantNodes().OfType <StructDeclarationSyntax>().Any())
            {
                return;
            }

            var result = await GenerateAsync(withRegeneration, options, solution, generationItem, semanticModel).ConfigureAwait(true);

            generationItem.TargetContent = result.FileContent;

            foreach (var asset in result.RequiredAssets)
            {
                generationItem.RequiredAssets.Add(asset);
            }

            foreach (var reference in result.AssemblyReferences)
            {
                if (!generationItem.AssemblyReferences.Any(x => string.Equals(x.Name, reference.Name, StringComparison.OrdinalIgnoreCase)))
                {
                    generationItem.AssemblyReferences.Add(reference);
                }
            }
        }
        private static GenerationResult Generate(SemanticModel sourceModel, SyntaxNode sourceSymbol, bool withRegeneration, IUnitTestGeneratorOptions options, NamespaceDeclarationSyntax targetNamespace, HashSet <string> usingsEmitted, CompilationUnitSyntax compilation, NamespaceDeclarationSyntax originalTargetNamespace)
        {
            var frameworkSet          = FrameworkSetFactory.Create(options);
            var typeParametersEmitted = new HashSet <string>();
            var model       = new TestableItemExtractor(sourceModel.SyntaxTree, sourceModel);
            var classModels = model.Extract(sourceSymbol).ToList();

            foreach (var c in classModels)
            {
                if (c.Declaration.Parent is NamespaceDeclarationSyntax namespaceDeclaration)
                {
                    targetNamespace = EmitUsingStatements(targetNamespace, usingsEmitted, SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(namespaceDeclaration.Name.ToString())));
                }
            }

            foreach (var classModel in classModels)
            {
                var targetType = GetOrCreateTargetType(sourceSymbol, targetNamespace, frameworkSet, classModel, out var originalTargetType);

                targetNamespace = AddTypeParameterAliases(classModel, typeParametersEmitted, targetNamespace);

                targetType = ApplyStrategies(withRegeneration, targetType, frameworkSet, classModel);

                targetNamespace = AddTypeToTargetNamespace(originalTargetType, targetNamespace, targetType);

                foreach (var parameter in frameworkSet.Context.GenericTypes)
                {
                    targetNamespace = targetNamespace.AddUsings(
                        SyntaxFactory.UsingDirective(SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName(Strings.UnitTestGenerator_AddUsingStatements_System), SyntaxFactory.IdentifierName("String")))
                        .WithAlias(SyntaxFactory.NameEquals(SyntaxFactory.IdentifierName(parameter))));
                }
            }

            targetNamespace = AddUsingStatements(targetNamespace, usingsEmitted, frameworkSet, classModels);

            compilation = AddTargetNamespaceToCompilation(originalTargetNamespace, compilation, targetNamespace);

            var generationResult = CreateGenerationResult(compilation, classModels);

            AddAssembliesToGenerationResult(sourceModel, frameworkSet, generationResult);

            return(generationResult);
        }
        public static async Task <GenerationResult> Generate(SemanticModel sourceModel, SyntaxNode sourceSymbol, SemanticModel targetModel, bool withRegeneration, IUnitTestGeneratorOptions options, Func <string, string> nameSpaceTransform)
        {
            if (nameSpaceTransform == null)
            {
                throw new ArgumentNullException(nameof(nameSpaceTransform));
            }

            var sourceNameSpace = await sourceModel.GetNamespace().ConfigureAwait(true);

            var targetNameSpace = nameSpaceTransform(sourceNameSpace);

            var usingsEmitted = new HashSet <string>();

            NamespaceDeclarationSyntax originalTargetNamespace = null;

            CompilationUnitSyntax      compilation;
            NamespaceDeclarationSyntax targetNamespace;

            if (targetModel != null)
            {
                var targetTree = await targetModel.SyntaxTree.GetRootAsync().ConfigureAwait(true);

                compilation = targetTree.AncestorsAndSelf().OfType <CompilationUnitSyntax>().FirstOrDefault() ?? SyntaxFactory.CompilationUnit();
                foreach (var syntax in targetTree.DescendantNodes().OfType <UsingDirectiveSyntax>())
                {
                    usingsEmitted.Add(syntax.NormalizeWhitespace().ToFullString());
                }

                originalTargetNamespace = targetNamespace = targetTree.DescendantNodesAndSelf().OfType <NamespaceDeclarationSyntax>().FirstOrDefault(x => string.Equals(x.Name.ToString(), targetNameSpace, StringComparison.OrdinalIgnoreCase)) ?? targetTree.DescendantNodesAndSelf().OfType <NamespaceDeclarationSyntax>().FirstOrDefault();
                if (targetNamespace == null)
                {
                    targetNamespace = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName(targetNameSpace));
                }
            }
            else
            {
                compilation     = SyntaxFactory.CompilationUnit();
                targetNamespace = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName(targetNameSpace));
            }

            return(Generate(sourceModel, sourceSymbol, withRegeneration, options, targetNamespace, usingsEmitted, compilation, originalTargetNamespace));
        }
Beispiel #6
0
        private static async Task <GenerationResult> GenerateAsync(bool withRegeneration, IUnitTestGeneratorOptions options, Solution solution, GenerationItem generationItem, SemanticModel semanticModel)
        {
            GenerationResult result;

            if (File.Exists(generationItem.TargetFileName))
            {
                var documentIds = solution.GetDocumentIdsWithFilePath(generationItem.TargetFileName);
                if (documentIds.FirstOrDefault() is DocumentId targetDocumentId)
                {
                    var targetDocument = solution.GetDocument(targetDocumentId);

                    var targetSemanticModel = await targetDocument.GetSemanticModelAsync().ConfigureAwait(true);

                    result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, targetSemanticModel, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true);
                }
                else
                {
                    result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, null, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true);
                }
            }
            else
            {
                result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, null, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true);
            }

            return(result);
        }
Beispiel #7
0
        private static void AddTargetItem(IReadOnlyCollection <GenerationItem> generationItems, IUnitTestGeneratorOptions options, GenerationItem generationItem)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (TargetFinder.FindExistingTargetItem(generationItem.Source, options.GenerationOptions, out var targetItem) != FindTargetStatus.Found)
            {
                File.WriteAllText(generationItem.TargetFileName, generationItem.TargetContent);
                targetItem = generationItem.TargetProjectItems.AddFromFile(generationItem.TargetFileName);
            }
            else
            {
                if (targetItem.Document is null)
                {
                    File.WriteAllText(generationItem.TargetFileName, generationItem.TargetContent);
                }
                else
                {
                    var textSelection = (TextSelection)targetItem.Document.Selection;
                    textSelection.SelectAll();
                    textSelection.Insert(generationItem.TargetContent);
                    targetItem.Document.Save();
                }
            }

            if (generationItems.Count == 1)
            {
                VsProjectHelper.ActivateItem(targetItem);
            }
        }
        public static IList <INugetPackageReference> GetReferencedNugetPackages(IUnitTestGeneratorOptions options)
        {
            var set = FrameworkSetFactory.Create(options);

            return(set.TestFramework.ReferencedNugetPackages(options.VersioningOptions).Concat(set.MockingFramework.ReferencedNugetPackages(options.VersioningOptions)).ToList());
        }
        public static async Task AssertTestGeneration(string resourceName, TestFrameworkTypes testFrameworkTypes, MockingFrameworkType mockingFrameworkType)
        {
            var classAsText = TestClasses.ResourceManager.GetString(resourceName, TestClasses.Culture);

            var tree = CSharpSyntaxTree.ParseText(classAsText, new CSharpParseOptions(LanguageVersion.Latest));

            var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
            var references   = new List <MetadataReference>
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(INotifyPropertyChanged).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Expression).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Brush).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Stream).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Form).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(SqlConnection).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Window).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(UIElement).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(DependencyObject).Assembly.Location),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Core.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Threading.Tasks.dll")),
            };

            references.AddRange(GetReferences(mockingFrameworkType));
            references.AddRange(GetReferences(testFrameworkTypes));

            var compilation = CSharpCompilation.Create(
                "MyTest",
                syntaxTrees: new[] { tree },
                references: references);

            var semanticModel = compilation.GetSemanticModel(tree);

            IUnitTestGeneratorOptions options = Substitute.For <IUnitTestGeneratorOptions>();

            options.GenerationOptions.FrameworkType.Returns(testFrameworkTypes);
            options.GenerationOptions.MockingFrameworkType.Returns(mockingFrameworkType);
            options.GenerationOptions.TestFileNaming.Returns("{0}Tests");
            options.GenerationOptions.TestTypeNaming.Returns("{0}Tests");
            options.GenerationOptions.TestProjectNaming.Returns("{0}.Tests");
            var core = await CoreGenerator.Generate(semanticModel, null, null, false, options, x => "Tests").ConfigureAwait(true);

            Assert.IsNotNull(core);
            Console.WriteLine(core.FileContent);
            Assert.IsNotNull(core.FileContent);

            var generatedTree = CSharpSyntaxTree.ParseText(core.FileContent, new CSharpParseOptions(LanguageVersion.Latest));

            var syntaxTrees = new List <SyntaxTree> {
                tree, generatedTree
            };

            if (core.RequiredAssets.Any(x => x == TargetAsset.PropertyTester))
            {
                var testerAsset    = AssetFactory.Create(TargetAsset.PropertyTester);
                var propertyTester = testerAsset.Content("Tests", testFrameworkTypes);
                syntaxTrees.Add(CSharpSyntaxTree.ParseText(propertyTester, new CSharpParseOptions(LanguageVersion.Latest)));
            }

            var validateCompilation = CSharpCompilation.Create(
                "MyTest",
                syntaxTrees: syntaxTrees,
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            var stream       = new MemoryStream();
            var result       = validateCompilation.Emit(stream);
            var streamLength = stream.Length;

            stream.Dispose();

            Assert.IsTrue(result.Success, string.Join(",", result.Diagnostics.Select(x => x.Location.GetLineSpan().StartLinePosition.Line + ": " + x.GetMessage())));
            Assert.That(streamLength, Is.GreaterThan(0));
        }