private static CompilationUnitSyntax ImportNeededNamespace(CompilationUnitSyntax root, SemanticModel semanticModel, MemberAccessExpressionSyntax callerMethod) { var symbolInfo = semanticModel.GetSymbolInfo(callerMethod.Name); var methodSymbol = symbolInfo.Symbol as IMethodSymbol; if (methodSymbol == null) return root; var namespaceDisplayString = methodSymbol.ContainingNamespace.ToDisplayString(); var hasNamespaceImported = root .DescendantNodes() .OfType<UsingDirectiveSyntax>() .Select(s => s.Name.ToString()) .Any(n => n == namespaceDisplayString); if (!hasNamespaceImported) { var namespaceQualifiedName = methodSymbol.ContainingNamespace.ToNameSyntax(); root = root.AddUsings(SyntaxFactory.UsingDirective(namespaceQualifiedName)); } return root; }
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(); }); }); }
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; }); }
private static bool ShouldAddExternAlias(ImmutableArray<string> aliases, CompilationUnitSyntax root) { var identifiers = root.DescendantNodes().OfType<ExternAliasDirectiveSyntax>().Select(e => e.Identifier.ToString()); var externAliases = aliases.Where(a => identifiers.Contains(a)); return !externAliases.Any(); }
/// <summary> /// Applies merge sort on Span.Start to obtain ordered stream of namespace decls and documentation /// syntax nodes. /// </summary> /// <param name="root">root of the syntax tree</param> /// <returns>stream ordered by span.start</returns> private static IEnumerable <SyntaxNode> NamespaceDeclsAndDocumentations(CompilationUnitSyntax root) { using var namespaceDecls = root .DescendantNodes() .OfType <Syntax.NamespaceDeclarationSyntax>() .GetEnumerator(); using var documentations = root .DescendantNodes(descendIntoTrivia: true) .OfType <Syntax.DocumentationCommentTriviaSyntax>() .GetEnumerator(); bool doneWithNamespaceDecls = !namespaceDecls.MoveNext(); bool doneWithDocumentations = !documentations.MoveNext(); SyntaxNode?prevWhat = null; // previous yield return while (!doneWithNamespaceDecls || !doneWithDocumentations) { SyntaxNode?what; // what to yield return if (doneWithNamespaceDecls && !doneWithDocumentations) { what = documentations.Current; doneWithDocumentations = !documentations.MoveNext(); } else if (!doneWithNamespaceDecls && doneWithDocumentations) { what = namespaceDecls.Current; doneWithNamespaceDecls = !namespaceDecls.MoveNext(); } else { if (namespaceDecls.Current.SpanStart < documentations.Current.SpanStart) { what = namespaceDecls.Current; doneWithNamespaceDecls = !namespaceDecls.MoveNext(); } else { what = documentations.Current; doneWithDocumentations = !documentations.MoveNext(); } } // Loop invariant if (what == null) { throw new InvalidOperationException("Unexpected null what"); } if (prevWhat != null && what.SpanStart <= prevWhat.SpanStart) { throw new InvalidOperationException( $"Unexpected {nameof(what)}.SpanStart (== {what.SpanStart}) " + $"before {nameof(prevWhat)}.SpanStart (== {prevWhat.SpanStart})"); } yield return(what); } }
static CompilationUnitSyntax RemovePrivateMethods(CompilationUnitSyntax root) { List<SyntaxNode> removes = new List<SyntaxNode>(); var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>(); foreach (var @class in classes) { var methods = @class.Members.OfType<MethodDeclarationSyntax>(); foreach (var method in methods) { SyntaxTokenList modifiers = method.Modifiers; bool result = false; foreach (SyntaxToken m in modifiers) { if (m.Text.Equals("private")) { result = true; removes.Add(method); break; } } } } root = root.RemoveNodes(removes,SyntaxRemoveOptions.KeepDirectives); return root; }
static CompilationUnitSyntax DumpEvents(CompilationUnitSyntax root) { Dictionary<SyntaxNode, SyntaxNode> changes = new Dictionary<SyntaxNode, SyntaxNode>(); var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>(); foreach (var @class in classes) { var events = @class.Members.OfType<EventDeclarationSyntax>(); foreach (var @event in events) { AccessorDeclarationSyntax add, remove; BlockSyntax newBody = SyntaxFactory.Block(SyntaxFactory.ParseStatement("throw new NotImplementedException();")); AccessorDeclarationSyntax adder = SyntaxFactory.AccessorDeclaration(SyntaxKind.AddAccessorDeclaration,newBody); AccessorDeclarationSyntax remover = SyntaxFactory.AccessorDeclaration(SyntaxKind.RemoveAccessorDeclaration, newBody); SyntaxList<AccessorDeclarationSyntax> syntaxes = new SyntaxList<AccessorDeclarationSyntax>(); syntaxes = syntaxes.Add(adder); syntaxes = syntaxes.Add(remover); AccessorListSyntax accessors = SyntaxFactory.AccessorList(syntaxes); EventDeclarationSyntax modifiedEvent = @event.WithAccessorList(accessors); changes.Add(@event, modifiedEvent); } } root = root.ReplaceNodes(changes.Keys, (n1, n2) => changes[n1]); return root; }
static CompilationUnitSyntax DumpProperties(CompilationUnitSyntax root) { Dictionary<SyntaxNode, SyntaxNode> changes = new Dictionary<SyntaxNode, SyntaxNode>(); var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>(); foreach (var @class in classes) { var properties = @class.Members.OfType<PropertyDeclarationSyntax>(); foreach (var property in properties) { AccessorDeclarationSyntax getter, setter; TryGetAccessors(property, out getter, out setter); BlockSyntax newBody = SyntaxFactory.Block(SyntaxFactory.ParseStatement("throw new NotImplementedException();")); BlockSyntax getterBody = null; BlockSyntax setterBody = null; PropertyDeclarationSyntax modifiedProperty = null; if (getter != null) { getterBody = getter.Body; if (getterBody == null) continue; changes.Add(getterBody, newBody); } if (setter != null) { setterBody = setter.Body; if (setterBody == null) continue; changes.Add(setterBody, newBody); } } } root = root.ReplaceNodes(changes.Keys, (n1, n2) => changes[n1]); return root; }
static CompilationUnitSyntax DumpConstructors(CompilationUnitSyntax root) { Dictionary<SyntaxNode, SyntaxNode> changes = new Dictionary<SyntaxNode, SyntaxNode>(); var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>(); foreach (var @class in classes) { var constructors = @class.Members.OfType<ConstructorDeclarationSyntax>(); var destructors = @class.Members.OfType<DestructorDeclarationSyntax>(); foreach (var c in constructors) { BlockSyntax newBody = SyntaxFactory.Block(SyntaxFactory.ParseStatement("throw new NotImplementedException();")); BlockSyntax body = c.Body; if (body == null) continue; var modifiedMethod = c.ReplaceNode(body, newBody); changes.Add(c, modifiedMethod); } foreach (var c in destructors) { BlockSyntax newBody = SyntaxFactory.Block(SyntaxFactory.ParseStatement("throw new NotImplementedException();")); BlockSyntax body = c.Body; if (body == null) continue; var modifiedMethod = c.ReplaceNode(body, newBody); changes.Add(c, modifiedMethod); } } root = root.ReplaceNodes(changes.Keys, (n1, n2) => changes[n1]); return root; }