private async Task<Solution> RenameThenRemoveAsyncTokenAsync(Document document, SyntaxNode node, IMethodSymbol methodSymbol, CancellationToken cancellationToken) { var name = methodSymbol.Name; var newName = name.Substring(0, name.Length - AsyncSuffix.Length); var solution = document.Project.Solution; var options = solution.Workspace.Options; // Store the path to this node. That way we can find it post rename. var syntaxPath = new SyntaxPath(node); // Rename the method to remove the 'Async' suffix, then remove the 'async' keyword. var newSolution = await Renamer.RenameSymbolAsync(solution, methodSymbol, newName, options, cancellationToken).ConfigureAwait(false); var newDocument = newSolution.GetDocument(document.Id); var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newNode; if (syntaxPath.TryResolve<SyntaxNode>(newRoot, out newNode)) { var semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var newMethod = (IMethodSymbol)semanticModel.GetDeclaredSymbol(newNode, cancellationToken); return await RemoveAsyncTokenAsync(newDocument, newMethod, newNode, cancellationToken).ConfigureAwait(false); } return newSolution; }
public void FailFirstType() { var node = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Hi")); var path = new SyntaxPath(node); Assert.False(path.TryResolve(SyntaxFactory.ParseExpression("Foo()"), out SyntaxNode recovered)); }
public void RecoverChild() { var node = SyntaxFactory.ParseExpression("Foo()"); var child = ((InvocationExpressionSyntax)node).ArgumentList; var path = new SyntaxPath(child); Assert.True(path.TryResolve(node, out SyntaxNode recovered)); Assert.Equal(child, recovered); }
public void FailChildType() { var root = SyntaxFactory.ParseExpression("Foo(a)"); var path = new SyntaxPath(((InvocationExpressionSyntax)root).ArgumentList.Arguments.First().Expression); var root2 = SyntaxFactory.ParseExpression("Foo(3)"); Assert.False(path.TryResolve(root2, out SyntaxNode recovered)); }
public void TestRoot1() { var tree = SyntaxFactory.ParseSyntaxTree(string.Empty); var root = tree.GetRoot(); var path = new SyntaxPath(root); Assert.True(path.TryResolve(tree, CancellationToken.None, out SyntaxNode node)); Assert.Equal(root, node); }
public WorkItem( DocumentId documentId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, IAsyncToken asyncToken) : this(documentId, documentId.ProjectId, language, invocationReasons, isLowPriority, activeMember, ImmutableHashSet.Create <IIncrementalAnalyzer>(), false, asyncToken) { }
public void RecoverSingle() { var node = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Hi")); var path = new SyntaxPath(node); Assert.True(path.TryResolve(node, out SyntaxNode recovered)); Assert.Equal(node, recovered); }
public WorkItem( DocumentId documentId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, IAsyncToken asyncToken) : this(documentId, documentId.ProjectId, language, invocationReasons, isLowPriority, activeMember, ImmutableHashSet.Create<IIncrementalAnalyzer>(), false, asyncToken) { }
public void RecoverGeneric() { var root = SyntaxFactory.ParseExpression("Foo()"); var node = ((InvocationExpressionSyntax)root).ArgumentList; var path = new SyntaxPath(node); Assert.True(path.TryResolve(root, out ArgumentListSyntax recovered)); Assert.Equal(node, recovered); }
public void RecoverGeneric() { var root = SyntaxFactory.ParseExpression("Goo()"); var node = ((InvocationExpressionSyntax)root).ArgumentList; var path = new SyntaxPath(node); Assert.True(path.TryResolve(root, out ArgumentListSyntax recovered)); Assert.Equal(node, recovered); }
public void RecoverChild() { var node = SyntaxFactory.ParseExpression("Goo()"); var child = ((InvocationExpressionSyntax)node).ArgumentList; var path = new SyntaxPath(child); Assert.True(path.TryResolve(node, out SyntaxNode recovered)); Assert.Equal(child, recovered); }
public void FailChildCount() { var root = SyntaxFactory.ParseExpression("Goo(a, b)"); var path = new SyntaxPath(((InvocationExpressionSyntax)root).ArgumentList.Arguments.Last()); var root2 = SyntaxFactory.ParseExpression("Goo(a)"); Assert.False(path.TryResolve(root2, out SyntaxNode recovered)); }
public void FailChildType() { var root = SyntaxFactory.ParseExpression("Goo(a)"); var path = new SyntaxPath(((InvocationExpressionSyntax)root).ArgumentList.Arguments.First().Expression); var root2 = SyntaxFactory.ParseExpression("Goo(3)"); Assert.False(path.TryResolve(root2, out SyntaxNode _)); }
public void FailFirstType() { var node = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Hi")); var path = new SyntaxPath(node); SyntaxNode recovered; Assert.False(path.TryResolve(SyntaxFactory.ParseExpression("Foo()"), out recovered)); }
public void FailChildCount() { var root = SyntaxFactory.ParseExpression("Foo(a, b)"); var path = new SyntaxPath(((InvocationExpressionSyntax)root).ArgumentList.Arguments.Last()); var root2 = SyntaxFactory.ParseExpression("Foo(a)"); SyntaxNode recovered; Assert.False(path.TryResolve(root2, out recovered)); }
public void TestRoot4() { var text = "class C {}"; var tree = SyntaxFactory.ParseSyntaxTree(text); var root = tree.GetRoot(); var path = new SyntaxPath(root); tree = WithReplaceFirst(tree, "C", "D"); Assert.True(path.TryResolve(tree, CancellationToken.None, out SyntaxNode node)); Assert.Equal(SyntaxKind.CompilationUnit, node.Kind()); }
public void TestRoot2() { var text = SourceText.From(string.Empty); var tree = SyntaxFactory.ParseSyntaxTree(string.Empty); var root = tree.GetCompilationUnitRoot(); var path = new SyntaxPath(root); var newText = text.WithChanges(new TextChange(new TextSpan(0, 0), "class C {}")); var newTree = tree.WithChangedText(newText); Assert.True(path.TryResolve(newTree, CancellationToken.None, out SyntaxNode node)); Assert.Equal(SyntaxKind.CompilationUnit, node.Kind()); }
private async Task <Solution> RenameThenRemoveAsyncTokenAsync( Document document, SyntaxNode node, IMethodSymbol methodSymbol, CancellationToken cancellationToken ) { var name = methodSymbol.Name; var newName = name.Substring(0, name.Length - AsyncSuffix.Length); var solution = document.Project.Solution; // Store the path to this node. That way we can find it post rename. var syntaxPath = new SyntaxPath(node); // Rename the method to remove the 'Async' suffix, then remove the 'async' keyword. var newSolution = await Renamer .RenameSymbolAsync( solution, methodSymbol, newName, solution.Options, cancellationToken ) .ConfigureAwait(false); var newDocument = newSolution.GetDocument(document.Id); var newRoot = await newDocument .GetSyntaxRootAsync(cancellationToken) .ConfigureAwait(false); if (syntaxPath.TryResolve(newRoot, out SyntaxNode newNode)) { var semanticModel = await newDocument .GetSemanticModelAsync(cancellationToken) .ConfigureAwait(false); var newMethod = (IMethodSymbol)semanticModel.GetDeclaredSymbol( newNode, cancellationToken ); return(await RemoveAsyncTokenAsync( newDocument, newMethod, newNode, cancellationToken ) .ConfigureAwait(false)); } return(newSolution); }
private void UpdateNodeAndReacquireParentNodeKey <T>(Action <SyntaxNode, T> parameterUpdater, T value) { Action <SyntaxNode, T> updater = (n, v) => { var parentNode = _parentHandle.Value.LookupNode(); var parentNodePath = new SyntaxPath(parentNode); parameterUpdater(n, v); _parentHandle.Value.ReacquireNodeKey(parentNodePath, CancellationToken.None); }; UpdateNode(updater, value); }
protected void UpdateNodeAndReacquireNodeKey <T>(Action <SyntaxNode, T> updater, T value, bool trackKinds = true) { FileCodeModel.EnsureEditor(() => { // Sometimes, changing an element can result in needing to update its node key. var node = LookupNode(); var nodePath = new SyntaxPath(node, trackKinds); updater(node, value); ReacquireNodeKey(nodePath, CancellationToken.None); }); }
/// <summary> /// This function re-acquires the key for this code element using the given syntax path. /// </summary> internal void ReacquireNodeKey(SyntaxPath syntaxPath, CancellationToken cancellationToken) { Debug.Assert(syntaxPath != null); if (!syntaxPath.TryResolve(GetSyntaxTree(), cancellationToken, out SyntaxNode node)) { throw Exceptions.ThrowEFail(); } var newNodeKey = CodeModelService.GetNodeKey(node); FileCodeModel.UpdateCodeElementNodeKey(this, _nodeKey, newNodeKey); _nodeKey = newNodeKey; }
public void TestRemoveUsing() { var text = SourceText.From("using X; class C {}"); var tree = SyntaxFactory.ParseSyntaxTree(text); var root = (CompilationUnitSyntax)tree.GetRoot(); var path = new SyntaxPath(root.Members[0]); var newText = WithReplaceFirst(text, "using X;", ""); var newTree = tree.WithChangedText(newText); Assert.True(path.TryResolve(newTree, CancellationToken.None, out SyntaxNode node)); Assert.Equal(SyntaxKind.ClassDeclaration, node.Kind()); }
public void TestMethodBodyChange() { var text = @"namespace N { class C { void M1() { int i1; } void M2() { int i2; } void M3() { int i3; } } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)( tree.GetRoot() as CompilationUnitSyntax ).Members[0]; var classDecl = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var member1 = classDecl.Members[0]; var member2 = classDecl.Members[1]; var member3 = classDecl.Members[2]; var path1 = new SyntaxPath(member1); var path2 = new SyntaxPath(member2); var path3 = new SyntaxPath(member3); tree = WithReplaceFirst( WithReplaceFirst(WithReplaceFirst(tree, "i1", "j1"), "i2", "j2"), "i3", "j3" ); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.True(path3.TryResolve(tree, CancellationToken.None, out SyntaxNode n3)); Assert.Equal(SyntaxKind.MethodDeclaration, n1.Kind()); Assert.Equal("M1", ((MethodDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n2.Kind()); Assert.Equal("M2", ((MethodDeclarationSyntax)n2).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n3.Kind()); Assert.Equal("M3", ((MethodDeclarationSyntax)n3).Identifier.ValueText); }
public void TestRoot3() { var text = SourceText.From("class C {}"); var tree = SyntaxFactory.ParseSyntaxTree(text); var root = tree.GetRoot(); var path = new SyntaxPath(root); var newText = text.WithChanges(new TextChange(new TextSpan(0, text.Length), "")); var newTree = tree.WithChangedText(newText); SyntaxNode node; Assert.True(path.TryResolve(newTree, CancellationToken.None, out node)); Assert.Equal(SyntaxKind.CompilationUnit, node.CSharpKind()); }
public EnvDTE.CodeParameter AddParameter(string name, object type, object position) { return(FileCodeModel.EnsureEditor(() => { // The parameters are part of the node key, so we need to update it // after adding a parameter. var node = LookupNode(); var nodePath = new SyntaxPath(node); var parameter = FileCodeModel.AddParameter(this, node, name, type, position); ReaquireNodeKey(nodePath, CancellationToken.None); return parameter; })); }
public WorkItem With( InvocationReasons invocationReasons, SyntaxPath currentMember, ImmutableHashSet <IIncrementalAnalyzer> analyzers, bool retry, IAsyncToken asyncToken) { // dispose old one AsyncToken.Dispose(); // create new work item return(new WorkItem( DocumentId, ProjectId, Language, InvocationReasons.With(invocationReasons), IsLowPriority, ActiveMember == currentMember ? currentMember : null, Union(analyzers), IsRetry || retry, asyncToken)); }
public void TestPP1() { var text = @"namespace N { class C { } struct D { } }"; var text2 = @"namespace N { #if true class C { } struct D { } #endif }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var class1 = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var class2 = (TypeDeclarationSyntax)namespaceDecl.Members[1]; var path1 = new SyntaxPath(class1); var path2 = new SyntaxPath(class2); tree = WithReplace(tree, 0, text.Length, text2); SyntaxNode n1; SyntaxNode n2; Assert.True(path1.TryResolve(tree, CancellationToken.None, out n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out n2)); Assert.Equal(SyntaxKind.ClassDeclaration, n1.Kind()); Assert.Equal("C", ((TypeDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.StructDeclaration, n2.Kind()); Assert.Equal("D", ((TypeDeclarationSyntax)n2).Identifier.ValueText); }
public void Enqueue(Document document, SyntaxPath changedMember) { UpdateLastAccessTime(); using (_workGate.DisposableWait(CancellationToken)) { if (_pendingWork.TryGetValue(document.Id, out var data)) { // create new async token and dispose old one. var newAsyncToken = Listener.BeginAsyncOperation(nameof(Enqueue), tag: _registration.Workspace); data.AsyncToken.Dispose(); _pendingWork[document.Id] = new Data(document, data.ChangedMember == changedMember ? changedMember : null, newAsyncToken); return; } _pendingWork.Add(document.Id, new Data(document, changedMember, Listener.BeginAsyncOperation(nameof(Enqueue), tag: _registration.Workspace))); _gate.Release(); } Logger.Log(FunctionId.WorkCoordinator_SemanticChange_Enqueue, s_enqueueLogger, Environment.TickCount, document.Id, changedMember != null); }
public void TestAddFieldBefore() { var text = @"namespace N { class C { void M1() { int i1; } bool M2() { int i2; } } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var classDecl = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var member1 = classDecl.Members[0]; var member2 = classDecl.Members[1]; var path1 = new SyntaxPath(member1); var path2 = new SyntaxPath(member2); tree = WithReplaceFirst(tree, "bool", "int field; bool"); SyntaxNode n1; SyntaxNode n2; Assert.True(path1.TryResolve(tree, CancellationToken.None, out n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out n2)); Assert.Equal(SyntaxKind.MethodDeclaration, n1.Kind()); Assert.Equal("M1", ((MethodDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n2.Kind()); Assert.Equal("M2", ((MethodDeclarationSyntax)n2).Identifier.ValueText); }
public void Enqueue(Document document, SyntaxPath changedMember) { this.UpdateLastAccessTime(); using (this.workGate.DisposableWait(this.CancellationToken)) { Data data; if (this.pendingWork.TryGetValue(document.Id, out data)) { // create new async token and dispose old one. var newAsyncToken = this.Listener.BeginAsyncOperation("EnqueueSemanticChange"); data.AsyncToken.Dispose(); this.pendingWork[document.Id] = new Data(document, data.ChangedMember == changedMember ? changedMember : null, newAsyncToken); return; } this.pendingWork.Add(document.Id, new Data(document, changedMember, this.Listener.BeginAsyncOperation("EnqueueSemanticChange"))); this.gate.Release(); } Logger.Log(FunctionId.WorkCoordinator_SemanticChange_Enqueue, enqueueLogger, Environment.TickCount, document.Id, changedMember != null); }
public void RemoveParameter(object element) { FileCodeModel.EnsureEditor(() => { // The parameters are part of the node key, so we need to update it // after removing a parameter. var node = LookupNode(); var nodePath = new SyntaxPath(node); var codeElement = ComAggregate.TryGetManagedObject <AbstractCodeElement>(element); codeElement ??= ComAggregate.TryGetManagedObject <AbstractCodeElement>(this.Parameters.Item(element)); if (codeElement == null) { throw new ArgumentException(ServicesVSResources.Element_is_not_valid, nameof(element)); } codeElement.Delete(); ReacquireNodeKey(nodePath, CancellationToken.None); }); }
private WorkItem( DocumentId documentId, ProjectId projectId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, ImmutableHashSet<IIncrementalAnalyzer> analyzers, bool retry, IAsyncToken asyncToken) { this.DocumentId = documentId; this.ProjectId = projectId; this.Language = language; this.InvocationReasons = invocationReasons; this.IsLowPriority = isLowPriority; this.ActiveMember = activeMember; this.Analyzers = analyzers; this.IsRetry = retry; this.AsyncToken = asyncToken; }
private WorkItem( DocumentId documentId, ProjectId projectId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, ImmutableHashSet <IIncrementalAnalyzer> analyzers, bool retry, IAsyncToken asyncToken) { DocumentId = documentId; ProjectId = projectId; Language = language; InvocationReasons = invocationReasons; IsLowPriority = isLowPriority; ActiveMember = activeMember; Analyzers = analyzers; IsRetry = retry; AsyncToken = asyncToken; }
public Data(Document document, SyntaxPath changedMember, IAsyncToken asyncToken) { AsyncToken = asyncToken; Document = document; ChangedMember = changedMember; }
public void TestChangeType1() { var text = @"namespace N { class C { void Foo(); } class D { } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var class1 = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var class2 = (TypeDeclarationSyntax)namespaceDecl.Members[1]; var method1 = class1.Members[0]; var path1 = new SyntaxPath(class1); var path2 = new SyntaxPath(class2); var path3 = new SyntaxPath(method1); tree = WithReplaceFirst(tree, "class", "struct"); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.False(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.False(path3.TryResolve(tree, CancellationToken.None, out SyntaxNode n3)); Assert.Equal(SyntaxKind.ClassDeclaration, n1.Kind()); Assert.Equal("D", ((TypeDeclarationSyntax)n1).Identifier.ValueText); }
public static void LogWorkItemEnqueue( LogAggregator logAggregator, string language, DocumentId documentId, InvocationReasons reasons, bool lowPriority, SyntaxPath activeMember, bool added) { logAggregator.IncreaseCount(language); logAggregator.IncreaseCount(added ? NewWorkItem : UpdateWorkItem); if (documentId != null) { logAggregator.IncreaseCount(activeMember == null ? TopLevel : MemberLevel); if (lowPriority) { logAggregator.IncreaseCount(LowerPriority); logAggregator.IncreaseCount(ValueTuple.Create(LowerPriority, documentId.Id)); } } foreach (var reason in reasons) { logAggregator.IncreaseCount(reason); } }
private async Task<Solution> RenameThenAddAsyncTokenAsync( bool keepVoid, Document document, SyntaxNode node, IMethodSymbol methodSymbol, CancellationToken cancellationToken) { var name = methodSymbol.Name; var newName = name + AsyncSuffix; var solution = document.Project.Solution; // Store the path to this node. That way we can find it post rename. var syntaxPath = new SyntaxPath(node); // Rename the method to add the 'Async' suffix, then add the 'async' keyword. var newSolution = await Renamer.RenameSymbolAsync(solution, methodSymbol, newName, solution.Options, cancellationToken).ConfigureAwait(false); var newDocument = newSolution.GetDocument(document.Id); var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newNode; if (syntaxPath.TryResolve(newRoot, out newNode)) { var semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var newMethod = (IMethodSymbol)semanticModel.GetDeclaredSymbol(newNode, cancellationToken); return await AddAsyncTokenAsync(keepVoid, newDocument, newMethod, newNode, cancellationToken).ConfigureAwait(false); } return newSolution; }
public Data(Document document, SyntaxPath changedMember, IAsyncToken asyncToken) { this.AsyncToken = asyncToken; this.Document = document; this.ChangedMember = changedMember; }
public void RemoveParameter(object element) { FileCodeModel.EnsureEditor(() => { // The parameters are part of the node key, so we need to update it // after removing a parameter. var node = LookupNode(); var nodePath = new SyntaxPath(node); var codeElement = ComAggregate.TryGetManagedObject<AbstractCodeElement>(element); if (codeElement == null) { codeElement = ComAggregate.TryGetManagedObject<AbstractCodeElement>(this.Parameters.Item(element)); } if (codeElement == null) { throw new ArgumentException(ServicesVSResources.ElementIsNotValid, "element"); } codeElement.Delete(); ReaquireNodeKey(nodePath, CancellationToken.None); }); }
public GlobalNodeKey(SyntaxNodeKey nodeKey, SyntaxPath path) { this.NodeKey = nodeKey; this.Path = path; }
public void TestComment() { var text = @"namespace N { class C { } struct D { } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var class1 = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var class2 = (TypeDeclarationSyntax)namespaceDecl.Members[1]; var path1 = new SyntaxPath(class1); var path2 = new SyntaxPath(class2); tree = WithReplaceFirst(WithReplaceFirst(tree, "class", "/* foo */ class"), "struct", "/* bar */ struct"); SyntaxNode n1; SyntaxNode n2; Assert.True(path1.TryResolve(tree, CancellationToken.None, out n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out n2)); Assert.Equal(SyntaxKind.ClassDeclaration, n1.Kind()); Assert.Equal("C", ((TypeDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.StructDeclaration, n2.Kind()); Assert.Equal("D", ((TypeDeclarationSyntax)n2).Identifier.ValueText); }
private void TryStartRenameSession(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { var changedDocuments = newSolution.GetChangedDocuments(oldSolution); foreach (var documentId in changedDocuments) { var document = newSolution.GetDocument(documentId); if (!document.SupportsSyntaxTree) { continue; } var root = document.GetSyntaxRootSynchronously(cancellationToken); var renameTokenOpt = root.GetAnnotatedNodesAndTokens(RenameAnnotation.Kind) .Where(s => s.IsToken) .Select(s => s.AsToken()) .FirstOrNullable(); if (renameTokenOpt.HasValue) { // It's possible that the workspace's current solution is not the same as // newSolution. This can happen if the workspace host performs other edits // during ApplyChanges, such as in the Venus scenario where indentation and // formatting can happen. To work around this, we create a SyntaxPath to the // rename token in the newSolution and resolve it to the current solution. var pathToRenameToken = new SyntaxPath(renameTokenOpt.Value); var latestDocument = workspace.CurrentSolution.GetDocument(documentId); var latestRoot = latestDocument.GetSyntaxRootSynchronously(cancellationToken); SyntaxNodeOrToken resolvedRenameToken; if (pathToRenameToken.TryResolve(latestRoot, out resolvedRenameToken) && resolvedRenameToken.IsToken) { var editorWorkspace = workspace; var navigationService = editorWorkspace.Services.GetService<IDocumentNavigationService>(); if (navigationService.TryNavigateToSpan(editorWorkspace, documentId, resolvedRenameToken.Span)) { var openDocument = workspace.CurrentSolution.GetDocument(documentId); var openRoot = openDocument.GetSyntaxRootSynchronously(cancellationToken); // NOTE: We need to resolve the syntax path again in case VB line commit kicked in // due to the navigation. // TODO(DustinCa): We still have a potential problem here with VB line commit, // because it can insert tokens and all sorts of other business, which could // wind up with us not being able to resolve the token. if (pathToRenameToken.TryResolve(openRoot, out resolvedRenameToken) && resolvedRenameToken.IsToken) { var snapshot = openDocument.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).FindCorrespondingEditorTextSnapshot(); if (snapshot != null) { _renameService.StartInlineSession(openDocument, resolvedRenameToken.AsToken().Span, cancellationToken); } } } } return; } } }
public WorkItem With( InvocationReasons invocationReasons, SyntaxPath currentMember, ImmutableHashSet<IIncrementalAnalyzer> analyzers, bool retry, IAsyncToken asyncToken) { // dispose old one this.AsyncToken.Dispose(); // create new work item return new WorkItem( this.DocumentId, this.ProjectId, this.Language, InvocationReasons.With(invocationReasons), IsLowPriority, this.ActiveMember == currentMember ? currentMember : null, Union(analyzers), this.IsRetry || retry, asyncToken); }
public void TestAddFieldBefore() { var text = @"namespace N { class C { void M1() { int i1; } bool M2() { int i2; } } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var classDecl = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var member1 = classDecl.Members[0]; var member2 = classDecl.Members[1]; var path1 = new SyntaxPath(member1); var path2 = new SyntaxPath(member2); tree = WithReplaceFirst(tree, "bool", "int field; bool"); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.Equal(SyntaxKind.MethodDeclaration, n1.Kind()); Assert.Equal("M1", ((MethodDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n2.Kind()); Assert.Equal("M2", ((MethodDeclarationSyntax)n2).Identifier.ValueText); }
public void TestPP1() { var text = @"namespace N { class C { } struct D { } }"; var text2 = @"namespace N { #if true class C { } struct D { } #endif }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)((CompilationUnitSyntax)tree.GetRoot()).Members[0]; var class1 = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var class2 = (TypeDeclarationSyntax)namespaceDecl.Members[1]; var path1 = new SyntaxPath(class1); var path2 = new SyntaxPath(class2); tree = WithReplace(tree, 0, text.Length, text2); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.Equal(SyntaxKind.ClassDeclaration, n1.Kind()); Assert.Equal("C", ((TypeDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.StructDeclaration, n2.Kind()); Assert.Equal("D", ((TypeDeclarationSyntax)n2).Identifier.ValueText); }
private void TryStartRenameSession(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { var changedDocuments = newSolution.GetChangedDocuments(oldSolution); foreach (var documentId in changedDocuments) { var document = newSolution.GetDocument(documentId); if (!document.SupportsSyntaxTree) { continue; } var root = document.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var renameTokenOpt = root.GetAnnotatedNodesAndTokens(RenameAnnotation.Kind) .Where(s => s.IsToken) .Select(s => s.AsToken()) .FirstOrNullable(); if (renameTokenOpt.HasValue) { // It's possible that the workspace's current solution is not the same as // newSolution. This can happen if the workspace host performs other edits // during ApplyChanges, such as in the Venus scenario where indentation and // formatting can happen. To work around this, we create a SyntaxPath to the // rename token in the newSolution and resolve it to the current solution. var pathToRenameToken = new SyntaxPath(renameTokenOpt.Value); var latestDocument = workspace.CurrentSolution.GetDocument(documentId); var latestRoot = latestDocument.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); SyntaxNodeOrToken resolvedRenameToken; if (pathToRenameToken.TryResolve(latestRoot, out resolvedRenameToken) && resolvedRenameToken.IsToken) { var editorWorkspace = workspace; var navigationService = editorWorkspace.Services.GetService <IDocumentNavigationService>(); if (navigationService.TryNavigateToSpan(editorWorkspace, documentId, resolvedRenameToken.Span)) { var openDocument = workspace.CurrentSolution.GetDocument(documentId); var openRoot = openDocument.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); // NOTE: We need to resolve the syntax path again in case VB line commit kicked in // due to the navigation. // TODO(DustinCa): We still have a potential problem here with VB line commit, // because it can insert tokens and all sorts of other business, which could // wind up with us not being able to resolve the token. if (pathToRenameToken.TryResolve(openRoot, out resolvedRenameToken) && resolvedRenameToken.IsToken) { var snapshot = openDocument.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).FindCorrespondingEditorTextSnapshot(); if (snapshot != null) { _renameService.StartInlineSession(openDocument, resolvedRenameToken.AsToken().Span, cancellationToken); } } } } return; } } }
private static SyntaxNode GetMemberNode(ISyntaxFactsService service, SyntaxNode root, SyntaxPath memberPath) { if (root == null || memberPath == null) { return(null); } SyntaxNode memberNode; if (!memberPath.TryResolve(root, out memberNode)) { return(null); } return(service.IsMethodLevelMember(memberNode) ? memberNode : null); }
public EnvDTE.CodeParameter AddParameter(string name, object type, object position) { return FileCodeModel.EnsureEditor(() => { // The parameters are part of the node key, so we need to update it // after adding a parameter. var node = LookupNode(); var nodePath = new SyntaxPath(node); var parameter = FileCodeModel.AddParameter(this, node, name, type, position); ReaquireNodeKey(nodePath, CancellationToken.None); return parameter; }); }
public void TestAddBase() { var text = @"namespace N { class C { } class D { } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)(tree.GetRoot() as CompilationUnitSyntax).Members[0]; var class1 = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var class2 = (TypeDeclarationSyntax)namespaceDecl.Members[1]; var path1 = new SyntaxPath(class1); var path2 = new SyntaxPath(class2); tree = WithReplaceFirst(tree, "C {", "C : Foo {"); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.Equal(SyntaxKind.ClassDeclaration, n1.Kind()); Assert.Equal("C", ((TypeDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.ClassDeclaration, n2.Kind()); Assert.Equal("D", ((TypeDeclarationSyntax)n2).Identifier.ValueText); }
public void TestMethodBodyChange() { var text = @"namespace N { class C { void M1() { int i1; } void M2() { int i2; } void M3() { int i3; } } }"; var tree = SyntaxFactory.ParseSyntaxTree(text); var namespaceDecl = (NamespaceDeclarationSyntax)(tree.GetRoot() as CompilationUnitSyntax).Members[0]; var classDecl = (TypeDeclarationSyntax)namespaceDecl.Members[0]; var member1 = classDecl.Members[0]; var member2 = classDecl.Members[1]; var member3 = classDecl.Members[2]; var path1 = new SyntaxPath(member1); var path2 = new SyntaxPath(member2); var path3 = new SyntaxPath(member3); tree = WithReplaceFirst(WithReplaceFirst(WithReplaceFirst(tree, "i1", "j1"), "i2", "j2"), "i3", "j3"); Assert.True(path1.TryResolve(tree, CancellationToken.None, out SyntaxNode n1)); Assert.True(path2.TryResolve(tree, CancellationToken.None, out SyntaxNode n2)); Assert.True(path3.TryResolve(tree, CancellationToken.None, out SyntaxNode n3)); Assert.Equal(SyntaxKind.MethodDeclaration, n1.Kind()); Assert.Equal("M1", ((MethodDeclarationSyntax)n1).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n2.Kind()); Assert.Equal("M2", ((MethodDeclarationSyntax)n2).Identifier.ValueText); Assert.Equal(SyntaxKind.MethodDeclaration, n3.Kind()); Assert.Equal("M3", ((MethodDeclarationSyntax)n3).Identifier.ValueText); }