private void ChangeTestMethodAttributesToFact(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List<AttributeSyntax> nodesToReplace = new List<AttributeSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType<AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestMethodAttribute")) { nodesToReplace.Add(attributeSyntax); } } } transformationTracker.AddTransformation(nodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { return transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { return ((AttributeSyntax)rewrittenNode).WithName(SyntaxFactory.ParseName("Fact")).NormalizeWhitespace(); }); }); }
private void RemoveTestClassAttributes(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { RemoveTestAttributes(root, semanticModel, transformationTracker, "TestClassAttribute"); }
private void RemoveTestAttributes(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker, string attributeName) { List<AttributeSyntax> nodesToRemove = new List<AttributeSyntax>(); foreach (var attributeListSyntax in root.DescendantNodes().OfType<AttributeListSyntax>()) { var attributesToRemove = attributeListSyntax.Attributes.Where(attributeSyntax => { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, attributeName)) { return true; } } return false; }).ToList(); nodesToRemove.AddRange(attributesToRemove); } transformationTracker.AddTransformation(nodesToRemove, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax rewrittenNode in rewrittenNodes) { var attributeListSyntax = (AttributeListSyntax)rewrittenNode.Parent; var newSyntaxList = attributeListSyntax.Attributes.Remove(rewrittenNode); if (newSyntaxList.Any()) { transformationRoot = transformationRoot.ReplaceNode(attributeListSyntax, attributeListSyntax.WithAttributes(newSyntaxList)); } else { transformationRoot = transformationRoot.RemoveNode(attributeListSyntax, SyntaxRemoveOptions.KeepLeadingTrivia); } } return transformationRoot; }); }
protected override async Task <Solution> ProcessAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var root = syntaxNode as CompilationUnitSyntax; if (root == null) { return(document.Project.Solution); } if (!LoadMSTestNamespaces()) { return(document.Project.Solution); } var originalRoot = root; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); List <UsingDirectiveSyntax> newUsings = new List <UsingDirectiveSyntax>(); bool needsChanges = false; foreach (var usingSyntax in root.Usings) { var symbolInfo = semanticModel.GetSymbolInfo(usingSyntax.Name); if (symbolInfo.Symbol != null) { string namespaceDocID = symbolInfo.Symbol.GetDocumentationCommentId(); if (s_mstestNamespaces.Contains(namespaceDocID)) { needsChanges = true; } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } if (!needsChanges) { return(document.Project.Solution); } TransformationTracker transformationTracker = new TransformationTracker(); RemoveTestClassAttributes(root, semanticModel, transformationTracker); RemoveContractsRequiredAttributes(root, semanticModel, transformationTracker); ChangeTestInitializeToCtor(root, semanticModel, transformationTracker); ChangeTestCleanupToIDisposable(root, semanticModel, transformationTracker); ChangeTestMethodAttributesToFact(root, semanticModel, transformationTracker); ChangeAssertCalls(root, semanticModel, transformationTracker); root = transformationTracker.TransformRoot(root); // Remove compiler directives before the first member of the file (e.g. an #endif after the using statements) var firstMember = root.Members.FirstOrDefault(); if (firstMember != null) { if (firstMember.HasLeadingTrivia) { var newLeadingTrivia = RemoveCompilerDirectives(firstMember.GetLeadingTrivia()); root = root.ReplaceNode(firstMember, firstMember.WithLeadingTrivia(newLeadingTrivia)); } } var isIDisposableImplemented = ( from baseType in root.DescendantNodes().OfType <SimpleBaseTypeSyntax>() select baseType.Type into baseTypeDefinition where baseTypeDefinition is IdentifierNameSyntax && ((IdentifierNameSyntax)baseTypeDefinition).Identifier.ValueText == nameof(IDisposable) select baseTypeDefinition).Any(); var isSystemAbsent = root .Usings .All(usingNode => usingNode.Name.ToString() != nameof(System)); if (isIDisposableImplemented && isSystemAbsent) { var systemUsing = SyntaxFactory .UsingDirective(SyntaxFactory.ParseName(nameof(System))) .NormalizeWhitespace() .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed); newUsings.Add(systemUsing); } var xUnitUsing = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Xunit")).NormalizeWhitespace(); newUsings.Add(xUnitUsing); // Apply trailing trivia from original last using statement to new last using statement SyntaxTriviaList usingTrailingTrivia = RemoveCompilerDirectives(originalRoot.Usings.Last().GetTrailingTrivia()); newUsings[newUsings.Count - 1] = newUsings.Last().WithTrailingTrivia(usingTrailingTrivia); root = root.WithUsings(SyntaxFactory.List <UsingDirectiveSyntax>(newUsings)); return(document.WithSyntaxRoot(root).Project.Solution); }
private void RemoveContractsRequiredAttributes(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { RemoveTestAttributes(root, semanticModel, transformationTracker, "ContractsRequiredAttribute"); }
private void ChangeTestInitializeAttributesToCtor(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List <AttributeSyntax> nodesToReplace = new List <AttributeSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType <AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestInitializeAttribute")) { nodesToReplace.Add(attributeSyntax); } } } transformationTracker.AddTransformation(nodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax rewrittenNode in rewrittenNodes) { var attributeListSyntax = (AttributeListSyntax)rewrittenNode.Parent; var methodDeclarationSyntax = (MethodDeclarationSyntax)attributeListSyntax.Parent; var className = transformationRoot.DescendantNodes().OfType <ClassDeclarationSyntax>().Last().Identifier; ConstructorDeclarationSyntax ctorSyntax = ConstructorDeclaration(new SyntaxList <AttributeListSyntax>(), methodDeclarationSyntax.Modifiers, className.NormalizeWhitespace(), methodDeclarationSyntax.ParameterList, null, methodDeclarationSyntax.Body); transformationRoot = transformationRoot.ReplaceNode(methodDeclarationSyntax, ctorSyntax); } return(transformationRoot); }); }
private void ChangeAssertCalls(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { Dictionary <string, string> assertMethodsToRename = new Dictionary <string, string>() { { "AreEqual", "Equal" }, { "AreNotEqual", "NotEqual" }, { "IsNull", "Null" }, { "IsNotNull", "NotNull" }, { "AreSame", "Same" }, { "AreNotSame", "NotSame" }, { "IsTrue", "True" }, { "IsFalse", "False" }, { "IsInstanceOfType", "IsAssignableFrom" }, }; Dictionary <SimpleNameSyntax, string> nameReplacementsForNodes = new Dictionary <SimpleNameSyntax, string>(); List <InvocationExpressionSyntax> methodCallsToReverseArguments = new List <InvocationExpressionSyntax>(); foreach (var methodCallSyntax in root.DescendantNodes().OfType <MemberAccessExpressionSyntax>()) { var expressionSyntax = methodCallSyntax.Expression; var expressionTypeInfo = semanticModel.GetTypeInfo(expressionSyntax); if (expressionTypeInfo.Type != null) { string expressionDocID = expressionTypeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(expressionDocID, "Assert")) { string newMethodName; if (assertMethodsToRename.TryGetValue(methodCallSyntax.Name.Identifier.Text, out newMethodName)) { nameReplacementsForNodes.Add(methodCallSyntax.Name, newMethodName); if (newMethodName == "IsAssignableFrom" && methodCallSyntax.Parent is InvocationExpressionSyntax) { // Parameter order is reversed between MSTest Assert.IsInstanceOfType and xUnit Assert.IsAssignableFrom methodCallsToReverseArguments.Add((InvocationExpressionSyntax)methodCallSyntax.Parent); } } } } } if (nameReplacementsForNodes.Any()) { transformationTracker.AddTransformation(nameReplacementsForNodes.Keys, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var realOriginalNode = (SimpleNameSyntax)originalNodeMap[originalNode]; string newName = nameReplacementsForNodes[realOriginalNode]; return SyntaxFactory.ParseName(newName); })); }); transformationTracker.AddTransformation(methodCallsToReverseArguments, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var invocationExpression = (InvocationExpressionSyntax)rewrittenNode; var oldArguments = invocationExpression.ArgumentList.Arguments; var newArguments = new SeparatedSyntaxList <ArgumentSyntax>().AddRange(new[] { oldArguments[1], oldArguments[0] }); return invocationExpression.WithArgumentList(invocationExpression.ArgumentList.WithArguments(newArguments)); })); }); } }
private void ChangeTestInitializeToCtor(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List <AttributeSyntax> nodesToReplace = new List <AttributeSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType <AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestInitializeAttribute")) { nodesToReplace.Add(attributeSyntax); } } } transformationTracker.AddTransformation(nodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax testInitializeAttribute in rewrittenNodes) { var methodNode = (MethodDeclarationSyntax)testInitializeAttribute.Parent.Parent; var classIdentifier = methodNode.Ancestors().OfType <ClassDeclarationSyntax>().Single().Identifier; var constructorIdentifier = classIdentifier.NormalizeWhitespace(); var constructorNode = SyntaxFactory .ConstructorDeclaration(constructorIdentifier) .WithModifiers(methodNode.Modifiers) .WithParameterList(methodNode.ParameterList) .WithBody(methodNode.Body); var oldAttributeList = (AttributeListSyntax)testInitializeAttribute.Parent; var newAttributes = oldAttributeList.Attributes.Remove(testInitializeAttribute); if (newAttributes.Any()) { var newAttributeList = oldAttributeList.WithAttributes(newAttributes); var newAttributeLists = methodNode.AttributeLists.Replace(oldAttributeList, newAttributeList); constructorNode = constructorNode.WithAttributeLists(newAttributeLists); } else { var newAttributeLists = methodNode.AttributeLists.Remove(oldAttributeList); if (newAttributeLists.Any()) { constructorNode = constructorNode.WithAttributeLists(newAttributeLists); } } return(transformationRoot.ReplaceNode(methodNode, constructorNode)); } return(transformationRoot); }); }
private void ChangeTestCleanupToIDisposable(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List <MethodDeclarationSyntax> methodNodesToReplace = new List <MethodDeclarationSyntax>(); List <ClassDeclarationSyntax> classNodesToAmend = new List <ClassDeclarationSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType <AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestCleanupAttribute")) { var methodNode = (MethodDeclarationSyntax)attributeSyntax.Parent.Parent; var classNode = (ClassDeclarationSyntax)methodNode.Parent; methodNodesToReplace.Add(methodNode); classNodesToAmend.Add(classNode); } } } transformationTracker.AddTransformation(methodNodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var testCleanupMethodNode = ((MethodDeclarationSyntax)rewrittenNode); return testCleanupMethodNode .WithIdentifier(SyntaxFactory.Identifier("Dispose")) .WithAttributeLists(default(SyntaxList <AttributeListSyntax>)); })); }); transformationTracker.AddTransformation(classNodesToAmend, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var classNode = ((ClassDeclarationSyntax)rewrittenNode); var classIdentifierNode = classNode.Identifier; var iDisposableBaseList = SyntaxFactory .BaseList( SyntaxFactory.SingletonSeparatedList <BaseTypeSyntax>( SyntaxFactory.SimpleBaseType( SyntaxFactory.IdentifierName("IDisposable")))) .NormalizeWhitespace(); iDisposableBaseList = iDisposableBaseList .WithLeadingTrivia(SyntaxFactory.Space) .WithTrailingTrivia(classIdentifierNode.TrailingTrivia); return classNode .WithBaseList(iDisposableBaseList) .WithIdentifier(classIdentifierNode.NormalizeWhitespace()); })); }); }
private void RemoveTestAttributes(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker, string attributeName) { List <AttributeSyntax> nodesToRemove = new List <AttributeSyntax>(); List <ClassDeclarationSyntax> classNodesToFixUp = new List <ClassDeclarationSyntax>(); foreach (var attributeListSyntax in root.DescendantNodes().OfType <AttributeListSyntax>()) { var attributesToRemove = attributeListSyntax.Attributes.Where(attributeSyntax => { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, attributeName)) { return(true); } } return(false); }).ToList(); nodesToRemove.AddRange(attributesToRemove); classNodesToFixUp.AddRange(attributesToRemove.Select(x => (ClassDeclarationSyntax)x.Parent.Parent)); } transformationTracker.AddTransformation(nodesToRemove, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax rewrittenNode in rewrittenNodes) { var attributeListSyntax = (AttributeListSyntax)rewrittenNode.Parent; var newSyntaxList = attributeListSyntax.Attributes.Remove(rewrittenNode); if (newSyntaxList.Any()) { transformationRoot = transformationRoot.ReplaceNode(attributeListSyntax, attributeListSyntax.WithAttributes(newSyntaxList)); } else { transformationRoot = transformationRoot.RemoveNode(attributeListSyntax, SyntaxRemoveOptions.KeepLeadingTrivia); } } return(transformationRoot); }); transformationTracker.AddTransformation(classNodesToFixUp, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var classNode = (ClassDeclarationSyntax)rewrittenNode; var leadingTrivia = classNode.GetLeadingTrivia(); var fixUppedTrivia = leadingTrivia.RemoveAt(leadingTrivia.Count - 1); return classNode.WithLeadingTrivia(fixUppedTrivia); })); }); }
protected override async Task <Solution> ProcessAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var root = syntaxNode as CompilationUnitSyntax; if (root == null) { return(document.Project.Solution); } if (!LoadMSTestNamespaces()) { return(document.Project.Solution); } var originalRoot = root; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); List <UsingDirectiveSyntax> newUsings = new List <UsingDirectiveSyntax>(); bool needsChanges = false; foreach (var usingSyntax in root.Usings) { var symbolInfo = semanticModel.GetSymbolInfo(usingSyntax.Name); if (symbolInfo.Symbol != null) { string namespaceDocID = symbolInfo.Symbol.GetDocumentationCommentId(); if (s_mstestNamespaces.Contains(namespaceDocID)) { needsChanges = true; } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } if (!needsChanges) { return(document.Project.Solution); } TransformationTracker transformationTracker = new TransformationTracker(); RemoveTestClassAttributes(root, semanticModel, transformationTracker); RemoveContractsRequiredAttributes(root, semanticModel, transformationTracker); ChangeTestMethodAttributesToFact(root, semanticModel, transformationTracker); ChangeAssertCalls(root, semanticModel, transformationTracker); root = transformationTracker.TransformRoot(root); // Remove compiler directives before the first member of the file (e.g. an #endif after the using statements) var firstMember = root.Members.FirstOrDefault(); if (firstMember != null) { if (firstMember.HasLeadingTrivia) { var newLeadingTrivia = RemoveCompilerDirectives(firstMember.GetLeadingTrivia()); root = root.ReplaceNode(firstMember, firstMember.WithLeadingTrivia(newLeadingTrivia)); } } var xUnitUsing = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Xunit")).NormalizeWhitespace(); newUsings.Add(xUnitUsing); // Apply trailing trivia from original last using statement to new last using statement SyntaxTriviaList usingTrailingTrivia = RemoveCompilerDirectives(originalRoot.Usings.Last().GetTrailingTrivia()); newUsings[newUsings.Count - 1] = newUsings.Last().WithTrailingTrivia(usingTrailingTrivia); root = root.WithUsings(SyntaxFactory.List <UsingDirectiveSyntax>(newUsings)); return(document.WithSyntaxRoot(root).Project.Solution); }
private void ChangeTestCleanupAttributesToDispose(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List <AttributeSyntax> nodesToReplace = new List <AttributeSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType <AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestCleanupAttribute")) { nodesToReplace.Add(attributeSyntax); } } } transformationTracker.AddTransformation(nodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax rewrittenNode in rewrittenNodes) { var attributeListSyntax = (AttributeListSyntax)rewrittenNode.Parent; var methodDeclarationSyntax = (MethodDeclarationSyntax)attributeListSyntax.Parent; transformationRoot = transformationRoot.ReplaceNode(methodDeclarationSyntax, methodDeclarationSyntax.WithAttributeLists(new SyntaxList <AttributeListSyntax>()).WithIdentifier(Identifier("Dispose").NormalizeWhitespace())); var classDeclarationSyntax = transformationRoot.DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var class2 = classDeclarationSyntax.WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( IdentifierName("IDisposable"))))).NormalizeWhitespace(); transformationRoot = transformationRoot.ReplaceNode(classDeclarationSyntax, class2); } return(transformationRoot); }); }
private void ChangeAssertCalls(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { Dictionary<string, string> assertMethodsToRename = new Dictionary<string, string>() { { "AreEqual", "Equal" }, { "AreNotEqual", "NotEqual" }, { "IsNull", "Null" }, { "IsNotNull", "NotNull" }, { "AreSame", "Same" }, { "AreNotSame", "NotSame" }, { "IsTrue", "True" }, { "IsFalse", "False" }, { "IsInstanceOfType", "IsAssignableFrom" }, }; Dictionary<SimpleNameSyntax, string> nameReplacementsForNodes = new Dictionary<SimpleNameSyntax, string>(); List<InvocationExpressionSyntax> methodCallsToReverseArguments = new List<InvocationExpressionSyntax>(); foreach (var methodCallSyntax in root.DescendantNodes().OfType<MemberAccessExpressionSyntax>()) { var expressionSyntax = methodCallSyntax.Expression; var expressionTypeInfo = semanticModel.GetTypeInfo(expressionSyntax); if (expressionTypeInfo.Type != null) { string expressionDocID = expressionTypeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(expressionDocID, "Assert")) { string newMethodName; if (assertMethodsToRename.TryGetValue(methodCallSyntax.Name.Identifier.Text, out newMethodName)) { nameReplacementsForNodes.Add(methodCallSyntax.Name, newMethodName); if (newMethodName == "IsAssignableFrom" && methodCallSyntax.Parent is InvocationExpressionSyntax) { // Parameter order is reversed between MSTest Assert.IsInstanceOfType and xUnit Assert.IsAssignableFrom methodCallsToReverseArguments.Add((InvocationExpressionSyntax)methodCallSyntax.Parent); } } } } } if (nameReplacementsForNodes.Any()) { transformationTracker.AddTransformation(nameReplacementsForNodes.Keys, (transformationRoot, rewrittenNodes, originalNodeMap) => { return transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var realOriginalNode = (SimpleNameSyntax)originalNodeMap[originalNode]; string newName = nameReplacementsForNodes[realOriginalNode]; return SyntaxFactory.ParseName(newName); }); }); transformationTracker.AddTransformation(methodCallsToReverseArguments, (transformationRoot, rewrittenNodes, originalNodeMap) => { return transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { var invocationExpression = (InvocationExpressionSyntax)rewrittenNode; var oldArguments = invocationExpression.ArgumentList.Arguments; var newArguments = new SeparatedSyntaxList<ArgumentSyntax>().AddRange(new[] { oldArguments[1], oldArguments[0] }); return invocationExpression.WithArgumentList(invocationExpression.ArgumentList.WithArguments(newArguments)); }); }); } }
private void ChangeTestMethodAttributesToFact(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker) { List <AttributeSyntax> nodesToReplace = new List <AttributeSyntax>(); foreach (var attributeSyntax in root.DescendantNodes().OfType <AttributeSyntax>()) { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, "TestMethodAttribute")) { nodesToReplace.Add(attributeSyntax); } } } transformationTracker.AddTransformation(nodesToReplace, (transformationRoot, rewrittenNodes, originalNodeMap) => { return(transformationRoot.ReplaceNodes(rewrittenNodes, (originalNode, rewrittenNode) => { return ((AttributeSyntax)rewrittenNode).WithName(SyntaxFactory.ParseName("Fact")).NormalizeWhitespace(); })); }); }
protected override async Task<Solution> ProcessAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var root = syntaxNode as CompilationUnitSyntax; if (root == null) return document.Project.Solution; if (!LoadMSTestNamespaces()) { return document.Project.Solution; } var originalRoot = root; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); List<UsingDirectiveSyntax> newUsings = new List<UsingDirectiveSyntax>(); bool needsChanges = false; foreach (var usingSyntax in root.Usings) { var symbolInfo = semanticModel.GetSymbolInfo(usingSyntax.Name); if (symbolInfo.Symbol != null) { string namespaceDocID = symbolInfo.Symbol.GetDocumentationCommentId(); if (s_mstestNamespaces.Contains(namespaceDocID)) { needsChanges = true; } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } else { newUsings.Add(RemoveLeadingAndTrailingCompilerDirectives(usingSyntax)); } } if (!needsChanges) { return document.Project.Solution; } TransformationTracker transformationTracker = new TransformationTracker(); RemoveTestClassAttributes(root, semanticModel, transformationTracker); RemoveContractsRequiredAttributes(root, semanticModel, transformationTracker); ChangeTestMethodAttributesToFact(root, semanticModel, transformationTracker); ChangeAssertCalls(root, semanticModel, transformationTracker); root = transformationTracker.TransformRoot(root); // Remove compiler directives before the first member of the file (e.g. an #endif after the using statements) var firstMember = root.Members.FirstOrDefault(); if (firstMember != null) { if (firstMember.HasLeadingTrivia) { var newLeadingTrivia = RemoveCompilerDirectives(firstMember.GetLeadingTrivia()); root = root.ReplaceNode(firstMember, firstMember.WithLeadingTrivia(newLeadingTrivia)); } } var xUnitUsing = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Xunit")).NormalizeWhitespace(); newUsings.Add(xUnitUsing); // Apply trailing trivia from original last using statement to new last using statement SyntaxTriviaList usingTrailingTrivia = RemoveCompilerDirectives(originalRoot.Usings.Last().GetTrailingTrivia()); newUsings[newUsings.Count - 1] = newUsings.Last().WithTrailingTrivia(usingTrailingTrivia); root = root.WithUsings(SyntaxFactory.List<UsingDirectiveSyntax>(newUsings)); return document.WithSyntaxRoot(root).Project.Solution; }
private void RemoveTestAttributes(CompilationUnitSyntax root, SemanticModel semanticModel, TransformationTracker transformationTracker, string attributeName) { List <AttributeSyntax> nodesToRemove = new List <AttributeSyntax>(); foreach (var attributeListSyntax in root.DescendantNodes().OfType <AttributeListSyntax>()) { var attributesToRemove = attributeListSyntax.Attributes.Where(attributeSyntax => { var typeInfo = semanticModel.GetTypeInfo(attributeSyntax); if (typeInfo.Type != null) { string attributeTypeDocID = typeInfo.Type.GetDocumentationCommentId(); if (IsTestNamespaceType(attributeTypeDocID, attributeName)) { return(true); } } return(false); }).ToList(); nodesToRemove.AddRange(attributesToRemove); } transformationTracker.AddTransformation(nodesToRemove, (transformationRoot, rewrittenNodes, originalNodeMap) => { foreach (AttributeSyntax rewrittenNode in rewrittenNodes) { var attributeListSyntax = (AttributeListSyntax)rewrittenNode.Parent; var newSyntaxList = attributeListSyntax.Attributes.Remove(rewrittenNode); if (newSyntaxList.Any()) { transformationRoot = transformationRoot.ReplaceNode(attributeListSyntax, attributeListSyntax.WithAttributes(newSyntaxList)); } else { transformationRoot = transformationRoot.RemoveNode(attributeListSyntax, SyntaxRemoveOptions.KeepNoTrivia); } } return(transformationRoot); }); }