提交 b78dd596 编写于 作者: G Gen Lu

Merge remote-tracking branch 'dotnet/stabilization' into InteractivePasteStable

......@@ -154,12 +154,23 @@ internal interface ISymUnmanagedWriter6 : ISymUnmanagedWriter5
void InitializeDeterministic([MarshalAs(UnmanagedType.IUnknown)] object emitter, [MarshalAs(UnmanagedType.IUnknown)] object stream);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("22DAEAF2-70F6-4EF1-B0C3-984F0BF27BFD"), SuppressUnmanagedCodeSecurity]
interface ISymUnmanagedWriter7 : ISymUnmanagedWriter6
{
// ISymUnmanagedWriter, ISymUnmanagedWriter2, ISymUnmanagedWriter3, ISymUnmanagedWriter4, ISymUnmanagedWriter5, ISymUnmanagedWriter6
void _VtblGap1_34();
// ISymUnmanagedWriter7
unsafe void UpdateSignatureByHashingContent([In]byte* buffer, int size);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B473C610-C958-4C3D-99A0-F2BA0A38807C"), SuppressUnmanagedCodeSecurity]
interface ISymUnmanagedWriter100 : ISymUnmanagedWriter6
{
// ISymUnmanagedWriter, ISymUnmanagedWriter2, ISymUnmanagedWriter3, ISymUnmanagedWriter4, ISymUnmanagedWriter5, ISymUnmanagedWriter6
void _VtblGap1_34();
// ISymUnmanagedWriter100
void SetSignature(uint sig, Guid sig70);
}
......
......@@ -82,7 +82,7 @@ private void MaybeFlush()
}
}
internal ContentId ContentIdFromLog()
internal byte[] GetLogHash()
{
Debug.Assert(_logData != null);
......@@ -104,7 +104,7 @@ internal ContentId ContentIdFromLog()
Debug.Assert(remaining == 0);
_logData.Clear();
return ContentId.FromHash(_hashAlgorithm.Hash.ToImmutableArray());
return _hashAlgorithm.Hash;
}
internal void Close()
......@@ -813,13 +813,12 @@ public void SetMetadataEmitter(MetadataWriter metadataWriter)
if (_deterministic)
{
var deterministicSymWriter = symWriter as ISymUnmanagedWriter6;
if (deterministicSymWriter == null)
if (!(symWriter is ISymUnmanagedWriter7 || symWriter is ISymUnmanagedWriter100))
{
throw new NotSupportedException(CodeAnalysisResources.SymWriterNotDeterministic);
}
deterministicSymWriter.InitializeDeterministic(new PdbMetadataWrapper(metadataWriter), _pdbStream);
((ISymUnmanagedWriter6)symWriter).InitializeDeterministic(new PdbMetadataWrapper(metadataWriter), _pdbStream);
}
else
{
......@@ -839,20 +838,32 @@ public unsafe ContentId GetContentId()
{
if (_deterministic)
{
// Call to GetDebugInfo fails for SymWriter initialized using InitializeDeterministic.
// We already have all the info we need though.
var id = _callLogger.ContentIdFromLog();
// rewrite GUID and timestamp in the PDB with hash of a has of the log content:
byte[] hash = _callLogger.GetLogHash();
try
{
// TODO: remove once we can rely on the presence of ISymUnmanagedWriter7
var writer100 = _symWriter as ISymUnmanagedWriter100;
if (writer100 != null)
{
var id = ContentId.FromHash(ImmutableArray.CreateRange(hash));
Debug.Assert(BitConverter.IsLittleEndian);
((ISymUnmanagedWriter100)_symWriter).SetSignature(BitConverter.ToUInt32(id.Stamp, 0), new Guid(id.Guid));
writer100.SetSignature(BitConverter.ToUInt32(id.Stamp, 0), new Guid(id.Guid));
return id;
}
fixed (byte* hashPtr = &hash[0])
{
((ISymUnmanagedWriter7)_symWriter).UpdateSignatureByHashingContent(hashPtr, hash.Length);
}
}
catch (Exception ex)
{
throw new PdbWritingException(ex);
}
return id;
}
// See symwrite.cpp - the data byte[] doesn't depend on the content of metadata tables or IL.
......
......@@ -168,7 +168,7 @@ class Class
{
void Method()
{
[|int x = 0, y = 0;|]
[|int x = 0, y = 0; string s;|]
}
}";
using (var workspace = CreateWorkspaceFromFile(source, parseOptions: null, compilationOptions: null))
......@@ -186,19 +186,28 @@ void Method()
TextSpan span;
var document = GetDocumentAndSelectSpan(workspace, out span);
var diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, span)
.WaitAndGetResult(CancellationToken.None)
.Where(d => d.Id == "CS0219");
Assert.Equal(2, diagnostics.Count());
.WaitAndGetResult(CancellationToken.None);
Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());
var fixes = fixService.GetFixesAsync(document, span, includeSuppressionFixes: true, cancellationToken: CancellationToken.None)
var allFixes = fixService.GetFixesAsync(document, span, includeSuppressionFixes: true, cancellationToken: CancellationToken.None)
.WaitAndGetResult(CancellationToken.None)
.SelectMany(fixCollection => fixCollection.Fixes)
.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");
.SelectMany(fixCollection => fixCollection.Fixes);
var cs0219Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");
// Ensure that both the fixes have identical equivalence key, and hence get de-duplicated in LB menu.
Assert.Equal(2, fixes.Count());
Assert.NotNull(fixes.First().Action.EquivalenceKey);
Assert.Equal(fixes.First().Action.EquivalenceKey, fixes.Last().Action.EquivalenceKey);
Assert.Equal(2, cs0219Fixes.Count());
var cs0219EquivalenceKey = cs0219Fixes.First().Action.EquivalenceKey;
Assert.NotNull(cs0219EquivalenceKey);
Assert.Equal(cs0219EquivalenceKey, cs0219Fixes.Last().Action.EquivalenceKey);
// Ensure that there *is* a fix for the other warning and that it has a *different*
// equivalence key so that it *doesn't* get de-duplicated
Assert.Equal(1, diagnostics.Where(d => d.Id == "CS0168").Count());
var cs0168Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0168");
var cs0168EquivalenceKey = cs0168Fixes.Single().Action.EquivalenceKey;
Assert.NotNull(cs0168EquivalenceKey);
Assert.NotEqual(cs0219EquivalenceKey, cs0168EquivalenceKey);
}
}
......
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.SymbolMapping;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
......@@ -50,6 +51,8 @@ internal void FindReferences(ITextSnapshot snapshot, int caretPosition)
{
var service = document.Project.LanguageServices.GetService<IFindReferencesService>();
if (service != null)
{
using (Logger.LogBlock(FunctionId.CommandHandler_FindAllReference, context.CancellationToken))
{
if (!service.TryFindReferences(document, caretPosition, context))
{
......@@ -61,6 +64,7 @@ internal void FindReferences(ITextSnapshot snapshot, int caretPosition)
}
}
}
}
}, allowCancel: true);
}
......
......@@ -7687,7 +7687,7 @@ End Class
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(995855)>
Public Sub VisualBasic_Remove_UnnecessaryCastInTernaryExpression()
Public Sub VisualBasic_DontRemove_NecessaryCastInTernaryExpression1()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
......@@ -7696,7 +7696,109 @@ Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, {|Simplify:CByte(0)|}, {|Simplify:CByte(0)|})
s += If(i = 0, CByte(0), {|Simplify:CByte(0)|})
End Sub
End Class
]]>
</Document>
</Project>
</Workspace>
Dim expected =
<code><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, CByte(0), CByte(0))
End Sub
End Class
]]>
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(995855)>
Public Sub VisualBasic_DontRemove_NecessaryCastInTernaryExpression2()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, {|Simplify:CByte(0)|}, CByte(0))
End Sub
End Class
]]>
</Document>
</Project>
</Workspace>
Dim expected =
<code><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, CByte(0), CByte(0))
End Sub
End Class
]]>
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(995855)>
Public Sub VisualBasic_Remove_UnnecessaryCastInTernaryExpression1()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, 0, {|Simplify:CByte(0)|})
End Sub
End Class
]]>
</Document>
</Project>
</Workspace>
Dim expected =
<code><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, 0, 0)
End Sub
End Class
]]>
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(995855)>
Public Sub VisualBasic_Remove_UnnecessaryCastInTernaryExpression2()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document><![CDATA[
Class C
Private Shared Sub Main(args As String())
Dim s As Byte = 0
Dim i As Integer = 0
s += If(i = 0, {|Simplify:CByte(0)|}, 0)
End Sub
End Class
]]>
......@@ -8201,6 +8303,165 @@ Class C
End Sub
End Class
]]>
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub VisualBasic_Remove_IntegerToByte_OptionStrictOff()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Option Strict Off
Class C
Sub M()
Dim b As Byte
b += {|Simplify:CByte(1)|}
End Sub
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Option Strict Off
Class C
Sub M()
Dim b As Byte
b += 1
End Sub
End Class
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub VisualBasic_DontRemove_IntegerToByte_OptionStrictOn1()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Option Strict On
Class C
Sub M()
Dim b As Byte
b += {|Simplify:CByte(1)|}
End Sub
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Option Strict On
Class C
Sub M()
Dim b As Byte
b += CByte(1)
End Sub
End Class
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub VisualBasic_DontRemove_IntegerToByte_OptionStrictOn2()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Option Strict On
Class C
Sub M()
Dim b As Byte
Const x = 1
b += {|Simplify:CByte(x)|}
End Sub
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Option Strict On
Class C
Sub M()
Dim b As Byte
Const x = 1
b += CByte(x)
End Sub
End Class
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub VisualBasic_DontRemove_IntegerToByte_OptionStrictOn3()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Option Strict On
Class C
Sub M()
Dim b As Byte
Dim x As Integer = 1
b += {|Simplify:CByte(x)|}
End Sub
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Option Strict On
Class C
Sub M()
Dim b As Byte
Dim x As Integer = 1
b += CByte(x)
End Sub
End Class
</code>
Test(input, expected)
End Sub
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub VisualBasic_DontRemove_IntegerToByte_OptionStrictOn4()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Option Strict On
Class C
Sub M()
Dim b As Byte
b = b + {|Simplify:CByte(1)|}
End Sub
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Option Strict On
Class C
Sub M()
Dim b As Byte
b = b + CByte(1)
End Sub
End Class
</code>
Test(input, expected)
......
......@@ -13,67 +13,10 @@ namespace Roslyn.Test.Utilities
{
public static class WaitHelper
{
/// <summary>
/// This is a hueristic for checking to see if we are in a deadlock state because
/// we are waiting on a Task that may be in the StaTaskScheduler queue from the
/// main thread.
/// </summary>
/// <param name="tasks"></param>
private static void CheckForStaDeadlockInPumpingWait(IEnumerable<Task> tasks)
{
var sta = StaTaskScheduler.DefaultSta;
Debug.Assert(sta.Threads.Length == 1);
if (Thread.CurrentThread != sta.Threads[0])
{
return;
}
if (tasks.Any(x => x.Status == TaskStatus.WaitingForActivation) && sta.IsAnyQueued())
{
throw new InvalidOperationException("PumingWait is likely in a deadlock");
}
}
public static void WaitForDispatchedOperationsToComplete(DispatcherPriority priority)
{
Action action = delegate { };
new FrameworkElement().Dispatcher.Invoke(action, priority);
}
public static void PumpingWait(this Task task)
{
PumpingWaitAll(new[] { task });
}
public static T PumpingWaitResult<T>(this Task<T> task)
{
PumpingWait(task);
return task.Result;
}
public static void PumpingWaitAll(this IEnumerable<Task> tasks)
{
var smallTimeout = TimeSpan.FromMilliseconds(10);
var taskArray = tasks.ToArray();
var done = false;
while (!done)
{
done = Task.WaitAll(taskArray, smallTimeout);
if (!done)
{
WaitForDispatchedOperationsToComplete(DispatcherPriority.ApplicationIdle);
CheckForStaDeadlockInPumpingWait(tasks);
}
}
foreach (var task in tasks)
{
if (task.Exception != null)
{
throw task.Exception;
}
}
}
}
}
\ No newline at end of file
......@@ -467,6 +467,13 @@ NewLines("Class AwesomeClass \n Sub M() \n Dim foo = New AwesomeClass() \n End S
index:=0)
End Sub
<WorkItem(6338, "https://github.com/dotnet/roslyn/issues/6338")>
<WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)>
Public Sub TestMissingName()
TestMissing(
NewLines("<Assembly: Microsoft.CodeAnalysis.[||]>"))
End Sub
Public Class AddImportTestsWithAddImportDiagnosticProvider
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
......
......@@ -9,24 +9,8 @@ namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
internal sealed class SuppressionCodeAction : CodeAction.SimpleCodeAction
{
public SuppressionCodeAction(Diagnostic diagnostic, IEnumerable<CodeAction> nestedActions)
: base(string.Format(FeaturesResources.SuppressionCodeActionTitle, diagnostic.Id), nestedActions.AsImmutableOrEmpty(), ComputeEquivalenceKey(nestedActions))
: base(string.Format(FeaturesResources.SuppressionCodeActionTitle, diagnostic.Id), nestedActions.AsImmutableOrEmpty())
{
}
private static string ComputeEquivalenceKey(IEnumerable<CodeAction> nestedActions)
{
if (nestedActions == null)
{
return null;
}
var equivalenceKey = string.Empty;
foreach (var action in nestedActions)
{
equivalenceKey += (action.EquivalenceKey ?? action.GetHashCode().ToString() + ";");
}
return equivalenceKey;
}
}
}
......@@ -79,7 +79,7 @@ protected AbstractGenerateTypeService()
// Wrap the generate type actions into a single top level suggestion
// so as to not clutter the list.
return SpecializedCollections.SingletonEnumerable(
new MyCodeAction(FeaturesResources.Generate_type, actions.AsImmutable(), actions[0].EquivalenceKey));
new MyCodeAction(FeaturesResources.Generate_type, actions.AsImmutable()));
}
else
{
......@@ -295,8 +295,8 @@ protected bool GeneratedTypesMustBePublic(Project project)
private class MyCodeAction : CodeAction.SimpleCodeAction
{
public MyCodeAction(string title, ImmutableArray<CodeAction> nestedActions, string equivalenceKey)
: base(title, nestedActions, equivalenceKey)
public MyCodeAction(string title, ImmutableArray<CodeAction> nestedActions)
: base(title, nestedActions)
{
}
}
......
......@@ -37,7 +37,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
// Only bother with identifiers that are at least 3 characters long.
// We don't want to be too noisy as you're just starting to type something.
var nameText = name.GetFirstToken().ValueText;
if (nameText.Length >= 3)
if (nameText?.Length >= 3)
{
semanticModel = semanticModel ?? await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var symbolInfo = semanticModel.GetSymbolInfo(name, cancellationToken);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
......@@ -9,9 +10,9 @@
namespace Microsoft.CodeAnalysis.Host
{
internal class BackgroundCompiler
internal class BackgroundCompiler : IDisposable
{
private readonly Workspace _workspace;
private Workspace _workspace;
private readonly IWorkspaceTaskScheduler _compilationScheduler;
private readonly IWorkspaceTaskScheduler _notificationQueue;
......@@ -33,12 +34,21 @@ public BackgroundCompiler(Workspace workspace)
_notificationQueue = taskSchedulerFactory.CreateTaskQueue();
_cancellationSource = new CancellationTokenSource();
_workspace.WorkspaceChanged += this.OnWorkspaceChanged;
_workspace.DocumentOpened += OnDocumentOpened;
_workspace.DocumentClosed += OnDocumentClosed;
}
var editorWorkspace = workspace as Workspace;
if (editorWorkspace != null)
public void Dispose()
{
if (_workspace != null)
{
editorWorkspace.DocumentOpened += OnDocumentOpened;
editorWorkspace.DocumentClosed += OnDocumentClosed;
this.CancelBuild(releasePreviousCompilations: true);
_workspace.DocumentClosed -= OnDocumentClosed;
_workspace.DocumentOpened -= OnDocumentOpened;
_workspace.WorkspaceChanged -= this.OnWorkspaceChanged;
_workspace = null;
}
}
......
......@@ -1456,51 +1456,24 @@ public void HostObjectAssemblyReference1()
// (1,8): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Microsoft.CodeAnalysis").WithArguments("CodeAnalysis", "Microsoft"));
scriptCompilation.VerifyAssemblyAliases(
"mscorlib: global,<host>",
"Microsoft.CodeAnalysis.Scripting: <host>",
"System.Collections.Immutable: <implicit>,<host>",
"Microsoft.CodeAnalysis: <implicit>,<host>",
"System.Diagnostics.Tools: <implicit>,<host>",
"System.Resources.ResourceManager: <implicit>,<host>",
"System.Console: <implicit>,<host>",
"System.Diagnostics.StackTrace: <implicit>,<host>",
"System.IO.FileSystem: <implicit>,<host>",
"System.Linq: <implicit>,<host>",
"System.Text.Encoding: <implicit>,<host>",
"System.IO.FileSystem.Primitives: <implicit>,<host>",
"System.Reflection.Extensions: <implicit>,<host>",
"System.Core: <implicit>,<host>",
"System: <implicit>,<host>",
"System.Xml: <implicit>,<host>",
"System.Numerics: <implicit>,<host>",
"System.Security: <implicit>,<host>",
"System.Data.SqlXml: <implicit>,<host>",
"System.Configuration: <implicit>,<host>",
"System.Runtime: <implicit>,<host>",
"System.Diagnostics.Debug: <implicit>,<host>",
"System.Runtime.InteropServices: <implicit>,<host>",
"System.Reflection.Metadata: <implicit>,<host>",
"System.IO: <implicit>,<host>",
"System.Collections: <implicit>,<host>",
"System.Threading.Tasks: <implicit>,<host>",
"System.Reflection.Primitives: <implicit>,<host>",
"System.Reflection: <implicit>,<host>",
"System.Globalization: <implicit>,<host>",
"System.Runtime.Extensions: <implicit>,<host>",
"System.Runtime.Numerics: <implicit>,<host>",
"System.Runtime.Serialization.Json: <implicit>,<host>",
"System.Collections.Concurrent: <implicit>,<host>",
"System.Xml.ReaderWriter: <implicit>,<host>",
"System.Xml.XDocument: <implicit>,<host>",
"System.Dynamic.Runtime: <implicit>,<host>",
"System.Threading: <implicit>,<host>",
"System.Text.Encoding.Extensions: <implicit>,<host>",
"System.Xml.Linq: <implicit>,<host>",
"System.Runtime.Serialization: <implicit>,<host>",
"System.ServiceModel.Internals: <implicit>,<host>",
"SMDiagnostics: <implicit>,<host>",
"System.ComponentModel.Composition: <implicit>,<host>");
foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
{
switch (assemblyAndAliases.Item1.Identity.Name)
{
case "mscorlib":
AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.Scripting":
AssertEx.SetEqual(new[] { "<host>" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis":
default:
AssertEx.SetEqual(new[] { "<implicit>", "<host>" }, assemblyAndAliases.Item2);
break;
}
}
}
[Fact]
......@@ -1513,56 +1486,33 @@ public void HostObjectAssemblyReference2()
scriptCompilation.VerifyDiagnostics();
scriptCompilation.VerifyAssemblyAliases(
"mscorlib: global,<host>",
"Microsoft.CodeAnalysis.Scripting: <host>,global",
"Microsoft.CodeAnalysis.Scripting.CSharp",
"Microsoft.CodeAnalysis.CSharp: <implicit>,global",
"Microsoft.CodeAnalysis: <implicit>,<host>,global",
"System.Collections.Immutable: <implicit>,<host>,global",
"System.Diagnostics.Tools: <implicit>,<host>,global",
"System.Resources.ResourceManager: <implicit>,<host>,global",
"System.Text.Encoding: <implicit>,<host>,global",
"System.AppContext: <implicit>,global",
"System.Reflection.Extensions: <implicit>,<host>,global",
"System: <implicit>,<host>,global",
"System.Configuration: <implicit>,<host>,global",
"System.Xml: <implicit>,<host>,global",
"System.Data.SqlXml: <implicit>,<host>,global",
"System.Security: <implicit>,<host>,global",
"System.Core: <implicit>,<host>,global",
"System.Numerics: <implicit>,<host>,global",
"System.Runtime: <implicit>,<host>,global",
"System.Diagnostics.Debug: <implicit>,<host>,global",
"System.Collections: <implicit>,<host>,global",
"System.Linq: <implicit>,<host>,global",
"System.Runtime.Extensions: <implicit>,<host>,global",
"System.Globalization: <implicit>,<host>,global",
"System.Threading: <implicit>,<host>,global",
"System.ComponentModel.Composition: <implicit>,<host>,global",
"System.Runtime.InteropServices: <implicit>,<host>,global",
"System.Reflection.Metadata: <implicit>,<host>,global",
"System.IO: <implicit>,<host>,global",
"System.Threading.Tasks: <implicit>,<host>,global",
"System.Reflection.Primitives: <implicit>,<host>,global",
"System.Reflection: <implicit>,<host>,global",
"System.Runtime.Numerics: <implicit>,<host>,global",
"System.Runtime.Serialization.Json: <implicit>,<host>,global",
"System.Collections.Concurrent: <implicit>,<host>,global",
"System.Xml.ReaderWriter: <implicit>,<host>,global",
"System.Xml.XDocument: <implicit>,<host>,global",
"System.Dynamic.Runtime: <implicit>,<host>,global",
"System.Text.Encoding.Extensions: <implicit>,<host>,global",
"System.Xml.Linq: <implicit>,<host>,global",
"System.Runtime.Serialization: <implicit>,<host>,global",
"System.ServiceModel.Internals: <implicit>,<host>,global",
"SMDiagnostics: <implicit>,<host>,global",
"System.Linq.Expressions: <implicit>,global",
"System.Threading.Tasks.Parallel: <implicit>,global",
"System.Console: <implicit>,<host>,global",
"System.Diagnostics.StackTrace: <implicit>,<host>,global",
"System.IO.FileSystem: <implicit>,<host>,global",
"System.IO.FileSystem.Primitives: <implicit>,<host>,global");
foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
{
switch (assemblyAndAliases.Item1.Identity.Name)
{
case "mscorlib":
AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.Scripting":
AssertEx.SetEqual(new[] { "<host>", "global" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.CSharp.Scripting":
AssertEx.SetEqual(new string[0], assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.CSharp":
AssertEx.SetEqual(new[] { "<implicit>", "global" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis":
case "System.IO":
case "System.Collections.Immutable":
AssertEx.SetEqual(new[] { "<implicit>", "<host>", "global" }, assemblyAndAliases.Item2);
break;
}
}
}
[Fact]
......@@ -1576,56 +1526,33 @@ public void HostObjectAssemblyReference3()
scriptCompilation.VerifyDiagnostics();
scriptCompilation.VerifyAssemblyAliases(
"Microsoft.CodeAnalysis.Scripting.CSharp",
"mscorlib: global,<host>",
"Microsoft.CodeAnalysis.Scripting: global,<host>",
"System.Collections.Immutable: <implicit>,global,<host>",
"Microsoft.CodeAnalysis: <implicit>,global,<host>",
"System.Diagnostics.Tools: <implicit>,global,<host>",
"System.Resources.ResourceManager: <implicit>,global,<host>",
"System.Console: <implicit>,global,<host>",
"System.Diagnostics.StackTrace: <implicit>,global,<host>",
"System.IO.FileSystem: <implicit>,global,<host>",
"System.Linq: <implicit>,global,<host>",
"System.Text.Encoding: <implicit>,global,<host>",
"System.IO.FileSystem.Primitives: <implicit>,global,<host>",
"System.Reflection.Extensions: <implicit>,global,<host>",
"System.Core: <implicit>,global,<host>",
"System: <implicit>,global,<host>",
"System.Xml: <implicit>,global,<host>",
"System.Numerics: <implicit>,global,<host>",
"System.Security: <implicit>,global,<host>",
"System.Data.SqlXml: <implicit>,global,<host>",
"System.Configuration: <implicit>,global,<host>",
"System.Runtime: <implicit>,global,<host>",
"System.Diagnostics.Debug: <implicit>,global,<host>",
"System.Runtime.InteropServices: <implicit>,global,<host>",
"System.Reflection.Metadata: <implicit>,global,<host>",
"System.IO: <implicit>,global,<host>",
"System.Collections: <implicit>,global,<host>",
"System.Threading.Tasks: <implicit>,global,<host>",
"System.Reflection.Primitives: <implicit>,global,<host>",
"System.Reflection: <implicit>,global,<host>",
"System.Globalization: <implicit>,global,<host>",
"System.Runtime.Extensions: <implicit>,global,<host>",
"System.Runtime.Numerics: <implicit>,global,<host>",
"System.Runtime.Serialization.Json: <implicit>,global,<host>",
"System.Collections.Concurrent: <implicit>,global,<host>",
"System.Xml.ReaderWriter: <implicit>,global,<host>",
"System.Xml.XDocument: <implicit>,global,<host>",
"System.Dynamic.Runtime: <implicit>,global,<host>",
"System.Threading: <implicit>,global,<host>",
"System.Text.Encoding.Extensions: <implicit>,global,<host>",
"System.Xml.Linq: <implicit>,global,<host>",
"System.Runtime.Serialization: <implicit>,global,<host>",
"System.ServiceModel.Internals: <implicit>,global,<host>",
"SMDiagnostics: <implicit>,global,<host>",
"System.ComponentModel.Composition: <implicit>,global,<host>",
"Microsoft.CodeAnalysis.CSharp: <implicit>,global",
"System.AppContext: <implicit>,global",
"System.Linq.Expressions: <implicit>,global",
"System.Threading.Tasks.Parallel: <implicit>,global");
foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
{
switch (assemblyAndAliases.Item1.Identity.Name)
{
case "mscorlib":
AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.CSharp.Scripting":
AssertEx.SetEqual(new string[0], assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.Scripting":
AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis.CSharp":
AssertEx.SetEqual(new[] { "<implicit>", "global" }, assemblyAndAliases.Item2);
break;
case "Microsoft.CodeAnalysis":
case "System.IO":
case "System.Collections.Immutable":
AssertEx.SetEqual(new[] { "<implicit>", "global", "<host>" }, assemblyAndAliases.Item2);
break;
}
}
}
#endregion
......
......@@ -118,10 +118,5 @@ public void EnableActiveTokenTracking(bool enable)
waiter.Value.TrackActiveTokens = enable;
}
}
public void PumpingWait(Task task)
{
task.PumpingWait();
}
}
}
......@@ -56,7 +56,11 @@ internal partial class CSharpCodeModelService : AbstractCodeModelService
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
private static readonly SymbolDisplayFormat s_fullNameFormat =
private static readonly SymbolDisplayFormat s_externalNameFormat =
new SymbolDisplayFormat(
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers);
private static readonly SymbolDisplayFormat s_externalFullNameFormat =
new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeExplicitInterface,
......@@ -943,17 +947,7 @@ public override string GetFullName(SyntaxNode node, SemanticModel semanticModel)
? semanticModel.GetTypeInfo(node).Type
: semanticModel.GetDeclaredSymbol(node);
return GetFullName(symbol);
}
public override string GetFullName(ISymbol symbol)
{
if (symbol == null)
{
throw Exceptions.ThrowEFail();
}
return symbol.ToDisplayString(s_fullNameFormat);
return GetExternalSymbolFullName(symbol);
}
public override string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel)
......@@ -980,6 +974,46 @@ public override string GetFullyQualifiedName(string name, int position, Semantic
return name;
}
public override bool IsValidExternalSymbol(ISymbol symbol)
{
var methodSymbol = symbol as IMethodSymbol;
if (methodSymbol != null)
{
if (methodSymbol.MethodKind == MethodKind.PropertyGet ||
methodSymbol.MethodKind == MethodKind.PropertySet ||
methodSymbol.MethodKind == MethodKind.EventAdd ||
methodSymbol.MethodKind == MethodKind.EventRemove ||
methodSymbol.MethodKind == MethodKind.EventRaise)
{
return false;
}
}
return symbol.DeclaredAccessibility == Accessibility.Public
|| symbol.DeclaredAccessibility == Accessibility.Protected
|| symbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal;
}
public override string GetExternalSymbolName(ISymbol symbol)
{
if (symbol == null)
{
throw Exceptions.ThrowEFail();
}
return symbol.ToDisplayString(s_externalNameFormat);
}
public override string GetExternalSymbolFullName(ISymbol symbol)
{
if (symbol == null)
{
throw Exceptions.ThrowEFail();
}
return symbol.ToDisplayString(s_externalFullNameFormat);
}
public override EnvDTE.vsCMAccess GetAccess(ISymbol symbol)
{
switch (symbol.DeclaredAccessibility)
......
......@@ -95,7 +95,7 @@ private string GetDelegatePrototype(INamedTypeSymbol symbol, PrototypeFlags flag
}
// The unique signature is simply the node key.
return GetFullName(symbol);
return GetExternalSymbolFullName(symbol);
}
var builder = new StringBuilder();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis;
......@@ -16,7 +17,7 @@ namespace Microsoft.VisualStudio.LanguageServices
/// </summary>
public abstract class VisualStudioWorkspace : Workspace
{
private readonly BackgroundCompiler _backgroundCompiler;
private BackgroundCompiler _backgroundCompiler;
private readonly BackgroundParser _backgroundParser;
internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWork backgroundWork)
......@@ -25,6 +26,12 @@ internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWor
if ((backgroundWork & WorkspaceBackgroundWork.Compile) != 0)
{
_backgroundCompiler = new BackgroundCompiler(this);
var cacheService = Services.GetService<IWorkspaceCacheService>();
if (cacheService != null)
{
cacheService.CacheFlushRequested += OnCacheFlushRequested;
}
}
if ((backgroundWork & WorkspaceBackgroundWork.Parse) != 0)
......@@ -34,6 +41,22 @@ internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWor
}
}
private void OnCacheFlushRequested(object sender, EventArgs e)
{
if (_backgroundCompiler != null)
{
_backgroundCompiler.Dispose();
_backgroundCompiler = null; // PartialSemanticsEnabled will now return false
}
// No longer need cache notifications
var cacheService = Services.GetService<IWorkspaceCacheService>();
if (cacheService != null)
{
cacheService.CacheFlushRequested -= OnCacheFlushRequested;
}
}
protected internal override bool PartialSemanticsEnabled
{
get { return _backgroundCompiler != null; }
......
......@@ -18,6 +18,7 @@ namespace Microsoft.VisualStudio.LanguageServices
internal sealed class VirtualMemoryNotificationListener : ForegroundThreadAffinitizedObject, IVsBroadcastMessageEvents
{
private WorkspaceCacheService _workspaceCacheService;
private bool _alreadyLogged;
[ImportingConstructor]
private VirtualMemoryNotificationListener(
......@@ -51,9 +52,13 @@ public int OnBroadcastMessage(uint msg, IntPtr wParam, IntPtr lParam)
{
case VSConstants.VSM_VIRTUALMEMORYLOW:
case VSConstants.VSM_VIRTUALMEMORYCRITICAL:
{
if (!_alreadyLogged)
{
// record that we had hit critical memory barrier
Logger.Log(FunctionId.VirtualMemory_MemoryLow, KeyValueLogMessage.Create(m => m["Memory"] = msg));
_alreadyLogged = true;
}
_workspaceCacheService.FlushCaches();
break;
......
......@@ -260,7 +260,10 @@ public EnvDTE.CodeElement CreateExternalCodeElement(CodeModelState state, Projec
}
case SymbolKind.Property:
return (EnvDTE.CodeElement)ExternalCodeProperty.Create(state, projectId, (IPropertySymbol)symbol);
var propertySymbol = (IPropertySymbol)symbol;
return propertySymbol.IsWithEvents
? (EnvDTE.CodeElement)ExternalCodeVariable.Create(state, projectId, propertySymbol)
: (EnvDTE.CodeElement)ExternalCodeProperty.Create(state, projectId, (IPropertySymbol)symbol);
default:
throw Exceptions.ThrowEFail();
}
......@@ -519,7 +522,6 @@ protected EnvDTE80.CodeAttributeArgument CreateInternalCodeAttributeArgument(Cod
public abstract SyntaxNode SetName(SyntaxNode node, string name);
public abstract string GetFullName(SyntaxNode node, SemanticModel semanticModel);
public abstract string GetFullName(ISymbol symbol);
public abstract string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel);
......@@ -568,6 +570,10 @@ public void Rename(ISymbol symbol, string newName, Solution solution)
nodeKeyValidation.RestoreKeys();
}
public abstract bool IsValidExternalSymbol(ISymbol symbol);
public abstract string GetExternalSymbolName(ISymbol symbol);
public abstract string GetExternalSymbolFullName(ISymbol symbol);
public VirtualTreePoint? GetStartPoint(SyntaxNode node, EnvDTE.vsCMPart? part)
{
return _nodeLocator.GetStartPoint(node, part);
......
......@@ -54,9 +54,12 @@ private ImmutableArray<EnvDTE.CodeElement> GetChildren()
var childrenBuilder = ImmutableArray.CreateBuilder<EnvDTE.CodeElement>();
foreach (var member in typeSymbol.GetMembers())
{
if (this.CodeModelService.IsValidExternalSymbol(member))
{
childrenBuilder.Add(this.State.CodeModelService.CreateExternalCodeElement(this.State, _projectId, member));
}
}
foreach (var typeMember in typeSymbol.GetTypeMembers())
{
......
......@@ -61,7 +61,7 @@ protected virtual string GetDocComment()
protected virtual string GetFullName()
{
return CodeModelService.GetFullName(LookupSymbol());
return CodeModelService.GetExternalSymbolFullName(LookupSymbol());
}
protected virtual bool GetIsShared()
......@@ -72,8 +72,7 @@ protected virtual bool GetIsShared()
protected virtual string GetName()
{
var symbol = LookupSymbol();
return symbol.Name;
return CodeModelService.GetExternalSymbolName(LookupSymbol());
}
protected virtual object GetParent()
......
......@@ -3,7 +3,6 @@
using System;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Collections;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities;
......
......@@ -11,20 +11,33 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Exter
[ComDefaultInterface(typeof(EnvDTE.CodeVariable))]
public sealed class ExternalCodeVariable : AbstractExternalCodeMember, EnvDTE.CodeVariable, EnvDTE80.CodeVariable2
{
internal static EnvDTE.CodeVariable Create(CodeModelState state, ProjectId projectId, IFieldSymbol symbol)
internal static EnvDTE.CodeVariable Create(CodeModelState state, ProjectId projectId, ISymbol symbol)
{
var element = new ExternalCodeVariable(state, projectId, symbol);
return (EnvDTE.CodeVariable)ComAggregate.CreateAggregatedObject(element);
}
private ExternalCodeVariable(CodeModelState state, ProjectId projectId, IFieldSymbol symbol)
private ExternalCodeVariable(CodeModelState state, ProjectId projectId, ISymbol symbol)
: base(state, projectId, symbol)
{
}
private IFieldSymbol FieldSymbol
private ITypeSymbol GetSymbolType()
{
get { return (IFieldSymbol)LookupSymbol(); }
var symbol = LookupSymbol();
if (symbol != null)
{
switch (symbol.Kind)
{
case SymbolKind.Field:
return ((IFieldSymbol)symbol).Type;
case SymbolKind.Property:
// Note: VB WithEvents fields are represented as properties
return ((IPropertySymbol)symbol).Type;
}
}
return null;
}
public override EnvDTE.vsCMElement Kind
......@@ -49,10 +62,14 @@ public bool IsConstant
{
get
{
// TODO: Verify VB implementation
var symbol = FieldSymbol;
return symbol.IsConst
|| symbol.IsReadOnly;
var fieldSymbol = LookupSymbol() as IFieldSymbol;
if (fieldSymbol == null)
{
return false;
}
return fieldSymbol.IsConst
|| fieldSymbol.IsReadOnly;
}
set
......@@ -65,7 +82,13 @@ public EnvDTE.CodeTypeRef Type
{
get
{
return CodeTypeRef.Create(this.State, this, this.ProjectId, FieldSymbol.Type);
var type = GetSymbolType();
if (type == null)
{
throw Exceptions.ThrowEFail();
}
return CodeTypeRef.Create(this.State, this, this.ProjectId, type);
}
set
......@@ -78,13 +101,17 @@ public EnvDTE80.vsCMConstKind ConstKind
{
get
{
// TODO: Verify VB Implementation
var symbol = FieldSymbol;
if (symbol.IsConst)
var fieldSymbol = LookupSymbol() as IFieldSymbol;
if (fieldSymbol == null)
{
return EnvDTE80.vsCMConstKind.vsCMConstKindNone;
}
if (fieldSymbol.IsConst)
{
return EnvDTE80.vsCMConstKind.vsCMConstKindConst;
}
else if (symbol.IsReadOnly)
else if (fieldSymbol.IsReadOnly)
{
return EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly;
}
......@@ -105,7 +132,7 @@ public bool IsGeneric
get
{
// TODO: C# checks whether the field Type is generic. What does VB do?
var namedType = FieldSymbol.Type as INamedTypeSymbol;
var namedType = GetSymbolType() as INamedTypeSymbol;
return namedType != null
? namedType.IsGenericType
: false;
......
......@@ -114,11 +114,6 @@ internal interface ICodeModelService : ICodeModelNavigationPointService
/// </summary>
string GetFullName(SyntaxNode node, SemanticModel semanticModel);
/// <summary>
/// Retrieves the value to be returned from the EnvDTE.CodeElement.FullName property for external code elements
/// </summary>
string GetFullName(ISymbol symbol);
/// <summary>
/// Given a name, attempts to convert it to a fully qualified name.
/// </summary>
......@@ -126,6 +121,21 @@ internal interface ICodeModelService : ICodeModelNavigationPointService
void Rename(ISymbol symbol, string newName, Solution solution);
/// <summary>
/// Returns true if the given <paramref name="symbol"/> can be used to create an external code element; otherwise, false.
/// </summary>
bool IsValidExternalSymbol(ISymbol symbol);
/// <summary>
/// Returns the value to be returned from <see cref="EnvDTE.CodeElement.Name"/> for external code elements.
/// </summary>
string GetExternalSymbolName(ISymbol symbol);
/// <summary>
/// Retrieves the value to be returned from <see cref="EnvDTE.CodeElement.FullName"/> for external code elements.
/// </summary>
string GetExternalSymbolFullName(ISymbol symbol);
SyntaxNode GetNodeWithModifiers(SyntaxNode node);
SyntaxNode GetNodeWithType(SyntaxNode node);
SyntaxNode GetNodeWithInitializer(SyntaxNode node);
......
......@@ -56,106 +56,69 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestAttributeArguments(code As XElement, ParamArray expectedAttributeArguments() As Action(Of Object))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim attributes = GetAttributeArguments(codeElement)
Assert.Equal(expectedAttributeArguments.Length, attributes.Count)
For i = 1 To attributes.Count
expectedAttributeArguments(i - 1)(attributes.Item(i))
Next
End Using
End Sub)
End Sub
Protected Sub TestTarget(code As XElement, expectedTarget As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim target = GetTarget(codeElement)
Assert.Equal(expectedTarget, target)
End Using
End Sub)
End Sub
Protected Sub TestSetTarget(code As XElement, expectedCode As XElement, target As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeAttribute = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeAttribute)
codeAttribute.Target = target
Dim text = state.GetDocumentAtCursor().GetTextAsync(CancellationToken.None).Result.ToString()
Assert.Equal(expectedCode.NormalizedValue().Trim(), text.Trim())
End Using
End Sub
Protected Sub TestSetValue(code As XElement, expectedCode As XElement, value As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeAttribute = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeAttribute)
codeAttribute.Value = value
Dim text = state.GetDocumentAtCursor().GetTextAsync(CancellationToken.None).Result.ToString()
Assert.Equal(expectedCode.NormalizedValue().Trim(), text.Trim())
End Using
TestElementUpdate(code, expectedCode,
Sub(codeElement)
codeElement.Target = target
End Sub)
End Sub
Protected Sub TestValue(code As XElement, expectedValue As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim target = GetValue(codeElement)
Assert.Equal(expectedValue, target)
End Using
End Sub)
End Sub
Protected Sub TestAddAttributeArgument(code As XElement, expectedCode As XElement, data As AttributeArgumentData)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
Protected Sub TestSetValue(code As XElement, expectedCode As XElement, value As String)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
codeElement.Value = value
End Sub)
End Sub
Protected Sub TestAddAttributeArgument(code As XElement, expectedCode As XElement, data As AttributeArgumentData)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
Dim attributeArgument = AddAttributeArgument(codeElement, data)
Assert.NotNull(attributeArgument)
Assert.Equal(data.Name, attributeArgument.Name)
Dim text = state.GetDocumentAtCursor().GetTextAsync(CancellationToken.None).Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Sub TestDelete(code As XElement, expectedCode As XElement)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
codeElement.Delete()
Dim text = state.GetDocumentAtCursor().GetTextAsync(CancellationToken.None).Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Sub TestDeleteAttributeArgument(code As XElement, expectedCode As XElement, indexToDelete As Integer)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
Dim argument = CType(codeElement.Arguments.Item(indexToDelete), EnvDTE80.CodeAttributeArgument)
argument.Delete()
Dim text = state.GetDocumentAtCursor().GetTextAsync(CancellationToken.None).Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Function IsAttributeArgument(Optional name As String = Nothing, Optional value As String = Nothing) As Action(Of Object)
......@@ -175,10 +138,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestAttributeArgumentStartPoint(code As XElement, index As Integer, ParamArray expectedParts() As Action(Of Func(Of EnvDTE.vsCMPart, EnvDTE.TextPoint)))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim startPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetStartPoint(part)
......@@ -186,14 +147,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
For Each action In expectedParts
action(startPointGetter)
Next
End Using
End Sub)
End Sub
Protected Sub TestAttributeArgumentEndPoint(code As XElement, index As Integer, ParamArray expectedParts() As Action(Of Func(Of EnvDTE.vsCMPart, EnvDTE.TextPoint)))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim endPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetEndPoint(part)
......@@ -201,7 +160,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
For Each action In expectedParts
action(endPointGetter)
Next
End Using
End Sub)
End Sub
End Class
......
......@@ -77,13 +77,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestBaseClass(code As XElement, expectedFullName As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeDelegate2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.NotNull(codeElement.BaseClass)
Assert.Equal(expectedFullName, codeElement.BaseClass.FullName)
End Using
End Sub)
End Sub
End Class
......
......@@ -73,12 +73,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestIsPropertyStyleEvent(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeEvent)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, codeElement.IsPropertyStyleEvent)
End Using
End Sub)
End Sub
End Class
......
......@@ -131,12 +131,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestCanOverride(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, codeElement.CanOverride)
End Using
End Sub)
End Sub
Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean)
......@@ -144,33 +142,23 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
action(value, Sub(v) codeElement.CanOverride = v)
Dim text = state.GetDocumentAtCursor().GetTextAsync().Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Sub TestIsOverloaded(code As XElement, expectedOverloaded As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim overloaded = GetIsOverloaded(codeElement)
Assert.Equal(expectedOverloaded, overloaded)
End Using
End Sub)
End Sub
Protected Sub TestOverloadsUniqueSignatures(code As XElement, ParamArray expectedOverloadNames As String())
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Dim actualOverloads = GetOverloads(codeElement)
Assert.Equal(expectedOverloadNames.Count, actualOverloads.Count)
For index = 1 To actualOverloads.Count
......@@ -178,61 +166,49 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Dim signature = GetPrototype(codeFunction, EnvDTE.vsCMPrototype.vsCMPrototypeUniqueSignature)
Assert.True(expectedOverloadNames.Contains(signature))
Next
End Using
End Sub)
End Sub
Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE.vsCMFunction)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, codeElement.FunctionKind)
End Using
End Sub)
End Sub
Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE80.vsCMFunction2)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, CType(codeElement.FunctionKind, EnvDTE80.vsCMFunction2))
End Using
End Sub)
End Sub
Protected Sub TestExtensionMethodExtender_IsExtension(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, ExtensionMethodExtender_GetIsExtension(codeElement))
End Using
End Sub)
End Sub
Protected Sub TestPartialMethodExtender_IsPartial(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, PartialMethodExtender_GetIsPartial(codeElement))
End Using
End Sub)
End Sub
Protected Sub TestPartialMethodExtender_IsDeclaration(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, PartialMethodExtender_GetIsDeclaration(codeElement))
End Using
End Sub)
End Sub
Protected Sub TestPartialMethodExtender_HasOtherPart(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, PartialMethodExtender_GetHasOtherPart(codeElement))
End Using
End Sub)
End Sub
End Class
......
......@@ -37,12 +37,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestNamespace(code As XElement, expectedNamespace As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeImport)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expectedNamespace, codeElement.Namespace)
End Using
End Sub)
End Sub
End Class
......
......@@ -65,21 +65,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestParameterKind(code As XElement, kind As vsCMParameterKind)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(kind, codeElement.ParameterKind)
End Using
End Sub)
End Sub
Protected Sub TestDefaultValue(code As XElement, expectedValue As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expectedValue, codeElement.DefaultValue)
End Using
End Sub)
End Sub
Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind)
......@@ -87,18 +83,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind, action As SetterAction(Of EnvDTE80.vsCMParameterKind))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
Dim parameterKindSetter = GetParameterKindSetter(codeElement)
action(kind, parameterKindSetter)
Dim text = state.GetDocumentAtCursor().GetTextAsync().Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Sub TestSetDefaultValue(code As XElement, expected As XElement, defaultValue As String)
......@@ -106,18 +95,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestSetDefaultValue(code As XElement, expectedCode As XElement, defaultValue As String, action As SetterAction(Of String))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
Dim defaultValueSetter = GetDefaultValueSetter(codeElement)
action(defaultValue, defaultValueSetter)
Dim text = state.GetDocumentAtCursor().GetTextAsync().Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
End Class
End Namespace
......@@ -101,30 +101,24 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestAutoImplementedPropertyExtender_IsAutoImplemented(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, AutoImplementedPropertyExtender_GetIsAutoImplemented(codeElement))
End Using
End Sub)
End Sub
Protected Sub TestGetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
verifier(codeElement.Getter)
End Using
End Sub)
End Sub
Protected Sub TestSetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
verifier(codeElement.Setter)
End Using
End Sub)
End Sub
End Class
......
......@@ -95,12 +95,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function
Protected Sub TestIsConstant(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, codeElement.IsConstant)
End Using
End Sub)
End Sub
Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean)
......@@ -108,25 +106,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
action(value, Sub(v) codeElement.IsConstant = v)
Dim text = state.GetDocumentAtCursor().GetTextAsync().Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
Protected Sub TestInitExpression(code As XElement, expected As Object)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)()
Assert.NotNull(codeElement)
TestElement(code,
Sub(codeElement)
Assert.Equal(expected, codeElement.InitExpression)
End Using
End Sub)
End Sub
Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object)
......@@ -134,16 +124,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub
Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object, action As SetterAction(Of Object))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)()
Assert.NotNull(codeElement)
TestElementUpdate(code, expectedCode,
Sub(codeElement)
action(value, Sub(v) codeElement.InitExpression = v)
Dim text = state.GetDocumentAtCursor().GetTextAsync().Result.ToString()
Assert.Equal(expectedCode.NormalizedValue.Trim(), text.Trim())
End Using
End Sub)
End Sub
End Class
......
......@@ -618,7 +618,7 @@ class C { }
End Sub
<ConditionalWpfFact(GetType(x86), Skip:="https://github.com/dotnet/roslyn/issues/5800"), Trait(Traits.Feature, Traits.Features.CodeModel)>
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub AddAttributeArgument3()
Dim code =
<Code>
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis
Imports Roslyn.Test.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.CSharp
Public Class ExternalCodeClassTests
Inherits AbstractCodeClassTests
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ExpectedClassMembers()
Dim code =
<Code>
class C$$
{
// fields
private int _privateX;
protected int ProtectedX;
internal int InternalX;
protected internal int ProtectedInternalX;
public int PublicX;
// methods
private void PrivateM() { }
protected void ProtectedM() { }
internal void InternalM() { }
protected internal void ProtectedInternalM() { }
public void PublicM() { }
}
</Code>
TestElement(code,
Sub(codeElement)
Dim members = codeElement.Members
Assert.Equal(7, members.Count)
Dim member1 = members.Item(1)
Assert.Equal("ProtectedX", member1.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member1.Kind)
Dim member2 = members.Item(2)
Assert.Equal("ProtectedInternalX", member2.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member2.Kind)
Dim member3 = members.Item(3)
Assert.Equal("PublicX", member3.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member3.Kind)
Dim member4 = members.Item(4)
Assert.Equal("ProtectedM", member4.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member4.Kind)
Dim member5 = members.Item(5)
Assert.Equal("ProtectedInternalM", member5.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member5.Kind)
Dim member6 = members.Item(6)
Assert.Equal("PublicM", member6.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member6.Kind)
Dim member7 = members.Item(7)
Assert.Equal("C", member7.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member7.Kind)
End Sub)
End Sub
Protected Overrides ReadOnly Property LanguageName As String
Get
Return LanguageNames.CSharp
End Get
End Property
Protected Overrides ReadOnly Property TargetExternalCodeElements As Boolean
Get
Return True
End Get
End Property
End Class
End Namespace
\ No newline at end of file
......@@ -949,14 +949,14 @@ class $$C
void M() { }
}
</Code>
Using workspaceAndFileCodeModel = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeClass = workspaceAndFileCodeModel.GetCodeElementAtCursor(Of EnvDTE80.CodeClass2)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeClass = state.GetCodeElementAtCursor(Of EnvDTE80.CodeClass2)
Assert.Equal(1, codeClass.Members.OfType(Of EnvDTE80.CodeFunction2)().Count())
Dim project = workspaceAndFileCodeModel.VisualStudioWorkspace.CurrentSolution.Projects.First()
Dim project = state.VisualStudioWorkspace.CurrentSolution.Projects.First()
Dim documentId = project.DocumentIds.First()
workspaceAndFileCodeModel.VisualStudioWorkspace.CloseDocument(documentId)
Dim newSolution = workspaceAndFileCodeModel.VisualStudioWorkspace.CurrentSolution.RemoveDocument(documentId)
workspaceAndFileCodeModel.VisualStudioWorkspace.TryApplyChanges(newSolution)
state.VisualStudioWorkspace.CloseDocument(documentId)
Dim newSolution = state.VisualStudioWorkspace.CurrentSolution.RemoveDocument(documentId)
state.VisualStudioWorkspace.TryApplyChanges(newSolution)
' throws COMException with HResult = E_FAIL
Assert.Throws(Of System.Runtime.InteropServices.COMException)(
Sub()
......
......@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.ComponentModelHost
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.InternalElements
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Interop
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Interop
Imports Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.Mocks
......@@ -162,6 +163,30 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Return CType(result, T)
End Function
''' <summary>
''' Creates an "external" version of the given code element.
''' </summary>
<Extension()>
Public Function AsExternal(Of T As Class)(element As T) As T
Dim codeElement = TryCast(element, EnvDTE.CodeElement)
Assert.True(codeElement IsNot Nothing, "Expected code element")
Assert.True(codeElement.InfoLocation = EnvDTE.vsCMInfoLocation.vsCMInfoLocationProject, "Expected internal code element")
Dim codeElementImpl = ComAggregate.GetManagedObject(Of AbstractCodeElement)(codeElement)
Dim state = codeElementImpl.State
Dim projectId = codeElementImpl.FileCodeModel.GetProjectId()
Dim symbol = codeElementImpl.LookupSymbol()
Dim externalCodeElement = codeElementImpl.CodeModelService.CreateExternalCodeElement(state, projectId, symbol)
Assert.True(externalCodeElement IsNot Nothing, "Could not create external code element")
Dim result = TryCast(externalCodeElement, T)
Assert.True(result IsNot Nothing, $"Created external code element was not of type, {GetType(T).FullName}")
Return result
End Function
<Extension()>
Public Function GetMethodXML(func As EnvDTE.CodeFunction) As XElement
Dim methodXml = TryCast(func, IMethodXML)
......
......@@ -798,7 +798,7 @@ End Class
End Sub
<ConditionalWpfFact(GetType(x86), Skip:="https://github.com/dotnet/roslyn/issues/5800"), Trait(Traits.Feature, Traits.Features.CodeModel)>
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub AddAttributeArgument2()
Dim code =
<Code>
......@@ -822,7 +822,7 @@ End Class
End Sub
<ConditionalWpfFact(GetType(x86), Skip:="https://github.com/dotnet/roslyn/issues/5800"), Trait(Traits.Feature, Traits.Features.CodeModel)>
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestAddArgument3()
Dim code =
<Code>
......
......@@ -3141,6 +3141,39 @@ End Class
End Sub)
End Sub
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ClassMembersForWithEventsField()
Dim code =
<Code>
Class C
Event E(x As Integer)
End Class
Class D$$
Inherits C
Private WithEvents x As C
Private Sub D_E(x As Integer) Handles Me.E
End Sub
End Class
</Code>
TestElement(code,
Sub(codeElement)
Dim members = codeElement.Members
Assert.Equal(2, members.Count)
Dim member1 = members.Item(1)
Assert.Equal("x", member1.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member1.Kind)
Dim member2 = members.Item(2)
Assert.Equal("D_E", member2.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member2.Kind)
End Sub)
End Sub
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ClassIncludedDeclareMethods()
Dim code =
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis
Imports Roslyn.Test.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.VisualBasic
Public Class ExternalCodeClassTests
Inherits AbstractCodeClassTests
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ExpectedClassMembers()
Dim code =
<Code>
Class C$$
' fields
Private _privateX As Integer
Protected ProtectedX As Integer
Friend InternalX As Integer
Protected Friend ProtectedInternalX As Integer
Public PublicX As Integer
' methods
Private Sub PrivateM()
End Sub
Protected Sub ProtectedM()
End Sub
Friend Sub InternalM()
End Sub
Protected Friend Sub ProtectedInternalM()
End Sub
Public Sub PublicM()
End Sub
End Class
</Code>
TestElement(code,
Sub(codeElement)
Dim members = codeElement.Members
Assert.Equal(9, members.Count)
Dim member1 = members.Item(1)
Assert.Equal("New", member1.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member1.Kind)
Dim member2 = members.Item(2)
Assert.Equal("ProtectedX", member2.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member2.Kind)
Dim member3 = members.Item(3)
Assert.Equal("InternalX", member3.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member3.Kind)
Dim member4 = members.Item(4)
Assert.Equal("ProtectedInternalX", member4.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member4.Kind)
Dim member5 = members.Item(5)
Assert.Equal("PublicX", member5.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member5.Kind)
Dim member6 = members.Item(6)
Assert.Equal("ProtectedM", member6.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member6.Kind)
Dim member7 = members.Item(7)
Assert.Equal("InternalM", member7.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member7.Kind)
Dim member8 = members.Item(8)
Assert.Equal("ProtectedInternalM", member8.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member8.Kind)
Dim member9 = members.Item(9)
Assert.Equal("PublicM", member9.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member9.Kind)
End Sub)
End Sub
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ClassMembersForWithEventsField_Private()
Dim code =
<Code>
Class C
Event E(x As Integer)
End Class
Class D$$
Inherits C
Private WithEvents x As C
Private Sub D_E(x As Integer) Handles Me.E
End Sub
End Class
</Code>
TestElement(code,
Sub(codeElement)
Dim members = codeElement.Members
Assert.Equal(2, members.Count)
Dim member1 = members.Item(1)
Assert.Equal("New", member1.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member1.Kind)
Assert.Equal(EnvDTE.vsCMAccess.vsCMAccessPublic, CType(member1, EnvDTE.CodeFunction).Access)
Dim member2 = members.Item(2)
Assert.Equal("_x", member2.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member2.Kind)
Assert.Equal(EnvDTE.vsCMAccess.vsCMAccessPrivate, CType(member2, EnvDTE.CodeVariable).Access)
End Sub)
End Sub
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ClassMembersForWithEventsField_Protected()
Dim code =
<Code>
Class C
Event E(x As Integer)
End Class
Class D$$
Inherits C
Protected WithEvents x As C
Private Sub D_E(x As Integer) Handles Me.E
End Sub
End Class
</Code>
TestElement(code,
Sub(codeElement)
Dim members = codeElement.Members
Assert.Equal(3, members.Count)
Dim member1 = members.Item(1)
Assert.Equal("New", member1.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementFunction, member1.Kind)
Assert.Equal(EnvDTE.vsCMAccess.vsCMAccessPublic, CType(member1, EnvDTE.CodeFunction).Access)
Dim member2 = members.Item(2)
Assert.Equal("_x", member2.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member2.Kind)
Assert.Equal(EnvDTE.vsCMAccess.vsCMAccessPrivate, CType(member2, EnvDTE.CodeVariable).Access)
Dim member3 = members.Item(3)
Assert.Equal("x", member3.Name)
Assert.Equal(EnvDTE.vsCMElement.vsCMElementVariable, member3.Kind)
Assert.Equal(EnvDTE.vsCMAccess.vsCMAccessProtected Or EnvDTE.vsCMAccess.vsCMAccessWithEvents, CType(member3, EnvDTE.CodeVariable).Access)
End Sub)
End Sub
Protected Overrides ReadOnly Property LanguageName As String
Get
Return LanguageNames.VisualBasic
End Get
End Property
Protected Overrides ReadOnly Property TargetExternalCodeElements As Boolean
Get
Return True
End Get
End Property
End Class
End Namespace
\ No newline at end of file
......@@ -284,6 +284,7 @@
<Compile Include="CodeModel\CSharp\CodeStructTests.vb" />
<Compile Include="CodeModel\CSharp\CodeVariableTests.vb" />
<Compile Include="CodeModel\CSharp\EventCollectorTests.vb" />
<Compile Include="CodeModel\CSharp\ExternalCodeClassTests.vb" />
<Compile Include="CodeModel\CSharp\FileCodeModelTests.vb" />
<Compile Include="CodeModel\CSharp\RootCodeModelTests.vb" />
<Compile Include="CodeModel\CSharp\SyntaxNodeKeyTests.vb" />
......@@ -317,6 +318,7 @@
<Compile Include="CodeModel\VisualBasic\CodeStructTests.vb" />
<Compile Include="CodeModel\VisualBasic\CodeVariableTests.vb" />
<Compile Include="CodeModel\VisualBasic\EventCollectorTests.vb" />
<Compile Include="CodeModel\VisualBasic\ExternalCodeClassTests.vb" />
<Compile Include="CodeModel\VisualBasic\FileCodeModelTests.vb" />
<Compile Include="CodeModel\VisualBasic\ImplementsStatementTests.vb" />
<Compile Include="CodeModel\VisualBasic\InheritsStatementTests.vb" />
......
......@@ -53,7 +53,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.UseSpecialTypes)
Private Shared ReadOnly s_fullNameFormat As SymbolDisplayFormat =
Private Shared ReadOnly s_externalNameFormat As SymbolDisplayFormat =
New SymbolDisplayFormat(
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.ExpandNullable)
Private Shared ReadOnly s_externalfullNameFormat As SymbolDisplayFormat =
New SymbolDisplayFormat(
typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
......@@ -430,15 +435,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
For Each member In DirectCast(container, CompilationUnitSyntax).Members
Yield member
Next
ElseIf TypeOf container Is NamespaceBlockSyntax
ElseIf TypeOf container Is NamespaceBlockSyntax Then
For Each member In DirectCast(container, NamespaceBlockSyntax).Members
Yield member
Next
ElseIf TypeOf container Is TypeBlockSyntax
ElseIf TypeOf container Is TypeBlockSyntax Then
For Each member In DirectCast(container, TypeBlockSyntax).Members
Yield member
Next
ElseIf TypeOf container Is EnumBlockSyntax
ElseIf TypeOf container Is EnumBlockSyntax Then
For Each member In DirectCast(container, EnumBlockSyntax).Members
Yield member
Next
......@@ -491,12 +499,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Next
Next
ElseIf Not onlySupportedNodes
ElseIf Not onlySupportedNodes Then
' Only return fields if the supported flag Is false.
Yield member
End If
ElseIf NodeIsSupported(onlySupportedNodes, member)
ElseIf NodeIsSupported(onlySupportedNodes, member) Then
Yield member
End If
......@@ -1023,15 +1031,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
semanticModel.GetTypeInfo(node).Type,
semanticModel.GetDeclaredSymbol(node))
Return GetFullName(symbol)
End Function
Public Overrides Function GetFullName(symbol As ISymbol) As String
If symbol Is Nothing Then
Throw Exceptions.ThrowEFail()
End If
Return symbol.ToDisplayString(s_fullNameFormat)
Return GetExternalSymbolFullName(symbol)
End Function
Public Overrides Function IsAccessorNode(node As SyntaxNode) As Boolean
......@@ -1341,20 +1341,62 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
.WaitAndGetResult(CancellationToken.None)
End Function
Public Overrides Function IsValidExternalSymbol(symbol As ISymbol) As Boolean
Dim methodSymbol = TryCast(symbol, IMethodSymbol)
If methodSymbol IsNot Nothing Then
If methodSymbol.MethodKind = MethodKind.PropertyGet OrElse
methodSymbol.MethodKind = MethodKind.PropertySet OrElse
methodSymbol.MethodKind = MethodKind.EventAdd OrElse
methodSymbol.MethodKind = MethodKind.EventRemove OrElse
methodSymbol.MethodKind = MethodKind.EventRaise Then
Return False
End If
End If
Dim fieldSymbol = TryCast(symbol, IFieldSymbol)
If fieldSymbol IsNot Nothing Then
Dim propertySymbol = TryCast(fieldSymbol.AssociatedSymbol, IPropertySymbol)
If propertySymbol?.IsWithEvents Then
Return True
End If
End If
Return symbol.DeclaredAccessibility = Accessibility.Public OrElse
symbol.DeclaredAccessibility = Accessibility.Protected OrElse
symbol.DeclaredAccessibility = Accessibility.ProtectedOrFriend OrElse
symbol.DeclaredAccessibility = Accessibility.Friend
End Function
Public Overrides Function GetExternalSymbolName(symbol As ISymbol) As String
If symbol Is Nothing Then
Throw Exceptions.ThrowEFail()
End If
Return symbol.ToDisplayString(s_externalNameFormat)
End Function
Public Overrides Function GetExternalSymbolFullName(symbol As ISymbol) As String
If symbol Is Nothing Then
Throw Exceptions.ThrowEFail()
End If
Return symbol.ToDisplayString(s_externalfullNameFormat)
End Function
Public Overrides Function GetAccess(symbol As ISymbol) As EnvDTE.vsCMAccess
Debug.Assert(symbol IsNot Nothing)
Dim access As EnvDTE.vsCMAccess = 0
' TODO: Add vsCMAccessWithEvents for fields symbols defined as WithEvents
Select Case symbol.DeclaredAccessibility
Case Accessibility.Private
access = access Or EnvDTE.vsCMAccess.vsCMAccessPrivate
Case Accessibility.Protected
access = access Or EnvDTE.vsCMAccess.vsCMAccessProtected
Case Accessibility.Internal
Case Accessibility.Internal, Accessibility.Friend
access = access Or EnvDTE.vsCMAccess.vsCMAccessProject
Case Accessibility.ProtectedOrInternal
Case Accessibility.ProtectedOrInternal, Accessibility.ProtectedOrFriend
access = access Or EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected
Case Accessibility.Public
access = access Or EnvDTE.vsCMAccess.vsCMAccessPublic
......@@ -1362,8 +1404,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Throw Exceptions.ThrowEFail()
End Select
If symbol.IsKind(SymbolKind.Property) AndAlso
DirectCast(symbol, IPropertySymbol).IsWithEvents Then
If TryCast(symbol, IPropertySymbol)?.IsWithEvents Then
access = access Or EnvDTE.vsCMAccess.vsCMAccessWithEvents
End If
......@@ -2853,7 +2894,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
If propertyStatement IsNot Nothing Then
If propertyStatement.Modifiers.Any(SyntaxKind.WriteOnlyKeyword) Then
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindWriteOnly
ElseIf propertyStatement.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)
ElseIf propertyStatement.Modifiers.Any(SyntaxKind.ReadOnlyKeyword) Then
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadOnly
Else
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadWrite
......@@ -3778,7 +3819,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Dim enumMember = DirectCast(container, EnumMemberDeclarationSyntax)
Dim attributeLists = enumMember.AttributeLists.Insert(index, attributeList)
Return enumMember.WithAttributeLists(attributeLists)
ElseIf TypeOf container Is DelegateStatementSyntax
ElseIf TypeOf container Is DelegateStatementSyntax Then
Dim delegateStatement = DirectCast(container, DelegateStatementSyntax)
Dim attributeLists = delegateStatement.AttributeLists.Insert(index, attributeList)
Return delegateStatement.WithAttributeLists(attributeLists)
......@@ -3817,7 +3858,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Dim eventStatement = DirectCast(container, EventStatementSyntax)
Dim attributeLists = eventStatement.AttributeLists.Insert(index, attributeList)
Return eventStatement.WithAttributeLists(attributeLists)
ElseIf TypeOf container Is EventBlockSyntax
ElseIf TypeOf container Is EventBlockSyntax Then
Dim eventBlock = DirectCast(container, EventBlockSyntax)
Dim attributeLists = eventBlock.EventStatement.AttributeLists.Insert(index, attributeList)
Return eventBlock.WithEventStatement(eventBlock.EventStatement.WithAttributeLists(attributeLists))
......
......@@ -618,7 +618,7 @@ private bool ReplacementBreaksAssignmentExpression(AssignmentExpressionSyntax as
if (assignmentExpression.IsCompoundAssignExpression() &&
assignmentExpression.Kind() != SyntaxKind.LeftShiftAssignmentExpression &&
assignmentExpression.Kind() != SyntaxKind.RightShiftAssignmentExpression &&
ReplacementBreaksCompoundAssignExpression(assignmentExpression.Left, assignmentExpression.Right, newAssignmentExpression.Left, newAssignmentExpression.Right))
ReplacementBreaksCompoundAssignment(assignmentExpression.Left, assignmentExpression.Right, newAssignmentExpression.Left, newAssignmentExpression.Right))
{
return true;
}
......
......@@ -293,30 +293,24 @@ public static CodeAction Create(string title, Func<CancellationToken, Task<Solut
return new SolutionChangeAction(title, createChangedSolution, equivalenceKey);
}
/// <summary>
/// Creates a top level code action with multiple code action choices a user can invoke.
/// </summary>
public static CodeAction Create(string title, IEnumerable<CodeAction> nestedActions, string equivalenceKey = null)
{
if (title == null)
{
throw new ArgumentNullException(nameof(title));
}
return new SimpleCodeAction(title, nestedActions.AsImmutableOrEmpty(), equivalenceKey);
}
internal class SimpleCodeAction : CodeAction
{
private readonly string _title;
private readonly string _equivalenceKey;
private readonly ImmutableArray<CodeAction> _nestedActions;
public SimpleCodeAction(string title, ImmutableArray<CodeAction> nestedActions, string equivalenceKey)
public SimpleCodeAction(string title, ImmutableArray<CodeAction> nestedActions)
{
_title = title;
_nestedActions = nestedActions;
_equivalenceKey = ComputeEquivalenceKey(nestedActions);
}
public SimpleCodeAction(string title, string equivalenceKey)
{
_title = title;
_equivalenceKey = equivalenceKey;
_nestedActions = ImmutableArray<CodeAction>.Empty;
}
public sealed override string Title => _title;
......@@ -334,6 +328,29 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc
{
return Task.FromResult<Document>(null);
}
private static string ComputeEquivalenceKey(IEnumerable<CodeAction> nestedActions)
{
if (nestedActions == null)
{
return null;
}
var equivalenceKey = StringBuilderPool.Allocate();
try
{
foreach (var action in nestedActions)
{
equivalenceKey.Append(action.EquivalenceKey ?? action.GetHashCode().ToString() + ";");
}
return equivalenceKey.Length > 0 ? equivalenceKey.ToString() : null;
}
finally
{
StringBuilderPool.ReturnAndFree(equivalenceKey);
}
}
}
internal class DocumentChangeAction : SimpleCodeAction
......@@ -341,7 +358,7 @@ internal class DocumentChangeAction : SimpleCodeAction
private readonly Func<CancellationToken, Task<Document>> _createChangedDocument;
public DocumentChangeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument, string equivalenceKey = null)
: base(title, nestedActions: ImmutableArray<CodeAction>.Empty, equivalenceKey: equivalenceKey)
: base(title, equivalenceKey)
{
_createChangedDocument = createChangedDocument;
}
......@@ -359,7 +376,7 @@ internal class SolutionChangeAction : SimpleCodeAction
private readonly Func<CancellationToken, Task<Solution>> _createChangedSolution;
public SolutionChangeAction(string title, Func<CancellationToken, Task<Solution>> createChangedSolution, string equivalenceKey = null)
: base(title, nestedActions: ImmutableArray<CodeAction>.Empty, equivalenceKey: equivalenceKey)
: base(title, equivalenceKey)
{
_createChangedSolution = createChangedSolution;
}
......
......@@ -311,5 +311,6 @@ internal enum FunctionId
NonFatalWatson,
GlobalOperationRegistration,
CommandHandler_FindAllReference,
}
}
......@@ -3,6 +3,5 @@ Microsoft.CodeAnalysis.Project.IsSubmission.get -> bool
Microsoft.CodeAnalysis.Workspace.UpdateReferencesAfterAdd() -> void
abstract Microsoft.CodeAnalysis.Editing.SyntaxGenerator.ArrayCreationExpression(Microsoft.CodeAnalysis.SyntaxNode elementType, Microsoft.CodeAnalysis.SyntaxNode size) -> Microsoft.CodeAnalysis.SyntaxNode
abstract Microsoft.CodeAnalysis.Editing.SyntaxGenerator.ArrayCreationExpression(Microsoft.CodeAnalysis.SyntaxNode elementType, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.SyntaxNode> elements) -> Microsoft.CodeAnalysis.SyntaxNode
static Microsoft.CodeAnalysis.CodeActions.CodeAction.Create(string title, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.CodeActions.CodeAction> nestedActions, string equivalenceKey = null) -> Microsoft.CodeAnalysis.CodeActions.CodeAction
static Microsoft.CodeAnalysis.Editing.SyntaxGenerator.GetGenerator(Microsoft.CodeAnalysis.Project project) -> Microsoft.CodeAnalysis.Editing.SyntaxGenerator
virtual Microsoft.CodeAnalysis.Editing.SyntaxGenerator.RemoveNode(Microsoft.CodeAnalysis.SyntaxNode root, Microsoft.CodeAnalysis.SyntaxNode node, Microsoft.CodeAnalysis.SyntaxRemoveOptions options) -> Microsoft.CodeAnalysis.SyntaxNode
\ No newline at end of file
......@@ -744,7 +744,7 @@ private bool ReplacementBreaksInvocableExpression(TExpressionSyntax expression,
return true;
}
protected bool ReplacementBreaksCompoundAssignExpression(
protected bool ReplacementBreaksCompoundAssignment(
TExpressionSyntax originalLeft,
TExpressionSyntax originalRight,
TExpressionSyntax newLeft,
......
......@@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
semanticModel = semanticModel.ParentModel
End If
Dim speculativeModel As semanticModel = Nothing
Dim speculativeModel As SemanticModel = Nothing
Dim statementNode = TryCast(nodeToSpeculate, ExecutableStatementSyntax)
If statementNode IsNot Nothing Then
semanticModel.TryGetSpeculativeSemanticModel(position, statementNode, speculativeModel)
......@@ -328,7 +328,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
End If
Return Not ImplicitConversionsAreCompatible(originalExpression, newExpression)
ElseIf currentOriginalNode.Kind = SyntaxKind.ConditionalAccessExpression
ElseIf TypeOf currentOriginalNode Is AssignmentStatementSyntax Then
Dim originalAssignmentStatement = DirectCast(currentOriginalNode, AssignmentStatementSyntax)
If SyntaxFacts.IsAssignmentStatementOperatorToken(originalAssignmentStatement.OperatorToken.Kind()) Then
Dim newAssignmentStatement = DirectCast(currentReplacedNode, AssignmentStatementSyntax)
If ReplacementBreaksCompoundAssignment(originalAssignmentStatement.Left, originalAssignmentStatement.Right, newAssignmentStatement.Left, newAssignmentStatement.Right) Then
Return True
End If
End If
ElseIf currentOriginalNode.Kind = SyntaxKind.ConditionalAccessExpression Then
Dim originalExpression = DirectCast(currentOriginalNode, ConditionalAccessExpressionSyntax)
Dim newExpression = DirectCast(currentReplacedNode, ConditionalAccessExpressionSyntax)
Return ReplacementBreaksConditionalAccessExpression(originalExpression, newExpression)
......@@ -472,7 +482,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
If SyntaxFacts.IsAssignmentStatementOperatorToken(operatorTokenKind) AndAlso
operatorTokenKind <> SyntaxKind.LessThanLessThanEqualsToken AndAlso
operatorTokenKind <> SyntaxKind.GreaterThanGreaterThanEqualsToken AndAlso
ReplacementBreaksCompoundAssignExpression(binaryExpression.Left, binaryExpression.Right, newBinaryExpression.Left, newBinaryExpression.Right) Then
ReplacementBreaksCompoundAssignment(binaryExpression.Left, binaryExpression.Right, newBinaryExpression.Left, newBinaryExpression.Right) Then
Return True
End If
......@@ -515,6 +525,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
Protected Overrides Function ConversionsAreCompatible(originalExpression As ExpressionSyntax, originalTargetType As ITypeSymbol, newExpression As ExpressionSyntax, newTargetType As ITypeSymbol) As Boolean
Dim originalConversion = Me.OriginalSemanticModel.ClassifyConversion(originalExpression, originalTargetType)
Dim newConversion = Me.SpeculativeSemanticModel.ClassifyConversion(newExpression, newTargetType)
' When Option Strict is not Off and the new expression has a constant value, it's possible that
' there Is a hidden narrowing conversion that will be missed. In that case, use the
' conversion between the type of the new expression and the new target type.
If Me.OriginalSemanticModel.OptionStrict() <> OptionStrict.Off AndAlso
Me.SpeculativeSemanticModel.GetConstantValue(newExpression).HasValue Then
Dim newExpressionType = Me.SpeculativeSemanticModel.GetTypeInfo(newExpression).Type
newConversion = Me.OriginalSemanticModel.Compilation.ClassifyConversion(newExpressionType, newTargetType)
End If
Return ConversionsAreCompatible(originalConversion, newConversion)
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册