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)); }
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)); }
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); }
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)); }