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

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

...@@ -154,12 +154,23 @@ internal interface ISymUnmanagedWriter6 : ISymUnmanagedWriter5 ...@@ -154,12 +154,23 @@ internal interface ISymUnmanagedWriter6 : ISymUnmanagedWriter5
void InitializeDeterministic([MarshalAs(UnmanagedType.IUnknown)] object emitter, [MarshalAs(UnmanagedType.IUnknown)] object stream); 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] [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B473C610-C958-4C3D-99A0-F2BA0A38807C"), SuppressUnmanagedCodeSecurity]
interface ISymUnmanagedWriter100 : ISymUnmanagedWriter6 interface ISymUnmanagedWriter100 : ISymUnmanagedWriter6
{ {
// ISymUnmanagedWriter, ISymUnmanagedWriter2, ISymUnmanagedWriter3, ISymUnmanagedWriter4, ISymUnmanagedWriter5, ISymUnmanagedWriter6 // ISymUnmanagedWriter, ISymUnmanagedWriter2, ISymUnmanagedWriter3, ISymUnmanagedWriter4, ISymUnmanagedWriter5, ISymUnmanagedWriter6
void _VtblGap1_34(); void _VtblGap1_34();
// ISymUnmanagedWriter100
void SetSignature(uint sig, Guid sig70); void SetSignature(uint sig, Guid sig70);
} }
......
...@@ -82,7 +82,7 @@ private void MaybeFlush() ...@@ -82,7 +82,7 @@ private void MaybeFlush()
} }
} }
internal ContentId ContentIdFromLog() internal byte[] GetLogHash()
{ {
Debug.Assert(_logData != null); Debug.Assert(_logData != null);
...@@ -104,7 +104,7 @@ internal ContentId ContentIdFromLog() ...@@ -104,7 +104,7 @@ internal ContentId ContentIdFromLog()
Debug.Assert(remaining == 0); Debug.Assert(remaining == 0);
_logData.Clear(); _logData.Clear();
return ContentId.FromHash(_hashAlgorithm.Hash.ToImmutableArray()); return _hashAlgorithm.Hash;
} }
internal void Close() internal void Close()
...@@ -813,13 +813,12 @@ public void SetMetadataEmitter(MetadataWriter metadataWriter) ...@@ -813,13 +813,12 @@ public void SetMetadataEmitter(MetadataWriter metadataWriter)
if (_deterministic) if (_deterministic)
{ {
var deterministicSymWriter = symWriter as ISymUnmanagedWriter6; if (!(symWriter is ISymUnmanagedWriter7 || symWriter is ISymUnmanagedWriter100))
if (deterministicSymWriter == null)
{ {
throw new NotSupportedException(CodeAnalysisResources.SymWriterNotDeterministic); throw new NotSupportedException(CodeAnalysisResources.SymWriterNotDeterministic);
} }
deterministicSymWriter.InitializeDeterministic(new PdbMetadataWrapper(metadataWriter), _pdbStream); ((ISymUnmanagedWriter6)symWriter).InitializeDeterministic(new PdbMetadataWrapper(metadataWriter), _pdbStream);
} }
else else
{ {
...@@ -839,20 +838,32 @@ public unsafe ContentId GetContentId() ...@@ -839,20 +838,32 @@ public unsafe ContentId GetContentId()
{ {
if (_deterministic) if (_deterministic)
{ {
// Call to GetDebugInfo fails for SymWriter initialized using InitializeDeterministic. // rewrite GUID and timestamp in the PDB with hash of a has of the log content:
// We already have all the info we need though. byte[] hash = _callLogger.GetLogHash();
var id = _callLogger.ContentIdFromLog();
try try
{ {
Debug.Assert(BitConverter.IsLittleEndian); // TODO: remove once we can rely on the presence of ISymUnmanagedWriter7
((ISymUnmanagedWriter100)_symWriter).SetSignature(BitConverter.ToUInt32(id.Stamp, 0), new Guid(id.Guid)); var writer100 = _symWriter as ISymUnmanagedWriter100;
if (writer100 != null)
{
var id = ContentId.FromHash(ImmutableArray.CreateRange(hash));
Debug.Assert(BitConverter.IsLittleEndian);
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) catch (Exception ex)
{ {
throw new PdbWritingException(ex); throw new PdbWritingException(ex);
} }
return id;
} }
// See symwrite.cpp - the data byte[] doesn't depend on the content of metadata tables or IL. // See symwrite.cpp - the data byte[] doesn't depend on the content of metadata tables or IL.
......
...@@ -168,7 +168,7 @@ class Class ...@@ -168,7 +168,7 @@ class Class
{ {
void Method() void Method()
{ {
[|int x = 0, y = 0;|] [|int x = 0, y = 0; string s;|]
} }
}"; }";
using (var workspace = CreateWorkspaceFromFile(source, parseOptions: null, compilationOptions: null)) using (var workspace = CreateWorkspaceFromFile(source, parseOptions: null, compilationOptions: null))
...@@ -186,19 +186,28 @@ void Method() ...@@ -186,19 +186,28 @@ void Method()
TextSpan span; TextSpan span;
var document = GetDocumentAndSelectSpan(workspace, out span); var document = GetDocumentAndSelectSpan(workspace, out span);
var diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, span) var diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, span)
.WaitAndGetResult(CancellationToken.None) .WaitAndGetResult(CancellationToken.None);
.Where(d => d.Id == "CS0219"); Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());
Assert.Equal(2, diagnostics.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) .WaitAndGetResult(CancellationToken.None)
.SelectMany(fixCollection => fixCollection.Fixes) .SelectMany(fixCollection => fixCollection.Fixes);
.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");
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. // Ensure that both the fixes have identical equivalence key, and hence get de-duplicated in LB menu.
Assert.Equal(2, fixes.Count()); Assert.Equal(2, cs0219Fixes.Count());
Assert.NotNull(fixes.First().Action.EquivalenceKey); var cs0219EquivalenceKey = cs0219Fixes.First().Action.EquivalenceKey;
Assert.Equal(fixes.First().Action.EquivalenceKey, fixes.Last().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 @@ ...@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.SymbolMapping; using Microsoft.CodeAnalysis.Editor.SymbolMapping;
using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
...@@ -51,12 +52,15 @@ internal void FindReferences(ITextSnapshot snapshot, int caretPosition) ...@@ -51,12 +52,15 @@ internal void FindReferences(ITextSnapshot snapshot, int caretPosition)
var service = document.Project.LanguageServices.GetService<IFindReferencesService>(); var service = document.Project.LanguageServices.GetService<IFindReferencesService>();
if (service != null) if (service != null)
{ {
if (!service.TryFindReferences(document, caretPosition, context)) using (Logger.LogBlock(FunctionId.CommandHandler_FindAllReference, context.CancellationToken))
{ {
foreach (var presenter in _presenters) if (!service.TryFindReferences(document, caretPosition, context))
{ {
presenter.DisplayResult(document.Project.Solution, SpecializedCollections.EmptyEnumerable<ReferencedSymbol>()); foreach (var presenter in _presenters)
return; {
presenter.DisplayResult(document.Project.Solution, SpecializedCollections.EmptyEnumerable<ReferencedSymbol>());
return;
}
} }
} }
} }
......
...@@ -7687,7 +7687,7 @@ End Class ...@@ -7687,7 +7687,7 @@ End Class
<WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)> <WpfFact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(995855)> <WorkItem(995855)>
Public Sub VisualBasic_Remove_UnnecessaryCastInTernaryExpression() Public Sub VisualBasic_DontRemove_NecessaryCastInTernaryExpression1()
Dim input = Dim input =
<Workspace> <Workspace>
<Project Language="Visual Basic" CommonReferences="true"> <Project Language="Visual Basic" CommonReferences="true">
...@@ -7696,7 +7696,109 @@ Class C ...@@ -7696,7 +7696,109 @@ Class C
Private Shared Sub Main(args As String()) Private Shared Sub Main(args As String())
Dim s As Byte = 0 Dim s As Byte = 0
Dim i As Integer = 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 Sub
End Class End Class
]]> ]]>
...@@ -8201,6 +8303,165 @@ Class C ...@@ -8201,6 +8303,165 @@ Class C
End Sub End Sub
End Class 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> </code>
Test(input, expected) Test(input, expected)
......
...@@ -13,67 +13,10 @@ namespace Roslyn.Test.Utilities ...@@ -13,67 +13,10 @@ namespace Roslyn.Test.Utilities
{ {
public static class WaitHelper 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) public static void WaitForDispatchedOperationsToComplete(DispatcherPriority priority)
{ {
Action action = delegate { }; Action action = delegate { };
new FrameworkElement().Dispatcher.Invoke(action, priority); 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 ...@@ -467,6 +467,13 @@ NewLines("Class AwesomeClass \n Sub M() \n Dim foo = New AwesomeClass() \n End S
index:=0) index:=0)
End Sub 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 Public Class AddImportTestsWithAddImportDiagnosticProvider
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
......
...@@ -9,24 +9,8 @@ namespace Microsoft.CodeAnalysis.CodeFixes.Suppression ...@@ -9,24 +9,8 @@ namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
internal sealed class SuppressionCodeAction : CodeAction.SimpleCodeAction internal sealed class SuppressionCodeAction : CodeAction.SimpleCodeAction
{ {
public SuppressionCodeAction(Diagnostic diagnostic, IEnumerable<CodeAction> nestedActions) 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() ...@@ -79,7 +79,7 @@ protected AbstractGenerateTypeService()
// Wrap the generate type actions into a single top level suggestion // Wrap the generate type actions into a single top level suggestion
// so as to not clutter the list. // so as to not clutter the list.
return SpecializedCollections.SingletonEnumerable( return SpecializedCollections.SingletonEnumerable(
new MyCodeAction(FeaturesResources.Generate_type, actions.AsImmutable(), actions[0].EquivalenceKey)); new MyCodeAction(FeaturesResources.Generate_type, actions.AsImmutable()));
} }
else else
{ {
...@@ -295,8 +295,8 @@ protected bool GeneratedTypesMustBePublic(Project project) ...@@ -295,8 +295,8 @@ protected bool GeneratedTypesMustBePublic(Project project)
private class MyCodeAction : CodeAction.SimpleCodeAction private class MyCodeAction : CodeAction.SimpleCodeAction
{ {
public MyCodeAction(string title, ImmutableArray<CodeAction> nestedActions, string equivalenceKey) public MyCodeAction(string title, ImmutableArray<CodeAction> nestedActions)
: base(title, nestedActions, equivalenceKey) : base(title, nestedActions)
{ {
} }
} }
......
...@@ -37,7 +37,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) ...@@ -37,7 +37,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
// Only bother with identifiers that are at least 3 characters long. // 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. // We don't want to be too noisy as you're just starting to type something.
var nameText = name.GetFirstToken().ValueText; var nameText = name.GetFirstToken().ValueText;
if (nameText.Length >= 3) if (nameText?.Length >= 3)
{ {
semanticModel = semanticModel ?? await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); semanticModel = semanticModel ?? await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var symbolInfo = semanticModel.GetSymbolInfo(name, cancellationToken); 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. // 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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
...@@ -9,9 +10,9 @@ ...@@ -9,9 +10,9 @@
namespace Microsoft.CodeAnalysis.Host 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 _compilationScheduler;
private readonly IWorkspaceTaskScheduler _notificationQueue; private readonly IWorkspaceTaskScheduler _notificationQueue;
...@@ -33,12 +34,21 @@ public BackgroundCompiler(Workspace workspace) ...@@ -33,12 +34,21 @@ public BackgroundCompiler(Workspace workspace)
_notificationQueue = taskSchedulerFactory.CreateTaskQueue(); _notificationQueue = taskSchedulerFactory.CreateTaskQueue();
_cancellationSource = new CancellationTokenSource(); _cancellationSource = new CancellationTokenSource();
_workspace.WorkspaceChanged += this.OnWorkspaceChanged; _workspace.WorkspaceChanged += this.OnWorkspaceChanged;
_workspace.DocumentOpened += OnDocumentOpened;
_workspace.DocumentClosed += OnDocumentClosed;
}
var editorWorkspace = workspace as Workspace; public void Dispose()
if (editorWorkspace != null) {
if (_workspace != null)
{ {
editorWorkspace.DocumentOpened += OnDocumentOpened; this.CancelBuild(releasePreviousCompilations: true);
editorWorkspace.DocumentClosed += OnDocumentClosed;
_workspace.DocumentClosed -= OnDocumentClosed;
_workspace.DocumentOpened -= OnDocumentOpened;
_workspace.WorkspaceChanged -= this.OnWorkspaceChanged;
_workspace = null;
} }
} }
......
...@@ -1453,54 +1453,27 @@ public void HostObjectAssemblyReference1() ...@@ -1453,54 +1453,27 @@ public void HostObjectAssemblyReference1()
globalsType: typeof(CommandLineScriptGlobals)).GetCompilation(); globalsType: typeof(CommandLineScriptGlobals)).GetCompilation();
scriptCompilation.VerifyDiagnostics( scriptCompilation.VerifyDiagnostics(
// (1,8): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) // (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")); Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Microsoft.CodeAnalysis").WithArguments("CodeAnalysis", "Microsoft"));
scriptCompilation.VerifyAssemblyAliases( foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
"mscorlib: global,<host>", {
"Microsoft.CodeAnalysis.Scripting: <host>", switch (assemblyAndAliases.Item1.Identity.Name)
"System.Collections.Immutable: <implicit>,<host>", {
"Microsoft.CodeAnalysis: <implicit>,<host>", case "mscorlib":
"System.Diagnostics.Tools: <implicit>,<host>", AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
"System.Resources.ResourceManager: <implicit>,<host>", break;
"System.Console: <implicit>,<host>",
"System.Diagnostics.StackTrace: <implicit>,<host>", case "Microsoft.CodeAnalysis.Scripting":
"System.IO.FileSystem: <implicit>,<host>", AssertEx.SetEqual(new[] { "<host>" }, assemblyAndAliases.Item2);
"System.Linq: <implicit>,<host>", break;
"System.Text.Encoding: <implicit>,<host>",
"System.IO.FileSystem.Primitives: <implicit>,<host>", case "Microsoft.CodeAnalysis":
"System.Reflection.Extensions: <implicit>,<host>", default:
"System.Core: <implicit>,<host>", AssertEx.SetEqual(new[] { "<implicit>", "<host>" }, assemblyAndAliases.Item2);
"System: <implicit>,<host>", break;
"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>");
} }
[Fact] [Fact]
...@@ -1513,56 +1486,33 @@ public void HostObjectAssemblyReference2() ...@@ -1513,56 +1486,33 @@ public void HostObjectAssemblyReference2()
scriptCompilation.VerifyDiagnostics(); scriptCompilation.VerifyDiagnostics();
scriptCompilation.VerifyAssemblyAliases( foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
"mscorlib: global,<host>", {
"Microsoft.CodeAnalysis.Scripting: <host>,global", switch (assemblyAndAliases.Item1.Identity.Name)
"Microsoft.CodeAnalysis.Scripting.CSharp", {
"Microsoft.CodeAnalysis.CSharp: <implicit>,global", case "mscorlib":
"Microsoft.CodeAnalysis: <implicit>,<host>,global", AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
"System.Collections.Immutable: <implicit>,<host>,global", break;
"System.Diagnostics.Tools: <implicit>,<host>,global",
"System.Resources.ResourceManager: <implicit>,<host>,global", case "Microsoft.CodeAnalysis.Scripting":
"System.Text.Encoding: <implicit>,<host>,global", AssertEx.SetEqual(new[] { "<host>", "global" }, assemblyAndAliases.Item2);
"System.AppContext: <implicit>,global", break;
"System.Reflection.Extensions: <implicit>,<host>,global",
"System: <implicit>,<host>,global", case "Microsoft.CodeAnalysis.CSharp.Scripting":
"System.Configuration: <implicit>,<host>,global", AssertEx.SetEqual(new string[0], assemblyAndAliases.Item2);
"System.Xml: <implicit>,<host>,global", break;
"System.Data.SqlXml: <implicit>,<host>,global",
"System.Security: <implicit>,<host>,global", case "Microsoft.CodeAnalysis.CSharp":
"System.Core: <implicit>,<host>,global", AssertEx.SetEqual(new[] { "<implicit>", "global" }, assemblyAndAliases.Item2);
"System.Numerics: <implicit>,<host>,global", break;
"System.Runtime: <implicit>,<host>,global",
"System.Diagnostics.Debug: <implicit>,<host>,global", case "Microsoft.CodeAnalysis":
"System.Collections: <implicit>,<host>,global", case "System.IO":
"System.Linq: <implicit>,<host>,global", case "System.Collections.Immutable":
"System.Runtime.Extensions: <implicit>,<host>,global", AssertEx.SetEqual(new[] { "<implicit>", "<host>", "global" }, assemblyAndAliases.Item2);
"System.Globalization: <implicit>,<host>,global", break;
"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");
} }
[Fact] [Fact]
...@@ -1576,56 +1526,33 @@ public void HostObjectAssemblyReference3() ...@@ -1576,56 +1526,33 @@ public void HostObjectAssemblyReference3()
scriptCompilation.VerifyDiagnostics(); scriptCompilation.VerifyDiagnostics();
scriptCompilation.VerifyAssemblyAliases( foreach (var assemblyAndAliases in scriptCompilation.GetBoundReferenceManager().GetReferencedAssemblyAliases())
"Microsoft.CodeAnalysis.Scripting.CSharp", {
"mscorlib: global,<host>", switch (assemblyAndAliases.Item1.Identity.Name)
"Microsoft.CodeAnalysis.Scripting: global,<host>", {
"System.Collections.Immutable: <implicit>,global,<host>", case "mscorlib":
"Microsoft.CodeAnalysis: <implicit>,global,<host>", AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
"System.Diagnostics.Tools: <implicit>,global,<host>", break;
"System.Resources.ResourceManager: <implicit>,global,<host>",
"System.Console: <implicit>,global,<host>", case "Microsoft.CodeAnalysis.CSharp.Scripting":
"System.Diagnostics.StackTrace: <implicit>,global,<host>", AssertEx.SetEqual(new string[0], assemblyAndAliases.Item2);
"System.IO.FileSystem: <implicit>,global,<host>", break;
"System.Linq: <implicit>,global,<host>",
"System.Text.Encoding: <implicit>,global,<host>", case "Microsoft.CodeAnalysis.Scripting":
"System.IO.FileSystem.Primitives: <implicit>,global,<host>", AssertEx.SetEqual(new[] { "global", "<host>" }, assemblyAndAliases.Item2);
"System.Reflection.Extensions: <implicit>,global,<host>", break;
"System.Core: <implicit>,global,<host>",
"System: <implicit>,global,<host>", case "Microsoft.CodeAnalysis.CSharp":
"System.Xml: <implicit>,global,<host>", AssertEx.SetEqual(new[] { "<implicit>", "global" }, assemblyAndAliases.Item2);
"System.Numerics: <implicit>,global,<host>", break;
"System.Security: <implicit>,global,<host>",
"System.Data.SqlXml: <implicit>,global,<host>", case "Microsoft.CodeAnalysis":
"System.Configuration: <implicit>,global,<host>", case "System.IO":
"System.Runtime: <implicit>,global,<host>", case "System.Collections.Immutable":
"System.Diagnostics.Debug: <implicit>,global,<host>", AssertEx.SetEqual(new[] { "<implicit>", "global", "<host>" }, assemblyAndAliases.Item2);
"System.Runtime.InteropServices: <implicit>,global,<host>", break;
"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");
} }
#endregion #endregion
......
...@@ -118,10 +118,5 @@ public void EnableActiveTokenTracking(bool enable) ...@@ -118,10 +118,5 @@ public void EnableActiveTokenTracking(bool enable)
waiter.Value.TrackActiveTokens = enable; waiter.Value.TrackActiveTokens = enable;
} }
} }
public void PumpingWait(Task task)
{
task.PumpingWait();
}
} }
} }
...@@ -56,7 +56,11 @@ internal partial class CSharpCodeModelService : AbstractCodeModelService ...@@ -56,7 +56,11 @@ internal partial class CSharpCodeModelService : AbstractCodeModelService
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); 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( new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeExplicitInterface, memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeExplicitInterface,
...@@ -943,17 +947,7 @@ public override string GetFullName(SyntaxNode node, SemanticModel semanticModel) ...@@ -943,17 +947,7 @@ public override string GetFullName(SyntaxNode node, SemanticModel semanticModel)
? semanticModel.GetTypeInfo(node).Type ? semanticModel.GetTypeInfo(node).Type
: semanticModel.GetDeclaredSymbol(node); : semanticModel.GetDeclaredSymbol(node);
return GetFullName(symbol); return GetExternalSymbolFullName(symbol);
}
public override string GetFullName(ISymbol symbol)
{
if (symbol == null)
{
throw Exceptions.ThrowEFail();
}
return symbol.ToDisplayString(s_fullNameFormat);
} }
public override string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel) public override string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel)
...@@ -980,6 +974,46 @@ public override string GetFullyQualifiedName(string name, int position, Semantic ...@@ -980,6 +974,46 @@ public override string GetFullyQualifiedName(string name, int position, Semantic
return name; 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) public override EnvDTE.vsCMAccess GetAccess(ISymbol symbol)
{ {
switch (symbol.DeclaredAccessibility) switch (symbol.DeclaredAccessibility)
......
...@@ -95,7 +95,7 @@ private string GetDelegatePrototype(INamedTypeSymbol symbol, PrototypeFlags flag ...@@ -95,7 +95,7 @@ private string GetDelegatePrototype(INamedTypeSymbol symbol, PrototypeFlags flag
} }
// The unique signature is simply the node key. // The unique signature is simply the node key.
return GetFullName(symbol); return GetExternalSymbolFullName(symbol);
} }
var builder = new StringBuilder(); 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. // 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.Collections.Generic;
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
...@@ -16,7 +17,7 @@ namespace Microsoft.VisualStudio.LanguageServices ...@@ -16,7 +17,7 @@ namespace Microsoft.VisualStudio.LanguageServices
/// </summary> /// </summary>
public abstract class VisualStudioWorkspace : Workspace public abstract class VisualStudioWorkspace : Workspace
{ {
private readonly BackgroundCompiler _backgroundCompiler; private BackgroundCompiler _backgroundCompiler;
private readonly BackgroundParser _backgroundParser; private readonly BackgroundParser _backgroundParser;
internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWork backgroundWork) internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWork backgroundWork)
...@@ -25,6 +26,12 @@ internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWor ...@@ -25,6 +26,12 @@ internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWor
if ((backgroundWork & WorkspaceBackgroundWork.Compile) != 0) if ((backgroundWork & WorkspaceBackgroundWork.Compile) != 0)
{ {
_backgroundCompiler = new BackgroundCompiler(this); _backgroundCompiler = new BackgroundCompiler(this);
var cacheService = Services.GetService<IWorkspaceCacheService>();
if (cacheService != null)
{
cacheService.CacheFlushRequested += OnCacheFlushRequested;
}
} }
if ((backgroundWork & WorkspaceBackgroundWork.Parse) != 0) if ((backgroundWork & WorkspaceBackgroundWork.Parse) != 0)
...@@ -34,6 +41,22 @@ internal VisualStudioWorkspace(HostServices hostServices, WorkspaceBackgroundWor ...@@ -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 protected internal override bool PartialSemanticsEnabled
{ {
get { return _backgroundCompiler != null; } get { return _backgroundCompiler != null; }
......
...@@ -18,6 +18,7 @@ namespace Microsoft.VisualStudio.LanguageServices ...@@ -18,6 +18,7 @@ namespace Microsoft.VisualStudio.LanguageServices
internal sealed class VirtualMemoryNotificationListener : ForegroundThreadAffinitizedObject, IVsBroadcastMessageEvents internal sealed class VirtualMemoryNotificationListener : ForegroundThreadAffinitizedObject, IVsBroadcastMessageEvents
{ {
private WorkspaceCacheService _workspaceCacheService; private WorkspaceCacheService _workspaceCacheService;
private bool _alreadyLogged;
[ImportingConstructor] [ImportingConstructor]
private VirtualMemoryNotificationListener( private VirtualMemoryNotificationListener(
...@@ -52,8 +53,12 @@ public int OnBroadcastMessage(uint msg, IntPtr wParam, IntPtr lParam) ...@@ -52,8 +53,12 @@ public int OnBroadcastMessage(uint msg, IntPtr wParam, IntPtr lParam)
case VSConstants.VSM_VIRTUALMEMORYLOW: case VSConstants.VSM_VIRTUALMEMORYLOW:
case VSConstants.VSM_VIRTUALMEMORYCRITICAL: case VSConstants.VSM_VIRTUALMEMORYCRITICAL:
{ {
// record that we had hit critical memory barrier if (!_alreadyLogged)
Logger.Log(FunctionId.VirtualMemory_MemoryLow, KeyValueLogMessage.Create(m => m["Memory"] = msg)); {
// record that we had hit critical memory barrier
Logger.Log(FunctionId.VirtualMemory_MemoryLow, KeyValueLogMessage.Create(m => m["Memory"] = msg));
_alreadyLogged = true;
}
_workspaceCacheService.FlushCaches(); _workspaceCacheService.FlushCaches();
break; break;
......
...@@ -260,7 +260,10 @@ public EnvDTE.CodeElement CreateExternalCodeElement(CodeModelState state, Projec ...@@ -260,7 +260,10 @@ public EnvDTE.CodeElement CreateExternalCodeElement(CodeModelState state, Projec
} }
case SymbolKind.Property: 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: default:
throw Exceptions.ThrowEFail(); throw Exceptions.ThrowEFail();
} }
...@@ -519,7 +522,6 @@ protected EnvDTE80.CodeAttributeArgument CreateInternalCodeAttributeArgument(Cod ...@@ -519,7 +522,6 @@ protected EnvDTE80.CodeAttributeArgument CreateInternalCodeAttributeArgument(Cod
public abstract SyntaxNode SetName(SyntaxNode node, string name); public abstract SyntaxNode SetName(SyntaxNode node, string name);
public abstract string GetFullName(SyntaxNode node, SemanticModel semanticModel); public abstract string GetFullName(SyntaxNode node, SemanticModel semanticModel);
public abstract string GetFullName(ISymbol symbol);
public abstract string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel); public abstract string GetFullyQualifiedName(string name, int position, SemanticModel semanticModel);
...@@ -568,6 +570,10 @@ public void Rename(ISymbol symbol, string newName, Solution solution) ...@@ -568,6 +570,10 @@ public void Rename(ISymbol symbol, string newName, Solution solution)
nodeKeyValidation.RestoreKeys(); 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) public VirtualTreePoint? GetStartPoint(SyntaxNode node, EnvDTE.vsCMPart? part)
{ {
return _nodeLocator.GetStartPoint(node, part); return _nodeLocator.GetStartPoint(node, part);
......
...@@ -55,7 +55,10 @@ private ImmutableArray<EnvDTE.CodeElement> GetChildren() ...@@ -55,7 +55,10 @@ private ImmutableArray<EnvDTE.CodeElement> GetChildren()
foreach (var member in typeSymbol.GetMembers()) foreach (var member in typeSymbol.GetMembers())
{ {
childrenBuilder.Add(this.State.CodeModelService.CreateExternalCodeElement(this.State, _projectId, member)); if (this.CodeModelService.IsValidExternalSymbol(member))
{
childrenBuilder.Add(this.State.CodeModelService.CreateExternalCodeElement(this.State, _projectId, member));
}
} }
foreach (var typeMember in typeSymbol.GetTypeMembers()) foreach (var typeMember in typeSymbol.GetTypeMembers())
......
...@@ -61,7 +61,7 @@ protected virtual string GetDocComment() ...@@ -61,7 +61,7 @@ protected virtual string GetDocComment()
protected virtual string GetFullName() protected virtual string GetFullName()
{ {
return CodeModelService.GetFullName(LookupSymbol()); return CodeModelService.GetExternalSymbolFullName(LookupSymbol());
} }
protected virtual bool GetIsShared() protected virtual bool GetIsShared()
...@@ -72,8 +72,7 @@ protected virtual bool GetIsShared() ...@@ -72,8 +72,7 @@ protected virtual bool GetIsShared()
protected virtual string GetName() protected virtual string GetName()
{ {
var symbol = LookupSymbol(); return CodeModelService.GetExternalSymbolName(LookupSymbol());
return symbol.Name;
} }
protected virtual object GetParent() protected virtual object GetParent()
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Collections; using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Collections;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interop; using Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities;
......
...@@ -11,20 +11,33 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Exter ...@@ -11,20 +11,33 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Exter
[ComDefaultInterface(typeof(EnvDTE.CodeVariable))] [ComDefaultInterface(typeof(EnvDTE.CodeVariable))]
public sealed class ExternalCodeVariable : AbstractExternalCodeMember, EnvDTE.CodeVariable, EnvDTE80.CodeVariable2 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); var element = new ExternalCodeVariable(state, projectId, symbol);
return (EnvDTE.CodeVariable)ComAggregate.CreateAggregatedObject(element); 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) : 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 public override EnvDTE.vsCMElement Kind
...@@ -49,10 +62,14 @@ public bool IsConstant ...@@ -49,10 +62,14 @@ public bool IsConstant
{ {
get get
{ {
// TODO: Verify VB implementation var fieldSymbol = LookupSymbol() as IFieldSymbol;
var symbol = FieldSymbol; if (fieldSymbol == null)
return symbol.IsConst {
|| symbol.IsReadOnly; return false;
}
return fieldSymbol.IsConst
|| fieldSymbol.IsReadOnly;
} }
set set
...@@ -65,7 +82,13 @@ public EnvDTE.CodeTypeRef Type ...@@ -65,7 +82,13 @@ public EnvDTE.CodeTypeRef Type
{ {
get 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 set
...@@ -78,13 +101,17 @@ public EnvDTE80.vsCMConstKind ConstKind ...@@ -78,13 +101,17 @@ public EnvDTE80.vsCMConstKind ConstKind
{ {
get get
{ {
// TODO: Verify VB Implementation var fieldSymbol = LookupSymbol() as IFieldSymbol;
var symbol = FieldSymbol; if (fieldSymbol == null)
if (symbol.IsConst) {
return EnvDTE80.vsCMConstKind.vsCMConstKindNone;
}
if (fieldSymbol.IsConst)
{ {
return EnvDTE80.vsCMConstKind.vsCMConstKindConst; return EnvDTE80.vsCMConstKind.vsCMConstKindConst;
} }
else if (symbol.IsReadOnly) else if (fieldSymbol.IsReadOnly)
{ {
return EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly; return EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly;
} }
...@@ -105,7 +132,7 @@ public bool IsGeneric ...@@ -105,7 +132,7 @@ public bool IsGeneric
get get
{ {
// TODO: C# checks whether the field Type is generic. What does VB do? // 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 return namedType != null
? namedType.IsGenericType ? namedType.IsGenericType
: false; : false;
......
...@@ -114,11 +114,6 @@ internal interface ICodeModelService : ICodeModelNavigationPointService ...@@ -114,11 +114,6 @@ internal interface ICodeModelService : ICodeModelNavigationPointService
/// </summary> /// </summary>
string GetFullName(SyntaxNode node, SemanticModel semanticModel); 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> /// <summary>
/// Given a name, attempts to convert it to a fully qualified name. /// Given a name, attempts to convert it to a fully qualified name.
/// </summary> /// </summary>
...@@ -126,6 +121,21 @@ internal interface ICodeModelService : ICodeModelNavigationPointService ...@@ -126,6 +121,21 @@ internal interface ICodeModelService : ICodeModelNavigationPointService
void Rename(ISymbol symbol, string newName, Solution solution); 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 GetNodeWithModifiers(SyntaxNode node);
SyntaxNode GetNodeWithType(SyntaxNode node); SyntaxNode GetNodeWithType(SyntaxNode node);
SyntaxNode GetNodeWithInitializer(SyntaxNode node); SyntaxNode GetNodeWithInitializer(SyntaxNode node);
......
...@@ -56,106 +56,69 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -56,106 +56,69 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestAttributeArguments(code As XElement, ParamArray expectedAttributeArguments() As Action(Of Object)) Protected Sub TestAttributeArguments(code As XElement, ParamArray expectedAttributeArguments() As Action(Of Object))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim attributes = GetAttributeArguments(codeElement)
Assert.Equal(expectedAttributeArguments.Length, attributes.Count)
Dim attributes = GetAttributeArguments(codeElement)
Assert.Equal(expectedAttributeArguments.Length, attributes.Count) For i = 1 To attributes.Count
expectedAttributeArguments(i - 1)(attributes.Item(i))
For i = 1 To attributes.Count Next
expectedAttributeArguments(i - 1)(attributes.Item(i)) End Sub)
Next
End Using
End Sub End Sub
Protected Sub TestTarget(code As XElement, expectedTarget As String) Protected Sub TestTarget(code As XElement, expectedTarget As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim target = GetTarget(codeElement)
Assert.Equal(expectedTarget, target)
Dim target = GetTarget(codeElement) End Sub)
Assert.Equal(expectedTarget, target)
End Using
End Sub End Sub
Protected Sub TestSetTarget(code As XElement, expectedCode As XElement, target As String) Protected Sub TestSetTarget(code As XElement, expectedCode As XElement, target As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeAttribute = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeAttribute) codeElement.Target = target
End Sub)
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
End Sub End Sub
Protected Sub TestValue(code As XElement, expectedValue As String) Protected Sub TestValue(code As XElement, expectedValue As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim target = GetValue(codeElement)
Assert.Equal(expectedValue, target)
End Sub)
End Sub
Dim target = GetValue(codeElement) Protected Sub TestSetValue(code As XElement, expectedCode As XElement, value As String)
Assert.Equal(expectedValue, target) TestElementUpdate(code, expectedCode,
End Using Sub(codeElement)
codeElement.Value = value
End Sub)
End Sub End Sub
Protected Sub TestAddAttributeArgument(code As XElement, expectedCode As XElement, data As AttributeArgumentData) Protected Sub TestAddAttributeArgument(code As XElement, expectedCode As XElement, data As AttributeArgumentData)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim attributeArgument = AddAttributeArgument(codeElement, data)
Assert.NotNull(attributeArgument)
Dim attributeArgument = AddAttributeArgument(codeElement, data) Assert.Equal(data.Name, attributeArgument.Name)
Assert.NotNull(attributeArgument) End Sub)
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) Protected Sub TestDelete(code As XElement, expectedCode As XElement)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) codeElement.Delete()
End Sub)
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) Protected Sub TestDeleteAttributeArgument(code As XElement, expectedCode As XElement, indexToDelete As Integer)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim argument = CType(codeElement.Arguments.Item(indexToDelete), EnvDTE80.CodeAttributeArgument)
argument.Delete()
Dim argument = CType(codeElement.Arguments.Item(indexToDelete), EnvDTE80.CodeAttributeArgument) End Sub)
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) Protected Function IsAttributeArgument(Optional name As String = Nothing, Optional value As String = Nothing) As Action(Of Object)
...@@ -175,33 +138,29 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -175,33 +138,29 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestAttributeArgumentStartPoint(code As XElement, index As Integer, ParamArray expectedParts() As Action(Of Func(Of EnvDTE.vsCMPart, EnvDTE.TextPoint))) 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)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim startPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetStartPoint(part) Dim startPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetStartPoint(part)
For Each action In expectedParts For Each action In expectedParts
action(startPointGetter) action(startPointGetter)
Next Next
End Using End Sub)
End Sub End Sub
Protected Sub TestAttributeArgumentEndPoint(code As XElement, index As Integer, ParamArray expectedParts() As Action(Of Func(Of EnvDTE.vsCMPart, EnvDTE.TextPoint))) 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)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeAttribute2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim arg = CType(codeElement.Arguments.Item(index), EnvDTE80.CodeAttributeArgument)
Dim endPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetEndPoint(part) Dim endPointGetter = Function(part As EnvDTE.vsCMPart) arg.GetEndPoint(part)
For Each action In expectedParts For Each action In expectedParts
action(endPointGetter) action(endPointGetter)
Next Next
End Using End Sub)
End Sub End Sub
End Class End Class
......
...@@ -77,13 +77,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -77,13 +77,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestBaseClass(code As XElement, expectedFullName As String) Protected Sub TestBaseClass(code As XElement, expectedFullName As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeDelegate2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.NotNull(codeElement.BaseClass)
Assert.NotNull(codeElement.BaseClass) Assert.Equal(expectedFullName, codeElement.BaseClass.FullName)
End Sub)
Assert.Equal(expectedFullName, codeElement.BaseClass.FullName)
End Using
End Sub End Sub
End Class End Class
......
...@@ -73,12 +73,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -73,12 +73,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestIsPropertyStyleEvent(code As XElement, expected As Boolean) Protected Sub TestIsPropertyStyleEvent(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeEvent)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, codeElement.IsPropertyStyleEvent)
End Sub)
Assert.Equal(expected, codeElement.IsPropertyStyleEvent)
End Using
End Sub End Sub
End Class End Class
......
...@@ -131,12 +131,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -131,12 +131,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestCanOverride(code As XElement, expected As Boolean) Protected Sub TestCanOverride(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, codeElement.CanOverride)
End Sub)
Assert.Equal(expected, codeElement.CanOverride)
End Using
End Sub End Sub
Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean) Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean)
...@@ -144,95 +142,73 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -144,95 +142,73 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean)) Protected Sub TestSetCanOverride(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) action(value, Sub(v) codeElement.CanOverride = v)
End Sub)
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) Protected Sub TestIsOverloaded(code As XElement, expectedOverloaded As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim overloaded = GetIsOverloaded(codeElement)
Assert.Equal(expectedOverloaded, overloaded)
Dim overloaded = GetIsOverloaded(codeElement) End Sub)
Assert.Equal(expectedOverloaded, overloaded)
End Using
End Sub End Sub
Protected Sub TestOverloadsUniqueSignatures(code As XElement, ParamArray expectedOverloadNames As String()) Protected Sub TestOverloadsUniqueSignatures(code As XElement, ParamArray expectedOverloadNames As String())
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim actualOverloads = GetOverloads(codeElement)
Assert.Equal(expectedOverloadNames.Count, actualOverloads.Count)
Dim actualOverloads = GetOverloads(codeElement) For index = 1 To actualOverloads.Count
Assert.Equal(expectedOverloadNames.Count, actualOverloads.Count) Dim codeFunction = CType(actualOverloads.Item(index), EnvDTE80.CodeFunction2)
For index = 1 To actualOverloads.Count Dim signature = GetPrototype(codeFunction, EnvDTE.vsCMPrototype.vsCMPrototypeUniqueSignature)
Dim codeFunction = CType(actualOverloads.Item(index), EnvDTE80.CodeFunction2) Assert.True(expectedOverloadNames.Contains(signature))
Dim signature = GetPrototype(codeFunction, EnvDTE.vsCMPrototype.vsCMPrototypeUniqueSignature) Next
Assert.True(expectedOverloadNames.Contains(signature)) End Sub)
Next
End Using
End Sub End Sub
Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE.vsCMFunction) Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE.vsCMFunction)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, codeElement.FunctionKind)
End Sub)
Assert.Equal(expected, codeElement.FunctionKind)
End Using
End Sub End Sub
Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE80.vsCMFunction2) Protected Sub TestFunctionKind(code As XElement, expected As EnvDTE80.vsCMFunction2)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, CType(codeElement.FunctionKind, EnvDTE80.vsCMFunction2))
End Sub)
Assert.Equal(expected, CType(codeElement.FunctionKind, EnvDTE80.vsCMFunction2))
End Using
End Sub End Sub
Protected Sub TestExtensionMethodExtender_IsExtension(code As XElement, expected As Boolean) Protected Sub TestExtensionMethodExtender_IsExtension(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, ExtensionMethodExtender_GetIsExtension(codeElement))
End Sub)
Assert.Equal(expected, ExtensionMethodExtender_GetIsExtension(codeElement))
End Using
End Sub End Sub
Protected Sub TestPartialMethodExtender_IsPartial(code As XElement, expected As Boolean) Protected Sub TestPartialMethodExtender_IsPartial(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, PartialMethodExtender_GetIsPartial(codeElement))
End Sub)
Assert.Equal(expected, PartialMethodExtender_GetIsPartial(codeElement))
End Using
End Sub End Sub
Protected Sub TestPartialMethodExtender_IsDeclaration(code As XElement, expected As Boolean) Protected Sub TestPartialMethodExtender_IsDeclaration(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, PartialMethodExtender_GetIsDeclaration(codeElement))
End Sub)
Assert.Equal(expected, PartialMethodExtender_GetIsDeclaration(codeElement))
End Using
End Sub End Sub
Protected Sub TestPartialMethodExtender_HasOtherPart(code As XElement, expected As Boolean) Protected Sub TestPartialMethodExtender_HasOtherPart(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeFunction2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, PartialMethodExtender_GetHasOtherPart(codeElement))
End Sub)
Assert.Equal(expected, PartialMethodExtender_GetHasOtherPart(codeElement))
End Using
End Sub End Sub
End Class End Class
......
...@@ -37,12 +37,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -37,12 +37,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestNamespace(code As XElement, expectedNamespace As String) Protected Sub TestNamespace(code As XElement, expectedNamespace As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeImport)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expectedNamespace, codeElement.Namespace)
End Sub)
Assert.Equal(expectedNamespace, codeElement.Namespace)
End Using
End Sub End Sub
End Class End Class
......
...@@ -65,21 +65,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -65,21 +65,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestParameterKind(code As XElement, kind As vsCMParameterKind) Protected Sub TestParameterKind(code As XElement, kind As vsCMParameterKind)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(kind, codeElement.ParameterKind)
End Sub)
Assert.Equal(kind, codeElement.ParameterKind)
End Using
End Sub End Sub
Protected Sub TestDefaultValue(code As XElement, expectedValue As String) Protected Sub TestDefaultValue(code As XElement, expectedValue As String)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expectedValue, codeElement.DefaultValue)
End Sub)
Assert.Equal(expectedValue, codeElement.DefaultValue)
End Using
End Sub End Sub
Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind) Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind)
...@@ -87,18 +83,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -87,18 +83,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind, action As SetterAction(Of EnvDTE80.vsCMParameterKind)) Protected Sub TestSetParameterKind(code As XElement, expectedCode As XElement, kind As EnvDTE80.vsCMParameterKind, action As SetterAction(Of EnvDTE80.vsCMParameterKind))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim parameterKindSetter = GetParameterKindSetter(codeElement)
action(kind, parameterKindSetter)
Dim parameterKindSetter = GetParameterKindSetter(codeElement) End Sub)
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) Protected Sub TestSetDefaultValue(code As XElement, expected As XElement, defaultValue As String)
...@@ -106,18 +95,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -106,18 +95,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestSetDefaultValue(code As XElement, expectedCode As XElement, defaultValue As String, action As SetterAction(Of String)) Protected Sub TestSetDefaultValue(code As XElement, expectedCode As XElement, defaultValue As String, action As SetterAction(Of String))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of CodeParameter2)() Sub(codeElement)
Assert.NotNull(codeElement) Dim defaultValueSetter = GetDefaultValueSetter(codeElement)
action(defaultValue, defaultValueSetter)
Dim defaultValueSetter = GetDefaultValueSetter(codeElement) End Sub)
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 Class
End Namespace End Namespace
...@@ -101,30 +101,24 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -101,30 +101,24 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestAutoImplementedPropertyExtender_IsAutoImplemented(code As XElement, expected As Boolean) Protected Sub TestAutoImplementedPropertyExtender_IsAutoImplemented(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, AutoImplementedPropertyExtender_GetIsAutoImplemented(codeElement))
End Sub)
Assert.Equal(expected, AutoImplementedPropertyExtender_GetIsAutoImplemented(codeElement))
End Using
End Sub End Sub
Protected Sub TestGetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction)) Protected Sub TestGetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)() Sub(codeElement)
Assert.NotNull(codeElement) verifier(codeElement.Getter)
End Sub)
verifier(codeElement.Getter)
End Using
End Sub End Sub
Protected Sub TestSetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction)) Protected Sub TestSetter(code As XElement, verifier As Action(Of EnvDTE.CodeFunction))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeProperty2)() Sub(codeElement)
Assert.NotNull(codeElement) verifier(codeElement.Setter)
End Sub)
verifier(codeElement.Setter)
End Using
End Sub End Sub
End Class End Class
......
...@@ -95,12 +95,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -95,12 +95,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Function End Function
Protected Sub TestIsConstant(code As XElement, expected As Boolean) Protected Sub TestIsConstant(code As XElement, expected As Boolean)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, codeElement.IsConstant)
End Sub)
Assert.Equal(expected, codeElement.IsConstant)
End Using
End Sub End Sub
Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean) Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean)
...@@ -108,25 +106,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -108,25 +106,17 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean)) Protected Sub TestSetIsConstant(code As XElement, expectedCode As XElement, value As Boolean, action As SetterAction(Of Boolean))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)() Sub(codeElement)
Assert.NotNull(codeElement) action(value, Sub(v) codeElement.IsConstant = v)
End Sub)
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) Protected Sub TestInitExpression(code As XElement, expected As Object)
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElement(code,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)() Sub(codeElement)
Assert.NotNull(codeElement) Assert.Equal(expected, codeElement.InitExpression)
End Sub)
Assert.Equal(expected, codeElement.InitExpression)
End Using
End Sub End Sub
Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object) Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object)
...@@ -134,16 +124,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -134,16 +124,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
End Sub End Sub
Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object, action As SetterAction(Of Object)) Protected Sub TestSetInitExpression(code As XElement, expectedCode As XElement, value As Object, action As SetterAction(Of Object))
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code)) TestElementUpdate(code, expectedCode,
Dim codeElement = state.GetCodeElementAtCursor(Of EnvDTE80.CodeVariable2)() Sub(codeElement)
Assert.NotNull(codeElement) action(value, Sub(v) codeElement.InitExpression = v)
End Sub)
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 End Class
......
...@@ -618,7 +618,7 @@ class C { } ...@@ -618,7 +618,7 @@ class C { }
End Sub 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() Public Sub AddAttributeArgument3()
Dim code = Dim code =
<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 ...@@ -949,14 +949,14 @@ class $$C
void M() { } void M() { }
} }
</Code> </Code>
Using workspaceAndFileCodeModel = CreateCodeModelTestState(GetWorkspaceDefinition(code)) Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Dim codeClass = workspaceAndFileCodeModel.GetCodeElementAtCursor(Of EnvDTE80.CodeClass2) Dim codeClass = state.GetCodeElementAtCursor(Of EnvDTE80.CodeClass2)
Assert.Equal(1, codeClass.Members.OfType(Of EnvDTE80.CodeFunction2)().Count()) 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() Dim documentId = project.DocumentIds.First()
workspaceAndFileCodeModel.VisualStudioWorkspace.CloseDocument(documentId) state.VisualStudioWorkspace.CloseDocument(documentId)
Dim newSolution = workspaceAndFileCodeModel.VisualStudioWorkspace.CurrentSolution.RemoveDocument(documentId) Dim newSolution = state.VisualStudioWorkspace.CurrentSolution.RemoveDocument(documentId)
workspaceAndFileCodeModel.VisualStudioWorkspace.TryApplyChanges(newSolution) state.VisualStudioWorkspace.TryApplyChanges(newSolution)
' throws COMException with HResult = E_FAIL ' throws COMException with HResult = E_FAIL
Assert.Throws(Of System.Runtime.InteropServices.COMException)( Assert.Throws(Of System.Runtime.InteropServices.COMException)(
Sub() Sub()
......
...@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces ...@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.ComponentModelHost Imports Microsoft.VisualStudio.ComponentModelHost
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel 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.CodeModel.Interop
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Interop Imports Microsoft.VisualStudio.LanguageServices.Implementation.Interop
Imports Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.Mocks Imports Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.Mocks
...@@ -162,6 +163,30 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel ...@@ -162,6 +163,30 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Return CType(result, T) Return CType(result, T)
End Function 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()> <Extension()>
Public Function GetMethodXML(func As EnvDTE.CodeFunction) As XElement Public Function GetMethodXML(func As EnvDTE.CodeFunction) As XElement
Dim methodXml = TryCast(func, IMethodXML) Dim methodXml = TryCast(func, IMethodXML)
......
...@@ -798,7 +798,7 @@ End Class ...@@ -798,7 +798,7 @@ End Class
End Sub 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() Public Sub AddAttributeArgument2()
Dim code = Dim code =
<Code> <Code>
...@@ -822,7 +822,7 @@ End Class ...@@ -822,7 +822,7 @@ End Class
End Sub 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() Public Sub TestAddArgument3()
Dim code = Dim code =
<Code> <Code>
......
...@@ -3141,6 +3141,39 @@ End Class ...@@ -3141,6 +3141,39 @@ End Class
End Sub) End Sub)
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)> <ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub ClassIncludedDeclareMethods() Public Sub ClassIncludedDeclareMethods()
Dim code = 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 @@ ...@@ -284,6 +284,7 @@
<Compile Include="CodeModel\CSharp\CodeStructTests.vb" /> <Compile Include="CodeModel\CSharp\CodeStructTests.vb" />
<Compile Include="CodeModel\CSharp\CodeVariableTests.vb" /> <Compile Include="CodeModel\CSharp\CodeVariableTests.vb" />
<Compile Include="CodeModel\CSharp\EventCollectorTests.vb" /> <Compile Include="CodeModel\CSharp\EventCollectorTests.vb" />
<Compile Include="CodeModel\CSharp\ExternalCodeClassTests.vb" />
<Compile Include="CodeModel\CSharp\FileCodeModelTests.vb" /> <Compile Include="CodeModel\CSharp\FileCodeModelTests.vb" />
<Compile Include="CodeModel\CSharp\RootCodeModelTests.vb" /> <Compile Include="CodeModel\CSharp\RootCodeModelTests.vb" />
<Compile Include="CodeModel\CSharp\SyntaxNodeKeyTests.vb" /> <Compile Include="CodeModel\CSharp\SyntaxNodeKeyTests.vb" />
...@@ -317,6 +318,7 @@ ...@@ -317,6 +318,7 @@
<Compile Include="CodeModel\VisualBasic\CodeStructTests.vb" /> <Compile Include="CodeModel\VisualBasic\CodeStructTests.vb" />
<Compile Include="CodeModel\VisualBasic\CodeVariableTests.vb" /> <Compile Include="CodeModel\VisualBasic\CodeVariableTests.vb" />
<Compile Include="CodeModel\VisualBasic\EventCollectorTests.vb" /> <Compile Include="CodeModel\VisualBasic\EventCollectorTests.vb" />
<Compile Include="CodeModel\VisualBasic\ExternalCodeClassTests.vb" />
<Compile Include="CodeModel\VisualBasic\FileCodeModelTests.vb" /> <Compile Include="CodeModel\VisualBasic\FileCodeModelTests.vb" />
<Compile Include="CodeModel\VisualBasic\ImplementsStatementTests.vb" /> <Compile Include="CodeModel\VisualBasic\ImplementsStatementTests.vb" />
<Compile Include="CodeModel\VisualBasic\InheritsStatementTests.vb" /> <Compile Include="CodeModel\VisualBasic\InheritsStatementTests.vb" />
...@@ -454,4 +456,4 @@ ...@@ -454,4 +456,4 @@
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" /> <Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" /> <Import Project="..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</ImportGroup> </ImportGroup>
</Project> </Project>
\ No newline at end of file
...@@ -53,7 +53,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -53,7 +53,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters, genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.UseSpecialTypes) 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( New SymbolDisplayFormat(
typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters, genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
...@@ -430,15 +435,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -430,15 +435,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
For Each member In DirectCast(container, CompilationUnitSyntax).Members For Each member In DirectCast(container, CompilationUnitSyntax).Members
Yield member Yield member
Next Next
ElseIf TypeOf container Is NamespaceBlockSyntax ElseIf TypeOf container Is NamespaceBlockSyntax Then
For Each member In DirectCast(container, NamespaceBlockSyntax).Members For Each member In DirectCast(container, NamespaceBlockSyntax).Members
Yield member Yield member
Next Next
ElseIf TypeOf container Is TypeBlockSyntax ElseIf TypeOf container Is TypeBlockSyntax Then
For Each member In DirectCast(container, TypeBlockSyntax).Members For Each member In DirectCast(container, TypeBlockSyntax).Members
Yield member Yield member
Next Next
ElseIf TypeOf container Is EnumBlockSyntax ElseIf TypeOf container Is EnumBlockSyntax Then
For Each member In DirectCast(container, EnumBlockSyntax).Members For Each member In DirectCast(container, EnumBlockSyntax).Members
Yield member Yield member
Next Next
...@@ -491,12 +499,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -491,12 +499,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Next Next
Next Next
ElseIf Not onlySupportedNodes ElseIf Not onlySupportedNodes Then
' Only return fields if the supported flag Is false. ' Only return fields if the supported flag Is false.
Yield member Yield member
End If End If
ElseIf NodeIsSupported(onlySupportedNodes, member) ElseIf NodeIsSupported(onlySupportedNodes, member) Then
Yield member Yield member
End If End If
...@@ -1023,15 +1031,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -1023,15 +1031,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
semanticModel.GetTypeInfo(node).Type, semanticModel.GetTypeInfo(node).Type,
semanticModel.GetDeclaredSymbol(node)) semanticModel.GetDeclaredSymbol(node))
Return GetFullName(symbol) Return GetExternalSymbolFullName(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)
End Function End Function
Public Overrides Function IsAccessorNode(node As SyntaxNode) As Boolean Public Overrides Function IsAccessorNode(node As SyntaxNode) As Boolean
...@@ -1341,20 +1341,62 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -1341,20 +1341,62 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
.WaitAndGetResult(CancellationToken.None) .WaitAndGetResult(CancellationToken.None)
End Function 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 Public Overrides Function GetAccess(symbol As ISymbol) As EnvDTE.vsCMAccess
Debug.Assert(symbol IsNot Nothing) Debug.Assert(symbol IsNot Nothing)
Dim access As EnvDTE.vsCMAccess = 0 Dim access As EnvDTE.vsCMAccess = 0
' TODO: Add vsCMAccessWithEvents for fields symbols defined as WithEvents
Select Case symbol.DeclaredAccessibility Select Case symbol.DeclaredAccessibility
Case Accessibility.Private Case Accessibility.Private
access = access Or EnvDTE.vsCMAccess.vsCMAccessPrivate access = access Or EnvDTE.vsCMAccess.vsCMAccessPrivate
Case Accessibility.Protected Case Accessibility.Protected
access = access Or EnvDTE.vsCMAccess.vsCMAccessProtected access = access Or EnvDTE.vsCMAccess.vsCMAccessProtected
Case Accessibility.Internal Case Accessibility.Internal, Accessibility.Friend
access = access Or EnvDTE.vsCMAccess.vsCMAccessProject access = access Or EnvDTE.vsCMAccess.vsCMAccessProject
Case Accessibility.ProtectedOrInternal Case Accessibility.ProtectedOrInternal, Accessibility.ProtectedOrFriend
access = access Or EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected access = access Or EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected
Case Accessibility.Public Case Accessibility.Public
access = access Or EnvDTE.vsCMAccess.vsCMAccessPublic access = access Or EnvDTE.vsCMAccess.vsCMAccessPublic
...@@ -1362,8 +1404,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -1362,8 +1404,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Throw Exceptions.ThrowEFail() Throw Exceptions.ThrowEFail()
End Select End Select
If symbol.IsKind(SymbolKind.Property) AndAlso If TryCast(symbol, IPropertySymbol)?.IsWithEvents Then
DirectCast(symbol, IPropertySymbol).IsWithEvents Then
access = access Or EnvDTE.vsCMAccess.vsCMAccessWithEvents access = access Or EnvDTE.vsCMAccess.vsCMAccessWithEvents
End If End If
...@@ -2853,7 +2894,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -2853,7 +2894,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
If propertyStatement IsNot Nothing Then If propertyStatement IsNot Nothing Then
If propertyStatement.Modifiers.Any(SyntaxKind.WriteOnlyKeyword) Then If propertyStatement.Modifiers.Any(SyntaxKind.WriteOnlyKeyword) Then
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindWriteOnly Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindWriteOnly
ElseIf propertyStatement.Modifiers.Any(SyntaxKind.ReadOnlyKeyword) ElseIf propertyStatement.Modifiers.Any(SyntaxKind.ReadOnlyKeyword) Then
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadOnly Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadOnly
Else Else
Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadWrite Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadWrite
...@@ -3778,7 +3819,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -3778,7 +3819,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Dim enumMember = DirectCast(container, EnumMemberDeclarationSyntax) Dim enumMember = DirectCast(container, EnumMemberDeclarationSyntax)
Dim attributeLists = enumMember.AttributeLists.Insert(index, attributeList) Dim attributeLists = enumMember.AttributeLists.Insert(index, attributeList)
Return enumMember.WithAttributeLists(attributeLists) Return enumMember.WithAttributeLists(attributeLists)
ElseIf TypeOf container Is DelegateStatementSyntax ElseIf TypeOf container Is DelegateStatementSyntax Then
Dim delegateStatement = DirectCast(container, DelegateStatementSyntax) Dim delegateStatement = DirectCast(container, DelegateStatementSyntax)
Dim attributeLists = delegateStatement.AttributeLists.Insert(index, attributeList) Dim attributeLists = delegateStatement.AttributeLists.Insert(index, attributeList)
Return delegateStatement.WithAttributeLists(attributeLists) Return delegateStatement.WithAttributeLists(attributeLists)
...@@ -3817,7 +3858,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel ...@@ -3817,7 +3858,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
Dim eventStatement = DirectCast(container, EventStatementSyntax) Dim eventStatement = DirectCast(container, EventStatementSyntax)
Dim attributeLists = eventStatement.AttributeLists.Insert(index, attributeList) Dim attributeLists = eventStatement.AttributeLists.Insert(index, attributeList)
Return eventStatement.WithAttributeLists(attributeLists) Return eventStatement.WithAttributeLists(attributeLists)
ElseIf TypeOf container Is EventBlockSyntax ElseIf TypeOf container Is EventBlockSyntax Then
Dim eventBlock = DirectCast(container, EventBlockSyntax) Dim eventBlock = DirectCast(container, EventBlockSyntax)
Dim attributeLists = eventBlock.EventStatement.AttributeLists.Insert(index, attributeList) Dim attributeLists = eventBlock.EventStatement.AttributeLists.Insert(index, attributeList)
Return eventBlock.WithEventStatement(eventBlock.EventStatement.WithAttributeLists(attributeLists)) Return eventBlock.WithEventStatement(eventBlock.EventStatement.WithAttributeLists(attributeLists))
......
...@@ -618,7 +618,7 @@ private bool ReplacementBreaksAssignmentExpression(AssignmentExpressionSyntax as ...@@ -618,7 +618,7 @@ private bool ReplacementBreaksAssignmentExpression(AssignmentExpressionSyntax as
if (assignmentExpression.IsCompoundAssignExpression() && if (assignmentExpression.IsCompoundAssignExpression() &&
assignmentExpression.Kind() != SyntaxKind.LeftShiftAssignmentExpression && assignmentExpression.Kind() != SyntaxKind.LeftShiftAssignmentExpression &&
assignmentExpression.Kind() != SyntaxKind.RightShiftAssignmentExpression && assignmentExpression.Kind() != SyntaxKind.RightShiftAssignmentExpression &&
ReplacementBreaksCompoundAssignExpression(assignmentExpression.Left, assignmentExpression.Right, newAssignmentExpression.Left, newAssignmentExpression.Right)) ReplacementBreaksCompoundAssignment(assignmentExpression.Left, assignmentExpression.Right, newAssignmentExpression.Left, newAssignmentExpression.Right))
{ {
return true; return true;
} }
......
...@@ -293,30 +293,24 @@ public static CodeAction Create(string title, Func<CancellationToken, Task<Solut ...@@ -293,30 +293,24 @@ public static CodeAction Create(string title, Func<CancellationToken, Task<Solut
return new SolutionChangeAction(title, createChangedSolution, equivalenceKey); 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 internal class SimpleCodeAction : CodeAction
{ {
private readonly string _title; private readonly string _title;
private readonly string _equivalenceKey; private readonly string _equivalenceKey;
private readonly ImmutableArray<CodeAction> _nestedActions; private readonly ImmutableArray<CodeAction> _nestedActions;
public SimpleCodeAction(string title, ImmutableArray<CodeAction> nestedActions, string equivalenceKey) public SimpleCodeAction(string title, ImmutableArray<CodeAction> nestedActions)
{ {
_title = title; _title = title;
_nestedActions = nestedActions; _nestedActions = nestedActions;
_equivalenceKey = ComputeEquivalenceKey(nestedActions);
}
public SimpleCodeAction(string title, string equivalenceKey)
{
_title = title;
_equivalenceKey = equivalenceKey; _equivalenceKey = equivalenceKey;
_nestedActions = ImmutableArray<CodeAction>.Empty;
} }
public sealed override string Title => _title; public sealed override string Title => _title;
...@@ -334,6 +328,29 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc ...@@ -334,6 +328,29 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc
{ {
return Task.FromResult<Document>(null); 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 internal class DocumentChangeAction : SimpleCodeAction
...@@ -341,7 +358,7 @@ internal class DocumentChangeAction : SimpleCodeAction ...@@ -341,7 +358,7 @@ internal class DocumentChangeAction : SimpleCodeAction
private readonly Func<CancellationToken, Task<Document>> _createChangedDocument; private readonly Func<CancellationToken, Task<Document>> _createChangedDocument;
public DocumentChangeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument, string equivalenceKey = null) 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; _createChangedDocument = createChangedDocument;
} }
...@@ -359,7 +376,7 @@ internal class SolutionChangeAction : SimpleCodeAction ...@@ -359,7 +376,7 @@ internal class SolutionChangeAction : SimpleCodeAction
private readonly Func<CancellationToken, Task<Solution>> _createChangedSolution; private readonly Func<CancellationToken, Task<Solution>> _createChangedSolution;
public SolutionChangeAction(string title, Func<CancellationToken, Task<Solution>> createChangedSolution, string equivalenceKey = null) 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; _createChangedSolution = createChangedSolution;
} }
......
...@@ -311,5 +311,6 @@ internal enum FunctionId ...@@ -311,5 +311,6 @@ internal enum FunctionId
NonFatalWatson, NonFatalWatson,
GlobalOperationRegistration, GlobalOperationRegistration,
CommandHandler_FindAllReference,
} }
} }
...@@ -3,6 +3,5 @@ Microsoft.CodeAnalysis.Project.IsSubmission.get -> bool ...@@ -3,6 +3,5 @@ Microsoft.CodeAnalysis.Project.IsSubmission.get -> bool
Microsoft.CodeAnalysis.Workspace.UpdateReferencesAfterAdd() -> void 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, 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 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 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 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, ...@@ -744,7 +744,7 @@ private bool ReplacementBreaksInvocableExpression(TExpressionSyntax expression,
return true; return true;
} }
protected bool ReplacementBreaksCompoundAssignExpression( protected bool ReplacementBreaksCompoundAssignment(
TExpressionSyntax originalLeft, TExpressionSyntax originalLeft,
TExpressionSyntax originalRight, TExpressionSyntax originalRight,
TExpressionSyntax newLeft, TExpressionSyntax newLeft,
......
...@@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities ...@@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
semanticModel = semanticModel.ParentModel semanticModel = semanticModel.ParentModel
End If End If
Dim speculativeModel As semanticModel = Nothing Dim speculativeModel As SemanticModel = Nothing
Dim statementNode = TryCast(nodeToSpeculate, ExecutableStatementSyntax) Dim statementNode = TryCast(nodeToSpeculate, ExecutableStatementSyntax)
If statementNode IsNot Nothing Then If statementNode IsNot Nothing Then
semanticModel.TryGetSpeculativeSemanticModel(position, statementNode, speculativeModel) semanticModel.TryGetSpeculativeSemanticModel(position, statementNode, speculativeModel)
...@@ -328,7 +328,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities ...@@ -328,7 +328,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
End If End If
Return Not ImplicitConversionsAreCompatible(originalExpression, newExpression) 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 originalExpression = DirectCast(currentOriginalNode, ConditionalAccessExpressionSyntax)
Dim newExpression = DirectCast(currentReplacedNode, ConditionalAccessExpressionSyntax) Dim newExpression = DirectCast(currentReplacedNode, ConditionalAccessExpressionSyntax)
Return ReplacementBreaksConditionalAccessExpression(originalExpression, newExpression) Return ReplacementBreaksConditionalAccessExpression(originalExpression, newExpression)
...@@ -472,7 +482,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities ...@@ -472,7 +482,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
If SyntaxFacts.IsAssignmentStatementOperatorToken(operatorTokenKind) AndAlso If SyntaxFacts.IsAssignmentStatementOperatorToken(operatorTokenKind) AndAlso
operatorTokenKind <> SyntaxKind.LessThanLessThanEqualsToken AndAlso operatorTokenKind <> SyntaxKind.LessThanLessThanEqualsToken AndAlso
operatorTokenKind <> SyntaxKind.GreaterThanGreaterThanEqualsToken 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 Return True
End If End If
...@@ -515,6 +525,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities ...@@ -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 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 originalConversion = Me.OriginalSemanticModel.ClassifyConversion(originalExpression, originalTargetType)
Dim newConversion = Me.SpeculativeSemanticModel.ClassifyConversion(newExpression, newTargetType) 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) Return ConversionsAreCompatible(originalConversion, newConversion)
End Function End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册