public async Task <Document> AddImportsAsync(Document document, IEnumerable <TextSpan> spans, OptionSet options, CancellationToken cancellationToken) { options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func <SyntaxNodeOrToken, bool> isInSpan = (nodeOrToken) => spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList(); var namespacesToAdd = new HashSet <INamespaceSymbol>(); namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(n => GetExplicitNamespaceSymbol(n, model))); // annotate these nodes so they get simplified later var newRoot = root.ReplaceNodes(nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation)); var newDoc = document.WithSyntaxRoot(newRoot); var newModel = await newDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); newRoot = await this.AddNamespaceImportsAsync(newDoc, newModel, options, namespacesToAdd, cancellationToken).ConfigureAwait(false); return(document.WithSyntaxRoot(newRoot)); }
public async Task<Document> AddImportsAsync(Document document, IEnumerable<TextSpan> spans, OptionSet options, CancellationToken cancellationToken) { options = options ?? document.Project.Solution.Workspace.Options; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree<TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func<SyntaxNodeOrToken, bool> isInSpan = (nodeOrToken) => spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList(); var namespacesToAdd = new HashSet<INamespaceSymbol>(); namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(n => GetExplicitNamespaceSymbol(n, model))); // annotate these nodes so they get simplified later var newRoot = root.ReplaceNodes(nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation)); var newDoc = document.WithSyntaxRoot(newRoot); var newModel = await newDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); newRoot = await this.AddNamespaceImportsAsync(newDoc, newModel, options, namespacesToAdd, cancellationToken).ConfigureAwait(false); return document.WithSyntaxRoot(newRoot); }
private void Validate(TextSpan textSpan) { #if DEBUG if (nonOverlappingSpans == null) { nonOverlappingSpans = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance); } // new span should not overlap with any span that we already have. Contract.Requires(!nonOverlappingSpans.GetOverlappingIntervals(textSpan.Start, textSpan.Length).Any()); nonOverlappingSpans = nonOverlappingSpans.AddInterval(textSpan); #endif }
private async Task <SyntaxNode> ReduceAsync( Document document, SyntaxNode root, SemanticModel semanticModel, IEnumerable <TextSpan> spans, OptionSet optionSet, IEnumerable <AbstractReducer> reducers, CancellationToken cancellationToken) { // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func <SyntaxNodeOrToken, bool> isNodeOrTokenOutsideSimplifySpans = (nodeOrToken) => !spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); // Get the list of syntax nodes and tokens that need to be reduced. ImmutableArray <NodeOrTokenToReduce> nodesAndTokensToReduce = this.GetNodesAndTokensToReduce(root, isNodeOrTokenOutsideSimplifySpans); if (nodesAndTokensToReduce.Any()) { if (reducers == null) { reducers = this.GetReducers(); } var reducedNodesMap = new ConcurrentDictionary <SyntaxNode, SyntaxNode>(); var reducedTokensMap = new ConcurrentDictionary <SyntaxToken, SyntaxToken>(); // Reduce all the nodesAndTokensToReduce using the given reducers/rewriters and // store the reduced nodes and/or tokens in the reduced nodes/tokens maps. // Note that this method doesn't update the original syntax tree. await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, optionSet, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false); if (reducedNodesMap.Any() || reducedTokensMap.Any()) { // Update the syntax tree with reduced nodes/tokens. root = root.ReplaceSyntax( nodes: reducedNodesMap.Keys, computeReplacementNode: (o, n) => TransformReducedNode(reducedNodesMap[o], n), tokens: reducedTokensMap.Keys, computeReplacementToken: (o, n) => reducedTokensMap[o], trivia: SpecializedCollections.EmptyEnumerable <SyntaxTrivia>(), computeReplacementTrivia: null); } } return(root); }
public async Task <Document> AddImportsAsync( Document document, IEnumerable <TextSpan> spans, OptionSet options, CancellationToken cancellationToken) { options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func <SyntaxNodeOrToken, bool> isInSpan = nodeOrToken => spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList(); var namespacesToAdd = new HashSet <INamespaceSymbol>(); namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select( n => GetExplicitNamespaceSymbol(n, model))); var generator = SyntaxGenerator.GetGenerator(document); var imports = namespacesToAdd.Select(ns => generator.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation)) .ToArray(); // annotate these nodes so they get simplified later var newRoot = root.ReplaceNodes( nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation)); var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); var addImportsService = document.GetLanguageService <IAddImportsService>(); var finalRoot = addImportsService.AddImports( model.Compilation, newRoot, newRoot, imports, placeSystemNamespaceFirst); return(document.WithSyntaxRoot(finalRoot)); }
public async Task<Document> AddImportsAsync( Document document, IEnumerable<TextSpan> spans, OptionSet options, CancellationToken cancellationToken) { options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree<TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func<SyntaxNodeOrToken, bool> isInSpan = nodeOrToken => spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList(); var namespacesToAdd = new HashSet<INamespaceSymbol>(); namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select( n => GetExplicitNamespaceSymbol(n, model))); var generator = SyntaxGenerator.GetGenerator(document); var imports = namespacesToAdd.Select(ns => generator.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation)) .ToArray(); // annotate these nodes so they get simplified later var newRoot = root.ReplaceNodes( nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation)); var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); var addImportsService = document.GetLanguageService<IAddImportsService>(); var finalRoot = addImportsService.AddImports( model.Compilation, newRoot, newRoot, imports, placeSystemNamespaceFirst); return document.WithSyntaxRoot(finalRoot); }
private async Task <Document> ReduceAsyncInternal( Document document, List <TextSpan> spans, OptionSet optionSet, IEnumerable <AbstractReducer> reducers, CancellationToken cancellationToken) { // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans); Func <SyntaxNodeOrToken, bool> isNodeOrTokenOutsideSimplifySpans = (nodeOrToken) => !spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); // prep namespace imports marked for simplification var removeIfUnusedAnnotation = new SyntaxAnnotation(); var originalRoot = root; root = this.PrepareNamespaceImportsForRemovalIfUnused(document, root, removeIfUnusedAnnotation, isNodeOrTokenOutsideSimplifySpans); var hasImportsToSimplify = root != originalRoot; if (hasImportsToSimplify) { document = document.WithSyntaxRoot(root); semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); root = semanticModel.SyntaxTree.GetRoot(cancellationToken); } // Get the list of syntax nodes and tokens that need to be reduced. var nodesAndTokensToReduce = this.GetNodesAndTokensToReduce(root, isNodeOrTokenOutsideSimplifySpans); if (nodesAndTokensToReduce.Any()) { if (reducers == null) { reducers = this.GetReducers(); } var reducedNodesMap = new ConcurrentDictionary <SyntaxNode, SyntaxNode>(); var reducedTokensMap = new ConcurrentDictionary <SyntaxToken, SyntaxToken>(); // Reduce all the nodesAndTokensToReduce using the given reducers/rewriters and // store the reduced nodes and/or tokens in the reduced nodes/tokens maps. // Note that this method doesn't update the original syntax tree. await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, optionSet, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false); if (reducedNodesMap.Any() || reducedTokensMap.Any()) { // Update the syntax tree with reduced nodes/tokens. root = root.ReplaceSyntax( nodes: reducedNodesMap.Keys, computeReplacementNode: (o, n) => TransformReducedNode(reducedNodesMap[o], n), tokens: reducedTokensMap.Keys, computeReplacementToken: (o, n) => reducedTokensMap[o], trivia: SpecializedCollections.EmptyEnumerable <SyntaxTrivia>(), computeReplacementTrivia: null); document = document.WithSyntaxRoot(root); } } if (hasImportsToSimplify) { // remove any unused namespace imports that were marked for simplification document = await this.RemoveUnusedNamespaceImportsAsync(document, removeIfUnusedAnnotation, cancellationToken).ConfigureAwait(false); } return(document); }