From 6fcd3675130249f70c9cc9f7607972166ce96032 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 30 Jun 2020 16:41:34 -0700 Subject: [PATCH] C# impl done. --- ...ceFactory.SemanticModelWorkspaceService.cs | 6 +- .../SolutionCrawler/WorkCoordinatorTests.cs | 40 ++--- ...CSharpSemanticModelReuseLanguageService.cs | 151 +++++++++++++++++- ...ceFactory.SemanticModelWorkspaceService.cs | 11 +- .../CoreTest/CodeCleanup/CodeCleanupTests.cs | 6 +- src/Workspaces/CoreTest/SymbolKeyTests.cs | 3 +- .../Services/SyntaxFacts/CSharpSyntaxFacts.cs | 66 +------- .../SyntaxFacts/VisualBasicSyntaxFacts.vb | 60 ------- .../CSharpSemanticFactsService.cs | 16 -- .../Core/Extensions/DocumentExtensions.cs | 5 +- .../VisualBasicSemanticFactsService.vb | 36 ----- 11 files changed, 179 insertions(+), 221 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/LanguageServices/SemanticModelWorkspaceService/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs b/src/CodeStyle/Core/CodeFixes/LanguageServices/SemanticModelWorkspaceService/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs index fb9ec0edd95..27b24729a55 100644 --- a/src/CodeStyle/Core/CodeFixes/LanguageServices/SemanticModelWorkspaceService/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs +++ b/src/CodeStyle/Core/CodeFixes/LanguageServices/SemanticModelWorkspaceService/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs @@ -9,11 +9,11 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; -namespace Microsoft.CodeAnalysis.SemanticModelWorkspaceService +namespace Microsoft.CodeAnalysis.SemanticModelReuse { - internal partial class SemanticModelWorkspaceServiceFactory : IWorkspaceServiceFactory + internal partial class SemanticModelReuseWorkspaceServiceFactory : IWorkspaceServiceFactory { - private sealed class SemanticModelService : ISemanticModelService + private sealed class SemanticModelReuseWorkspaceService : ISemanticModelReuseWorkspaceService { public Task ReuseExistingSpeculativeModelAsync(Document document, SyntaxNode node, CancellationToken cancellationToken = default) { diff --git a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs index 0e0e271fc36..4c36e08001f 100644 --- a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs +++ b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs @@ -1063,26 +1063,26 @@ public void Test() await InsertText(code, textToInsert, expectDocumentAnalysis: true); } - [Fact] - public void VBPropertyTest() - { - var markup = @"Class C - Default Public Property G(x As Integer) As Integer - Get - $$ - End Get - Set(value As Integer) - End Set - End Property -End Class"; - MarkupTestFile.GetPosition(markup, out var code, out int position); - - var root = Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseCompilationUnit(code); - var property = root.FindToken(position).Parent.FirstAncestorOrSelf(); - var memberId = Microsoft.CodeAnalysis.VisualBasic.LanguageServices.VisualBasicSyntaxFacts.Instance.GetMethodLevelMemberId(root, property); - - Assert.Equal(0, memberId); - } +// [Fact] +// public void VBPropertyTest() +// { +// var markup = @"Class C +// Default Public Property G(x As Integer) As Integer +// Get +// $$ +// End Get +// Set(value As Integer) +// End Set +// End Property +//End Class"; +// MarkupTestFile.GetPosition(markup, out var code, out int position); + +// var root = Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseCompilationUnit(code); +// var property = root.FindToken(position).Parent.FirstAncestorOrSelf(); +// var memberId = Microsoft.CodeAnalysis.VisualBasic.LanguageServices.VisualBasicSyntaxFacts.Instance.GetMethodLevelMemberId(root, property); + +// Assert.Equal(0, memberId); +// } [Fact, WorkItem(739943, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739943")] public async Task SemanticChange_Propagation_Transitive() diff --git a/src/Workspaces/CSharp/Portable/SemanticModelReuse/CSharpSemanticModelReuseLanguageService.cs b/src/Workspaces/CSharp/Portable/SemanticModelReuse/CSharpSemanticModelReuseLanguageService.cs index a1663935e99..2a0c984ab9e 100644 --- a/src/Workspaces/CSharp/Portable/SemanticModelReuse/CSharpSemanticModelReuseLanguageService.cs +++ b/src/Workspaces/CSharp/Portable/SemanticModelReuse/CSharpSemanticModelReuseLanguageService.cs @@ -4,11 +4,11 @@ #nullable enable -using System; -using System.Collections.Generic; -using System.Text; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.LanguageServices; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.SemanticModelReuse; namespace Microsoft.CodeAnalysis.CSharp.SemanticModelReuse @@ -17,13 +17,152 @@ internal class CSharpSemanticModelReuseLanguageService : ISemanticModelReuseLang { public SyntaxNode? TryGetContainingMethodBodyForSpeculation(SyntaxNode node) { - throw new NotImplementedException(); + for (var current = node; current != null; current = current.Parent) + { + // These are the exact types that SemanticModel.TryGetSpeculativeSemanticModelForMethodBody accepts. + if (node is BaseMethodDeclarationSyntax baseMethod && baseMethod.Body != null) + return node; + + if (node is AccessorDeclarationSyntax accessor && accessor.Body != null) + return node; + } + + return null; } - public Task TryGetSpeculativeSemanticModelAsync( + public async Task TryGetSpeculativeSemanticModelAsync( SemanticModel previousSemanticModel, SyntaxNode currentBodyNode, CancellationToken cancellationToken) { - throw new NotImplementedException(); + var previousRoot = await previousSemanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + var currentRoot = await currentBodyNode.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + + var previousBodyNode = GetPreviousBodyNode(previousRoot, currentRoot, currentBodyNode); + + if (previousBodyNode is BaseMethodDeclarationSyntax previousBaseMethod && + currentBodyNode is BaseMethodDeclarationSyntax currentBaseMethod && + previousBaseMethod.Body != null && + previousSemanticModel.TryGetSpeculativeSemanticModelForMethodBody(previousBaseMethod.Body.SpanStart, currentBaseMethod, out var speculativeModel)) + { + return speculativeModel; + } + + if (previousBodyNode is AccessorDeclarationSyntax previousAccessorDeclaration && + currentBodyNode is AccessorDeclarationSyntax currentAccessorDeclaration && + previousAccessorDeclaration.Body != null && + previousSemanticModel.TryGetSpeculativeSemanticModelForMethodBody(previousAccessorDeclaration.Body.SpanStart, currentAccessorDeclaration, out speculativeModel)) + { + return speculativeModel; + } + + return null; + } + + private static SyntaxNode? GetPreviousBodyNode(SyntaxNode previousRoot, SyntaxNode currentRoot, SyntaxNode currentBodyNode) + { + var currentMembers = CSharpSyntaxFacts.Instance.GetMethodLevelMembers(currentRoot); + var index = currentMembers.IndexOf(currentBodyNode is AccessorDeclarationSyntax + ? currentBodyNode.Parent!.Parent + : currentBodyNode); + if (index < 0) + { + Debug.Fail("Unhandled member type in GetPreviousBodyNode"); + return null; + } + + var previousMembers = CSharpSyntaxFacts.Instance.GetMethodLevelMembers(previousRoot); + if (currentMembers.Count != previousMembers.Count) + { + Debug.Fail("Member count shouldn't have changed as there were no top level edits."); + return null; + } + + var previousBodyNode = previousMembers[index]; + if (!(currentBodyNode is AccessorDeclarationSyntax currentAccessor)) + return previousBodyNode; + + // in the case of an accessor, have to find the previous accessor in the previous prop/event corresponding + // to the current prop/event. + var previousAccessorList = previousBodyNode switch + { + PropertyDeclarationSyntax previousProperty => previousProperty.AccessorList, + EventDeclarationSyntax previousEvent => previousEvent.AccessorList, + _ => null, + }; + + if (previousAccessorList == null) + { + Debug.Fail("Didn't find a corresponding accessor in the previous tree."); + return null; + } + + var accessorIndex = ((AccessorListSyntax)currentAccessor.Parent!).Accessors.IndexOf(currentAccessor); + return previousAccessorList.Accessors[accessorIndex]; } + + //public int GetMethodLevelMemberId(SyntaxNode root, SyntaxNode node) + //{ + // Debug.Assert(root.SyntaxTree == node.SyntaxTree); + + // var currentId = 0; + // Contract.ThrowIfFalse(TryGetMethodLevelMember(root, (n, i) => n == node, ref currentId, out var currentNode)); + + // Contract.ThrowIfFalse(currentId >= 0); + // CheckMemberId(root, node, currentId); + // return currentId; + //} + + //public SyntaxNode GetMethodLevelMember(SyntaxNode root, int memberId) + //{ + // var currentId = 0; + // if (!TryGetMethodLevelMember(root, (n, i) => i == memberId, ref currentId, out var currentNode)) + // { + // return null; + // } + + // Contract.ThrowIfNull(currentNode); + // CheckMemberId(root, currentNode, memberId); + // return currentNode; + //} + + //private void GetMethodLevelMember( + // SyntaxNode node, Func predicate, out int resultId, out SyntaxNode? resultNode) + //{ + // resultId = 0; + // resultNode = null; + + // GetMethodLevelMemberWorker(node, predicate, ref resultId, ref resultNode); + + // static GetMethodLevelMember(SyntaxNode node, Func predicate, ref int resultId, ref SyntaxNode? resultNode) + // { + // foreach (var member in node.) + // } + + // foreach (var member in node.GetMembers()) + // { + // if (IsTopLevelNodeWithMembers(member)) + // { + // if (TryGetMethodLevelMember(member, predicate, ref currentId, out currentNode)) + // { + // return true; + // } + + // continue; + // } + + // if (IsMethodLevelMember(member)) + // { + // if (predicate(member, currentId)) + // { + // currentNode = member; + // return true; + // } + + // currentId++; + // } + // } + + // currentNode = null; + // return false; + //} } } diff --git a/src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs b/src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs index a4eac539821..cd6d5b839a7 100644 --- a/src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs +++ b/src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelWorkspaceServiceFactory.SemanticModelWorkspaceService.cs @@ -4,18 +4,11 @@ #nullable enable -using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -42,7 +35,7 @@ private sealed class SemanticModelReuseWorkspaceService : ISemanticModelReuseWor public async Task ReuseExistingSpeculativeModelAsync( Document document, SyntaxNode node, CancellationToken cancellationToken) { - var reuseService = document.GetRequiredLanguageService(); + var reuseService = document.GetRequiredLanguageService(); // See if we're asking about a node actually in a method body. If so, see if we can reuse the // existing semantic model. If not, return the current semantic model for the file. @@ -126,7 +119,7 @@ private sealed class SemanticModelReuseWorkspaceService : ISemanticModelReuseWor if (cachedBodyNode == bodyNode) return cachedSemanticModel; - var reuseService = document.GetRequiredLanguageService(); + var reuseService = document.GetRequiredLanguageService(); return await reuseService.TryGetSpeculativeSemanticModelAsync(cachedSemanticModel, bodyNode, cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs b/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs index 64dffa40c97..a62a66c4d94 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeCleanup.Providers; -using Microsoft.CodeAnalysis.SemanticModelWorkspaceService; +using Microsoft.CodeAnalysis.SemanticModelReuse; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; @@ -230,8 +230,8 @@ End Class var semanticModel = await document.GetSemanticModelAsync(); var root = await document.GetSyntaxRootAsync(); var accessor = root.DescendantNodes().OfType().Last(); - var factory = new SemanticModelWorkspaceServiceFactory(); - var service = (ISemanticModelService)factory.CreateService(document.Project.Solution.Workspace.Services); + var factory = new SemanticModelReuseWorkspaceServiceFactory(); + var service = (ISemanticModelReuseWorkspaceService)factory.CreateService(document.Project.Solution.Workspace.Services); var newSemanticModel = await service.ReuseExistingSpeculativeModelAsync(document, accessor, CancellationToken.None); Assert.NotNull(newSemanticModel); var newDocument = CreateDocument(code, LanguageNames.VisualBasic); diff --git a/src/Workspaces/CoreTest/SymbolKeyTests.cs b/src/Workspaces/CoreTest/SymbolKeyTests.cs index f099dd77d18..aa29fe7e220 100644 --- a/src/Workspaces/CoreTest/SymbolKeyTests.cs +++ b/src/Workspaces/CoreTest/SymbolKeyTests.cs @@ -635,7 +635,8 @@ void goo() var basemethod2 = tree2.FindTokenOnLeftOfPosition(position, CancellationToken.None).GetAncestor(); var service = CSharp.CSharpSemanticFactsService.Instance; - var m = service.TryGetSpeculativeSemanticModel(firstModel, basemethod1, basemethod2, out var testModel); + var testModel = await document.ReuseExistingSpeculativeModelAsync(position, CancellationToken.None); + Assert.True(testModel.IsSpeculativeSemanticModel); var xSymbol = testModel.LookupSymbols(position).First(s => s.Name == "x"); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs index f5f4477862b..d9b948b26cf 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs @@ -730,6 +730,7 @@ public bool IsMethodLevelMember(SyntaxNode node) { return node is BaseMethodDeclarationSyntax || node is BasePropertyDeclarationSyntax || + node is EventDeclarationSyntax || node is EnumMemberDeclarationSyntax || node is BaseFieldDeclarationSyntax; } @@ -978,71 +979,6 @@ public bool ContainsInMemberBody(SyntaxNode node, TextSpan span) private static TextSpan GetBlockBodySpan(BlockSyntax body) => TextSpan.FromBounds(body.OpenBraceToken.Span.End, body.CloseBraceToken.SpanStart); - public int GetMethodLevelMemberId(SyntaxNode root, SyntaxNode node) - { - Debug.Assert(root.SyntaxTree == node.SyntaxTree); - - var currentId = 0; - Contract.ThrowIfFalse(TryGetMethodLevelMember(root, (n, i) => n == node, ref currentId, out var currentNode)); - - Contract.ThrowIfFalse(currentId >= 0); - CheckMemberId(root, node, currentId); - return currentId; - } - - public SyntaxNode GetMethodLevelMember(SyntaxNode root, int memberId) - { - var currentId = 0; - if (!TryGetMethodLevelMember(root, (n, i) => i == memberId, ref currentId, out var currentNode)) - { - return null; - } - - Contract.ThrowIfNull(currentNode); - CheckMemberId(root, currentNode, memberId); - return currentNode; - } - - private bool TryGetMethodLevelMember( - SyntaxNode node, Func predicate, ref int currentId, out SyntaxNode currentNode) - { - foreach (var member in node.GetMembers()) - { - if (IsTopLevelNodeWithMembers(member)) - { - if (TryGetMethodLevelMember(member, predicate, ref currentId, out currentNode)) - { - return true; - } - - continue; - } - - if (IsMethodLevelMember(member)) - { - if (predicate(member, currentId)) - { - currentNode = member; - return true; - } - - currentId++; - } - } - - currentNode = null; - return false; - } - - [Conditional("DEBUG")] - private void CheckMemberId(SyntaxNode root, SyntaxNode node, int memberId) - { - var list = GetMethodLevelMembers(root); - var index = list.IndexOf(node); - - Contract.ThrowIfFalse(index == memberId); - } - #nullable enable public SyntaxNode? TryGetBindableParent(SyntaxToken token) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb index 5b056c94605..8c2df8a58cf 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb @@ -1065,66 +1065,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices Next End Sub - Public Function GetMethodLevelMemberId(root As SyntaxNode, node As SyntaxNode) As Integer Implements ISyntaxFacts.GetMethodLevelMemberId - Debug.Assert(root.SyntaxTree Is node.SyntaxTree) - - Dim currentId As Integer = Nothing - Dim currentNode As SyntaxNode = Nothing - Contract.ThrowIfFalse(TryGetMethodLevelMember(root, Function(n, i) n Is node, currentId, currentNode)) - - Contract.ThrowIfFalse(currentId >= 0) - CheckMemberId(root, node, currentId) - - Return currentId - End Function - - Public Function GetMethodLevelMember(root As SyntaxNode, memberId As Integer) As SyntaxNode Implements ISyntaxFacts.GetMethodLevelMember - Dim currentId As Integer = Nothing - Dim currentNode As SyntaxNode = Nothing - - If Not TryGetMethodLevelMember(root, Function(n, i) i = memberId, currentId, currentNode) Then - Return Nothing - End If - - Contract.ThrowIfNull(currentNode) - CheckMemberId(root, currentNode, memberId) - - Return currentNode - End Function - - Private Function TryGetMethodLevelMember(node As SyntaxNode, predicate As Func(Of SyntaxNode, Integer, Boolean), ByRef currentId As Integer, ByRef currentNode As SyntaxNode) As Boolean - For Each member In node.GetMembers() - If TypeOf member Is NamespaceBlockSyntax OrElse - TypeOf member Is TypeBlockSyntax OrElse - TypeOf member Is EnumBlockSyntax Then - If TryGetMethodLevelMember(member, predicate, currentId, currentNode) Then - Return True - End If - - Continue For - End If - - If IsMethodLevelMember(member) Then - If predicate(member, currentId) Then - currentNode = member - Return True - End If - - currentId += 1 - End If - Next - - currentNode = Nothing - Return False - End Function - - - Private Sub CheckMemberId(root As SyntaxNode, node As SyntaxNode, memberId As Integer) - Dim list = GetMethodLevelMembers(root) - Dim index = list.IndexOf(node) - Contract.ThrowIfFalse(index = memberId) - End Sub - Public Function TryGetBindableParent(token As SyntaxToken) As SyntaxNode Implements ISyntaxFacts.TryGetBindableParent Dim node = token.Parent While node IsNot Nothing diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSemanticFactsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSemanticFactsService.cs index 19dd5b06600..4ea9d7e6edc 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSemanticFactsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSemanticFactsService.cs @@ -181,22 +181,6 @@ public bool LastEnumValueHasInitializer(INamedTypeSymbol namedTypeSymbol) public bool SupportsParameterizedProperties => false; - public bool TryGetSpeculativeSemanticModel(SemanticModel oldSemanticModel, SyntaxNode oldNode, SyntaxNode newNode, out SemanticModel speculativeModel) - { - Debug.Assert(oldNode.Kind() == newNode.Kind()); - - var model = oldSemanticModel; - if (!(oldNode is BaseMethodDeclarationSyntax oldMethod) || !(newNode is BaseMethodDeclarationSyntax newMethod) || oldMethod.Body == null) - { - speculativeModel = null; - return false; - } - - var success = model.TryGetSpeculativeSemanticModelForMethodBody(oldMethod.Body.OpenBraceToken.Span.End, newMethod, out var csharpModel); - speculativeModel = csharpModel; - return success; - } - public ImmutableHashSet GetAliasNameSet(SemanticModel model, CancellationToken cancellationToken) { var original = model.GetOriginalSemanticModel(); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs index f7da40dc8a3..a8adda1339a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs @@ -12,7 +12,7 @@ using Microsoft.CodeAnalysis.GeneratedCodeRecognition; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServices; -using Microsoft.CodeAnalysis.SemanticModelWorkspaceService; +using Microsoft.CodeAnalysis.SemanticModelReuse; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -131,8 +131,9 @@ public static Task ReuseExistingSpeculativeModelAsync(this Docume private static Task ReuseExistingSpeculativeModelAsync( Document document, SyntaxNode node, TextSpan span, CancellationToken cancellationToken) { + var workspace = document.Project.Solution.Workspace; var syntaxFactService = document.GetRequiredLanguageService(); - var semanticModelService = document.Project.Solution.Workspace.Services.GetRequiredService(); + var semanticModelService = workspace.Services.GetRequiredService(); // check whether given span is a valid span to do speculative binding var speculativeBindingSpan = syntaxFactService.GetMemberBodySpanForSpeculativeBinding(node); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSemanticFactsService.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSemanticFactsService.vb index aa6eeab5496..bb7d190e230 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSemanticFactsService.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSemanticFactsService.vb @@ -200,42 +200,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property - Public Function TryGetSpeculativeSemanticModel(oldSemanticModel As SemanticModel, oldNode As SyntaxNode, newNode As SyntaxNode, ByRef speculativeModel As SemanticModel) As Boolean Implements ISemanticFactsService.TryGetSpeculativeSemanticModel - Debug.Assert(oldNode.Kind = newNode.Kind) - - Dim model = oldSemanticModel - - ' currently we only support method. field support will be added later. - Dim oldMethod = TryCast(oldNode, MethodBlockBaseSyntax) - Dim newMethod = TryCast(newNode, MethodBlockBaseSyntax) - If oldMethod Is Nothing OrElse newMethod Is Nothing Then - speculativeModel = Nothing - Return False - End If - - ' No method body? - If oldMethod.Statements.IsEmpty AndAlso oldMethod.EndBlockStatement.IsMissing Then - speculativeModel = Nothing - Return False - End If - - Dim position As Integer - If model.IsSpeculativeSemanticModel Then - ' Chaining speculative semantic model is not supported, use the original model. - position = model.OriginalPositionForSpeculation - model = model.ParentModel - Contract.ThrowIfNull(model) - Contract.ThrowIfTrue(model.IsSpeculativeSemanticModel) - Else - position = oldMethod.BlockStatement.FullSpan.End - End If - - Dim vbSpeculativeModel As SemanticModel = Nothing - Dim success = model.TryGetSpeculativeSemanticModelForMethodBody(position, newMethod, vbSpeculativeModel) - speculativeModel = vbSpeculativeModel - Return success - End Function - Public Function GetAliasNameSet(model As SemanticModel, cancellationToken As CancellationToken) As ImmutableHashSet(Of String) Implements ISemanticFactsService.GetAliasNameSet Dim original = DirectCast(model.GetOriginalSemanticModel(), SemanticModel) -- GitLab