static async Task<SyntaxNode> GetNewRootWithAddedNamespaces(Document document, SyntaxNode relativeToNode, CancellationToken cancellationToken, ImmutableHashSet<string> namespaceQualifiedStrings) { var namespaceWithUsings = relativeToNode .GetAncestorsOrThis<NamespaceDeclarationSyntax>() .FirstOrDefault(ns => ns.DescendantNodes().OfType<UsingDirectiveSyntax>().Any()); var root = await document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot; var usings = namespaceQualifiedStrings .Select(ns => UsingDirective(ParseName(ns).WithAdditionalAnnotations(Simplifier.Annotation))); if (namespaceWithUsings != null) { var newNamespaceDeclaration = namespaceWithUsings.WithUsings(namespaceWithUsings.Usings.AddRange(usings)); newRoot = root.ReplaceNode(namespaceWithUsings, newNamespaceDeclaration); } else { var compilationUnit = (CompilationUnitSyntax)root; newRoot = compilationUnit.WithUsings(compilationUnit.Usings.AddRange(usings)); } return newRoot; }
private SyntaxNode Complexify(SyntaxNode originalNode, SyntaxNode newNode) { _isProcessingComplexifiedSpans = true; _modifiedSubSpans = new List<ValueTuple<TextSpan, TextSpan>>(); var annotation = new SyntaxAnnotation(); newNode = newNode.WithAdditionalAnnotations(annotation); var speculativeTree = originalNode.SyntaxTree.GetRoot(_cancellationToken).ReplaceNode(originalNode, newNode); newNode = speculativeTree.GetAnnotatedNodes<SyntaxNode>(annotation).First(); _speculativeModel = GetSemanticModelForNode(newNode, _semanticModel); Debug.Assert(_speculativeModel != null, "expanding a syntax node which cannot be speculated?"); var oldSpan = originalNode.Span; var expandParameter = originalNode.GetAncestorsOrThis(n => n is SimpleLambdaExpressionSyntax || n is ParenthesizedLambdaExpressionSyntax).Count() == 0; newNode = _simplificationService.Expand(newNode, _speculativeModel, annotationForReplacedAliasIdentifier: null, expandInsideNode: null, expandParameter: expandParameter, cancellationToken: _cancellationToken); speculativeTree = originalNode.SyntaxTree.GetRoot(_cancellationToken).ReplaceNode(originalNode, newNode); newNode = speculativeTree.GetAnnotatedNodes<SyntaxNode>(annotation).First(); _speculativeModel = GetSemanticModelForNode(newNode, _semanticModel); newNode = base.Visit(newNode); var newSpan = newNode.Span; newNode = newNode.WithoutAnnotations(annotation); newNode = _renameAnnotations.WithAdditionalAnnotations(newNode, new RenameNodeSimplificationAnnotation() { OriginalTextSpan = oldSpan }); _renameSpansTracker.AddComplexifiedSpan(_documentId, oldSpan, new TextSpan(oldSpan.Start, newSpan.Length), _modifiedSubSpans); _modifiedSubSpans = null; _isProcessingComplexifiedSpans = false; _speculativeModel = null; return newNode; }
public override SyntaxNode Visit(SyntaxNode node) { if (node == null) { return node; } var isInConflictLambdaBody = false; var lambdas = node.GetAncestorsOrThis(n => n is SimpleLambdaExpressionSyntax || n is ParenthesizedLambdaExpressionSyntax); if (lambdas.Count() != 0) { foreach (var lambda in lambdas) { if (_conflictLocations.Any(cf => cf.Contains(lambda.Span))) { isInConflictLambdaBody = true; break; } } } var shouldComplexifyNode = !isInConflictLambdaBody && _skipRenameForComplexification == 0 && !_isProcessingComplexifiedSpans && _conflictLocations.Contains(node.Span); SyntaxNode result; // in case the current node was identified as being a complexification target of // a previous node, we'll handle it accordingly. if (shouldComplexifyNode) { _skipRenameForComplexification += shouldComplexifyNode ? 1 : 0; result = base.Visit(node); _skipRenameForComplexification -= shouldComplexifyNode ? 1 : 0; result = Complexify(node, result); } else { result = base.Visit(node); } return result; }
/// <summary> /// Gets the semantic model for the given node. /// If the node belongs to the syntax tree of the original semantic model, then returns originalSemanticModel. /// Otherwise, returns a speculative model. /// The assumption for the later case is that span start position of the given node in it's syntax tree is same as /// the span start of the original node in the original syntax tree. /// </summary> public static SemanticModel GetSemanticModelForNode(SyntaxNode node, SemanticModel originalSemanticModel) { if (node.SyntaxTree == originalSemanticModel.SyntaxTree) { // This is possible if the previous rename phase didn't rewrite any nodes in this tree. return originalSemanticModel; } var nodeToSpeculate = node.GetAncestorsOrThis(n => SpeculationAnalyzer.CanSpeculateOnNode(n)).LastOrDefault(); if (nodeToSpeculate == null) { if (node.IsKind(SyntaxKind.NameMemberCref)) { nodeToSpeculate = ((NameMemberCrefSyntax)node).Name; } else if (node.IsKind(SyntaxKind.QualifiedCref)) { nodeToSpeculate = ((QualifiedCrefSyntax)node).Container; } else if (node.IsKind(SyntaxKind.TypeConstraint)) { nodeToSpeculate = ((TypeConstraintSyntax)node).Type; } else if (node is BaseTypeSyntax) { nodeToSpeculate = ((BaseTypeSyntax)node).Type; } else { return null; } } bool isInNamespaceOrTypeContext = SyntaxFacts.IsInNamespaceOrTypeContext(node as ExpressionSyntax); var position = nodeToSpeculate.SpanStart; return SpeculationAnalyzer.CreateSpeculativeSemanticModelForNode(nodeToSpeculate, originalSemanticModel, position, isInNamespaceOrTypeContext); }
public override IEnumerable<SyntaxNode> GetOuterReturnStatements(SyntaxNode commonRoot, IEnumerable<SyntaxNode> jumpsOutOfRegion) { var returnStatements = jumpsOutOfRegion.Where(s => s is ReturnStatementSyntax); var container = commonRoot.GetAncestorsOrThis<SyntaxNode>().Where(a => a.IsReturnableConstruct()).FirstOrDefault(); if (container == null) { return SpecializedCollections.EmptyEnumerable<SyntaxNode>(); } var returnableConstructPairs = returnStatements.Select(r => Tuple.Create(r, r.GetAncestors<SyntaxNode>().Where(a => a.IsReturnableConstruct()).FirstOrDefault())) .Where(p => p.Item2 != null); // now filter return statements to only include the one under outmost container return returnableConstructPairs.Where(p => p.Item2 == container).Select(p => p.Item1); }