diff --git a/BuildAndTest.proj b/BuildAndTest.proj
index 385739580af0a..f2fac6687f7a7 100644
--- a/BuildAndTest.proj
+++ b/BuildAndTest.proj
@@ -7,57 +7,51 @@
$(MSBuildThisFileDirectory)Roslyn.sln
$(MSBuildThisFileDirectory)src\Samples\Samples.sln
+ true
Debug
$(RunTestArgs) -xml
$(RunTestArgs) -test64
$(RunTestArgs) -testVsi
+ $(RunTestArgs) -trait:Feature=NetCore
$(RunTestArgs) -trait:$(Trait)
$(RunTestArgs) -notrait:$(NoTrait)
+ false
*.UnitTests.dll
*.IntegrationTests.dll
$(MSBuildThisFileDirectory)Binaries\$(Configuration)\
$(RunTestArgs) -log:"$(OutputDirectory)\runtests.log"
$(OutputDirectory)\CoreClrTest
-
- RestorePackages=false;
- TreatWarningsAsErrors=true;
- DeployExtension=false;
-
@@ -81,6 +75,7 @@
@@ -115,7 +110,7 @@
-
+
$(NuGetPackageRoot)\roslyntools.microsoft.vsixexpinstaller\$(RoslynToolsMicrosoftVSIXExpInstallerVersion)\tools\VsixExpInstaller.exe
diff --git a/README.md b/README.md
index 09374138191bd..192a511459271 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
|**dev16**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev16/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev16/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_vs-integration/)|
### Linux/Mac - Unit Tests
-|Branch|Ubuntu14|Ubuntu16|MacOSX|
+|Branch|Ubuntu14|Ubuntu16|macOS|
|:--:|:--:|:--:|:--:|
|**master**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/master/job/ubuntu_14_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/master/job/ubuntu_14_debug/)|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/master/job/ubuntu_16_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/master/job/ubuntu_16_debug/)|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/master/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/master/job/mac_debug/)|
|**dev15.0.x**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/linux_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/linux_debug/)||[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/mac_debug/)|
diff --git a/build/Targets/Imports.targets b/build/Targets/Imports.targets
index 6aaa705f52acc..6a54279474a86 100644
--- a/build/Targets/Imports.targets
+++ b/build/Targets/Imports.targets
@@ -133,6 +133,8 @@
true
false
false
+
+ $(NuGetPackageRoot)\Microsoft.DotNet.IBCMerge\$(MicrosoftDotNetIBCMerge)\lib\net45\ibcmerge.exe
@@ -423,16 +425,24 @@
-
+
+
+
+ ConsoleToMSBuild="true"
+ Condition="Exists('$(IbcMergePath)')">
@@ -440,22 +450,18 @@
-
-
-
+ Condition="'$(_IsAnyPortableUnitTest)' == 'true' AND '$(DeveloperBuild)' == 'true' AND '$(OS)' == 'Windows_NT'">
+
+
+
+
+
+
+
+
+
+
+
-
+
add to 'defines'
- If defines.ContainsKey(symbolName) Then
- defines = defines.Remove(symbolName)
- End If
- defines = defines.Add(symbolName, value)
+ defines = defines.SetItem(symbolName, value)
ElseIf tokens.Current.Kind = SyntaxKind.CommaToken OrElse
tokens.Current.Kind = SyntaxKind.ColonToken OrElse
tokens.Current.Kind = SyntaxKind.EndOfFileToken Then
' We have no value being assigned, so we'll just assign it to true
- If defines.ContainsKey(symbolName) Then
- defines = defines.Remove(symbolName)
- End If
- defines = defines.Add(symbolName, InternalSyntax.CConst.Create(True))
+ defines = defines.SetItem(symbolName, InternalSyntax.CConst.Create(True))
ElseIf tokens.Current.Kind = SyntaxKind.BadToken Then
GetErrorStringForRemainderOfConditionalCompilation(tokens, parsedTokensAsString)
diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
index 3e3947ff04456..19c0e78b86ca6 100644
--- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
+++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
@@ -245,7 +245,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(tree IsNot VisualBasicSyntaxTree.Dummy)
Debug.Assert(tree.IsMyTemplate)
- Interlocked.CompareExchange(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy)
+ Interlocked.CompareExchange(Of SyntaxTree)(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy)
Else
' we need to make one.
Dim text As String = EmbeddedResources.VbMyTemplateText
@@ -260,7 +260,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw ExceptionUtilities.Unreachable
End If
- If Interlocked.CompareExchange(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy) Is VisualBasicSyntaxTree.Dummy Then
+ If Interlocked.CompareExchange(Of SyntaxTree)(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy) Is VisualBasicSyntaxTree.Dummy Then
' set global cache
s_myTemplateCache(parseOptions) = tree
End If
diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb
index 32e5fa5769498..815b55c770ffa 100644
--- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb
+++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb
@@ -134,7 +134,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
typesByName.Add(type.Name, type)
End If
Next
- Interlocked.CompareExchange(Me._lazyTopLevelTypes, typesByName, Nothing)
+ Interlocked.CompareExchange(Of IReadOnlyDictionary(Of String, Cci.INamespaceTypeDefinition))(Me._lazyTopLevelTypes, typesByName, Nothing)
End If
Return Me._lazyTopLevelTypes
End Function
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceLambdaSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceLambdaSymbol.vb
index 8b2c68f7619ea..15b986a2f43a5 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceLambdaSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceLambdaSymbol.vb
@@ -55,7 +55,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Get
If Me._lazyAnonymousDelegateSymbol Is ErrorTypeSymbol.UnknownResultType Then
Dim newValue As NamedTypeSymbol = MakeAssociatedAnonymousDelegate()
- Dim oldValue As NamedTypeSymbol = Interlocked.CompareExchange(Me._lazyAnonymousDelegateSymbol, newValue, ErrorTypeSymbol.UnknownResultType)
+ Dim oldValue As NamedTypeSymbol = Interlocked.CompareExchange(Of NamedTypeSymbol)(Me._lazyAnonymousDelegateSymbol, newValue, ErrorTypeSymbol.UnknownResultType)
Debug.Assert(oldValue Is ErrorTypeSymbol.UnknownResultType OrElse oldValue Is newValue)
End If
Return Me._lazyAnonymousDelegateSymbol
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb
index b97582748a043..6a1a6a0d13c40 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb
@@ -1296,7 +1296,7 @@ lReportErrorOnTwoTokens:
meParameter = Nothing
Else
If _lazyMeParameter Is Nothing Then
- Interlocked.CompareExchange(_lazyMeParameter, New MeParameterSymbol(Me), Nothing)
+ Interlocked.CompareExchange(Of ParameterSymbol)(_lazyMeParameter, New MeParameterSymbol(Me), Nothing)
End If
meParameter = _lazyMeParameter
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedMethodBase.vb b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedMethodBase.vb
index cf7dfb5a7b6b2..5613d3dca11c5 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedMethodBase.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedMethodBase.vb
@@ -178,7 +178,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
meParameter = Nothing
Else
If _lazyMeParameter Is Nothing Then
- Interlocked.CompareExchange(_lazyMeParameter, New MeParameterSymbol(Me), Nothing)
+ Interlocked.CompareExchange(Of ParameterSymbol)(_lazyMeParameter, New MeParameterSymbol(Me), Nothing)
End If
meParameter = _lazyMeParameter
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
index f2fce5f8fc94a..84f612cb5eb24 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
+++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
@@ -8290,6 +8290,29 @@ End Module
parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("langversion", "1000").WithLocation(1, 1))
End Sub
+
+
+ Public Sub MissingCompilerAssembly()
+ Dim dir = Temp.CreateDirectory()
+ Dim vbcPath = dir.CopyFile(GetType(Vbc).Assembly.Location).Path
+
+ ' Missing Microsoft.CodeAnalysis.VisualBasic.dll.
+ Dim result = ProcessUtilities.Run(vbcPath, arguments:="/nologo /t:library unknown.vb", workingDirectory:=dir.Path)
+ Assert.Equal(1, result.ExitCode)
+ Assert.Equal(
+ $"Could not load file or assembly '{GetType(VisualBasicCompilation).Assembly.FullName}' or one of its dependencies. The system cannot find the file specified.",
+ result.Output.Trim())
+
+ ' Missing System.Collections.Immutable.dll.
+ dir.CopyFile(GetType(Compilation).Assembly.Location)
+ dir.CopyFile(GetType(VisualBasicCompilation).Assembly.Location)
+ result = ProcessUtilities.Run(vbcPath, arguments:="/nologo /t:library unknown.vb", workingDirectory:=dir.Path)
+ Assert.Equal(1, result.ExitCode)
+ Assert.Equal(
+ $"Could not load file or assembly '{GetType(ImmutableArray).Assembly.FullName}' or one of its dependencies. The system cannot find the file specified.",
+ result.Output.Trim())
+ End Sub
+
Private Function MakeTrivialExe(Optional directory As String = Nothing) As String
Return Temp.CreateFile(directory:=directory, prefix:="", extension:=".vb").WriteAllText("
Class Program
diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.vb
index eecd8ec2417cb..89023dcc6d729 100644
--- a/src/Compilers/VisualBasic/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.vb
@@ -7,8 +7,6 @@ Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Test.Utilities.VBInstrumentationChecker
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
-Imports Roslyn.Test.Utilities
-Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.DynamicAnalysis.UnitTests
@@ -2368,6 +2366,173 @@ End Class
AssertInstrumented(verifier, "D.M")
End Sub
+
+ Public Sub TestPartialMethodsWithImplementation()
+ Dim testSource =
+ 0
+ Console.WriteLine("Method1: x > 0")
+ Method1(0)
+ ElseIf x < 0
+ Console.WriteLine("Method1: x < 0")
+ End If
+ End Sub
+End Class
+
+Module Program
+ Public Sub Main()
+ Test()
+ Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload()
+ End Sub
+
+ Sub Test()
+ Console.WriteLine("Test")
+ Dim c = new Class1()
+ c.Method2(1)
+ End Sub
+End Module
+]]>
+
+
+ Dim source =
+ <%= testSource %>
+ <%= InstrumentationHelperSource %>
+
+
+ Dim checker = New VBInstrumentationChecker()
+ checker.Method(1, 1, "New", expectBodySpan:=False)
+ checker.Method(2, 1, "Private Sub Method1(x as Integer)").
+ True("Console.WriteLine(""Method1: x = {0}"", x)").
+ True("Console.WriteLine(""Method1: x > 0"")").
+ True("Method1(0)").
+ False("Console.WriteLine(""Method1: x < 0"")").
+ True("x < 0").
+ True("x > 0")
+ checker.Method(3, 1, "Public Sub Method2(x as Integer)").
+ True("Console.WriteLine(""Method2: x = {0}"", x)").
+ True("Method1(x)")
+ checker.Method(4, 1, "Public Sub Main()").
+ True("Test()").
+ True("Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload()")
+ checker.Method(5, 1, "Sub Test()").
+ True("Console.WriteLine(""Test"")").
+ True("new Class1()").
+ True("c.Method2(1)")
+ checker.Method(8, 1).
+ True().
+ False().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True()
+
+ Dim expectedOutput = "Test
+Method2: x = 1
+Method1: x = 1
+Method1: x > 0
+Method1: x = 0
+" + XCDataToString(checker.ExpectedOutput)
+
+ Dim verifier = CompileAndVerify(source, expectedOutput, options:=TestOptions.ReleaseExe)
+ checker.CompleteCheck(verifier.Compilation, testSource)
+ verifier.VerifyDiagnostics()
+
+ verifier = CompileAndVerify(source, expectedOutput, options:=TestOptions.DebugExe)
+ checker.CompleteCheck(verifier.Compilation, testSource)
+ verifier.VerifyDiagnostics()
+ End Sub
+
+
+ Public Sub TestPartialMethodsWithoutImplementation()
+ Dim testSource =
+
+
+
+ Dim source =
+ <%= testSource %>
+ <%= InstrumentationHelperSource %>
+
+
+ Dim checker = New VBInstrumentationChecker()
+ checker.Method(1, 1, "New", expectBodySpan:=False)
+ checker.Method(2, 1, "Public Sub Method2(x as Integer)").
+ True("Console.WriteLine(""Method2: x = {0}"", x)")
+ checker.Method(3, 1, "Public Sub Main()").
+ True("Test()").
+ True("Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload()")
+ checker.Method(4, 1, "Sub Test()").
+ True("Console.WriteLine(""Test"")").
+ True("new Class1()").
+ True("c.Method2(1)")
+ checker.Method(7, 1).
+ True().
+ False().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True().
+ True()
+
+ Dim expectedOutput = "Test
+Method2: x = 1
+" + XCDataToString(checker.ExpectedOutput)
+
+ Dim verifier = CompileAndVerify(source, expectedOutput, options:=TestOptions.ReleaseExe)
+ checker.CompleteCheck(verifier.Compilation, testSource)
+ verifier.VerifyDiagnostics()
+
+ verifier = CompileAndVerify(source, expectedOutput, options:=TestOptions.DebugExe)
+ checker.CompleteCheck(verifier.Compilation, testSource)
+ verifier.VerifyDiagnostics()
+ End Sub
+
Private Shared Sub AssertNotInstrumented(verifier As CompilationVerifier, qualifiedMethodName As String)
AssertInstrumented(verifier, qualifiedMethodName, expected:=False)
End Sub
@@ -2394,6 +2559,14 @@ End Class
emitOptions:=EmitOptions.Default.WithInstrumentationKinds(ImmutableArray.Create(InstrumentationKind.TestCoverage)))
End Function
+ Private Overloads Function CompileAndVerify(source As XElement, Optional expectedOutput As String = Nothing, Optional options As VisualBasicCompilationOptions = Nothing) As CompilationVerifier
+ Return CompileAndVerify(source,
+ LatestVbReferences,
+ expectedOutput,
+ options:=If(options, TestOptions.ReleaseExe).WithDeterministic(True),
+ emitOptions:=EmitOptions.Default.WithInstrumentationKinds(ImmutableArray.Create(InstrumentationKind.TestCoverage)))
+ End Function
+
Private Overloads Function CompileAndVerify(source As String, Optional expectedOutput As String = Nothing, Optional options As VisualBasicCompilationOptions = Nothing) As CompilationVerifier
Return CompileAndVerify(source,
LatestVbReferences,
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTupleTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTupleTests.vb
index 3c2dee5be373d..c78d3704c08d5 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTupleTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTupleTests.vb
@@ -1,6 +1,7 @@
' 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.Test.Utilities
+Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB
@@ -9,16 +10,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB
Public Sub Local()
- Dim source =
-
-
-
+"
Dim comp = CreateCompilationWithMscorlib(source, references:={ValueTupleRef, SystemRuntimeFacadeRef}, options:=TestOptions.DebugDll)
comp.VerifyPdb("C.F",
@@ -33,9 +31,9 @@ End Class
-
-
-
+
+
+
@@ -46,6 +44,88 @@ End Class
)
End Sub
+
+ Public Sub VariablesAndConstantsInUnreachableCode()
+ Dim source = "
+Imports System
+Imports System.Collections.Generic
+
+Class C(Of T)
+ Enum E
+ A
+ End Enum
+
+ Sub F()
+ Dim v1 As C(Of (a As Integer, b As Integer)).E = Nothing
+ Const c1 As C(Of (a As Integer, b As Integer)).E = Nothing
+
+ Throw New Exception()
+
+ Dim v2 As C(Of (a As Integer, b As Integer)).E = Nothing
+ Const c2 As C(Of (a As Integer, b As Integer)).E = Nothing
+
+ Do
+ Dim v3 As C(Of (a As Integer, b As Integer)).E = Nothing
+ Const c3 As C(Of (a As Integer, b As Integer)).E = Nothing
+ Loop
+ End Sub
+End Class
+"
+ Dim c = CreateCompilationWithMscorlib(source, references:={ValueTupleRef, SystemRuntimeFacadeRef}, options:=TestOptions.DebugDll)
+
+ Dim v = CompileAndVerify(c)
+ v.VerifyIL("C(Of T).F()", "
+{
+ // Code size 9 (0x9)
+ .maxstack 1
+ .locals init (C(Of (a As Integer, b As Integer)).E V_0, //v1
+ C(Of (a As Integer, b As Integer)).E V_1, //v2
+ C(Of (a As Integer, b As Integer)).E V_2) //v3
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: newobj ""Sub System.Exception..ctor()""
+ IL_0008: throw
+}
+")
+
+ c.VerifyPdb(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ End Sub
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
index 3ba2d014bb6af..c12ac6254f277 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
+++ b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
@@ -107,6 +107,8 @@
+
+
diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.vb
new file mode 100644
index 0000000000000..016cd8a89dcb6
--- /dev/null
+++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.vb
@@ -0,0 +1,36 @@
+' 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.Semantics
+Imports Microsoft.CodeAnalysis.Test.Utilities
+Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
+Imports Roslyn.Test.Utilities
+
+Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
+
+ Partial Public Class IOperationTests
+ Inherits SemanticModelTestBase
+
+
+ Public Sub FieldReference_Attribute()
+ Dim source = 'BIND:"Conditional(field)"
+ Private Sub M()
+ End Sub
+End Class]]>.Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of AttributeSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+ End Class
+End Namespace
diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb
new file mode 100644
index 0000000000000..65581f7e4b429
--- /dev/null
+++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb
@@ -0,0 +1,631 @@
+' 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.Semantics
+Imports Microsoft.CodeAnalysis.Test.Utilities
+Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
+Imports Roslyn.Test.Utilities
+
+Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
+
+ Partial Public Class IOperationTests
+ Inherits SemanticModelTestBase
+
+
+ Public Sub ParameterReference_TupleExpression()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of TupleExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_AnonymousObjectCreation()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of AnonymousObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_QueryExpression()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of QueryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_QueryExpressionAggregateClause()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of QueryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_QueryExpressionOrderByClause()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of QueryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_QueryExpressionGroupByClause()
+ Dim source = .Value
+
+ Dim expectedOperationTree = , )(keySelector As System.Func(Of System.String, ), resultSelector As System.Func(Of , System.Collections.Generic.IEnumerable(Of System.String), )) As System.Collections.Generic.IEnumerable(Of )) (OperationKind.InvocationExpression, Type: System.Collections.Generic.IEnumerable(Of )) (Syntax: 'Group By w ... nto Count()')
+ Instance Receiver: IConversionExpression (ConversionKind.Basic, Implicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IEnumerable(Of System.String)) (Syntax: 'y In x')
+ IOperation: (OperationKind.None) (Syntax: 'y In x')
+ Children(1): IOperation: (OperationKind.None) (Syntax: 'x')
+ Children(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.String()) (Syntax: 'x')
+ Arguments(2): IArgument (ArgumentKind.DefaultValue, Matching Parameter: keySelector) (OperationKind.Argument) (Syntax: 'x')
+ IConversionExpression (ConversionKind.Basic, Implicit) (OperationKind.ConversionExpression, Type: System.Func(Of System.String, )) (Syntax: 'x')
+ IOperation: (OperationKind.None) (Syntax: 'x')
+ Children(1): IOperation: (OperationKind.None) (Syntax: 'Group By w ... nto Count()')
+ Children(2): IOperation: (OperationKind.None) (Syntax: 'w = x')
+ Children(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.String()) (Syntax: 'x')
+ IOperation: (OperationKind.None) (Syntax: 'z = y')
+ Children(1): IOperation: (OperationKind.None) (Syntax: 'y')
+ IArgument (ArgumentKind.DefaultValue, Matching Parameter: resultSelector) (OperationKind.Argument) (Syntax: 'Group By w ... nto Count()')
+ IConversionExpression (ConversionKind.Basic, Implicit) (OperationKind.ConversionExpression, Type: System.Func(Of , System.Collections.Generic.IEnumerable(Of System.String), )) (Syntax: 'Group By w ... nto Count()')
+ IOperation: (OperationKind.None) (Syntax: 'Group By w ... nto Count()')
+ Children(1): IOperation: (OperationKind.None) (Syntax: 'Group By w ... nto Count()')
+ Children(3): IOperation: (OperationKind.None) (Syntax: 'w')
+ IOperation: (OperationKind.None) (Syntax: 'z')
+ IOperation: (OperationKind.None) (Syntax: 'Count()')
+ Children(1): IOperation: (OperationKind.None) (Syntax: 'Count()')
+ Children(1): IInvocationExpression ( Function System.Collections.Generic.IEnumerable(Of System.String).Count() As System.Int32) (OperationKind.InvocationExpression, Type: System.Int32) (Syntax: 'Count()')
+ Instance Receiver: IParameterReferenceExpression: $VB$ItAnonymous (OperationKind.ParameterReferenceExpression, Type: System.Collections.Generic.IEnumerable(Of System.String)) (Syntax: 'Group By w ... nto Count()')
+]]>.Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of QueryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_ObjectAndCollectionInitializer()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_NameOfExpression()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of NameOfExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_LateBoundIndexerAccess()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_LateBoundMemberAccess()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_LateBoundInvocation()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_InterpolatedStringExpression()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of InterpolatedStringExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_MidAssignmentStatement()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_MisplacedCaseStatement()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = .Value
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of CaseStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_RedimStatement()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of ReDimStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_EraseStatement()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of EraseStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_UnstructuredExceptionHandlingStatement()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_LateAddressOfOperator()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of UnaryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_NullableIsTrueOperator()
+ Dim source = .Value
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = String.Empty
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree, expectedDiagnostics)
+ End Sub
+
+
+ Public Sub ParameterReference_NoPiaObjectCreation()
+ Dim sources0 =
+
+
+
+
+
+Public Interface I
+ Property P As Integer
+End Interface
+
+Public Class C
+ Public Sub New(o As Object)
+ End Sub
+End Class
+]]>
+
+ Dim sources1 =
+
+
+ Dim compilation0 = CreateCompilationWithMscorlib(sources0)
+ compilation0.AssertTheseDiagnostics()
+
+ ' No errors for /r:_.dll
+ Dim compilation1 = CreateCompilationWithReferences(
+ sources1,
+ references:={MscorlibRef, SystemRef, compilation0.EmitToImageReference(embedInteropTypes:=True)})
+
+ Dim expectedOperationTree = .Value
+
+ Dim expectedDiagnostics = .Value
+
+ VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(compilation1, "a.vb", expectedOperationTree, expectedDiagnostics)
+ End Sub
+ End Class
+End Namespace
diff --git a/src/Compilers/VisualBasic/vbc/Program.cs b/src/Compilers/VisualBasic/vbc/Program.cs
index 0422f7a3c2079..7aef6f564b99a 100644
--- a/src/Compilers/VisualBasic/vbc/Program.cs
+++ b/src/Compilers/VisualBasic/vbc/Program.cs
@@ -1,19 +1,30 @@
// 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.IO;
using Microsoft.CodeAnalysis.CommandLine;
-using Roslyn.Utilities;
-using System;
namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine
{
public class Program
{
public static int Main(string[] args)
- => Main(args, Array.Empty());
+ {
+ try
+ {
+ return MainCore(args);
+ }
+ catch (FileNotFoundException e)
+ {
+ // Catch exception from missing compiler assembly.
+ // Report the exception message and terminate the process.
+ Console.WriteLine(e.Message);
+ return CommonCompiler.Failed;
+ }
+ }
- public static int Main(string[] args, string[] extraArgs)
- => DesktopBuildClient.Run(args, extraArgs, RequestLanguage.VisualBasicCompile, Vbc.Run, new DesktopAnalyzerAssemblyLoader());
+ private static int MainCore(string[] args)
+ => DesktopBuildClient.Run(args, RequestLanguage.VisualBasicCompile, Vbc.Run, new DesktopAnalyzerAssemblyLoader());
public static int Run(string[] args, string clientDir, string workingDir, string sdkDir, string tempDir, TextWriter textWriter, IAnalyzerAssemblyLoader analyzerLoader)
=> Vbc.Run(args, new BuildPaths(clientDir: clientDir, workingDir: workingDir, sdkDir: sdkDir, tempDir: tempDir), textWriter, analyzerLoader);
diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs
index df00e9a350471..3c674d113aea5 100644
--- a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs
+++ b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs
@@ -4554,5 +4554,54 @@ void M()
}
}");
}
+
+ [WorkItem(19218, "https://github.com/dotnet/roslyn/issues/19218")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)]
+ public async Task TestChangeCaseWithUsingsInNestedNamespace()
+ {
+ await TestInRegularAndScriptAsync(
+@"namespace VS
+{
+ interface IVsStatusbar
+ {
+ }
+}
+
+namespace Outer
+{
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ // Note: IVsStatusBar is cased incorrectly.
+ [|IVsStatusBar|] b;
+ }
+ }
+}
+",
+@"namespace VS
+{
+ interface IVsStatusbar
+ {
+ }
+}
+
+namespace Outer
+{
+ using System;
+ using VS;
+
+ class C
+ {
+ void M()
+ {
+ IVsStatusbar b;
+ }
+ }
+}
+");
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs
index 53155eedcb87e..28f2e728a387f 100644
--- a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs
+++ b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs
@@ -54,7 +54,7 @@ public async Task TestSearchPackageSingleName()
// Make a loose mock for the installer service. We don't care what this test
// calls on it.
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackage(It.IsAny(), It.IsAny(), It.IsAny(), "NuGetPackage", It.IsAny(), It.IsAny(), It.IsAny()))
.Returns(true);
@@ -83,7 +83,7 @@ public async Task TestSearchPackageMultipleNames()
// Make a loose mock for the installer service. We don't care what this test
// calls on it.
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackage(It.IsAny(), It.IsAny(), It.IsAny(), "NuGetPackage", It.IsAny(), It.IsAny(), It.IsAny()))
.Returns(true);
@@ -112,7 +112,7 @@ public async Task TestMissingIfPackageAlreadyInstalled()
// Make a loose mock for the installer service. We don't care what this test
// calls on it.
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.IsInstalled(It.IsAny(), It.IsAny(), "NuGetPackage"))
.Returns(true);
@@ -135,7 +135,7 @@ public async Task TestOptionsOffered()
// Make a loose mock for the installer service. We don't care what this test
// calls on it.
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0", "2.0"));
@@ -177,7 +177,7 @@ await TestSmartTagTextAsync(
public async Task TestInstallGetsCalledNoVersion()
{
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackage(It.IsAny(), It.IsAny(), It.IsAny(), "NuGetPackage", /*versionOpt*/ null, It.IsAny(), It.IsAny()))
.Returns(true);
@@ -205,7 +205,7 @@ class C
public async Task TestInstallGetsCalledWithVersion()
{
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0"));
@@ -235,7 +235,7 @@ class C
public async Task TestFailedInstallRollsBackFile()
{
var installerServiceMock = new Mock(MockBehavior.Loose);
- installerServiceMock.SetupGet(i => i.IsEnabled).Returns(true);
+ installerServiceMock.Setup(i => i.IsEnabled(It.IsAny())).Returns(true);
installerServiceMock.SetupGet(i => i.PackageSources).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0"));
diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
index e127ecce924f6..52d3cdfc1212c 100644
--- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
+++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
@@ -294,7 +294,6 @@
-
@@ -307,8 +306,8 @@
-
-
+
+
diff --git a/src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs
index 9b5a317f94b7d..9cbed1ce3a764 100644
--- a/src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs
+++ b/src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs
@@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
-using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Test.Utilities;
using Xunit;
@@ -556,7 +555,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
}
@@ -574,7 +573,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
}
@@ -600,7 +599,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
}
@@ -618,7 +617,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
}
@@ -643,7 +642,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
@@ -658,7 +657,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
@@ -681,7 +680,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
@@ -696,7 +695,7 @@ public class @class
{
}
- public static void Add(object t)
+ public static void Add(object @class)
{
}
@@ -2180,8 +2179,8 @@ int Main(int i)
switch (1)
{
case 0:
- const int {|Rename:V|} = 1 + 1;
- var f = Main(V);
+ const int {|Rename:I|} = 1 + 1;
+ var f = Main(I);
Console.WriteLine(f);
}
}
@@ -2432,8 +2431,8 @@ class C
static void Main(string[] args)
{
var set = new HashSet();
- var {|Rename:v|} = set.ToString();
- set.Add(v);
+ var {|Rename:item|} = set.ToString();
+ set.Add(item);
}
}",
options: ImplicitTypingEverywhere());
@@ -2530,8 +2529,8 @@ class Program
static void Main(string[] args)
{
var d = new Dictionary();
- var {|Rename:exception|} = new Exception();
- d.Add(""a"", exception);
+ var {|Rename:value|} = new Exception();
+ d.Add(""a"", value);
}
}",
ignoreTrivia: false, options: ImplicitTypingEverywhere());
@@ -3091,8 +3090,8 @@ class Complex
int real; int imaginary;
public static Complex operator +(Complex a, Complex b)
{
- var {|Rename:v|} = b.real + 1;
- return a.Add(v);
+ var {|Rename:b1|} = b.real + 1;
+ return a.Add(b1);
}
private Complex Add(int b)
@@ -3161,7 +3160,7 @@ public struct DBBool
@"using System;
public struct DBBool
{
- private const int {|Rename:V|} = 1;
+ private const int {|Rename:Value|} = 1;
public static readonly DBBool dbFalse = new DBBool(-1);
int value;
@@ -3170,7 +3169,7 @@ public struct DBBool
this.value = value;
}
- public static implicit operator DBBool(bool x) => x ? new DBBool(V) : dbFalse;
+ public static implicit operator DBBool(bool x) => x ? new DBBool(Value) : dbFalse;
}";
await TestInRegularAndScriptAsync(code, expected, ignoreTrivia: false);
@@ -3574,8 +3573,8 @@ class TestClass
{
static void Test(string[] args)
{
- var {|Rename:v|} = $""{DateTime.Now.ToString()}Text{args[0]}"";
- Console.WriteLine(v);
+ var {|Rename:value|} = $""{DateTime.Now.ToString()}Text{args[0]}"";
+ Console.WriteLine(value);
}
}";
@@ -3603,9 +3602,9 @@ class TestClass
{
static void Test(string[] args)
{
- var {|Rename:v|} = $""Text{{s}}"";
- Console.WriteLine(v);
- Console.WriteLine(v);
+ var {|Rename:value|} = $""Text{{s}}"";
+ Console.WriteLine(value);
+ Console.WriteLine(value);
}
}";
@@ -3773,8 +3772,8 @@ class C
{
public async Task M()
{
- FormattableString {|Rename:v|} = $"""";
- var f = FormattableString.Invariant(v);
+ FormattableString {|Rename:formattable|} = $"""";
+ var f = FormattableString.Invariant(formattable);
}
}
}";
@@ -4254,5 +4253,81 @@ void M()
await TestInRegularAndScriptAsync(code, expected, index: 1, ignoreTrivia: false);
}
+
+ [WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)]
+ public async Task TestPickNameBasedOnArgument1()
+ {
+ await TestInRegularAndScriptAsync(
+@"class C
+{
+ public C(string a, string b)
+ {
+ new TextSpan([|int.Parse(a)|], int.Parse(b));
+ }
+}
+
+struct TextSpan
+{
+ public TextSpan(int start, int length)
+ {
+
+ }
+}",
+@"class C
+{
+ public C(string a, string b)
+ {
+ int {|Rename:start|} = int.Parse(a);
+ new TextSpan(start, int.Parse(b));
+ }
+}
+
+struct TextSpan
+{
+ public TextSpan(int start, int length)
+ {
+
+ }
+}");
+ }
+
+ [WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)]
+ public async Task TestPickNameBasedOnArgument2()
+ {
+ await TestInRegularAndScriptAsync(
+@"class C
+{
+ public C(string a, string b)
+ {
+ new TextSpan(int.Parse(a), [|int.Parse(b)|]);
+ }
+}
+
+struct TextSpan
+{
+ public TextSpan(int start, int length)
+ {
+
+ }
+}",
+@"class C
+{
+ public C(string a, string b)
+ {
+ int {|Rename:length|} = int.Parse(b);
+ new TextSpan(int.Parse(a), length);
+ }
+}
+
+struct TextSpan
+{
+ public TextSpan(int start, int length)
+ {
+
+ }
+}");
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs
index 5b99c51236817..f66cd2e8496bf 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs
@@ -16,9 +16,7 @@ public EnumAndCompletionListTagCompletionProviderTests(CSharpTestWorkspaceFixtur
}
internal override CompletionProvider CreateCompletionProvider()
- {
- return new EnumAndCompletionListTagCompletionProvider();
- }
+ => new EnumAndCompletionListTagCompletionProvider();
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NullableEnum()
@@ -518,5 +516,105 @@ enum E
";
await VerifyNoItemsExistAsync(markup);
}
+
+ [WorkItem(5419, "https://github.com/dotnet/roslyn/issues/5419")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ public async Task TestInEnumInitializer1()
+ {
+ var markup =
+@"using System;
+
+[Flags]
+internal enum ProjectTreeWriterOptions
+{
+ None,
+ Tags,
+ FilePath,
+ Capabilities,
+ Visibility,
+ AllProperties = FilePath | Visibility | $$
+}";
+ await VerifyItemExistsAsync(markup, "ProjectTreeWriterOptions");
+ }
+
+ [WorkItem(5419, "https://github.com/dotnet/roslyn/issues/5419")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ public async Task TestInEnumInitializer2()
+ {
+ var markup =
+@"using System;
+
+[Flags]
+internal enum ProjectTreeWriterOptions
+{
+ None,
+ Tags,
+ FilePath,
+ Capabilities,
+ Visibility,
+ AllProperties = FilePath | $$ Visibility
+}";
+ await VerifyItemExistsAsync(markup, "ProjectTreeWriterOptions");
+ }
+
+ [WorkItem(5419, "https://github.com/dotnet/roslyn/issues/5419")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ public async Task TestInEnumInitializer3()
+ {
+ var markup =
+@"using System;
+
+[Flags]
+internal enum ProjectTreeWriterOptions
+{
+ None,
+ Tags,
+ FilePath,
+ Capabilities,
+ Visibility,
+ AllProperties = FilePath | $$ | Visibility
+}";
+ await VerifyItemExistsAsync(markup, "ProjectTreeWriterOptions");
+ }
+
+ [WorkItem(5419, "https://github.com/dotnet/roslyn/issues/5419")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ public async Task TestInEnumInitializer4()
+ {
+ var markup =
+@"using System;
+
+[Flags]
+internal enum ProjectTreeWriterOptions
+{
+ None,
+ Tags,
+ FilePath,
+ Capabilities,
+ Visibility,
+ AllProperties = FilePath ^ $$
+}";
+ await VerifyItemExistsAsync(markup, "ProjectTreeWriterOptions");
+ }
+
+ [WorkItem(5419, "https://github.com/dotnet/roslyn/issues/5419")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ public async Task TestInEnumInitializer5()
+ {
+ var markup =
+@"using System;
+
+[Flags]
+internal enum ProjectTreeWriterOptions
+{
+ None,
+ Tags,
+ FilePath,
+ Capabilities,
+ Visibility,
+ AllProperties = FilePath & $$
+}";
+ await VerifyItemExistsAsync(markup, "ProjectTreeWriterOptions");
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/GlobalAssemblyCacheCompletionHelperTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/GlobalAssemblyCacheCompletionHelperTests.cs
deleted file mode 100644
index 890aa50a1db85..0000000000000
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/GlobalAssemblyCacheCompletionHelperTests.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.Collections.Generic;
-using System.Linq;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Completion;
-using Microsoft.CodeAnalysis.Editor.Completion.FileSystem;
-using Microsoft.CodeAnalysis.Text;
-using Roslyn.Test.Utilities;
-using Xunit;
-
-namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.IntelliSense.CompletionSetSources
-{
- public class GlobalAssemblyCacheCompletionHelperTests
- {
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public void ExistingReference()
- {
- var code = "System.Windows";
- VerifyPresence(code, "System.Windows.Forms");
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public void FullReferenceIdentity()
- {
- var code = "System,";
- VerifyPresence(code, typeof(System.Diagnostics.Process).Assembly.FullName);
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public void FullReferenceIdentityDescription()
- {
- var code = "System";
- var completions = GetItems(code);
- var systemsColl = from completion in completions
- where completion.DisplayText == "System"
- select completion;
-
- Assert.True(systemsColl.Any(
- completion => CommonCompletionItem.GetDescription(completion).Text == typeof(System.Diagnostics.Process).Assembly.FullName));
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public void NothingOnForwardSlash()
- {
- var code = "System.Windows/";
- VerifyAbsence(code);
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public void NothingOnBackSlash()
- {
- var code = @"System.Windows\";
- VerifyAbsence(code);
- }
-
- private static void VerifyPresence(string pathSoFar, string completionItem)
- {
- var completions = GetItems(pathSoFar);
- Assert.True(completions.Any(c => c.DisplayText == completionItem));
- }
-
- private static void VerifyAbsence(string pathSoFar)
- {
- var completions = GetItems(pathSoFar);
- Assert.True(completions == null || !completions.Any(), "Expected null or non-empty completions");
- }
-
- private static IEnumerable GetItems(string pathSoFar)
- {
- var helper = new GlobalAssemblyCacheCompletionHelper(null, new TextSpan());
-
- return helper.GetItems(pathSoFar, documentPath: null);
- }
- }
-}
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs
new file mode 100644
index 0000000000000..f0ef0ce6d1106
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs
@@ -0,0 +1,69 @@
+// 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.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Completion;
+using Microsoft.CodeAnalysis.Editor.CSharp.Completion.FileSystem;
+using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
+{
+ [Trait(Traits.Feature, Traits.Features.Completion)]
+ public class LoadDirectiveCompletionProviderTests : AbstractCSharpCompletionProviderTests
+ {
+ public LoadDirectiveCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
+ {
+ }
+
+ internal override CompletionProvider CreateCompletionProvider()
+ {
+ return new LoadDirectiveCompletionProvider();
+ }
+
+ protected override bool CompareItems(string actualItem, string expectedItem)
+ {
+ return actualItem.Equals(expectedItem, StringComparison.OrdinalIgnoreCase);
+ }
+
+ protected override Task VerifyWorkerAsync(
+ string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull,
+ SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence,
+ int? glyph, int? matchPriority, bool? hasSuggestionItem)
+ {
+ return BaseVerifyWorkerAsync(
+ code, position, expectedItemOrNull, expectedDescriptionOrNull,
+ sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence,
+ glyph, matchPriority, hasSuggestionItem);
+ }
+
+ [Fact]
+ public async Task IsCommitCharacterTest()
+ {
+ var commitCharacters = new[] { '"', '\\' };
+ await VerifyCommitCharactersAsync("#load \"$$", textTypedSoFar: "", validChars: commitCharacters);
+ }
+
+ [Fact]
+ public void IsTextualTriggerCharacterTest()
+ {
+ var validMarkupList = new[]
+ {
+ "#load \"$$/",
+ "#load \"$$\\",
+ "#load \"$$,",
+ "#load \"$$A",
+ "#load \"$$!",
+ "#load \"$$(",
+ };
+
+ foreach (var markup in validMarkupList)
+ {
+ VerifyTextualTriggerCharacter(markup, shouldTriggerWithTriggerOnLettersEnabled: true, shouldTriggerWithTriggerOnLettersDisabled: true);
+ }
+ }
+ }
+}
diff --git a/src/EditorFeatures/CSharpTest/Completion/ReferenceDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs
similarity index 55%
rename from src/EditorFeatures/CSharpTest/Completion/ReferenceDirectiveCompletionProviderTests.cs
rename to src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs
index 1004329dbd9d5..67d4b98cac117 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ReferenceDirectiveCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs
@@ -6,13 +6,14 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.CSharp.Completion.FileSystem;
-using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Roslyn.Test.Utilities;
+using Roslyn.Utilities;
using Xunit;
-namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.IntelliSense.CompletionSetSources
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
{
+ [Trait(Traits.Feature, Traits.Features.Completion)]
public class ReferenceDirectiveCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
public ReferenceDirectiveCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
@@ -40,50 +41,33 @@ protected override Task VerifyWorkerAsync(
glyph, matchPriority, hasSuggestionItem);
}
- private async Task VerifyItemsExistInScriptAndInteractiveAsync(string code, params string[] expected)
- {
- foreach (var ex in expected)
- {
- await VerifyItemExistsAsync(code, ex, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script);
- }
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ [Fact]
public async Task IsCommitCharacterTest()
{
- var commitCharacters = new[] { '"', '\\', ',' };
+ var commitCharacters = PathUtilities.IsUnixLikePlatform ? new[] { '"', '/' } : new[] { '"', '\\', '/', ',' };
await VerifyCommitCharactersAsync("#r \"$$", textTypedSoFar: "", validChars: commitCharacters);
}
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ [Fact]
public void IsTextualTriggerCharacterTest()
{
var validMarkupList = new[]
{
+ "#r \"$$/",
"#r \"$$\\",
"#r \"$$,",
- "#r \"$$A"
- };
-
- foreach (var markup in validMarkupList)
- {
- VerifyTextualTriggerCharacter(markup, shouldTriggerWithTriggerOnLettersEnabled: true, shouldTriggerWithTriggerOnLettersDisabled: true);
- }
-
- var invalidMarkupList = new[]
- {
- "#r \"$$/",
+ "#r \"$$A",
"#r \"$$!",
"#r \"$$(",
};
- foreach (var markup in invalidMarkupList)
+ foreach (var markup in validMarkupList)
{
- VerifyTextualTriggerCharacter(markup, shouldTriggerWithTriggerOnLettersEnabled: false, shouldTriggerWithTriggerOnLettersDisabled: false);
+ VerifyTextualTriggerCharacter(markup, shouldTriggerWithTriggerOnLettersEnabled: true, shouldTriggerWithTriggerOnLettersDisabled: true);
}
}
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ [ConditionalFact(typeof(WindowsOnly))]
public async Task SendEnterThroughToEditorTest()
{
await VerifySendEnterThroughToEnterAsync("#r \"System$$", "System", sendThroughEnterOption: EnterKeyRule.Never, expected: false);
@@ -91,57 +75,34 @@ public async Task SendEnterThroughToEditorTest()
await VerifySendEnterThroughToEnterAsync("#r \"System$$", "System", sendThroughEnterOption: EnterKeyRule.Always, expected: false); // note: GAC completion helper uses its own EnterKeyRule
}
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task RootDrives()
- {
- // ensure drives are listed without the trailing backslash
- var drive = Environment.GetLogicalDrives().First().TrimEnd('\\');
- await VerifyItemsExistInScriptAndInteractiveAsync(
- "#r \"$$",
- drive);
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task RelativeDirectories()
- {
- await VerifyItemsExistInScriptAndInteractiveAsync(
- "#r \"$$",
- ".",
- "..");
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task GACReference()
+ [ConditionalFact(typeof(WindowsOnly))]
+ public async Task GacReference()
{
- await VerifyItemsExistInScriptAndInteractiveAsync(
- "#r \"$$",
- "System.Windows.Forms");
+ await VerifyItemExistsAsync("#r \"$$", "System.Windows.Forms", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script);
}
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task GACReferenceFullyQualified()
+ [ConditionalFact(typeof(WindowsOnly))]
+ public async Task GacReferenceFullyQualified()
{
- await VerifyItemsExistInScriptAndInteractiveAsync(
- "#r \"System.Windows.Forms,$$",
- "System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
+ await VerifyItemExistsAsync(
+ "#r \"System.Windows.Forms,$$",
+ "System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script);
}
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
+ [ConditionalFact(typeof(WindowsOnly))]
public async Task FileSystemReference()
{
- string systemDir = Path.GetFullPath(Environment.SystemDirectory);
- DirectoryInfo windowsDir = System.IO.Directory.GetParent(systemDir);
- string windowsDirPath = windowsDir.FullName;
- string windowsRoot = System.IO.Directory.GetDirectoryRoot(systemDir);
+ var systemDir = Path.GetFullPath(Environment.SystemDirectory);
+ var windowsDir = Directory.GetParent(systemDir);
+ var windowsDirPath = windowsDir.FullName;
+ var windowsRoot = Directory.GetDirectoryRoot(systemDir);
// we need to get the exact casing from the file system:
var normalizedWindowsPath = Directory.GetDirectories(windowsRoot, windowsDir.Name).Single();
var windowsFolderName = Path.GetFileName(normalizedWindowsPath);
var code = "#r \"" + windowsRoot + "$$";
- await VerifyItemsExistInScriptAndInteractiveAsync(
- code,
- windowsFolderName);
+ await VerifyItemExistsAsync(code, windowsFolderName, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script);
}
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Completion/LoadDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/LoadDirectiveCompletionProviderTests.cs
deleted file mode 100644
index 44a4914fc15af..0000000000000
--- a/src/EditorFeatures/CSharpTest/Completion/LoadDirectiveCompletionProviderTests.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-// 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.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.Completion;
-using Microsoft.CodeAnalysis.Editor.CSharp.Completion.FileSystem;
-using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
-using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
-using Roslyn.Test.Utilities;
-using Xunit;
-
-namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion
-{
- public class LoadDirectiveCompletionProviderTests : AbstractCSharpCompletionProviderTests
- {
- public LoadDirectiveCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
- {
- }
-
- internal override CompletionProvider CreateCompletionProvider()
- {
- return new LoadDirectiveCompletionProvider();
- }
-
- protected override bool CompareItems(string actualItem, string expectedItem)
- {
- return actualItem.Equals(expectedItem, StringComparison.OrdinalIgnoreCase);
- }
-
- protected override Task VerifyWorkerAsync(
- string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull,
- SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence,
- int? glyph, int? matchPriority, bool? hasSuggestionItem)
- {
- return BaseVerifyWorkerAsync(
- code, position, expectedItemOrNull, expectedDescriptionOrNull,
- sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence,
- glyph, matchPriority, hasSuggestionItem);
- }
-
- private async Task VerifyItemExistsInScriptAsync(string markup, string expected)
- {
- await VerifyItemExistsAsync(markup, expected, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: false);
- }
-
- private async Task VerifyItemIsAbsentInInteractiveAsync(string markup, string expected)
- {
- await VerifyItemIsAbsentAsync(markup, expected, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: false);
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task NetworkPath()
- {
- await VerifyItemExistsInScriptAsync(
- @"#load ""$$",
- @"\\");
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task NetworkPathAfterInitialBackslash()
- {
- await VerifyItemExistsInScriptAsync(
- @"#load ""\$$",
- @"\\");
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
- public async Task UpOneDirectoryNotShownAtRoot()
- {
- // after so many ".." we should be at the root drive an should no longer suggest the parent. we can determine
- // our current directory depth by counting the number of backslashes present in the current working directory
- // and after that many references to "..", we are at the root.
- int depth = Directory.GetCurrentDirectory().Count(c => c == Path.DirectorySeparatorChar);
- var pathToRoot = string.Concat(Enumerable.Repeat(@"..\", depth));
-
- await VerifyItemExistsInScriptAsync(
- @"#load ""$$",
- "..");
- await VerifyItemIsAbsentInInteractiveAsync(
- @"#load """ + pathToRoot + "$$",
- "..");
- }
- }
-}
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs
index 3532565a413de..5866588f098b2 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs
@@ -7262,7 +7262,7 @@ private object Method()
parseOptions: TestOptions.Regular);
}
- [Fact/*(Skip = "https://github.com/dotnet/roslyn/issues/15508")*/, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
[WorkItem(14136, "https://github.com/dotnet/roslyn/issues/14136")]
public async Task TestDeconstruction4()
{
@@ -7379,5 +7379,67 @@ private ref int Bar()
}
}");
}
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
+ [WorkItem(18969, "https://github.com/dotnet/roslyn/issues/18969")]
+ public async Task TestTupleElement1()
+ {
+ await TestAsync(
+@"using System;
+
+class C
+{
+ public void M1()
+ {
+ (int x, string y) t = ([|Method|](), null);
+ }
+}",
+@"using System;
+
+class C
+{
+ public void M1()
+ {
+ (int x, string y) t = (Method(), null);
+ }
+
+ private int Method()
+ {
+ throw new NotImplementedException();
+ }
+}",
+parseOptions: TestOptions.Regular);
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
+ [WorkItem(18969, "https://github.com/dotnet/roslyn/issues/18969")]
+ public async Task TestTupleElement2()
+ {
+ await TestAsync(
+@"using System;
+
+class C
+{
+ public void M1()
+ {
+ (int x, string y) t = (0, [|Method|]());
+ }
+}",
+@"using System;
+
+class C
+{
+ public void M1()
+ {
+ (int x, string y) t = (0, Method());
+ }
+
+ private string Method()
+ {
+ throw new NotImplementedException();
+ }
+}",
+parseOptions: TestOptions.Regular);
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
index bd45b420d589c..e3e978a102ef5 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
@@ -599,5 +599,180 @@ async ValueTask TestAsync()
}";
await TestInRegularAndScriptAsync(initial, expected);
}
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(14133, "https://github.com/dotnet/roslyn/issues/14133")]
+ public async Task AddAsyncInLocalFunction()
+ {
+ await TestInRegularAndScriptAsync(
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ void M2()
+ {
+ [|await M3Async();|]
+ }
+ }
+
+ async Task M3Async()
+ {
+ return 1;
+ }
+}",
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ async Task M2Async()
+ {
+ await M3Async();
+ }
+ }
+
+ async Task M3Async()
+ {
+ return 1;
+ }
+}");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(14133, "https://github.com/dotnet/roslyn/issues/14133")]
+ public async Task AddAsyncInLocalFunctionKeepVoidReturn()
+ {
+ await TestInRegularAndScriptAsync(
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ void M2()
+ {
+ [|await M3Async();|]
+ }
+ }
+
+ async Task M3Async()
+ {
+ return 1;
+ }
+}",
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ async void M2Async()
+ {
+ await M3Async();
+ }
+ }
+
+ async Task M3Async()
+ {
+ return 1;
+ }
+}",
+index: 1);
+ }
+
+ [Theory]
+ [InlineData(0, "Task")]
+ [InlineData(1, "void", Skip = "https://github.com/dotnet/roslyn/issues/18396")]
+ [Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(18307, "https://github.com/dotnet/roslyn/issues/18307")]
+ public async Task AddAsyncInLocalFunctionKeepsTrivia(int codeFixIndex, string expectedReturn)
+ {
+ await TestInRegularAndScriptAsync(
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ // Leading trivia
+ /*1*/ void /*2*/ M2/*3*/() /*4*/
+ {
+ [|await M3Async();|]
+ }
+ }
+
+ async Task M3Async()
+ {
+ return 1;
+ }
+}",
+$@"using System.Threading.Tasks;
+
+class C
+{{
+ public void M1()
+ {{
+ // Leading trivia
+ /*1*/ async {expectedReturn} /*2*/ M2Async/*3*/() /*4*/
+ {{
+ await M3Async();
+ }}
+ }}
+
+ async Task M3Async()
+ {{
+ return 1;
+ }}
+}}",
+ index: codeFixIndex,
+ ignoreTrivia: false);
+ }
+
+ [Theory]
+ [InlineData("", 0, "Task")]
+ [InlineData("", 1, "void", Skip = "https://github.com/dotnet/roslyn/issues/18396")]
+ [InlineData("public", 0, "Task")]
+ [InlineData("public", 1, "void")]
+ [Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(18307, "https://github.com/dotnet/roslyn/issues/18307")]
+ public async Task AddAsyncKeepsTrivia(string modifiers, int codeFixIndex, string expectedReturn)
+ {
+ await TestInRegularAndScriptAsync(
+$@"using System.Threading.Tasks;
+
+class C
+{{
+ // Leading trivia
+ {modifiers}/*1*/ void /*2*/ M2/*3*/() /*4*/
+ {{
+ [|await M3Async();|]
+ }}
+
+ async Task M3Async()
+ {{
+ return 1;
+ }}
+}}",
+$@"using System.Threading.Tasks;
+
+class C
+{{
+ // Leading trivia
+ {modifiers}/*1*/ async {expectedReturn} /*2*/ M2Async/*3*/() /*4*/
+ {{
+ await M3Async();
+ }}
+
+ async Task M3Async()
+ {{
+ return 1;
+ }}
+}}",
+ index: codeFixIndex,
+ ignoreTrivia: false);
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
index 8942b2569cda3..a60f6c8bee688 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
@@ -548,5 +548,112 @@ async void BarAsync()
}
}", ignoreTrivia: false);
}
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(14133, "https://github.com/dotnet/roslyn/issues/14133")]
+ public async Task RemoveAsyncInLocalFunction()
+ {
+ await TestInRegularAndScriptAsync(
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ async Task [|M2Async|]()
+ {
+ }
+ }
+}",
+@"using System.Threading.Tasks;
+
+class C
+{
+ public void M1()
+ {
+ void M2()
+ {
+ }
+ }
+}");
+ }
+
+ [Theory]
+ [InlineData("Task", "C")]
+ [InlineData("Task", "int")]
+ [InlineData("Task", "void")]
+ [InlineData("void", "void")]
+ [Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(18307, "https://github.com/dotnet/roslyn/issues/18307")]
+ public async Task RemoveAsyncInLocalFunctionKeepsTrivia(string asyncReturn, string expectedReturn)
+ {
+ await TestInRegularAndScriptAsync(
+$@"using System;
+using System.Threading.Tasks;
+
+class C
+{{
+ public void M1()
+ {{
+ // Leading trivia
+ /*1*/ async {asyncReturn} /*2*/ [|M2Async|]/*3*/() /*4*/
+ {{
+ throw new NotImplementedException();
+ }}
+ }}
+}}",
+$@"using System;
+using System.Threading.Tasks;
+
+class C
+{{
+ public void M1()
+ {{
+ // Leading trivia
+ /*1*/ {expectedReturn} /*2*/ M2/*3*/() /*4*/
+ {{
+ throw new NotImplementedException();
+ }}
+ }}
+}}");
+ }
+
+ [Theory]
+ [InlineData("", "Task", "C")]
+ [InlineData("", "Task", "int")]
+ [InlineData("", "Task", "void")]
+ [InlineData("", "void", "void")]
+ [InlineData("public", "Task", "C")]
+ [InlineData("public", "Task", "int")]
+ [InlineData("public", "Task", "void")]
+ [InlineData("public", "void", "void")]
+ [Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodAsynchronous)]
+ [WorkItem(18307, "https://github.com/dotnet/roslyn/issues/18307")]
+ public async Task RemoveAsyncKeepsTrivia(string modifiers, string asyncReturn, string expectedReturn)
+ {
+ await TestInRegularAndScriptAsync(
+$@"using System;
+using System.Threading.Tasks;
+
+class C
+{{
+ // Leading trivia
+ {modifiers}/*1*/ async {asyncReturn} /*2*/ [|M2Async|]/*3*/() /*4*/
+ {{
+ throw new NotImplementedException();
+ }}
+}}",
+$@"using System;
+using System.Threading.Tasks;
+
+class C
+{{
+ // Leading trivia
+ {modifiers}/*1*/ {expectedReturn} /*2*/ M2/*3*/() /*4*/
+ {{
+ throw new NotImplementedException();
+ }}
+}}");
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests.cs
index 9ec9e68a01925..614005d31d0d4 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests.cs
@@ -1,10 +1,12 @@
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.NamingStyles;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.NamingStyles;
using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Roslyn.Test.Utilities;
using Xunit;
@@ -319,5 +321,27 @@ internal interface
[|}|]
", new TestParameters(options: InterfaceNamesStartWithI));
}
+
+ [WorkItem(16562, "https://github.com/dotnet/roslyn/issues/16562")]
+ public async Task TestRefactorNotify()
+ {
+ var markup = @"public class [|c|] { }";
+ var testParameters = new TestParameters(options: ClassNamesArePascalCase);
+
+ using (var workspace = CreateWorkspaceFromOptions(markup, testParameters))
+ {
+ var actions = await GetCodeActionsAsync(workspace, testParameters);
+
+ var previewOperations = await actions[0].GetPreviewOperationsAsync(CancellationToken.None);
+ Assert.Empty(previewOperations.OfType());
+
+ var commitOperations = await actions[0].GetOperationsAsync(CancellationToken.None);
+ Assert.Equal(2, commitOperations.Length);
+
+ var symbolRenamedOperation = (TestSymbolRenamedCodeActionOperationFactoryWorkspaceService.Operation)commitOperations[1];
+ Assert.Equal("c", symbolRenamedOperation._symbol.Name);
+ Assert.Equal("C", symbolRenamedOperation._newName);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.cs b/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.cs
index 3af44cb53b939..6afc81cf3de69 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.cs
@@ -13,9 +13,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.RemoveUnuse
public partial class RemoveUnusedVariableTest : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
- {
- return(null, new RemoveUnusedVariableCodeFixProvider());
- }
+ => (null, new CSharpRemoveUnusedVariableCodeFixProvider());
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
public async Task RemoveUnusedVariable()
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
index b4be75cb1764c..9848a492cf754 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
@@ -179,6 +179,25 @@ class Program
index: 1);
}
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task UpgradeProjectFromCSharp7ToCSharp7_1_B()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"public class Base { }
+public class Derived : Base { }
+public class Program
+{
+ public static void M(T x) where T: Base
+ {
+ System.Console.Write(x is [|Derived|] b0);
+ }
+}
+",
+ LanguageVersion.CSharp7_1,
+ new CSharpParseOptions(LanguageVersion.CSharp7),
+ index: 1);
+ }
+
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
public async Task UpgradeAllProjectsToDefault()
{
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
index 52366c79d5517..a67a29f425690 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
@@ -3184,6 +3184,41 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariableBody_Update_ExpressionActive()
+ {
+ string src1 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(0);
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(1);
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEachBody_Update_InKeywordActive()
{
@@ -3219,6 +3254,41 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariableBody_Update_InKeywordActive()
+ {
+ string src1 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(0);
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(1);
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEachBody_Update_VariableActive()
{
@@ -3254,6 +3324,41 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariableBody_Update_VariableActive()
+ {
+ string src1 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(0);
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(1);
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEachBody_Update_ForeachKeywordActive()
{
@@ -3289,6 +3394,41 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariableBody_Update_ForeachKeywordActive()
+ {
+ string src1 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(0);
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ private static (string, int) F() { return null; }
+
+ static void Main(string[] args)
+ {
+ foreach ((string s, int i) in F())
+ {
+ System.Console.Write(1);
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEachVariable_Update()
{
@@ -3328,7 +3468,44 @@ static void Main(string[] args)
}
[Fact]
- public void ForEach_Reorder_Leaf1()
+ public void ForEachDeconstructionVariable_Update()
+ {
+ string src1 = @"
+class Test
+{
+ private static (int, (bool, double))[] F() { return new[] { (1, (true, 2.0)) }; }
+
+ static void Main(string[] args)
+ {
+ foreach ((int i, (bool b, double d)) in F())
+ {
+ System.Console.Write(0);
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ private static (int, (bool, double))[] F() { return new[] { (1, (true, 2.0)) }; }
+
+ static void Main(string[] args)
+ {
+ foreach ((int i, (var b, double d)) in F())
+ {
+ System.Console.Write(1);
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active,
+ Diagnostic(RudeEditKind.ActiveStatementUpdate, "(int i, (var b, double d))"),
+ Diagnostic(RudeEditKind.UpdateAroundActiveStatement, "foreach ( (int i, (var b, double d)) in F())", CSharpFeaturesResources.foreach_statement));
+ }
+
+ [Fact]
+ public void ForEach_Reorder_Leaf()
{
string src1 = @"
class Test
@@ -3377,19 +3554,19 @@ static void Main(string[] args)
}
[Fact]
- public void ForEach_Update_Leaf1()
+ public void ForEachVariable_Reorder_Leaf()
{
string src1 = @"
class Test
{
- public static int[] e1 = new int[1];
- public static int[] e2 = new int[1];
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
- foreach (var a in e1)
+ foreach ((var a1, var a2) in e1)
{
- foreach (var b in e1)
+ foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
@@ -3402,16 +3579,16 @@ static void Main(string[] args)
string src2 = @"
class Test
{
- public static int[] e1 = new int[1];
- public static int[] e2 = new int[1];
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
- foreach (var b in e1)
+ foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
- foreach (var a in e1)
+ foreach ((var a1, var a2) in e1)
{
System.Console.Write();
}
@@ -3426,7 +3603,7 @@ static void Main(string[] args)
}
[Fact]
- public void ForEach_Update_Leaf2()
+ public void ForEach_Update_Leaf()
{
string src1 = @"
class Test
@@ -3468,6 +3645,49 @@ static void Main(string[] args)
Diagnostic(RudeEditKind.InsertAroundActiveStatement, "foreach (var a in e1)", CSharpFeaturesResources.foreach_statement));
}
+ [Fact]
+ public void ForEachVariable_Update_Leaf()
+ {
+ string src1 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ System.Console.Write();
+ }
+}";
+ string src2 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active,
+ Diagnostic(RudeEditKind.InsertAroundActiveStatement, "foreach (var c in e1)", CSharpFeaturesResources.foreach_statement),
+ Diagnostic(RudeEditKind.InsertAroundActiveStatement, "foreach ((int b1, bool b2) in e1)", CSharpFeaturesResources.foreach_statement),
+ Diagnostic(RudeEditKind.InsertAroundActiveStatement, "foreach ((var a1, var a2) in e1)", CSharpFeaturesResources.foreach_statement));
+ }
+
[Fact]
public void ForEach_Delete_Leaf1()
{
@@ -3514,6 +3734,52 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariable_Delete_Leaf1()
+ {
+ string src1 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEach_Delete_Leaf2()
{
@@ -3560,6 +3826,52 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariable_Delete_Leaf2()
+ {
+ string src1 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ public static (int, bool)[] e1 = new (int, bool)[1];
+ public static (int, bool)[] e2 = new (int, bool)[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEach_Delete_Leaf3()
{
@@ -3606,6 +3918,52 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void ForEachVariable_Delete_Leaf3()
+ {
+ string src1 = @"
+class Test
+{
+ public static int[] e1 = new int[1];
+ public static int[] e2 = new int[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ foreach ((int b1, bool b2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+ }
+}";
+ string src2 = @"
+class Test
+{
+ public static int[] e1 = new int[1];
+ public static int[] e2 = new int[1];
+
+ static void Main(string[] args)
+ {
+ foreach ((var a1, var a2) in e1)
+ {
+ foreach (var c in e1)
+ {
+ System.Console.Write();
+ }
+ }
+ }
+}";
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active);
+ }
+
[Fact]
public void ForEach_Lambda1()
{
@@ -8182,8 +8540,7 @@ static void F(object o)
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.UpdateAroundActiveStatement, "var (x, y)", CSharpFeaturesResources.deconstruction));
+ edits.VerifyRudeDiagnostics(active);
}
[Fact]
diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
index bf80853e2d617..3453a4230e427 100644
--- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
+++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
@@ -2349,6 +2349,56 @@ public int M2()
index: 1);
}
+ [WorkItem(18556, "https://github.com/dotnet/roslyn/issues/18556")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
+ public async Task TestImplementInterfaceThroughExplicitProperty()
+ {
+ await TestActionCountAsync(
+@"interface IA
+{
+ IB B { get; }
+}
+interface IB
+{
+ int M();
+}
+class AB : IA, [|IB|]
+{
+ IB IA.B => null;
+}",
+count: 3);
+ await TestWithAllCodeStyleOptionsOffAsync(
+@"interface IA
+{
+ IB B { get; }
+}
+interface IB
+{
+ int M();
+}
+class AB : IA, [|IB|]
+{
+ IB IA.B => null;
+}",
+@"interface IA
+{
+ IB B { get; }
+}
+interface IB
+{
+ int M();
+}
+class AB : IA, [|IB|]
+{
+ IB IA.B => null;
+
+ public int M()
+ {
+ return ((IA)this).B.M();
+ }
+}", index: 1);
+ }
+
[WorkItem(768799, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768799")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
public async Task TestNoImplementThroughIndexer()
diff --git a/src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs b/src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs
index 870815e7c612f..b700377c7cebf 100644
--- a/src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs
+++ b/src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs
@@ -704,5 +704,56 @@ public C(string s)
}
}", index: 2);
}
+
+ [WorkItem(19173, "https://github.com/dotnet/roslyn/issues/19173")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInitializeParameter)]
+ public async Task TestMissingOnUnboundTypeWithExistingNullCheck()
+ {
+ await TestMissingAsync(
+@"
+class C
+{
+ public C(String [||]s)
+ {
+ if (s == null)
+ {
+ throw new System.Exception();
+ }
+ }
+}");
+ }
+
+ [WorkItem(19174, "https://github.com/dotnet/roslyn/issues/19174")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInitializeParameter)]
+ public async Task TestRespectPredefinedTypePreferences()
+ {
+ await TestInRegularAndScript1Async(
+@"
+using System;
+
+class Program
+{
+ static void Main([||]String bar)
+ {
+ }
+}",
+@"
+using System;
+
+class Program
+{
+ static void Main(String bar)
+ {
+ if (String.IsNullOrEmpty(bar))
+ {
+ throw new ArgumentException(""message"", nameof(bar));
+ }
+ }
+}", index: 1,
+ parameters: new TestParameters(
+ options: Option(
+ CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess,
+ CodeStyleOptions.FalseWithSuggestionEnforcement)));
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs b/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs
index e9020f4603ee6..9e0057e717c0e 100644
--- a/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs
+++ b/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs
@@ -168,8 +168,8 @@ public static void Main()
{
for (int i = 0; i < 10; i++)
{
- int {|Rename:v|} = i + 1;
- Console.WriteLine(v);
+ int {|Rename:value|} = i + 1;
+ Console.WriteLine(value);
}
}
}
diff --git a/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs b/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
index a6f091f146cdd..4b6e6b6be07aa 100644
--- a/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
+++ b/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
@@ -981,5 +981,40 @@ public void M()
}
}");
}
+
+ [WorkItem(19253, "https://github.com/dotnet/roslyn/issues/19253")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)]
+ public async Task TestKeepBlankLinesAfter()
+ {
+ await TestInRegularAndScript1Async(
+@"
+using System.Collections.Generic;
+
+class MyClass
+{
+ public void Main()
+ {
+ var list = [||]new List();
+ list.Add(1);
+
+ int horse = 1;
+ }
+}",
+@"
+using System.Collections.Generic;
+
+class MyClass
+{
+ public void Main()
+ {
+ var list = new List
+ {
+ 1
+ };
+
+ int horse = 1;
+ }
+}", ignoreTrivia: false);
+ }
}
}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/UseObjectInitializer/UseObjectInitializerTests.cs b/src/EditorFeatures/CSharpTest/UseObjectInitializer/UseObjectInitializerTests.cs
index 395fbfce9252e..5d42f49353f05 100644
--- a/src/EditorFeatures/CSharpTest/UseObjectInitializer/UseObjectInitializerTests.cs
+++ b/src/EditorFeatures/CSharpTest/UseObjectInitializer/UseObjectInitializerTests.cs
@@ -534,6 +534,47 @@ public void M()
}
public string Value { get; set; }
+}", ignoreTrivia: false);
+ }
+
+ [WorkItem(19253, "https://github.com/dotnet/roslyn/issues/19253")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseObjectInitializer)]
+ public async Task TestKeepBlankLinesAfter()
+ {
+ await TestInRegularAndScript1Async(
+@"
+class Foo
+{
+ public int Bar { get; set; }
+}
+
+class MyClass
+{
+ public void Main()
+ {
+ var foo = [||]new Foo();
+ foo.Bar = 1;
+
+ int horse = 1;
+ }
+}",
+@"
+class Foo
+{
+ public int Bar { get; set; }
+}
+
+class MyClass
+{
+ public void Main()
+ {
+ var foo = new Foo
+ {
+ Bar = 1
+ };
+
+ int horse = 1;
+ }
}", ignoreTrivia: false);
}
}
diff --git a/src/EditorFeatures/CSharpTest/Workspaces/WorkspaceTests.cs b/src/EditorFeatures/CSharpTest/Workspaces/WorkspaceTests.cs
index a14156a13a993..7ecdff7862988 100644
--- a/src/EditorFeatures/CSharpTest/Workspaces/WorkspaceTests.cs
+++ b/src/EditorFeatures/CSharpTest/Workspaces/WorkspaceTests.cs
@@ -1,6 +1,8 @@
// 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.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -11,11 +13,10 @@
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
+using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Text;
using Roslyn.Test.Utilities;
using Xunit;
-using System.Composition;
-using Microsoft.VisualStudio.Composition;
namespace Microsoft.CodeAnalysis.UnitTests.Workspaces
{
@@ -1003,5 +1004,51 @@ public void TestAdditionalFile_AddRemove_FromProject()
Assert.Equal("original.config", workspace.CurrentSolution.GetProject(project1.Id).AdditionalDocuments.Single().Name);
}
}
+
+ [Fact, WorkItem(209299, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=209299")]
+ public async Task TestLinkedFilesStayInSync()
+ {
+ var originalText = "class Program1 { }";
+ var updatedText = "class Program2 { }";
+
+ var input = $@"
+
+
+ { originalText }
+
+
+
+
+";
+
+ using (var workspace = TestWorkspace.Create(input, exportProvider: s_exportProvider.Value))
+ {
+ var eventArgs = new List();
+
+ workspace.WorkspaceChanged += (s, e) =>
+ {
+ Assert.Equal(WorkspaceChangeKind.DocumentChanged, e.Kind);
+ eventArgs.Add(e);
+ };
+
+ var originalDocumentId = workspace.GetOpenDocumentIds().Single(id => !workspace.GetTestDocument(id).IsLinkFile);
+ var linkedDocumentId = workspace.GetOpenDocumentIds().Single(id => workspace.GetTestDocument(id).IsLinkFile);
+
+ workspace.GetTestDocument(originalDocumentId).Update(SourceText.From("class Program2 { }"));
+ await WaitForWorkspaceOperationsToComplete(workspace);
+
+ Assert.Equal(2, eventArgs.Count);
+ AssertEx.SetEqual(workspace.Projects.SelectMany(p => p.Documents).Select(d => d.Id), eventArgs.Select(e => e.DocumentId));
+
+ Assert.Equal(eventArgs[0].OldSolution, eventArgs[1].OldSolution);
+ Assert.Equal(eventArgs[0].NewSolution, eventArgs[1].NewSolution);
+
+ Assert.Equal(originalText, (await eventArgs[0].OldSolution.GetDocument(originalDocumentId).GetTextAsync().ConfigureAwait(false)).ToString());
+ Assert.Equal(originalText, (await eventArgs[1].OldSolution.GetDocument(originalDocumentId).GetTextAsync().ConfigureAwait(false)).ToString());
+
+ Assert.Equal(updatedText, (await eventArgs[0].NewSolution.GetDocument(originalDocumentId).GetTextAsync().ConfigureAwait(false)).ToString());
+ Assert.Equal(updatedText, (await eventArgs[1].NewSolution.GetDocument(originalDocumentId).GetTextAsync().ConfigureAwait(false)).ToString());
+ }
+ }
}
}
diff --git a/src/EditorFeatures/Core/EditorFeatures.csproj b/src/EditorFeatures/Core/EditorFeatures.csproj
index 18b9836a0c890..3a5b371a27e54 100644
--- a/src/EditorFeatures/Core/EditorFeatures.csproj
+++ b/src/EditorFeatures/Core/EditorFeatures.csproj
@@ -466,9 +466,7 @@
-
-
diff --git a/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs b/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs
index c97332511ba64..6c70c68e4bf9c 100644
--- a/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs
+++ b/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs
@@ -150,7 +150,24 @@ await AppendFixesAsync(
{
// sort the result to the order defined by the fixers
var priorityMap = _fixerPriorityMap[document.Project.Language].Value;
- result.Sort((d1, d2) => priorityMap.ContainsKey((CodeFixProvider)d1.Provider) ? (priorityMap.ContainsKey((CodeFixProvider)d2.Provider) ? priorityMap[(CodeFixProvider)d1.Provider] - priorityMap[(CodeFixProvider)d2.Provider] : -1) : 1);
+ result.Sort((d1, d2) =>
+ {
+ if (priorityMap.TryGetValue((CodeFixProvider)d1.Provider, out int priority1))
+ {
+ if (priorityMap.TryGetValue((CodeFixProvider)d2.Provider, out int priority2))
+ {
+ return priority1 - priority2;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ return 1;
+ }
+ });
}
// TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/FileSystemCompletionHelper.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/FileSystemCompletionHelper.cs
deleted file mode 100644
index e334b9a4a8896..0000000000000
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/FileSystemCompletionHelper.cs
+++ /dev/null
@@ -1,289 +0,0 @@
-// 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.Immutable;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Completion;
-using Microsoft.CodeAnalysis.Shared.Extensions;
-using Microsoft.CodeAnalysis.Shared.Utilities;
-using Microsoft.CodeAnalysis.Text;
-using Roslyn.Utilities;
-
-namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.FileSystem
-{
- internal sealed class FileSystemCompletionHelper
- {
- private readonly ICurrentWorkingDirectoryDiscoveryService _fileSystemDiscoveryService;
- private readonly Func _exclude;
- private readonly Glyph _folderGlyph;
- private readonly Glyph _fileGlyph;
-
- // absolute paths
- private readonly ImmutableArray _searchPaths;
-
- private readonly ISet _allowableExtensions;
-
- private readonly Lazy _lazyGetDrives;
- private readonly CompletionProvider _completionProvider;
- private readonly TextSpan _textChangeSpan;
- private readonly CompletionItemRules _itemRules;
-
- public FileSystemCompletionHelper(
- CompletionProvider completionProvider,
- TextSpan textChangeSpan,
- ICurrentWorkingDirectoryDiscoveryService fileSystemDiscoveryService,
- Glyph folderGlyph,
- Glyph fileGlyph,
- ImmutableArray searchPaths,
- IEnumerable allowableExtensions,
- Func exclude = null,
- CompletionItemRules itemRules = null)
- {
- Debug.Assert(searchPaths.All(path => PathUtilities.IsAbsolute(path)));
-
- _completionProvider = completionProvider;
- _textChangeSpan = textChangeSpan;
- _searchPaths = searchPaths;
- _allowableExtensions = allowableExtensions.Select(e => e.ToLowerInvariant()).ToSet();
- _fileSystemDiscoveryService = fileSystemDiscoveryService;
- _folderGlyph = folderGlyph;
- _fileGlyph = fileGlyph;
- _exclude = exclude;
- _itemRules = itemRules;
-
- _lazyGetDrives = new Lazy(() =>
- IOUtilities.PerformIO(Directory.GetLogicalDrives, Array.Empty()));
- }
-
- public ImmutableArray GetItems(string pathSoFar, string documentPath)
- {
- if (_exclude != null && _exclude(pathSoFar))
- {
- return ImmutableArray.Empty;
- }
-
- return GetFilesAndDirectories(pathSoFar, documentPath);
- }
-
- private CompletionItem CreateCurrentDirectoryItem()
- {
- return CommonCompletionItem.Create(".", rules: _itemRules);
- }
-
- private CompletionItem CreateParentDirectoryItem()
- {
- return CommonCompletionItem.Create("..", rules: _itemRules);
- }
-
- private CompletionItem CreateNetworkRoot(TextSpan textChangeSpan)
- {
- return CommonCompletionItem.Create("\\\\", rules: _itemRules);
- }
-
- private ImmutableArray GetFilesAndDirectories(string path, string basePath)
- {
- var result = ArrayBuilder.GetInstance();
- var pathKind = PathUtilities.GetPathKind(path);
- switch (pathKind)
- {
- case PathKind.Empty:
- result.Add(CreateCurrentDirectoryItem());
-
- if (!IsDriveRoot(_fileSystemDiscoveryService.WorkingDirectory))
- {
- result.Add(CreateParentDirectoryItem());
- }
-
- result.Add(CreateNetworkRoot(_textChangeSpan));
- result.AddRange(GetLogicalDrives());
- result.AddRange(GetFilesAndDirectoriesInSearchPaths());
- break;
-
- case PathKind.Absolute:
- case PathKind.RelativeToCurrentDirectory:
- case PathKind.RelativeToCurrentParent:
- case PathKind.RelativeToCurrentRoot:
- {
- var fullPath = FileUtilities.ResolveRelativePath(
- path,
- basePath,
- _fileSystemDiscoveryService.WorkingDirectory);
-
- if (fullPath != null)
- {
- result.AddRange(GetFilesAndDirectoriesInDirectory(fullPath));
-
- // although it is possible to type "." here, it doesn't make any sense to do so:
- if (!IsDriveRoot(fullPath) && pathKind != PathKind.Absolute)
- {
- result.Add(CreateParentDirectoryItem());
- }
-
- if (path == "\\" && pathKind == PathKind.RelativeToCurrentRoot)
- {
- // The user has typed only "\". In this case, we want to add "\\" to
- // the list. Also, the textChangeSpan needs to be backed up by one
- // so that it will consume the "\" when "\\" is inserted.
- result.Add(CreateNetworkRoot(TextSpan.FromBounds(_textChangeSpan.Start - 1, _textChangeSpan.End)));
- }
- }
- else
- {
- // invalid path
- result.Clear();
- }
- }
-
- break;
-
- case PathKind.Relative:
-
- // although it is possible to type "." here, it doesn't make any sense to do so:
- result.Add(CreateParentDirectoryItem());
-
- foreach (var searchPath in _searchPaths)
- {
- var fullPath = PathUtilities.CombineAbsoluteAndRelativePaths(searchPath, path);
-
- // search paths are always absolute:
- Debug.Assert(PathUtilities.IsAbsolute(fullPath));
- result.AddRange(GetFilesAndDirectoriesInDirectory(fullPath));
- }
-
- break;
-
- case PathKind.RelativeToDriveDirectory:
- // these paths are not supported
- break;
-
- default:
- throw ExceptionUtilities.UnexpectedValue(pathKind);
- }
-
- return result.ToImmutableAndFree();
- }
-
- private static bool IsDriveRoot(string fullPath)
- {
- return IOUtilities.PerformIO(() => new DirectoryInfo(fullPath).Parent == null);
- }
-
- private IEnumerable GetFilesAndDirectoriesInDirectory(string fullDirectoryPath)
- {
- Debug.Assert(PathUtilities.IsAbsolute(fullDirectoryPath));
- if (IOUtilities.PerformIO(() => Directory.Exists(fullDirectoryPath)))
- {
- var directoryInfo = IOUtilities.PerformIO(() => new DirectoryInfo(fullDirectoryPath));
- if (directoryInfo != null)
- {
- return from child in GetFileSystemInfos(directoryInfo)
- where ShouldShow(child)
- where CanAccess(child)
- select this.CreateCompletion(child);
- }
- }
-
- return SpecializedCollections.EmptyEnumerable();
- }
-
- private CompletionItem CreateCompletion(FileSystemInfo child)
- {
- return CommonCompletionItem.Create(
- child.Name,
- glyph: child is DirectoryInfo ? _folderGlyph : _fileGlyph,
- description: child.FullName.ToSymbolDisplayParts(),
- rules: _itemRules);
- }
-
- private bool ShouldShow(FileSystemInfo child)
- {
- // Get the attributes. If we can't, assume it's hidden.
- var attributes = IOUtilities.PerformIO(() => child.Attributes, FileAttributes.Hidden);
-
- // Don't show hidden/system files.
- if ((attributes & FileAttributes.Hidden) != 0 ||
- (attributes & FileAttributes.System) != 0)
- {
- return false;
- }
-
- if (child is DirectoryInfo)
- {
- return true;
- }
-
- if (child is FileInfo)
- {
- return
- _allowableExtensions.Count == 0 ||
- _allowableExtensions.Contains(Path.GetExtension(child.Name).ToLowerInvariant());
- }
-
- return false;
- }
-
- private bool CanAccess(FileSystemInfo info)
- {
- switch (info)
- {
- case DirectoryInfo d: return CanAccessDirectory(d);
- case FileInfo f: return CanAccessFile(f);
- }
-
- return false;
- }
-
- private bool CanAccessFile(FileInfo file)
- {
- var accessControl = IOUtilities.PerformIO(file.GetAccessControl);
-
- // Quick and dirty check. If we can't even get the access control object, then we
- // can't access the file.
- if (accessControl == null)
- {
- return false;
- }
-
- // TODO(cyrusn): Actually add checks here.
- return true;
- }
-
- private bool CanAccessDirectory(DirectoryInfo directory)
- {
- var accessControl = IOUtilities.PerformIO(directory.GetAccessControl);
-
- // Quick and dirty check. If we can't even get the access control object, then we
- // can't access the file.
- if (accessControl == null)
- {
- return false;
- }
-
- // TODO(cyrusn): Do more checks here.
- return true;
- }
-
- private IEnumerable GetFilesAndDirectoriesInSearchPaths()
- {
- return _searchPaths.SelectMany(GetFilesAndDirectoriesInDirectory);
- }
-
- private IEnumerable GetLogicalDrives()
- {
- // First, we may have a filename, so let's include all drives
- return from d in _lazyGetDrives.Value
- where d.Length > 0 && (d.Last() == Path.DirectorySeparatorChar || d.Last() == Path.AltDirectorySeparatorChar)
- let text = d.Substring(0, d.Length - 1)
- select CommonCompletionItem.Create(text, glyph: _folderGlyph, rules: _itemRules);
- }
-
- private static FileSystemInfo[] GetFileSystemInfos(DirectoryInfo directoryInfo)
- {
- return IOUtilities.PerformIO(directoryInfo.GetFileSystemInfos, Array.Empty());
- }
- }
-}
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/PathCompletionUtilities.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/PathCompletionUtilities.cs
deleted file mode 100644
index 2f6774440b78c..0000000000000
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/FileSystem/PathCompletionUtilities.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-// 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 Microsoft.CodeAnalysis.Completion;
-using Microsoft.CodeAnalysis.Text;
-using Roslyn.Utilities;
-
-namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.FileSystem
-{
- internal static class PathCompletionUtilities
- {
- internal static bool IsTriggerCharacter(SourceText text, int characterPosition)
- {
- // Bring up completion when the user types a quote (i.e.: #r "), or if they type a slash
- // path separator character, or if they type a comma (#r "foo,version...").
- //
- // Also, if they're starting a word. i.e. #r "c:\W
- var ch = text[characterPosition];
- return ch == '"' || ch == '\\' || ch == ',' ||
- CommonCompletionUtilities.IsStartingNewWord(text, characterPosition, char.IsLetter, char.IsLetterOrDigit);
- }
-
- internal static bool IsFilterCharacter(CompletionItem item, char ch, string textTypedSoFar)
- {
- // If the user types something that matches what is in the completion list, then just
- // count it as a filter character.
-
- // For example, if they type "Program " and "Program Files" is in the list, the
- // should be counted as a filter character and not a commit character.
- return item.DisplayText.StartsWith(textTypedSoFar, StringComparison.OrdinalIgnoreCase);
- }
-
- internal static bool IsCommitcharacter(CompletionItem item, char ch, string textTypedSoFar)
- {
- return ch == '"' || ch == '\\' || ch == ',';
- }
-
- internal static bool SendEnterThroughToEditor(CompletionItem item, string textTypedSoFar)
- {
- return false;
- }
-
- internal static string GetPathThroughLastSlash(string quotedPath, int quotedPathStart, int position)
- {
- Contract.ThrowIfTrue(quotedPath[0] != '"');
-
- const int QuoteLength = 1;
-
- var positionInQuotedPath = position - quotedPathStart;
- var path = quotedPath.Substring(QuoteLength, positionInQuotedPath - QuoteLength).Trim();
- var afterLastSlashIndex = AfterLastSlashIndex(path, path.Length);
-
- // We want the portion up to, and including the last slash if there is one. That way if
- // the user pops up completion in the middle of a path (i.e. "C:\Win") then we'll
- // consider the path to be "C:\" and we will show appropriate completions.
- return afterLastSlashIndex >= 0 ? path.Substring(0, afterLastSlashIndex) : path;
- }
-
- internal static TextSpan GetTextChangeSpan(string quotedPath, int quotedPathStart, int position)
- {
- // We want the text change to be from after the last slash to the end of the quoted
- // path. If there is no last slash, then we want it from right after the start quote
- // character.
- var positionInQuotedPath = position - quotedPathStart;
-
- // Where we want to start tracking is right after the slash (if we have one), or else
- // right after the string starts.
- var afterLastSlashIndex = PathCompletionUtilities.AfterLastSlashIndex(quotedPath, positionInQuotedPath);
- var afterFirstQuote = 1;
-
- var startIndex = Math.Max(afterLastSlashIndex, afterFirstQuote);
- var endIndex = quotedPath.Length;
-
- // If the string ends with a quote, the we do not want to consume that.
- if (EndsWithQuote(quotedPath))
- {
- endIndex--;
- }
-
- return TextSpan.FromBounds(startIndex + quotedPathStart, endIndex + quotedPathStart);
- }
-
- internal static bool EndsWithQuote(string quotedPath)
- {
- return quotedPath.Length >= 2 && quotedPath[quotedPath.Length - 1] == '"';
- }
-
- ///
- /// Returns the index right after the last slash that precedes 'position'. If there is no
- /// slash in the string, -1 is returned.
- ///
- private static int AfterLastSlashIndex(string text, int position)
- {
- // Position might be out of bounds of the string (if the string is unterminated. Make
- // sure it's within bounds.
- position = Math.Min(position, text.Length - 1);
-
- int index;
- if ((index = text.LastIndexOf('/', position)) >= 0 ||
- (index = text.LastIndexOf('\\', position)) >= 0)
- {
- return index + 1;
- }
-
- return -1;
- }
- }
-}
diff --git a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs
index 6aea6a5cfd0cb..c55a80cabbe01 100644
--- a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs
+++ b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs
@@ -600,28 +600,28 @@ private void ProcessNewTagTrees(
var bufferToChanges = new Dictionary();
using (Logger.LogBlock(FunctionId.Tagger_TagSource_ProcessNewTags, cancellationToken))
{
- foreach (var latestBuffer in newTagTrees.Keys)
+ foreach (var (latestBuffer, latestSpans) in newTagTrees)
{
var snapshot = spansToTag.First(s => s.SnapshotSpan.Snapshot.TextBuffer == latestBuffer).SnapshotSpan.Snapshot;
- if (oldTagTrees.ContainsKey(latestBuffer))
+ if (oldTagTrees.TryGetValue(latestBuffer, out var previousSpans))
{
- var difference = ComputeDifference(snapshot, newTagTrees[latestBuffer], oldTagTrees[latestBuffer]);
+ var difference = ComputeDifference(snapshot, latestSpans, previousSpans);
bufferToChanges[latestBuffer] = difference;
}
else
{
// It's a new buffer, so report all spans are changed
- bufferToChanges[latestBuffer] = new DiffResult(added: newTagTrees[latestBuffer].GetSpans(snapshot).Select(t => t.Span), removed: null);
+ bufferToChanges[latestBuffer] = new DiffResult(added: latestSpans.GetSpans(snapshot).Select(t => t.Span), removed: null);
}
}
- foreach (var oldBuffer in oldTagTrees.Keys)
+ foreach (var (oldBuffer, previousSpans) in oldTagTrees)
{
if (!newTagTrees.ContainsKey(oldBuffer))
{
// This buffer disappeared, so let's notify that the old tags are gone
- bufferToChanges[oldBuffer] = new DiffResult(added: null, removed: oldTagTrees[oldBuffer].GetSpans(oldBuffer.CurrentSnapshot).Select(t => t.Span));
+ bufferToChanges[oldBuffer] = new DiffResult(added: null, removed: previousSpans.GetSpans(oldBuffer.CurrentSnapshot).Select(t => t.Span));
}
}
}
diff --git a/src/EditorFeatures/Test/Completion/FileSystemCompletionHelperTests.cs b/src/EditorFeatures/Test/Completion/FileSystemCompletionHelperTests.cs
new file mode 100644
index 0000000000000..75c0a5a0af3a0
--- /dev/null
+++ b/src/EditorFeatures/Test/Completion/FileSystemCompletionHelperTests.cs
@@ -0,0 +1,234 @@
+// 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.Immutable;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis.Completion;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.UnitTests.Completion
+{
+ public class FileSystemCompletionHelperTests
+ {
+ private void AssertItemsEqual(ImmutableArray actual, params string[] expected)
+ {
+ AssertEx.Equal(
+ expected,
+ actual.Select(c => $"'{c.DisplayText}', {string.Join(", ", c.Tags)}, '{c.Properties["Description"]}'"),
+ itemInspector: c => $"@\"{c}\"");
+
+ Assert.True(actual.All(i => i.Rules == TestFileSystemCompletionHelper.CompletionRules));
+ }
+
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void GetItems_Windows1()
+ {
+ var fsc = new TestFileSystemCompletionHelper(
+ searchPaths: ImmutableArray.Create(@"X:\A", @"X:\B"),
+ baseDirectoryOpt: @"Z:\C",
+ allowableExtensions: ImmutableArray.Create(".abc", ".def"),
+ drives: new[] { @"X:\", @"Z:\" },
+ directories: new[]
+ {
+ @"X:",
+ @"X:\A",
+ @"X:\A\1",
+ @"X:\A\2",
+ @"X:\A\3",
+ @"X:\B",
+ @"Z:",
+ @"Z:\C",
+ @"Z:\D",
+ },
+ files: new[]
+ {
+ @"X:\A\1\file1.abc",
+ @"X:\A\2\file2.abc",
+ @"X:\B\file4.x",
+ @"X:\B\file5.abc",
+ @"X:\B\hidden.def",
+ @"Z:\C\file6.def",
+ @"Z:\C\file.7.def",
+ });
+
+ // Note backslashes in description are escaped
+ AssertItemsEqual(fsc.GetItems("", CancellationToken.None),
+ @"'file6.def', File, C#, 'Text|Z:\5CC\5Cfile6.def'",
+ @"'file.7.def', File, C#, 'Text|Z:\5CC\5Cfile.7.def'",
+ @"'X:', Folder, 'Text|X:'",
+ @"'Z:', Folder, 'Text|Z:'",
+ @"'\\', , 'Text|\5C\5C'",
+ @"'1', Folder, 'Text|X:\5CA\5C1'",
+ @"'2', Folder, 'Text|X:\5CA\5C2'",
+ @"'3', Folder, 'Text|X:\5CA\5C3'",
+ @"'file5.abc', File, C#, 'Text|X:\5CB\5Cfile5.abc'");
+
+ AssertItemsEqual(fsc.GetItems(@"X:\A\", CancellationToken.None),
+ @"'1', Folder, 'Text|X:\5CA\5C1'",
+ @"'2', Folder, 'Text|X:\5CA\5C2'",
+ @"'3', Folder, 'Text|X:\5CA\5C3'");
+
+ AssertItemsEqual(fsc.GetItems(@"X:\B\", CancellationToken.None),
+ @"'file5.abc', File, C#, 'Text|X:\5CB\5Cfile5.abc'");
+
+ AssertItemsEqual(fsc.GetItems(@"Z:\", CancellationToken.None),
+ @"'C', Folder, 'Text|Z:\5CC'",
+ @"'D', Folder, 'Text|Z:\5CD'");
+
+ AssertItemsEqual(fsc.GetItems(@"Z:", CancellationToken.None),
+ @"'Z:', Folder, 'Text|Z:'");
+
+ AssertItemsEqual(fsc.GetItems(@"\", CancellationToken.None),
+ @"'\\', , 'Text|\5C\5C'");
+ }
+
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void GetItems_Windows_NoBaseDirectory()
+ {
+ var fsc = new TestFileSystemCompletionHelper(
+ searchPaths: ImmutableArray.Create(@"X:\A", @"X:\B"),
+ baseDirectoryOpt: null,
+ allowableExtensions: ImmutableArray.Create(".abc", ".def"),
+ drives: new[] { @"X:\" },
+ directories: new[]
+ {
+ @"X:",
+ @"X:\A",
+ @"X:\A\1",
+ @"X:\A\2",
+ @"X:\A\3",
+ @"X:\B",
+ },
+ files: new[]
+ {
+ @"X:\A\1\file1.abc",
+ @"X:\A\2\file2.abc",
+ @"X:\B\file4.x",
+ @"X:\B\file5.abc",
+ @"X:\B\hidden.def",
+ });
+
+ // Note backslashes in description are escaped
+ AssertItemsEqual(fsc.GetItems(@"", CancellationToken.None),
+ @"'X:', Folder, 'Text|X:'",
+ @"'\\', , 'Text|\5C\5C'",
+ @"'1', Folder, 'Text|X:\5CA\5C1'",
+ @"'2', Folder, 'Text|X:\5CA\5C2'",
+ @"'3', Folder, 'Text|X:\5CA\5C3'",
+ @"'file5.abc', File, C#, 'Text|X:\5CB\5Cfile5.abc'");
+ }
+
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void GetItems_Windows_NoSearchPaths()
+ {
+ var fsc = new TestFileSystemCompletionHelper(
+ searchPaths: ImmutableArray.Empty,
+ baseDirectoryOpt: null,
+ allowableExtensions: ImmutableArray.Create(".abc", ".def"),
+ drives: new[] { @"X:\" },
+ directories: new[]
+ {
+ @"X:",
+ @"X:\A",
+ @"X:\A\1",
+ @"X:\A\2",
+ @"X:\A\3",
+ @"X:\B",
+ },
+ files: new[]
+ {
+ @"X:\A\1\file1.abc",
+ @"X:\A\2\file2.abc",
+ @"X:\B\file4.x",
+ @"X:\B\file5.abc",
+ @"X:\B\hidden.def",
+ });
+
+ // Note backslashes in description are escaped
+ AssertItemsEqual(fsc.GetItems(@"", CancellationToken.None),
+ @"'X:', Folder, 'Text|X:'",
+ @"'\\', , 'Text|\5C\5C'");
+ }
+
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void GetItems_Windows_Network()
+ {
+ var fsc = new TestFileSystemCompletionHelper(
+ searchPaths: ImmutableArray.Empty,
+ baseDirectoryOpt: null,
+ allowableExtensions: ImmutableArray.Create(".cs"),
+ drives: Array.Empty(),
+ directories: new[]
+ {
+ @"\\server\share",
+ @"\\server\share\C",
+ @"\\server\share\D",
+ },
+ files: new[]
+ {
+ @"\\server\share\C\b.cs",
+ @"\\server\share\C\c.cs",
+ @"\\server\share\D\e.cs",
+ });
+
+ AssertItemsEqual(fsc.GetItems(@"\\server\share\", CancellationToken.None),
+ @"'C', Folder, 'Text|\5C\5Cserver\5Cshare\5CC'",
+ @"'D', Folder, 'Text|\5C\5Cserver\5Cshare\5CD'");
+
+ AssertItemsEqual(fsc.GetItems(@"\\server\share\C\", CancellationToken.None),
+ @"'b.cs', File, C#, 'Text|\5C\5Cserver\5Cshare\5CC\5Cb.cs'",
+ @"'c.cs', File, C#, 'Text|\5C\5Cserver\5Cshare\5CC\5Cc.cs'");
+ }
+
+ [ConditionalFact(typeof(UnixLikeOnly))]
+ public void GetItems_Unix1()
+ {
+ var fsc = new TestFileSystemCompletionHelper(
+ searchPaths: ImmutableArray.Create(@"/A", @"/B"),
+ baseDirectoryOpt: @"/C",
+ allowableExtensions: ImmutableArray.Create(".abc", ".def"),
+ drives: Array.Empty(),
+ directories: new[]
+ {
+ @"/A",
+ @"/A/1",
+ @"/A/2",
+ @"/A/3",
+ @"/B",
+ @"/C",
+ @"/D",
+ },
+ files: new[]
+ {
+ @"/A/1/file1.abc",
+ @"/A/2/file2.abc",
+ @"/B/file4.x",
+ @"/B/file5.abc",
+ @"/B/hidden.def",
+ @"/C/file6.def",
+ @"/C/file.7.def",
+ });
+
+ // Note backslashes in description are escaped
+ AssertItemsEqual(fsc.GetItems(@"", CancellationToken.None),
+ @"'file6.def', File, C#, 'Text|/C/file6.def'",
+ @"'file.7.def', File, C#, 'Text|/C/file.7.def'",
+ @"'/', Folder, 'Text|/'",
+ @"'1', Folder, 'Text|/A/1'",
+ @"'2', Folder, 'Text|/A/2'",
+ @"'3', Folder, 'Text|/A/3'",
+ @"'file5.abc', File, C#, 'Text|/B/file5.abc'");
+
+ AssertItemsEqual(fsc.GetItems(@"/", CancellationToken.None),
+ @"'A', Folder, 'Text|/A'",
+ @"'B', Folder, 'Text|/B'",
+ @"'C', Folder, 'Text|/C'",
+ @"'D', Folder, 'Text|/D'");
+
+ AssertItemsEqual(fsc.GetItems(@"/B/", CancellationToken.None),
+ @"'file5.abc', File, C#, 'Text|/B/file5.abc'");
+ }
+ }
+}
diff --git a/src/EditorFeatures/Test/Completion/GlobalAssemblyCacheCompletionHelperTests.cs b/src/EditorFeatures/Test/Completion/GlobalAssemblyCacheCompletionHelperTests.cs
new file mode 100644
index 0000000000000..ce5abe28ef17a
--- /dev/null
+++ b/src/EditorFeatures/Test/Completion/GlobalAssemblyCacheCompletionHelperTests.cs
@@ -0,0 +1,44 @@
+// 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.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Completion;
+using Microsoft.CodeAnalysis.Editor.Completion.FileSystem;
+using Microsoft.CodeAnalysis.Text;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.IntelliSense.CompletionSetSources
+{
+ [Trait(Traits.Feature, Traits.Features.Completion)]
+ public class GlobalAssemblyCacheCompletionHelperTests
+ {
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void ExistingReference()
+ {
+ var code = "System.Windows";
+ VerifyPresence(code, "System.Windows.Forms");
+ }
+
+ [ConditionalFact(typeof(WindowsOnly))]
+ public void FullReferenceIdentity()
+ {
+ var code = "System,";
+ VerifyPresence(code, typeof(System.Diagnostics.Process).Assembly.FullName);
+ }
+
+ private static void VerifyPresence(string pathSoFar, string completionItem)
+ {
+ var completions = GetItems(pathSoFar);
+ Assert.True(completions.Any(c => c.DisplayText == completionItem));
+ }
+
+ private static IEnumerable GetItems(string pathSoFar)
+ {
+ var helper = new GlobalAssemblyCacheCompletionHelper(CompletionItemRules.Default);
+ return helper.GetItems(pathSoFar, CancellationToken.None);
+ }
+ }
+}
diff --git a/src/EditorFeatures/Test/Completion/TestFileSystemCompletionHelper.cs b/src/EditorFeatures/Test/Completion/TestFileSystemCompletionHelper.cs
new file mode 100644
index 0000000000000..c1a8d9d180256
--- /dev/null
+++ b/src/EditorFeatures/Test/Completion/TestFileSystemCompletionHelper.cs
@@ -0,0 +1,62 @@
+// 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.Immutable;
+using System.Linq;
+using Microsoft.CodeAnalysis.Completion;
+using Roslyn.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.UnitTests.Completion
+{
+ internal sealed class TestFileSystemCompletionHelper : FileSystemCompletionHelper
+ {
+ internal static readonly CompletionItemRules CompletionRules = CompletionItemRules.Default;
+
+ private readonly ImmutableArray _directories;
+ private readonly ImmutableArray _files;
+ private readonly ImmutableArray _drives;
+
+ public TestFileSystemCompletionHelper(
+ ImmutableArray searchPaths,
+ string baseDirectoryOpt,
+ ImmutableArray allowableExtensions,
+ IEnumerable drives,
+ IEnumerable directories,
+ IEnumerable files)
+ : base(Glyph.OpenFolder, Glyph.CSharpFile, searchPaths, baseDirectoryOpt, allowableExtensions, CompletionRules)
+ {
+ Assert.True(drives.All(d => d.EndsWith(PathUtilities.DirectorySeparatorStr)));
+ Assert.True(directories.All(d => !d.EndsWith(PathUtilities.DirectorySeparatorStr)));
+
+ _drives = ImmutableArray.CreateRange(drives);
+ _directories = ImmutableArray.CreateRange(directories);
+ _files = ImmutableArray.CreateRange(files);
+ }
+
+ protected override string[] GetLogicalDrives() =>
+ _drives.ToArray();
+
+ protected override bool IsVisibleFileSystemEntry(string fullPath) =>
+ !fullPath.Contains("hidden");
+
+ protected override bool DirectoryExists(string fullPath) =>
+ _directories.Contains(fullPath.TrimEnd(PathUtilities.DirectorySeparatorChar));
+
+ protected override IEnumerable EnumerateDirectories(string fullDirectoryPath) =>
+ Enumerate(_directories, fullDirectoryPath);
+
+ protected override IEnumerable EnumerateFiles(string fullDirectoryPath) =>
+ Enumerate(_files, fullDirectoryPath);
+
+ private IEnumerable Enumerate(ImmutableArray entries, string fullDirectoryPath)
+ {
+ var withTrailingSeparator = fullDirectoryPath.TrimEnd(PathUtilities.DirectorySeparatorChar) + PathUtilities.DirectorySeparatorChar;
+ return from d in entries
+ where d.StartsWith(withTrailingSeparator)
+ let nextSeparator = d.IndexOf(PathUtilities.DirectorySeparatorChar, withTrailingSeparator.Length)
+ select d.Substring(0, (nextSeparator >= 0) ? nextSeparator : d.Length);
+ }
+ }
+}
diff --git a/src/EditorFeatures/Test/EditorServicesTest.csproj b/src/EditorFeatures/Test/EditorServicesTest.csproj
index 3e97cdf6e5b5e..2e67d5ab70e6b 100644
--- a/src/EditorFeatures/Test/EditorServicesTest.csproj
+++ b/src/EditorFeatures/Test/EditorServicesTest.csproj
@@ -224,6 +224,9 @@
+
+
+
diff --git a/src/EditorFeatures/Test2/Rename/RenameEngineTests.CSharpConflicts.vb b/src/EditorFeatures/Test2/Rename/RenameEngineTests.CSharpConflicts.vb
index acc436b8b6db9..e7a15b31985d4 100644
--- a/src/EditorFeatures/Test2/Rename/RenameEngineTests.CSharpConflicts.vb
+++ b/src/EditorFeatures/Test2/Rename/RenameEngineTests.CSharpConflicts.vb
@@ -3585,6 +3585,31 @@ partial class {|current:$$C|} { }
result.AssertLabeledSpansAre("current", type:=RelatedLocationType.NoConflict)
End Using
End Sub
+
+
+
+
+ Public Sub RenameMethodToFinalizeWithDestructorPresent()
+ Using result = RenameEngineResult.Create(_outputHelper,
+
+
+
+class C
+{
+ ~{|Conflict:C|}() { }
+ void $$[|M|]()
+ {
+ int x = 7;
+ int y = ~x;
+ }
+}
+
+
+ , renameTo:="Finalize")
+
+ result.AssertLabeledSpansAre("Conflict", type:=RelatedLocationType.UnresolvedConflict)
+ End Using
+ End Sub
End Class
End Namespace
diff --git a/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj b/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj
index e72245fa212ed..af02f007d3e4b 100644
--- a/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj
+++ b/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj
@@ -287,6 +287,7 @@
+
diff --git a/src/EditorFeatures/TestUtilities/TestExportProvider.cs b/src/EditorFeatures/TestUtilities/TestExportProvider.cs
index 5451bfbcc8d90..47ded14219e30 100644
--- a/src/EditorFeatures/TestUtilities/TestExportProvider.cs
+++ b/src/EditorFeatures/TestUtilities/TestExportProvider.cs
@@ -72,6 +72,8 @@ private static Type[] GetNeutralAndCSharpAndVisualBasicTypes()
typeof(CodeAnalysis.VisualBasic.CodeGeneration.VisualBasicSyntaxGenerator),
typeof(CSharp.LanguageServices.CSharpContentTypeLanguageService),
typeof(VisualBasic.LanguageServices.VisualBasicContentTypeLanguageService),
+ typeof(CodeAnalysis.CSharp.Execution.CSharpOptionsSerializationService),
+ typeof(CodeAnalysis.VisualBasic.Execution.VisualBasicOptionsSerializationService),
typeof(TestExportProvider)
};
diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs
new file mode 100644
index 0000000000000..cbd71aef192f9
--- /dev/null
+++ b/src/EditorFeatures/TestUtilities/Workspaces/TestSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs
@@ -0,0 +1,34 @@
+// 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.Composition;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices;
+using Microsoft.CodeAnalysis.Host.Mef;
+
+namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
+{
+ [ExportWorkspaceService(typeof(ISymbolRenamedCodeActionOperationFactoryWorkspaceService), TestWorkspace.WorkspaceName), Shared]
+ public class TestSymbolRenamedCodeActionOperationFactoryWorkspaceService : ISymbolRenamedCodeActionOperationFactoryWorkspaceService
+ {
+ public CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution)
+ {
+ return new Operation(symbol, newName, startingSolution, updatedSolution);
+ }
+
+ public class Operation : CodeActionOperation
+ {
+ public ISymbol _symbol;
+ public string _newName;
+ public Solution _startingSolution;
+ public Solution _updatedSolution;
+
+ public Operation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution)
+ {
+ _symbol = symbol;
+ _newName = newName;
+ _startingSolution = startingSolution;
+ _updatedSolution = updatedSolution;
+ }
+ }
+ }
+}
diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb
index b3680cdeb1b2c..82c174427f336 100644
--- a/src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb
@@ -28,8 +28,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
- Const {|Rename:V|} As Integer = 1 + 1
- Console.WriteLine(V)
+ Const {|Rename:Value|} As Integer = 1 + 1
+ Console.WriteLine(Value)
End Sub
End Module",
index:=2)
@@ -51,8 +51,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
- Const {|Rename:V|} As Integer = 1 + 1
- Console.WriteLine(V)
+ Const {|Rename:Value|} As Integer = 1 + 1
+ Console.WriteLine(Value)
End Sub
End Module",
index:=3)
@@ -826,9 +826,9 @@ End Class")
End Sub
End Class",
"Class Foo
- Private Const {|Rename:V|} As Integer = 42
+ Private Const {|Rename:X|} As Integer = 42
Sub New()
- MyClass.New(V)
+ MyClass.New(X)
End Sub
Sub New(x As Integer)
End Sub
@@ -1158,8 +1158,8 @@ Module Program
If True Then
If True Then
- Const {|Rename:V|} As Integer = 1
- Console.WriteLine(V)
+ Const {|Rename:Value|} As Integer = 1
+ Console.WriteLine(Value)
Else
Console.WriteLine(2)
End If
@@ -1198,8 +1198,8 @@ Module Program
If True Then
Console.WriteLine(1)
Else
- Const {|Rename:V|} As Integer = 2
- Console.WriteLine(V)
+ Const {|Rename:Value|} As Integer = 2
+ Console.WriteLine(Value)
End If
Else
Console.WriteLine(3)
@@ -1234,8 +1234,8 @@ Module Program
If True Then
If True Then Console.WriteLine(1) Else Console.WriteLine(2)
Else
- Const {|Rename:V|} As Integer = 3
- Console.WriteLine(V)
+ Const {|Rename:Value|} As Integer = 3
+ Console.WriteLine(Value)
End If
End Sub
End Module
@@ -1258,8 +1258,8 @@ End Module",
Module Program
Sub Main
Dim a = Sub(x As Integer)
- Dim {|Rename:v|} As Integer = x + 1
- Console.WriteLine(v) ' Introduce local
+ Dim {|Rename:value|} As Integer = x + 1
+ Console.WriteLine(value) ' Introduce local
End Sub
End Sub
End Module")
@@ -1280,8 +1280,8 @@ Module Program
Sub Main
Dim a = Sub(x As Integer)
If True Then
- Dim {|Rename:v|} As Integer = x + 1
- Console.WriteLine(v)
+ Dim {|Rename:value|} As Integer = x + 1
+ Console.WriteLine(value)
Else
Console.WriteLine()
End If
@@ -1307,8 +1307,8 @@ Module Program
If True Then
Console.WriteLine()
Else
- Dim {|Rename:v|} As Integer = x + 1
- Console.WriteLine(v)
+ Dim {|Rename:value|} As Integer = x + 1
+ Console.WriteLine(value)
End If
End Sub
End Sub
@@ -1329,8 +1329,8 @@ End Module",
Module Program
Sub Main
Dim a = Sub(x As Integer)
- Dim {|Rename:v|} As Integer = x + 1
- If True Then Console.WriteLine(v) Else Console.WriteLine(v)
+ Dim {|Rename:value|} As Integer = x + 1
+ If True Then Console.WriteLine(value) Else Console.WriteLine(value)
End Sub
End Sub
End Module",
@@ -1351,10 +1351,10 @@ End Module",
"Module Program
Sub Main(args As String())
Dim query = Sub(a)
- Dim {|Rename:v|} As Object = a Or a
+ Dim {|Rename:arg1|} As Object = a Or a
a = New With {Key .Key = Function(ByVal arg As Integer) As Integer
Return arg
- End Function}.Key.Invoke(v)
+ End Function}.Key.Invoke(arg1)
End Sub
End Sub
End Module")
@@ -2093,8 +2093,8 @@ End Class",
Class C
Private Shared Sub Main(args As String())
Dim hSet = New HashSet(Of String)()
- Dim {|Rename:v|} As String = hSet.ToString()
- hSet.Add(v)
+ Dim {|Rename:item|} As String = hSet.ToString()
+ hSet.Add(item)
End Sub
End Class")
End Function
@@ -2175,8 +2175,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main()
- Dim {|Rename:enumerable1|} As IEnumerable(Of Char) = From x In """"
- [Take](enumerable1)
+ Dim {|Rename:x1|} As IEnumerable(Of Char) = From x In """"
+ [Take](x1)
End Sub
Sub Take(x)
End Sub
@@ -2621,8 +2621,8 @@ Imports System
Namespace N
Class C
Public Sub M()
- Dim {|Rename:v|} As FormattableString = $""""
- Dim f = FormattableString.Invariant(v)
+ Dim {|Rename:formattable|} As FormattableString = $""""
+ Dim f = FormattableString.Invariant(formattable)
End Sub
End Class
End Namespace"
@@ -2889,5 +2889,58 @@ End Class
Await TestInRegularAndScriptAsync(code, expected, ignoreTrivia:=False)
End Function
+
+
+ Public Async Function TestPickNameBasedOnArgument1() As Task
+ Await TestInRegularAndScriptAsync(
+"class C
+ public sub new(a as string, b as string)
+ dim c = new TextSpan([|integer.Parse(a)|], integer.Parse(b))
+ end sub
+end class
+
+structure TextSpan
+ public sub new(start as integer, length as integer)
+ end sub
+end structure",
+"class C
+ public sub new(a as string, b as string)
+ Dim {|Rename:start|} As Integer = integer.Parse(a)
+ dim c = new TextSpan(start, integer.Parse(b))
+ end sub
+end class
+
+structure TextSpan
+ public sub new(start as integer, length as integer)
+ end sub
+end structure")
+ End Function
+
+
+
+ Public Async Function TestPickNameBasedOnArgument2() As Task
+ Await TestInRegularAndScriptAsync(
+"class C
+ public sub new(a as string, b as string)
+ dim c = new TextSpan(integer.Parse(a), [|integer.Parse(b)|])
+ end sub
+end class
+
+structure TextSpan
+ public sub new(start as integer, length as integer)
+ end sub
+end structure",
+"class C
+ public sub new(a as string, b as string)
+ Dim {|Rename:length|} As Integer = integer.Parse(b)
+ dim c = new TextSpan(integer.Parse(a), length)
+ end sub
+end class
+
+structure TextSpan
+ public sub new(start as integer, length as integer)
+ end sub
+end structure")
+ End Function
End Class
-End Namespace
+End Namespace
\ No newline at end of file
diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb
index 92d7484321008..fff18f70367c7 100644
--- a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb
+++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb
@@ -44,7 +44,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.AddImp
' Make a loose mock for the installer service. We don't care what this test
' calls on it.
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of CancellationToken))).
Returns(True)
@@ -71,7 +71,7 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa
' Make a loose mock for the installer service. We don't care what this test
' calls on it.
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of CancellationToken))).
Returns(True)
@@ -98,7 +98,7 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa
' Make a loose mock for the installer service. We don't care what this test
' calls on it.
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of CancellationToken))).
Returns(False)
@@ -123,7 +123,7 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa
' Make a loose mock for the installer service. We don't care what this test
' calls on it.
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.IsInstalled(It.IsAny(Of Workspace)(), It.IsAny(Of ProjectId)(), "NuGetPackage")).
Returns(True)
@@ -145,7 +145,7 @@ New TestParameters(fixProviderData:=New ProviderData(installerServiceMock.Object
' Make a loose mock for the installer service. We don't care what this test
' calls on it.
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.GetInstalledVersions("NuGetPackage")).
Returns(ImmutableArray.Create("1.0", "2.0"))
@@ -185,7 +185,7 @@ parameters:=New TestParameters(fixProviderData:=data))
Public Async Function TestInstallGetsCalledNoVersion() As Task
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", Nothing, It.IsAny(Of Boolean), It.IsAny(Of CancellationToken))).
Returns(True)
@@ -211,7 +211,7 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa
Public Async Function TestInstallGetsCalledWithVersion() As Task
Dim installerServiceMock = New Mock(Of IPackageInstallerService)(MockBehavior.Loose)
- installerServiceMock.SetupGet(Function(i) i.IsEnabled).Returns(True)
+ installerServiceMock.Setup(Function(i) i.IsEnabled(It.IsAny(Of ProjectId))).Returns(True)
installerServiceMock.SetupGet(Function(i) i.PackageSources).Returns(NugetPackageSources)
installerServiceMock.Setup(Function(s) s.GetInstalledVersions("NuGetPackage")).
Returns(ImmutableArray.Create("1.0"))
diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb
index 3d589a34251cd..d2210b700b9b4 100644
--- a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb
@@ -3926,6 +3926,62 @@ Class Program
End Class")
End Function
+
+
+ Public Async Function TupleElement1() As Task
+ Await TestInRegularAndScriptAsync(
+"
+Imports System
+
+Public Class Q
+ Sub Main()
+ Dim x As (Integer, String) = ([|Foo|](), """")
+ End Sub
+End Class
+",
+"
+Imports System
+
+Public Class Q
+ Sub Main()
+ Dim x As (Integer, String) = (Foo(), """")
+ End Sub
+
+ Private Function Foo() As Integer
+ Throw New NotImplementedException()
+ End Function
+End Class
+")
+ End Function
+
+
+
+ Public Async Function TupleElement2() As Task
+ Await TestInRegularAndScriptAsync(
+"
+Imports System
+
+Public Class Q
+ Sub Main()
+ Dim x As (Integer, String) = (0, [|Foo|]())
+ End Sub
+End Class
+",
+"
+Imports System
+
+Public Class Q
+ Sub Main()
+ Dim x As (Integer, String) = (0, Foo())
+ End Sub
+
+ Private Function Foo() As String
+ Throw New NotImplementedException()
+ End Function
+End Class
+")
+ End Function
+
Public Async Function MethodWithTupleWithNames() As Task
Await TestInRegularAndScriptAsync(
diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.vb
index 582664dc59c2f..15fce1a1aa589 100644
--- a/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.vb
+++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnusedVariable/RemoveUnusedVariableTest.vb
@@ -9,8 +9,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Remove
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As (DiagnosticAnalyzer, CodeFixProvider)
- Return (Nothing,
- New RemoveUnusedVariableCodeFixProvider())
+ Return (Nothing, New VisualBasicRemoveUnusedVariableCodeFixProvider())
End Function
diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs
index c933b603d5757..dd41414e39b75 100644
--- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs
+++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs
@@ -1452,6 +1452,28 @@ .locals init (C.<>c__DisplayClass1_0 V_0, //CS$<>8__locals0
});
}
+ [Fact(Skip = "18273"), WorkItem(18273, "https://github.com/dotnet/roslyn/issues/18273")]
+ public void CapturedLocalInNestedLambda()
+ {
+ var source = @"
+using System;
+
+class C
+{
+ void M() { }
+}";
+ var compilation0 = CreateStandardCompilation(source, options: TestOptions.DebugDll);
+ WithRuntimeInstance(compilation0, runtime =>
+ {
+ var context = CreateMethodContext(runtime, "C.M");
+
+ var testData = new CompilationTestData();
+ context.CompileExpression("new Action(() => { int x; new Func(() => x).Invoke(); }).Invoke()", out var error, testData);
+ Assert.Null(error);
+ testData.GetMethodData("<>x.<>m0").VerifyIL("");
+ });
+ }
+
[Fact]
public void NestedLambdas()
{
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/BasicExpressionCompiler.vbproj b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/BasicExpressionCompiler.vbproj
index 2c1e27c49f631..4b839e0102d4c 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/BasicExpressionCompiler.vbproj
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/BasicExpressionCompiler.vbproj
@@ -9,6 +9,7 @@
Library
Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.ExpressionCompiler
netstandard1.3
+ $(NoWarn);40057
portable-net46
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/NetFX20/BasicResultProvider.NetFX20.vbproj b/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/NetFX20/BasicResultProvider.NetFX20.vbproj
index 973c1b53661b3..0b1a76f72bf1c 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/NetFX20/BasicResultProvider.NetFX20.vbproj
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/NetFX20/BasicResultProvider.NetFX20.vbproj
@@ -12,6 +12,7 @@
Library
Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.ResultProvider
net20
+ $(NoWarn);40057
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Portable/BasicResultProvider.Portable.vbproj b/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Portable/BasicResultProvider.Portable.vbproj
index 7344f2e4c6ae3..927ec6ffb56a3 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Portable/BasicResultProvider.Portable.vbproj
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Portable/BasicResultProvider.Portable.vbproj
@@ -11,6 +11,7 @@
netstandard1.3
portable-net45+win8
false
+ $(NoWarn);40057
diff --git a/src/Features/CSharp/Portable/CSharpFeatures.csproj b/src/Features/CSharp/Portable/CSharpFeatures.csproj
index a15b756b7d3c3..1dfc62d0c6efa 100644
--- a/src/Features/CSharp/Portable/CSharpFeatures.csproj
+++ b/src/Features/CSharp/Portable/CSharpFeatures.csproj
@@ -62,7 +62,7 @@
-
+
diff --git a/src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/RemoveUnusedVariableCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs
similarity index 74%
rename from src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/RemoveUnusedVariableCodeFixProvider.cs
rename to src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs
index 9dddc12e4263b..6e20eff76d446 100644
--- a/src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/RemoveUnusedVariableCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/CodeFixes/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs
@@ -9,7 +9,8 @@
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveUnusedVariable
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnusedVariable), Shared]
- internal partial class RemoveUnusedVariableCodeFixProvider : AbstractRemoveUnusedVariableCodeFixProvider
+ [ExtensionOrder(After = PredefinedCodeFixProviderNames.AddImport)]
+ internal partial class CSharpRemoveUnusedVariableCodeFixProvider : AbstractRemoveUnusedVariableCodeFixProvider
{
private const string CS0168 = nameof(CS0168);
private const string CS0219 = nameof(CS0219);
diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs
index cb53f35a8b39a..f7a154963db18 100644
--- a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs
+++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs
@@ -91,7 +91,9 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
if (type.TypeKind != TypeKind.Enum)
{
- type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation);
+ type = TryGetEnumTypeInEnumInitializer(semanticModel, token, type, cancellationToken) ??
+ TryGetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation);
+
if (type == null)
{
return;
@@ -104,7 +106,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
}
// Does type have any aliases?
- ISymbol alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false);
+ var alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false);
var displayService = document.GetLanguageService();
var displayText = alias != null
@@ -128,6 +130,47 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
}
}
+ private ITypeSymbol TryGetEnumTypeInEnumInitializer(
+ SemanticModel semanticModel, SyntaxToken token,
+ ITypeSymbol type, CancellationToken cancellationToken)
+ {
+ // https://github.com/dotnet/roslyn/issues/5419
+ //
+ // 14.3: "Within an enum member initializer, values of other enum members are always
+ // treated as having the type of their underlying type"
+
+ // i.e. if we have "enum E { X, Y, Z = X |
+ // then we want to offer the enum after the |. However, the compiler will report this
+ // as an 'int' type, not the enum type.
+
+ // See if we're after a common enum-combining operator.
+ if (token.Kind() == SyntaxKind.BarToken ||
+ token.Kind() == SyntaxKind.AmpersandToken ||
+ token.Kind() == SyntaxKind.CaretToken)
+ {
+ // See if the type we're looking at is the underlying type for the enum we're contained in.
+ var containingType = semanticModel.GetEnclosingNamedType(token.SpanStart, cancellationToken);
+ if (containingType?.TypeKind == TypeKind.Enum &&
+ type.Equals(containingType.EnumUnderlyingType))
+ {
+ // If so, walk back to the token before the operator token and see if it binds to a member
+ // of this enum.
+ var previousToken = token.GetPreviousToken();
+ var symbol = semanticModel.GetSymbolInfo(previousToken.Parent, cancellationToken).Symbol;
+
+ if (symbol?.Kind == SymbolKind.Field &&
+ containingType.Equals(symbol.ContainingType))
+ {
+ // If so, then offer this as a place for enum completion for the enum we're currently
+ // inside of.
+ return containingType;
+ }
+ }
+ }
+
+ return null;
+ }
+
protected override Task GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
=> SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken);
@@ -136,7 +179,7 @@ protected override Task GetDescriptionWorkerAsync(Documen
.WithMatchPriority(MatchPriority.Preselect)
.WithSelectionBehavior(CompletionItemSelectionBehavior.HardSelection);
- private INamedTypeSymbol GetCompletionListType(ITypeSymbol type, INamedTypeSymbol within, Compilation compilation)
+ private INamedTypeSymbol TryGetCompletionListType(ITypeSymbol type, INamedTypeSymbol within, Compilation compilation)
{
// PERF: None of the SpecialTypes include tags,
// so we don't even need to load the documentation.
diff --git a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
index a49f7d2650dd7..a60a91374a1ba 100644
--- a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
+++ b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
@@ -1,6 +1,5 @@
// 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.Immutable;
using System.Composition;
@@ -306,7 +305,8 @@ protected override SyntaxNode FindStatementAndPartner(SyntaxNode declarationBody
break;
case SyntaxKind.ForEachStatement:
- statementPart = (int)GetStatementPart((ForEachStatementSyntax)node, position);
+ case SyntaxKind.ForEachVariableStatement:
+ statementPart = (int)GetStatementPart((CommonForEachStatementSyntax)node, position);
break;
case SyntaxKind.VariableDeclaration:
@@ -352,7 +352,7 @@ private static TextSpan GetActiveSpan(BlockSyntax node, BlockPart part)
}
}
- private static ForEachPart GetStatementPart(ForEachStatementSyntax node, int position)
+ private static ForEachPart GetStatementPart(CommonForEachStatementSyntax node, int position)
{
return position < node.OpenParenToken.SpanStart ? ForEachPart.ForEach :
position < node.InKeyword.SpanStart ? ForEachPart.VariableDeclaration :
@@ -381,6 +381,27 @@ private static TextSpan GetActiveSpan(ForEachStatementSyntax node, ForEachPart p
}
}
+ private static TextSpan GetActiveSpan(ForEachVariableStatementSyntax node, ForEachPart part)
+ {
+ switch (part)
+ {
+ case ForEachPart.ForEach:
+ return node.ForEachKeyword.Span;
+
+ case ForEachPart.VariableDeclaration:
+ return TextSpan.FromBounds(node.Variable.SpanStart, node.Variable.Span.End);
+
+ case ForEachPart.In:
+ return node.InKeyword.Span;
+
+ case ForEachPart.Expression:
+ return node.Expression.Span;
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(part);
+ }
+ }
+
protected override bool AreEquivalent(SyntaxNode left, SyntaxNode right)
{
return SyntaxFactory.AreEquivalent(left, right);
@@ -601,6 +622,10 @@ protected override bool TryGetActiveSpan(SyntaxNode node, int statementPart, out
span = GetActiveSpan((ForEachStatementSyntax)node, (ForEachPart)statementPart);
return true;
+ case SyntaxKind.ForEachVariableStatement:
+ span = GetActiveSpan((ForEachVariableStatementSyntax)node, (ForEachPart)statementPart);
+ return true;
+
case SyntaxKind.DoStatement:
// The active statement of DoStatement node is the while condition,
// which is lexically not the closest breakpoint span (the body is).
@@ -732,10 +757,11 @@ protected override bool AreEquivalentActiveStatements(SyntaxNode oldStatement, S
return true;
case SyntaxKind.ForEachStatement:
+ case SyntaxKind.ForEachVariableStatement:
Debug.Assert(statementPart != 0);
// only check the expression, edits in the body and the variable declaration are allowed:
- return AreEquivalentActiveStatements((ForEachStatementSyntax)oldStatement, (ForEachStatementSyntax)newStatement);
+ return AreEquivalentActiveStatements((CommonForEachStatementSyntax)oldStatement, (CommonForEachStatementSyntax)newStatement);
case SyntaxKind.IfStatement:
// only check the condition, edits in the body are allowed:
@@ -807,11 +833,30 @@ private static bool AreEquivalentActiveStatements(UsingStatementSyntax oldNode,
(SyntaxNode)newNode.Declaration ?? newNode.Expression);
}
- private static bool AreEquivalentActiveStatements(ForEachStatementSyntax oldNode, ForEachStatementSyntax newNode)
+ private static bool AreEquivalentActiveStatements(CommonForEachStatementSyntax oldNode, CommonForEachStatementSyntax newNode)
{
- // This is conservative, we might be able to allow changing the type.
- return AreEquivalentIgnoringLambdaBodies(oldNode.Type, newNode.Type)
- && AreEquivalentIgnoringLambdaBodies(oldNode.Expression, newNode.Expression);
+ if (oldNode.Kind() != newNode.Kind() || !AreEquivalentIgnoringLambdaBodies(oldNode.Expression, newNode.Expression))
+ {
+ return false;
+ }
+
+ switch (oldNode.Kind())
+ {
+ case SyntaxKind.ForEachStatement: return AreEquivalentIgnoringLambdaBodies(((ForEachStatementSyntax)oldNode).Type, ((ForEachStatementSyntax)newNode).Type);
+ case SyntaxKind.ForEachVariableStatement: return AreEquivalentIgnoringLambdaBodies(((ForEachVariableStatementSyntax)oldNode).Variable, ((ForEachVariableStatementSyntax)newNode).Variable);
+ default: throw ExceptionUtilities.UnexpectedValue(oldNode.Kind());
+ }
+ }
+
+ private static bool AreSimilarActiveStatements(CommonForEachStatementSyntax oldNode, CommonForEachStatementSyntax newNode)
+ {
+ List oldTokens = null;
+ List newTokens = null;
+
+ StatementSyntaxComparer.GetLocalNames(oldNode, ref oldTokens);
+ StatementSyntaxComparer.GetLocalNames(newNode, ref newTokens);
+
+ return DeclareSameIdentifiers(oldTokens.ToArray(), newTokens.ToArray());
}
internal override bool IsMethod(SyntaxNode declaration)
@@ -1259,8 +1304,9 @@ internal static TextSpan GetDiagnosticSpanImpl(SyntaxKind kind, SyntaxNode node,
return TextSpan.FromBounds(forStatement.ForKeyword.SpanStart, forStatement.CloseParenToken.Span.End);
case SyntaxKind.ForEachStatement:
- var forEachStatement = (ForEachStatementSyntax)node;
- return TextSpan.FromBounds(forEachStatement.ForEachKeyword.SpanStart, forEachStatement.CloseParenToken.Span.End);
+ case SyntaxKind.ForEachVariableStatement:
+ var commonForEachStatement = (CommonForEachStatementSyntax)node;
+ return TextSpan.FromBounds(commonForEachStatement.ForEachKeyword.SpanStart, commonForEachStatement.CloseParenToken.Span.End);
case SyntaxKind.LabeledStatement:
return ((LabeledStatementSyntax)node).Identifier.Span;
@@ -1342,9 +1388,6 @@ internal static TextSpan GetDiagnosticSpanImpl(SyntaxKind kind, SyntaxNode node,
case SyntaxKind.GroupClause:
return ((GroupClauseSyntax)node).GroupKeyword.Span;
- case SyntaxKind.ForEachVariableStatement:
- return ((ForEachVariableStatementSyntax)node).Variable.Span;
-
case SyntaxKind.IsPatternExpression:
case SyntaxKind.TupleType:
case SyntaxKind.TupleExpression:
@@ -1549,6 +1592,7 @@ internal static string GetStatementDisplayNameImpl(SyntaxNode node)
return CSharpFeaturesResources.lock_statement;
case SyntaxKind.ForEachStatement:
+ case SyntaxKind.ForEachVariableStatement:
return CSharpFeaturesResources.foreach_statement;
case SyntaxKind.CheckedStatement:
@@ -1604,9 +1648,6 @@ internal static string GetStatementDisplayNameImpl(SyntaxNode node)
case SyntaxKind.IsPatternExpression:
return CSharpFeaturesResources.is_pattern;
- case SyntaxKind.ForEachVariableStatement:
- return CSharpFeaturesResources.deconstruction;
-
case SyntaxKind.SimpleAssignmentExpression:
if (((AssignmentExpressionSyntax)node).IsDeconstruction())
{
@@ -3108,7 +3149,6 @@ private static bool IsUnsupportedCSharp7EnCNode(SyntaxNode n)
{
switch (n.Kind())
{
- case SyntaxKind.ForEachVariableStatement:
case SyntaxKind.LocalFunctionStatement:
return true;
default:
@@ -3187,15 +3227,15 @@ private void ReportRudeEditsForAncestorsDeclaringInterStatementTemps(
//
// Unlike exception regions matching where we use LCS, we allow reordering of the statements.
- ReportUnmatchedStatements(diagnostics, match, (int)SyntaxKind.LockStatement, oldActiveStatement, newActiveStatement,
+ ReportUnmatchedStatements(diagnostics, match, new[] { (int)SyntaxKind.LockStatement }, oldActiveStatement, newActiveStatement,
areEquivalent: AreEquivalentActiveStatements,
areSimilar: null);
- ReportUnmatchedStatements(diagnostics, match, (int)SyntaxKind.FixedStatement, oldActiveStatement, newActiveStatement,
+ ReportUnmatchedStatements(diagnostics, match, new[] { (int)SyntaxKind.FixedStatement }, oldActiveStatement, newActiveStatement,
areEquivalent: AreEquivalentActiveStatements,
areSimilar: (n1, n2) => DeclareSameIdentifiers(n1.Declaration.Variables, n2.Declaration.Variables));
- ReportUnmatchedStatements(diagnostics, match, (int)SyntaxKind.UsingStatement, oldActiveStatement, newActiveStatement,
+ ReportUnmatchedStatements(diagnostics, match, new[] { (int)SyntaxKind.UsingStatement }, oldActiveStatement, newActiveStatement,
areEquivalent: AreEquivalentActiveStatements,
areSimilar: (using1, using2) =>
{
@@ -3203,21 +3243,26 @@ private void ReportRudeEditsForAncestorsDeclaringInterStatementTemps(
DeclareSameIdentifiers(using1.Declaration.Variables, using2.Declaration.Variables);
});
- ReportUnmatchedStatements(diagnostics, match, (int)SyntaxKind.ForEachStatement, oldActiveStatement, newActiveStatement,
+ ReportUnmatchedStatements(diagnostics, match, new[] { (int)SyntaxKind.ForEachStatement, (int)SyntaxKind.ForEachVariableStatement }, oldActiveStatement, newActiveStatement,
areEquivalent: AreEquivalentActiveStatements,
- areSimilar: (n1, n2) => SyntaxFactory.AreEquivalent(n1.Identifier, n2.Identifier));
+ areSimilar: AreSimilarActiveStatements);
}
private static bool DeclareSameIdentifiers(SeparatedSyntaxList oldVariables, SeparatedSyntaxList newVariables)
{
- if (oldVariables.Count != newVariables.Count)
+ return DeclareSameIdentifiers(oldVariables.Select(v => v.Identifier).ToArray(), newVariables.Select(v => v.Identifier).ToArray());
+ }
+
+ private static bool DeclareSameIdentifiers(SyntaxToken[] oldVariables, SyntaxToken[] newVariables)
+ {
+ if (oldVariables.Length != newVariables.Length)
{
return false;
}
- for (int i = 0; i < oldVariables.Count; i++)
+ for (int i = 0; i < oldVariables.Length; i++)
{
- if (!SyntaxFactory.AreEquivalent(oldVariables[i].Identifier, newVariables[i].Identifier))
+ if (!SyntaxFactory.AreEquivalent(oldVariables[i], newVariables[i]))
{
return false;
}
diff --git a/src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs b/src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
index f4700d61ebfd5..cb58a82f1cf29 100644
--- a/src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
+++ b/src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
@@ -1006,7 +1006,7 @@ private static void GetLocalNames(VariableDeclarationSyntax localDeclaration, re
}
}
- private static void GetLocalNames(CommonForEachStatementSyntax commonForEach, ref List result)
+ internal static void GetLocalNames(CommonForEachStatementSyntax commonForEach, ref List result)
{
switch (commonForEach.Kind())
{
diff --git a/src/Features/CSharp/Portable/GenerateConstructor/CSharpGenerateConstructorService.cs b/src/Features/CSharp/Portable/GenerateConstructor/CSharpGenerateConstructorService.cs
index 547d78a7a7b9c..93679a43412f1 100644
--- a/src/Features/CSharp/Portable/GenerateConstructor/CSharpGenerateConstructorService.cs
+++ b/src/Features/CSharp/Portable/GenerateConstructor/CSharpGenerateConstructorService.cs
@@ -166,24 +166,18 @@ protected override bool TryInitializeSimpleAttributeNameGenerationState(
}
protected override ImmutableArray GenerateParameterNames(
- SemanticModel semanticModel, IEnumerable arguments, IList reservedNames)
- => semanticModel.GenerateParameterNames(arguments, reservedNames);
+ SemanticModel semanticModel, IEnumerable arguments, IList reservedNames, CancellationToken cancellationToken)
+ => semanticModel.GenerateParameterNames(arguments, reservedNames, cancellationToken);
protected override ImmutableArray GenerateParameterNames(
- SemanticModel semanticModel, IEnumerable arguments, IList reservedNames)
- => semanticModel.GenerateParameterNames(arguments, reservedNames).ToImmutableArray();
+ SemanticModel semanticModel, IEnumerable arguments, IList reservedNames, CancellationToken cancellationToken)
+ => semanticModel.GenerateParameterNames(arguments, reservedNames, cancellationToken).ToImmutableArray();
- protected override string GenerateNameForArgument(
- SemanticModel semanticModel, ArgumentSyntax argument)
- {
- return semanticModel.GenerateNameForArgument(argument);
- }
+ protected override string GenerateNameForArgument(SemanticModel semanticModel, ArgumentSyntax argument, CancellationToken cancellationToken)
+ => semanticModel.GenerateNameForArgument(argument, cancellationToken);
- protected override string GenerateNameForArgument(
- SemanticModel semanticModel, AttributeArgumentSyntax argument)
- {
- return semanticModel.GenerateNameForArgument(argument);
- }
+ protected override string GenerateNameForArgument(SemanticModel semanticModel, AttributeArgumentSyntax argument, CancellationToken cancellationToken)
+ => semanticModel.GenerateNameForArgument(argument, cancellationToken);
protected override RefKind GetRefKind(ArgumentSyntax argument)
{
diff --git a/src/Features/CSharp/Portable/GenerateMember/GenerateParameterizedMember/CSharpGenerateParameterizedMemberService.cs b/src/Features/CSharp/Portable/GenerateMember/GenerateParameterizedMember/CSharpGenerateParameterizedMemberService.cs
index 3d7d1a4c984f0..16fb81c27c9ac 100644
--- a/src/Features/CSharp/Portable/GenerateMember/GenerateParameterizedMember/CSharpGenerateParameterizedMemberService.cs
+++ b/src/Features/CSharp/Portable/GenerateMember/GenerateParameterizedMember/CSharpGenerateParameterizedMemberService.cs
@@ -34,7 +34,7 @@ public InvocationExpressionInfo(SemanticDocument document, State state)
protected override ImmutableArray DetermineParameterNames(CancellationToken cancellationToken)
{
return this.Document.SemanticModel.GenerateParameterNames(
- _invocationExpression.ArgumentList);
+ _invocationExpression.ArgumentList, cancellationToken);
}
protected override bool DetermineReturnsByRef(CancellationToken cancellationToken)
diff --git a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs
index 8038b7882b1f9..76869a833a8f7 100644
--- a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs
+++ b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs
@@ -526,9 +526,9 @@ protected override bool TryGetArgumentList(ObjectCreationExpressionSyntax object
}
protected override IList GenerateParameterNames(
- SemanticModel semanticModel, IList arguments)
+ SemanticModel semanticModel, IList arguments, CancellationToken cancellationToken)
{
- return semanticModel.GenerateParameterNames(arguments);
+ return semanticModel.GenerateParameterNames(arguments, reservedNames: null, cancellationToken: cancellationToken);
}
public override string GetRootNamespace(CompilationOptions options)
diff --git a/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
index 55e0d1e65dac5..b495f04a52263 100644
--- a/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
+++ b/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
@@ -1,12 +1,10 @@
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.InitializeParameter;
-using Microsoft.CodeAnalysis.Semantics;
namespace Microsoft.CodeAnalysis.CSharp.InitializeParameter
{
diff --git a/src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs b/src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
index 7676ce0266c8f..a8c795ba0dc4e 100644
--- a/src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
@@ -33,10 +33,8 @@ protected override string GetMakeAsyncVoidFunctionResource()
return CSharpFeaturesResources.Make_method_async_remain_void;
}
- protected override bool IsMethodOrAnonymousFunction(SyntaxNode node)
- {
- return node.IsKind(SyntaxKind.MethodDeclaration) || node.IsAnyLambdaOrAnonymousMethod();
- }
+ protected override bool IsAsyncSupportingFunctionSyntax(SyntaxNode node)
+ => node.IsAsyncSupportingFunctionSyntax();
protected override SyntaxNode AddAsyncTokenAndFixReturnType(
bool keepVoid, IMethodSymbol methodSymbolOpt, SyntaxNode node,
@@ -45,6 +43,7 @@ protected override SyntaxNode AddAsyncTokenAndFixReturnType(
switch (node)
{
case MethodDeclarationSyntax method: return FixMethod(keepVoid, methodSymbolOpt, method, taskType, taskOfTType, valueTaskOfTType);
+ case LocalFunctionStatementSyntax localFunction: return FixLocalFunction(keepVoid, methodSymbolOpt, localFunction, taskType, taskOfTType, valueTaskOfTType);
case AnonymousMethodExpressionSyntax method: return FixAnonymousMethod(method);
case ParenthesizedLambdaExpressionSyntax lambda: return FixParenthesizedLambda(lambda);
case SimpleLambdaExpressionSyntax lambda: return FixSimpleLambda(lambda);
@@ -56,7 +55,25 @@ private SyntaxNode FixMethod(
bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method,
INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType)
{
- var newReturnType = method.ReturnType;
+ var newReturnType = FixMethodReturnType(keepVoid, methodSymbol, method.ReturnType, taskType, taskOfTType, valueTaskOfTType);
+ var newModifiers = AddAsyncModifierWithCorrectedTrivia(method.Modifiers, ref newReturnType);
+ return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ }
+
+ private SyntaxNode FixLocalFunction(
+ bool keepVoid, IMethodSymbol methodSymbol, LocalFunctionStatementSyntax localFunction,
+ INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType)
+ {
+ var newReturnType = FixMethodReturnType(keepVoid, methodSymbol, localFunction.ReturnType, taskType, taskOfTType, valueTaskOfTType);
+ var newModifiers = AddAsyncModifierWithCorrectedTrivia(localFunction.Modifiers, ref newReturnType);
+ return localFunction.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ }
+
+ private static TypeSyntax FixMethodReturnType(
+ bool keepVoid, IMethodSymbol methodSymbol, TypeSyntax returnType,
+ INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType)
+ {
+ var newReturnType = returnType;
if (methodSymbol.ReturnsVoid)
{
@@ -75,8 +92,18 @@ private SyntaxNode FixMethod(
}
}
- var newModifiers = method.Modifiers.Add(s_asyncToken);
- return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ return newReturnType.WithTriviaFrom(returnType);
+ }
+
+ private static SyntaxTokenList AddAsyncModifierWithCorrectedTrivia(SyntaxTokenList modifiers, ref TypeSyntax newReturnType)
+ {
+ if (modifiers.Any())
+ return modifiers.Add(s_asyncToken);
+
+ // Move the leading trivia from the return type to the new modifiers list.
+ SyntaxTokenList result = SyntaxFactory.TokenList(s_asyncToken.WithLeadingTrivia(newReturnType.GetLeadingTrivia()));
+ newReturnType = newReturnType.WithoutLeadingTrivia();
+ return result;
}
private SyntaxNode FixParenthesizedLambda(ParenthesizedLambdaExpressionSyntax lambda)
diff --git a/src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs b/src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
index 96d8e9a609312..afed98fce2574 100644
--- a/src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
@@ -17,16 +17,15 @@ internal class CSharpMakeMethodSynchronousCodeFixProvider : AbstractMakeMethodSy
public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(CS1998);
- protected override bool IsMethodOrAnonymousFunction(SyntaxNode node)
- {
- return node.IsKind(SyntaxKind.MethodDeclaration) || node.IsAnyLambdaOrAnonymousMethod();
- }
+ protected override bool IsAsyncSupportingFunctionSyntax(SyntaxNode node)
+ => node.IsAsyncSupportingFunctionSyntax();
protected override SyntaxNode RemoveAsyncTokenAndFixReturnType(IMethodSymbol methodSymbolOpt, SyntaxNode node, ITypeSymbol taskType, ITypeSymbol taskOfTType)
{
switch (node)
{
case MethodDeclarationSyntax method: return FixMethod(methodSymbolOpt, method, taskType, taskOfTType);
+ case LocalFunctionStatementSyntax localFunction: return FixLocalFunction(methodSymbolOpt, localFunction, taskType, taskOfTType);
case AnonymousMethodExpressionSyntax method: return FixAnonymousMethod(method);
case ParenthesizedLambdaExpressionSyntax lambda: return FixParenthesizedLambda(lambda);
case SimpleLambdaExpressionSyntax lambda: return FixSimpleLambda(lambda);
@@ -36,47 +35,66 @@ protected override SyntaxNode RemoveAsyncTokenAndFixReturnType(IMethodSymbol met
private SyntaxNode FixMethod(IMethodSymbol methodSymbol, MethodDeclarationSyntax method, ITypeSymbol taskType, ITypeSymbol taskOfTType)
{
- var newReturnType = method.ReturnType;
+ var newReturnType = FixMethodReturnType(methodSymbol, method.ReturnType, taskType, taskOfTType);
+ var newModifiers = FixMethodModifiers(method.Modifiers, ref newReturnType);
+ return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ }
+
+ private SyntaxNode FixLocalFunction(IMethodSymbol methodSymbol, LocalFunctionStatementSyntax localFunction, ITypeSymbol taskType, ITypeSymbol taskOfTType)
+ {
+ var newReturnType = FixMethodReturnType(methodSymbol, localFunction.ReturnType, taskType, taskOfTType);
+ var newModifiers = FixMethodModifiers(localFunction.Modifiers, ref newReturnType);
+ return localFunction.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ }
+
+ private static TypeSyntax FixMethodReturnType(IMethodSymbol methodSymbol, TypeSyntax returnType, ITypeSymbol taskType, ITypeSymbol taskOfTType)
+ {
+ var newReturnType = returnType;
// If the return type is Task, then make the new return type "T".
// If it is Task, then make the new return type "void".
if (methodSymbol.ReturnType.OriginalDefinition.Equals(taskType))
{
- newReturnType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)).WithTriviaFrom(method.ReturnType);
+ newReturnType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)).WithTriviaFrom(returnType);
}
else if (methodSymbol.ReturnType.OriginalDefinition.Equals(taskOfTType))
{
- newReturnType = methodSymbol.ReturnType.GetTypeArguments()[0].GenerateTypeSyntax().WithTriviaFrom(method.ReturnType);
+ newReturnType = methodSymbol.ReturnType.GetTypeArguments()[0].GenerateTypeSyntax().WithTriviaFrom(returnType);
}
- var asyncTokenIndex = method.Modifiers.IndexOf(SyntaxKind.AsyncKeyword);
+ return newReturnType;
+ }
+
+ private static SyntaxTokenList FixMethodModifiers(SyntaxTokenList modifiers, ref TypeSyntax newReturnType)
+ {
+ var asyncTokenIndex = modifiers.IndexOf(SyntaxKind.AsyncKeyword);
SyntaxTokenList newModifiers;
if (asyncTokenIndex == 0)
{
- // Have to move the trivia on teh async token appropriately.
- var asyncLeadingTrivia = method.Modifiers[0].LeadingTrivia;
+ // Have to move the trivia on the async token appropriately.
+ var asyncLeadingTrivia = modifiers[0].LeadingTrivia;
- if (method.Modifiers.Count > 1)
+ if (modifiers.Count > 1)
{
// Move the trivia to the next modifier;
- newModifiers = method.Modifiers.Replace(
- method.Modifiers[1],
- method.Modifiers[1].WithPrependedLeadingTrivia(asyncLeadingTrivia));
+ newModifiers = modifiers.Replace(
+ modifiers[1],
+ modifiers[1].WithPrependedLeadingTrivia(asyncLeadingTrivia));
newModifiers = newModifiers.RemoveAt(0);
}
else
{
// move it to the return type.
- newModifiers = method.Modifiers.RemoveAt(0);
+ newModifiers = modifiers.RemoveAt(0);
newReturnType = newReturnType.WithPrependedLeadingTrivia(asyncLeadingTrivia);
}
}
else
{
- newModifiers = method.Modifiers.RemoveAt(asyncTokenIndex);
+ newModifiers = modifiers.RemoveAt(asyncTokenIndex);
}
- return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
+ return newModifiers;
}
private SyntaxNode FixParenthesizedLambda(ParenthesizedLambdaExpressionSyntax lambda)
diff --git a/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
index 627811613da25..bed9a14231d66 100644
--- a/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
@@ -25,9 +25,10 @@ internal class CSharpUpgradeProjectCodeFixProvider : AbstractUpgradeProjectCodeF
private const string CS8107 = nameof(CS8107); // error CS8059: Feature is not available in C# 7.0. Please use language version X or greater.
private const string CS8302 = nameof(CS8302); // error CS8302: Feature is not available in C# 7.1. Please use language version X or greater.
private const string CS8306 = nameof(CS8306); // error CS8306: ... Please use language version 7.1 or greater to access a un-named element by its inferred name.
+ private const string CS9003 = nameof(CS9003); // error CS9003: An expression of type '{0}' cannot be handled by a pattern of type '{1}' in C# {2}. Please use language version {3} or greater.
public override ImmutableArray FixableDiagnosticIds { get; } =
- ImmutableArray.Create(CS8022, CS8023, CS8024, CS8025, CS8026, CS8059, CS8107, CS8302, CS8306);
+ ImmutableArray.Create(CS8022, CS8023, CS8024, CS8025, CS8026, CS8059, CS8107, CS8302, CS8306, CS9003);
public override string UpgradeThisProjectResource => CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0;
public override string UpgradeAllProjectsResource => CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0;
diff --git a/src/Features/Core/Portable/AddImport/CodeActions/PackageReference.ParentCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/PackageReference.ParentCodeAction.cs
index 87560df22c47d..f7265a2c46e4b 100644
--- a/src/Features/Core/Portable/AddImport/CodeActions/PackageReference.ParentCodeAction.cs
+++ b/src/Features/Core/Portable/AddImport/CodeActions/PackageReference.ParentCodeAction.cs
@@ -107,7 +107,8 @@ private static async Task GetInstallDataAsync(
CancellationToken cancellationToken)
{
var oldDocument = document;
- reference.ReplaceNameNode(ref node, ref document, cancellationToken);
+ (node, document) = await reference.ReplaceNameNodeAsync(
+ node, document, cancellationToken).ConfigureAwait(false);
var newDocument = await reference.provider.AddImportAsync(
node, reference.SearchResult.NameParts, document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
diff --git a/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs b/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs
index 07f8df2926288..ba59aac0fadb1 100644
--- a/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs
+++ b/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs
@@ -105,9 +105,8 @@ protected override async Task> ComputeOperation
var reference = service.GetReference(resolvedPath, MetadataReferenceProperties.Assembly);
// First add the "using/import" directive in the code.
- var node = _node;
- var document = _document;
- _reference.ReplaceNameNode(ref node, ref document, cancellationToken);
+ (SyntaxNode node, Document document) = await _reference.ReplaceNameNodeAsync(
+ _node, _document, cancellationToken).ConfigureAwait(false);
var newDocument = await _reference.provider.AddImportAsync(
node, _reference.SearchResult.NameParts, document, _placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
diff --git a/src/Features/Core/Portable/AddImport/References/Reference.cs b/src/Features/Core/Portable/AddImport/References/Reference.cs
index a36eb4646d36c..51f51030b7c03 100644
--- a/src/Features/Core/Portable/AddImport/References/Reference.cs
+++ b/src/Features/Core/Portable/AddImport/References/Reference.cs
@@ -92,12 +92,12 @@ public override int GetHashCode()
return Hash.CombineValues(this.SearchResult.NameParts);
}
- protected void ReplaceNameNode(
- ref SyntaxNode contextNode, ref Document document, CancellationToken cancellationToken)
+ protected async Task<(SyntaxNode, Document)> ReplaceNameNodeAsync(
+ SyntaxNode contextNode, Document document, CancellationToken cancellationToken)
{
if (!this.SearchResult.DesiredNameDiffersFromSourceName())
{
- return;
+ return (contextNode, document);
}
var identifier = SearchResult.NameNode.GetFirstToken();
@@ -107,11 +107,15 @@ protected void ReplaceNameNode(
var root = contextNode.SyntaxTree.GetRoot(cancellationToken);
root = root.ReplaceToken(identifier, newIdentifier.WithAdditionalAnnotations(annotation));
- document = document.WithSyntaxRoot(root);
- contextNode = root.GetAnnotatedTokens(annotation).First().Parent;
+
+ var newDocument = document.WithSyntaxRoot(root);
+ var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var newContextNode = newRoot.GetAnnotatedTokens(annotation).First().Parent;
+
+ return (newContextNode, newDocument);
}
public abstract Task CreateCodeActionAsync(Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/AddImport/References/SymbolReference.cs b/src/Features/Core/Portable/AddImport/References/SymbolReference.cs
index 4ad54cbb54f05..9b27495bbc966 100644
--- a/src/Features/Core/Portable/AddImport/References/SymbolReference.cs
+++ b/src/Features/Core/Portable/AddImport/References/SymbolReference.cs
@@ -2,9 +2,11 @@
using System;
using System.Collections.Immutable;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.FindSymbols;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
@@ -61,22 +63,23 @@ private async Task GetOperationAsync(
protected virtual Solution GetUpdatedSolution(Document newDocument)
=> newDocument.Project.Solution;
- private Task UpdateDocumentAsync(
+ private async Task UpdateDocumentAsync(
Document document, SyntaxNode contextNode,
bool placeSystemNamespaceFirst, bool hasExistingImport,
CancellationToken cancellationToken)
{
- ReplaceNameNode(ref contextNode, ref document, cancellationToken);
-
// Defer to the language to add the actual import/using.
if (hasExistingImport)
{
- return Task.FromResult(document);
+ return document;
}
- return provider.AddImportAsync(contextNode,
- this.SymbolResult.Symbol, document,
- placeSystemNamespaceFirst, cancellationToken);
+ (var newContextNode, var newDocument) = await ReplaceNameNodeAsync(
+ contextNode, document, cancellationToken).ConfigureAwait(false);
+
+ return await provider.AddImportAsync(
+ newContextNode, this.SymbolResult.Symbol, newDocument,
+ placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
}
public override async Task CreateCodeActionAsync(
diff --git a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs
index 9945ac8a2dfdc..c3bce9a2bfa1d 100644
--- a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs
+++ b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs
@@ -84,7 +84,7 @@ await FindReferenceAssemblyTypeReferencesAsync(
if (symbolSearchService != null &&
installerService != null &&
searchNugetPackages &&
- installerService.IsEnabled)
+ installerService.IsEnabled(_document.Project.Id))
{
foreach (var packageSource in installerService.PackageSources)
{
diff --git a/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs b/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs
index 26178cc3e638a..7d5f063e534cd 100644
--- a/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs
+++ b/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs
@@ -51,7 +51,7 @@ protected async Task> GetAddPackagesCodeActionsAsync(
if (symbolSearchService != null &&
installerService != null &&
searchNugetPackages &&
- installerService.IsEnabled)
+ installerService.IsEnabled(document.Project.Id))
{
foreach (var packageSource in installerService.PackageSources)
{
diff --git a/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs b/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs
index 181e77085f8f8..cec5a750f6aed 100644
--- a/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs
+++ b/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs
@@ -185,7 +185,8 @@ private async Task FixAsync(
var newMethodDeclaration = GetNewMethodDeclaration(
method, argument, argumentList, generator, methodDeclaration,
- semanticFacts, argumentName, expression, semanticModel, parameterType);
+ semanticFacts, argumentName, expression, semanticModel,
+ parameterType, cancellationToken);
var root = methodDeclaration.SyntaxTree.GetRoot(cancellationToken);
var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);
@@ -206,7 +207,8 @@ private static SyntaxNode GetNewMethodDeclaration(
string argumentName,
SyntaxNode expression,
SemanticModel semanticModel,
- ITypeSymbol parameterType)
+ ITypeSymbol parameterType,
+ CancellationToken cancellationToken)
{
if (!string.IsNullOrWhiteSpace(argumentName))
{
@@ -222,7 +224,8 @@ private static SyntaxNode GetNewMethodDeclaration(
}
else
{
- var name = semanticFacts.GenerateNameForExpression(semanticModel, expression);
+ var name = semanticFacts.GenerateNameForExpression(
+ semanticModel, expression, capitalize: false, cancellationToken: cancellationToken);
var uniqueName = NameGenerator.EnsureUniqueness(name, method.Parameters.Select(p => p.Name));
var newParameterSymbol = CodeGenerationSymbolFactory.CreateParameterSymbol(
diff --git a/src/Features/Core/Portable/CodeFixes/NamingStyle/AbstractNamingStyleCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/NamingStyle/AbstractNamingStyleCodeFixProvider.cs
index b5b902eeb1e5e..e0212f23dc80b 100644
--- a/src/Features/Core/Portable/CodeFixes/NamingStyle/AbstractNamingStyleCodeFixProvider.cs
+++ b/src/Features/Core/Portable/CodeFixes/NamingStyle/AbstractNamingStyleCodeFixProvider.cs
@@ -1,6 +1,7 @@
// 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.Immutable;
using System.Composition;
using System.Linq;
@@ -8,6 +9,7 @@
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.NamingStyles;
using Microsoft.CodeAnalysis.Rename;
@@ -52,9 +54,12 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
var solution = context.Document.Project.Solution;
context.RegisterCodeFix(
new FixNameCodeAction(
+ solution,
+ symbol,
+ fixedName,
string.Format(FeaturesResources.Fix_Name_Violation_colon_0, fixedName),
c => FixAsync(document, symbol, fixedName, c),
- nameof(NamingStyleCodeFixProvider)),
+ equivalenceKey: nameof(NamingStyleCodeFixProvider)),
diagnostic);
}
}
@@ -68,12 +73,51 @@ await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false),
cancellationToken).ConfigureAwait(false);
}
- private class FixNameCodeAction : CodeAction.SolutionChangeAction
+ private class FixNameCodeAction : CodeAction
{
- public FixNameCodeAction(string title, Func> createChangedSolution, string equivalenceKey)
- : base(title, createChangedSolution, equivalenceKey)
+ private readonly Solution _startingSolution;
+ private readonly ISymbol _symbol;
+ private readonly string _newName;
+ private readonly string _title;
+ private readonly Func> _createChangedSolutionAsync;
+ private readonly string _equivalenceKey;
+
+ public FixNameCodeAction(
+ Solution startingSolution,
+ ISymbol symbol,
+ string newName,
+ string title,
+ Func> createChangedSolutionAsync,
+ string equivalenceKey)
{
+ _startingSolution = startingSolution;
+ _symbol = symbol;
+ _newName = newName;
+ _title = title;
+ _createChangedSolutionAsync = createChangedSolutionAsync;
+ _equivalenceKey = equivalenceKey;
}
+
+ protected override async Task> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
+ {
+ return SpecializedCollections.SingletonEnumerable(
+ new ApplyChangesOperation(await _createChangedSolutionAsync(cancellationToken).ConfigureAwait(false)));
+ }
+
+ protected override async Task> ComputeOperationsAsync(CancellationToken cancellationToken)
+ {
+ var factory =_startingSolution.Workspace.Services.GetService();
+ var newSolution = await _createChangedSolutionAsync(cancellationToken).ConfigureAwait(false);
+ return new CodeActionOperation[]
+ {
+ new ApplyChangesOperation(newSolution),
+ factory.CreateSymbolRenamedOperation(_symbol, _newName, _startingSolution, newSolution)
+ }.AsEnumerable();
+ }
+
+ public override string Title => _title;
+
+ public override string EquivalenceKey => _equivalenceKey;
}
}
}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/CodeRefactorings/WorkspaceServices/ISymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/Features/Core/Portable/CodeRefactorings/WorkspaceServices/ISymbolRenamedCodeActionOperationFactoryWorkspaceService.cs
new file mode 100644
index 0000000000000..67e52d65bb1d8
--- /dev/null
+++ b/src/Features/Core/Portable/CodeRefactorings/WorkspaceServices/ISymbolRenamedCodeActionOperationFactoryWorkspaceService.cs
@@ -0,0 +1,11 @@
+// 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 Microsoft.CodeAnalysis.Host;
+
+namespace Microsoft.CodeAnalysis.CodeActions.WorkspaceServices
+{
+ internal interface ISymbolRenamedCodeActionOperationFactoryWorkspaceService : IWorkspaceService
+ {
+ CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution);
+ }
+}
diff --git a/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs b/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs
new file mode 100644
index 0000000000000..d432201d14c20
--- /dev/null
+++ b/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs
@@ -0,0 +1,252 @@
+// 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.Immutable;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Shared.Utilities;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.Completion
+{
+ internal class FileSystemCompletionHelper
+ {
+ private static readonly char[] s_windowsDirectorySeparator = { '\\' };
+
+ private readonly Glyph _folderGlyph;
+ private readonly Glyph _fileGlyph;
+
+ // absolute paths
+ private readonly ImmutableArray _searchPaths;
+ private readonly string _baseDirectoryOpt;
+
+ private readonly ImmutableArray _allowableExtensions;
+ private readonly CompletionItemRules _itemRules;
+
+ public FileSystemCompletionHelper(
+ Glyph folderGlyph,
+ Glyph fileGlyph,
+ ImmutableArray searchPaths,
+ string baseDirectoryOpt,
+ ImmutableArray allowableExtensions,
+ CompletionItemRules itemRules)
+ {
+ Debug.Assert(searchPaths.All(path => PathUtilities.IsAbsolute(path)));
+ Debug.Assert(baseDirectoryOpt == null || PathUtilities.IsAbsolute(baseDirectoryOpt));
+
+ _searchPaths = searchPaths;
+ _baseDirectoryOpt = baseDirectoryOpt;
+ _allowableExtensions = allowableExtensions;
+ _folderGlyph = folderGlyph;
+ _fileGlyph = fileGlyph;
+ _itemRules = itemRules;
+ }
+
+ // virtual for testing
+ protected virtual string[] GetLogicalDrives()
+ => IOUtilities.PerformIO(CorLightup.Desktop.GetLogicalDrives, Array.Empty());
+
+ // virtual for testing
+ protected virtual bool DirectoryExists(string fullPath)
+ {
+ Debug.Assert(PathUtilities.IsAbsolute(fullPath));
+ return Directory.Exists(fullPath);
+ }
+
+ // virtual for testing
+ protected virtual IEnumerable EnumerateDirectories(string fullDirectoryPath)
+ {
+ Debug.Assert(PathUtilities.IsAbsolute(fullDirectoryPath));
+ return IOUtilities.PerformIO(() => Directory.EnumerateDirectories(fullDirectoryPath), Array.Empty());
+ }
+
+ // virtual for testing
+ protected virtual IEnumerable EnumerateFiles(string fullDirectoryPath)
+ {
+ Debug.Assert(PathUtilities.IsAbsolute(fullDirectoryPath));
+ return IOUtilities.PerformIO(() => Directory.EnumerateFiles(fullDirectoryPath), Array.Empty());
+ }
+
+ // virtual for testing
+ protected virtual bool IsVisibleFileSystemEntry(string fullPath)
+ {
+ Debug.Assert(PathUtilities.IsAbsolute(fullPath));
+ return IOUtilities.PerformIO(() => (File.GetAttributes(fullPath) & (FileAttributes.Hidden | FileAttributes.System)) == 0, false);
+ }
+
+ private CompletionItem CreateNetworkRoot()
+ => CommonCompletionItem.Create(
+ "\\\\",
+ glyph: null,
+ description: "\\\\".ToSymbolDisplayParts(),
+ rules: _itemRules);
+
+ private CompletionItem CreateUnixRoot()
+ => CommonCompletionItem.Create(
+ "/",
+ glyph: _folderGlyph,
+ description: "/".ToSymbolDisplayParts(),
+ rules: _itemRules);
+
+ private CompletionItem CreateFileSystemEntryItem(string fullPath, bool isDirectory)
+ => CommonCompletionItem.Create(
+ PathUtilities.GetFileName(fullPath),
+ glyph: isDirectory ? _folderGlyph : _fileGlyph,
+ description: fullPath.ToSymbolDisplayParts(),
+ rules: _itemRules);
+
+ private CompletionItem CreateLogicalDriveItem(string drive)
+ => CommonCompletionItem.Create(
+ drive,
+ glyph: _folderGlyph,
+ description: drive.ToSymbolDisplayParts(),
+ rules: _itemRules);
+
+ public Task> GetItemsAsync(string directoryPath, CancellationToken cancellationToken)
+ {
+ return Task.Run(() => GetItems(directoryPath, cancellationToken), cancellationToken);
+ }
+
+ // internal for testing
+ internal ImmutableArray GetItems(string directoryPath, CancellationToken cancellationToken)
+ {
+ if (!PathUtilities.IsUnixLikePlatform && directoryPath.Length == 1 && directoryPath[0] == '\\')
+ {
+ // The user has typed only "\". In this case, we want to add "\\" to the list.
+ return ImmutableArray.Create(CreateNetworkRoot());
+ }
+
+ var result = ArrayBuilder.GetInstance();
+
+ var pathKind = PathUtilities.GetPathKind(directoryPath);
+ switch (pathKind)
+ {
+ case PathKind.Empty:
+ // base directory
+ if (_baseDirectoryOpt != null)
+ {
+ result.AddRange(GetItemsInDirectory(_baseDirectoryOpt, cancellationToken));
+ }
+
+ // roots
+ if (PathUtilities.IsUnixLikePlatform)
+ {
+ result.AddRange(CreateUnixRoot());
+ }
+ else
+ {
+ foreach (var drive in GetLogicalDrives())
+ {
+ result.Add(CreateLogicalDriveItem(drive.TrimEnd(s_windowsDirectorySeparator)));
+ }
+
+ result.Add(CreateNetworkRoot());
+ }
+
+ // entries on search paths
+ foreach (var searchPath in _searchPaths)
+ {
+ result.AddRange(GetItemsInDirectory(searchPath, cancellationToken));
+ }
+
+ break;
+
+ case PathKind.Absolute:
+ case PathKind.RelativeToCurrentDirectory:
+ case PathKind.RelativeToCurrentParent:
+ case PathKind.RelativeToCurrentRoot:
+ var fullDirectoryPath = FileUtilities.ResolveRelativePath(directoryPath, basePath: null, baseDirectory: _baseDirectoryOpt);
+ if (fullDirectoryPath != null)
+ {
+ result.AddRange(GetItemsInDirectory(fullDirectoryPath, cancellationToken));
+ }
+ else
+ {
+ // invalid path
+ result.Clear();
+ }
+
+ break;
+
+ case PathKind.Relative:
+
+ // base directory:
+ if (_baseDirectoryOpt != null)
+ {
+ result.AddRange(GetItemsInDirectory(PathUtilities.CombineAbsoluteAndRelativePaths(_baseDirectoryOpt, directoryPath), cancellationToken));
+ }
+
+ // search paths:
+ foreach (var searchPath in _searchPaths)
+ {
+ result.AddRange(GetItemsInDirectory(PathUtilities.CombineAbsoluteAndRelativePaths(searchPath, directoryPath), cancellationToken));
+ }
+
+ break;
+
+ case PathKind.RelativeToDriveDirectory:
+ // Paths "C:dir" are not supported, but when the path doesn't include any directory, i.e. "C:",
+ // we return the drive itself.
+ if (directoryPath.Length == 2)
+ {
+ result.Add(CreateLogicalDriveItem(directoryPath));
+ }
+
+ break;
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(pathKind);
+ }
+
+ return result.ToImmutableAndFree();
+ }
+
+ private IEnumerable GetItemsInDirectory(string fullDirectoryPath, CancellationToken cancellationToken)
+ {
+ Debug.Assert(PathUtilities.IsAbsolute(fullDirectoryPath));
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (!DirectoryExists(fullDirectoryPath))
+ {
+ yield break;
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ foreach (var directory in EnumerateDirectories(fullDirectoryPath))
+ {
+ if (IsVisibleFileSystemEntry(directory))
+ {
+ yield return CreateFileSystemEntryItem(directory, isDirectory: true);
+ }
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ foreach (var file in EnumerateFiles(fullDirectoryPath))
+ {
+ if (_allowableExtensions.Length != 0 &&
+ !_allowableExtensions.Contains(
+ PathUtilities.GetExtension(file),
+ PathUtilities.IsUnixLikePlatform ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (IsVisibleFileSystemEntry(file))
+ {
+ yield return CreateFileSystemEntryItem(file, isDirectory: false);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Features/Core/Portable/DesignerAttributes/AbstractDesignerAttributeService.cs b/src/Features/Core/Portable/DesignerAttributes/AbstractDesignerAttributeService.cs
index a2672a62b64ee..7259b2d7c1635 100644
--- a/src/Features/Core/Portable/DesignerAttributes/AbstractDesignerAttributeService.cs
+++ b/src/Features/Core/Portable/DesignerAttributes/AbstractDesignerAttributeService.cs
@@ -1,61 +1,22 @@
// 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.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Versions;
namespace Microsoft.CodeAnalysis.DesignerAttributes
{
- internal struct DesignerAttributeResult
- {
- public string DesignerAttributeArgument;
- public bool ContainsErrors;
- public bool NotApplicable;
-
- public DesignerAttributeResult(string designerAttributeArgument, bool containsErrors, bool notApplicable)
- {
- DesignerAttributeArgument = designerAttributeArgument;
- ContainsErrors = containsErrors;
- NotApplicable = notApplicable;
- }
- }
-
internal abstract class AbstractDesignerAttributeService : IDesignerAttributeService
{
protected abstract bool ProcessOnlyFirstTypeDefined();
protected abstract IEnumerable GetAllTopLevelTypeDefined(SyntaxNode root);
protected abstract bool HasAttributesOrBaseTypeOrIsPartial(SyntaxNode typeNode);
- public async Task ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken)
- {
- var workspace = document.Project.Solution.Workspace;
-
- // same service run in both inproc and remote host, but remote host will not have RemoteHostClient service,
- // so inproc one will always run
- var client = await workspace.TryGetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
- if (client != null && !document.IsOpen())
- {
- // run designer attributes scanner on remote host
- // we only run closed files to make open document to have better responsiveness.
- // also we cache everything related to open files anyway, no saving by running
- // them in remote host
- return await ScanDesignerAttributesInRemoteHostAsync(client, document, cancellationToken).ConfigureAwait(false);
- }
-
- return await ScanDesignerAttributesInCurrentProcessAsync(document, cancellationToken).ConfigureAwait(false);
- }
-
- private async Task ScanDesignerAttributesInRemoteHostAsync(RemoteHostClient client, Document document, CancellationToken cancellationToken)
- {
- return await client.RunCodeAnalysisServiceOnRemoteHostAsync(
- document.Project.Solution, nameof(IRemoteDesignerAttributeService.ScanDesignerAttributesAsync),
- document.Id, cancellationToken).ConfigureAwait(false);
- }
-
- private async Task ScanDesignerAttributesInCurrentProcessAsync(Document document, CancellationToken cancellationToken)
+ public async Task ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
@@ -83,7 +44,7 @@ private async Task ScanDesignerAttributesInCurrentProce
{
// The DesignerCategoryAttribute doesn't exist. either not applicable or
// no idea on design attribute status, just leave things as it is.
- return new DesignerAttributeResult(designerAttributeArgument, documentHasError, notApplicable: true);
+ return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: true);
}
}
@@ -114,7 +75,7 @@ private async Task ScanDesignerAttributesInCurrentProce
if (attribute != null && attribute.ConstructorArguments.Length == 1)
{
designerAttributeArgument = GetArgumentString(attribute.ConstructorArguments[0]);
- return new DesignerAttributeResult(designerAttributeArgument, documentHasError, notApplicable: false);
+ return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
}
}
}
@@ -126,7 +87,7 @@ private async Task ScanDesignerAttributesInCurrentProce
}
}
- return new DesignerAttributeResult(designerAttributeArgument, documentHasError, notApplicable: false);
+ return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
}
private static string GetArgumentString(TypedConstant argument)
@@ -140,5 +101,49 @@ private static string GetArgumentString(TypedConstant argument)
return ((string)argument.Value).Trim();
}
+
+ internal static async Task> TryAnalyzeProjectInCurrentProcessAsync(
+ Project project, CancellationToken cancellationToken)
+ {
+ var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
+ var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
+
+ // Get whatever data we've current persisted.
+ var designerAttributeData = await DesignerAttributeProjectData.ReadAsync(
+ project, cancellationToken).ConfigureAwait(false);
+
+ // If we have no persisted data, or the persisted data is for a previous version of
+ // the project, then compute the results for the current project snapshot.
+ if (designerAttributeData == null ||
+ !VersionStamp.CanReusePersistedVersion(semanticVersion, designerAttributeData.SemanticVersion))
+ {
+ designerAttributeData = await ComputeAndPersistDesignerAttributeProjectDataAsync(
+ project, semanticVersion, cancellationToken).ConfigureAwait(false);
+ }
+
+ return designerAttributeData.PathToDocumentData;
+ }
+
+ private static async Task ComputeAndPersistDesignerAttributeProjectDataAsync(
+ Project project, VersionStamp semanticVersion, CancellationToken cancellationToken)
+ {
+ var service = project.LanguageServices.GetService();
+
+ var tasks = project.Documents.Select(
+ d => service.ScanDesignerAttributesAsync(d, cancellationToken)).ToArray();
+
+ await Task.WhenAll(tasks).ConfigureAwait(false);
+
+ var builder = ImmutableDictionary.CreateBuilder();
+ foreach (var task in tasks)
+ {
+ var result = await task.ConfigureAwait(false);
+ builder[result.FilePath] = result;
+ }
+
+ var data = new DesignerAttributeProjectData(semanticVersion, builder.ToImmutable());
+ await data.PersistAsync(project, cancellationToken).ConfigureAwait(false);
+ return data;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeDocumentData.cs b/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeDocumentData.cs
new file mode 100644
index 0000000000000..7ab94603a35be
--- /dev/null
+++ b/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeDocumentData.cs
@@ -0,0 +1,41 @@
+// 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;
+
+namespace Microsoft.CodeAnalysis.DesignerAttributes
+{
+ ///
+ /// Marshalling type to pass designer attribute data to/from the OOP process.
+ ///
+ internal struct DesignerAttributeDocumentData : IEquatable
+ {
+ public string FilePath;
+ public string DesignerAttributeArgument;
+ public bool ContainsErrors;
+ public bool NotApplicable;
+
+ public DesignerAttributeDocumentData(string filePath, string designerAttributeArgument, bool containsErrors, bool notApplicable)
+ {
+ FilePath = filePath;
+ DesignerAttributeArgument = designerAttributeArgument;
+ ContainsErrors = containsErrors;
+ NotApplicable = notApplicable;
+ }
+
+ public override bool Equals(object obj)
+ => Equals((DesignerAttributeDocumentData)obj);
+
+ public bool Equals(DesignerAttributeDocumentData other)
+ {
+ return FilePath == other.FilePath &&
+ DesignerAttributeArgument == other.DesignerAttributeArgument &&
+ ContainsErrors == other.ContainsErrors &&
+ NotApplicable == other.NotApplicable;
+ }
+
+ // Currently no need for GetHashCode. If we end up using this as a key in a dictionary,
+ // feel free to add.
+ public override int GetHashCode()
+ => throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeProjectData.cs b/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeProjectData.cs
new file mode 100644
index 0000000000000..d82db11bd93c6
--- /dev/null
+++ b/src/Features/Core/Portable/DesignerAttributes/DesignerAttributeProjectData.cs
@@ -0,0 +1,108 @@
+// 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.Immutable;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Host;
+using Microsoft.CodeAnalysis.Shared.Utilities;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.DesignerAttributes
+{
+ internal class DesignerAttributeProjectData
+ {
+ private const string StreamName = "";
+ private const string FormatVersion = "3";
+
+ public readonly VersionStamp SemanticVersion;
+ public readonly ImmutableDictionary PathToDocumentData;
+
+ public DesignerAttributeProjectData(
+ VersionStamp semanticVersion, ImmutableDictionary pathToDocumentData)
+ {
+ SemanticVersion = semanticVersion;
+ PathToDocumentData = pathToDocumentData;
+ }
+
+ public static async Task ReadAsync(
+ Project project, CancellationToken cancellationToken)
+ {
+ try
+ {
+ var solution = project.Solution;
+ var storageService = (IPersistentStorageService2)solution.Workspace.Services.GetService();
+
+ using (var persistenceService = storageService.GetStorage(solution, checkBranchId: false))
+ using (var stream = await persistenceService.ReadStreamAsync(project, StreamName, cancellationToken).ConfigureAwait(false))
+ using (var reader = ObjectReader.TryGetReader(stream, cancellationToken))
+ {
+ if (reader != null)
+ {
+ var version = reader.ReadString();
+ if (version == FormatVersion)
+ {
+ var semanticVersion = VersionStamp.ReadFrom(reader);
+
+ var resultCount = reader.ReadInt32();
+ var builder = ImmutableDictionary.CreateBuilder();
+
+ for (var i = 0; i < resultCount; i++)
+ {
+ var filePath = reader.ReadString();
+ var attribute = reader.ReadString();
+ var containsErrors = reader.ReadBoolean();
+ var notApplicable = reader.ReadBoolean();
+
+ builder[filePath] = new DesignerAttributeDocumentData(filePath, attribute, containsErrors, notApplicable);
+ }
+
+ return new DesignerAttributeProjectData(semanticVersion, builder.ToImmutable());
+ }
+ }
+ }
+ }
+ catch (Exception e) when (IOUtilities.IsNormalIOException(e))
+ {
+ // Storage APIs can throw arbitrary exceptions.
+ }
+
+ return null;
+ }
+
+ public async Task PersistAsync(Project project, CancellationToken cancellationToken)
+ {
+ try
+ {
+ var solution = project.Solution;
+ var storageService = (IPersistentStorageService2)solution.Workspace.Services.GetService();
+
+ using (var storage = storageService.GetStorage(solution, checkBranchId: false))
+ using (var stream = SerializableBytes.CreateWritableStream())
+ using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
+ {
+ writer.WriteString(FormatVersion);
+ this.SemanticVersion.WriteTo(writer);
+
+ writer.WriteInt32(this.PathToDocumentData.Count);
+
+ foreach (var kvp in this.PathToDocumentData)
+ {
+ var result = kvp.Value;
+ writer.WriteString(result.FilePath);
+ writer.WriteString(result.DesignerAttributeArgument);
+ writer.WriteBoolean(result.ContainsErrors);
+ writer.WriteBoolean(result.NotApplicable);
+ }
+
+ stream.Position = 0;
+ await storage.WriteStreamAsync(project, StreamName, stream, cancellationToken).ConfigureAwait(false);
+ }
+ }
+ catch (Exception e) when (IOUtilities.IsNormalIOException(e))
+ {
+ // Storage APIs can throw arbitrary exceptions.
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/DesignerAttributes/IDesignerAttributeService.cs b/src/Features/Core/Portable/DesignerAttributes/IDesignerAttributeService.cs
index aa76cc91a4316..4a9b923387293 100644
--- a/src/Features/Core/Portable/DesignerAttributes/IDesignerAttributeService.cs
+++ b/src/Features/Core/Portable/DesignerAttributes/IDesignerAttributeService.cs
@@ -8,6 +8,6 @@ namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal interface IDesignerAttributeService : ILanguageService
{
- Task ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken);
+ Task ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken);
}
}
diff --git a/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs b/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs
index c202d46d8ab44..e17055ec67a63 100644
--- a/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs
+++ b/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs
@@ -6,6 +6,6 @@ namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal interface IRemoteDesignerAttributeService
{
- Task ScanDesignerAttributesAsync(DocumentId documentId);
+ Task ScanDesignerAttributesAsync(ProjectId projectId);
}
}
diff --git a/src/Features/Core/Portable/Diagnostics/AbstractHostDiagnosticUpdateSource.cs b/src/Features/Core/Portable/Diagnostics/AbstractHostDiagnosticUpdateSource.cs
index ec520c252c0fa..b1e97f4c5628c 100644
--- a/src/Features/Core/Portable/Diagnostics/AbstractHostDiagnosticUpdateSource.cs
+++ b/src/Features/Core/Portable/Diagnostics/AbstractHostDiagnosticUpdateSource.cs
@@ -101,7 +101,7 @@ public void ClearAnalyzerDiagnostics(ImmutableArray analyzer
public void ClearAnalyzerDiagnostics(ProjectId projectId)
{
- foreach (var analyzer in _analyzerHostDiagnosticsMap.Keys)
+ foreach (var (analyzer, _) in _analyzerHostDiagnosticsMap)
{
ClearAnalyzerDiagnostics(analyzer, projectId);
}
diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
index fa0ccc66fcbc6..936df0f01ac57 100644
--- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
+++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2
{
@@ -95,7 +96,7 @@ public IEnumerable GetAnalyzers()
yield return _compilerAnalyzer;
}
- foreach (var analyzer in _map.Keys)
+ foreach (var (analyzer, _) in _map)
{
yield return analyzer;
}
@@ -111,7 +112,7 @@ public IEnumerable GetStateSets()
}
// TODO: for now, this is static, but in future, we might consider making this a dynamic so that we process cheaper analyzer first.
- foreach (var set in _map.Values)
+ foreach (var (_, set) in _map)
{
yield return set;
}
diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
index 2126145774738..d8f76241727ea 100644
--- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
+++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
@@ -1696,7 +1696,7 @@ protected void AddRudeDeleteAroundActiveStatement(List diagn
protected void ReportUnmatchedStatements(
List diagnostics,
Match match,
- int syntaxKind,
+ int[] syntaxKinds,
SyntaxNode oldActiveStatement,
SyntaxNode newActiveStatement,
Func areEquivalent,
@@ -1704,8 +1704,8 @@ protected void ReportUnmatchedStatements(
where TSyntaxNode : SyntaxNode
{
List oldNodes = null, newNodes = null;
- GetAncestors(GetEncompassingAncestor(match.OldRoot), oldActiveStatement, syntaxKind, ref oldNodes);
- GetAncestors(GetEncompassingAncestor(match.NewRoot), newActiveStatement, syntaxKind, ref newNodes);
+ GetAncestors(GetEncompassingAncestor(match.OldRoot), oldActiveStatement, syntaxKinds, ref oldNodes);
+ GetAncestors(GetEncompassingAncestor(match.NewRoot), newActiveStatement, syntaxKinds, ref newNodes);
if (newNodes != null)
{
@@ -1836,11 +1836,11 @@ private static int IndexOfEquivalent(SyntaxNode newNode, List list)
+ private static void GetAncestors(SyntaxNode root, SyntaxNode node, int[] syntaxKinds, ref List list)
{
while (node != root)
{
- if (node.RawKind == syntaxKind)
+ if (syntaxKinds.Contains(node.RawKind))
{
if (list == null)
{
diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj
index 92bc7f231b944..cff5327a8c52d 100644
--- a/src/Features/Core/Portable/Features.csproj
+++ b/src/Features/Core/Portable/Features.csproj
@@ -112,6 +112,8 @@
+
+
@@ -122,6 +124,8 @@
+
+
diff --git a/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.Editor.cs b/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.Editor.cs
index d89174f79e706..243db44431116 100644
--- a/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.Editor.cs
+++ b/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.Editor.cs
@@ -188,7 +188,8 @@ private async Task GenerateDelegatingConstructorAsync(
// delegating.
var remainingParameterNames = _service.GenerateParameterNames(
_document.SemanticModel, remainingArguments,
- delegatedConstructor.Parameters.Select(p => p.Name).ToList());
+ delegatedConstructor.Parameters.Select(p => p.Name).ToList(),
+ _cancellationToken);
// Can't generate the constructor if the parameter names we're copying over forcibly
// conflict with any names we generated.
@@ -275,8 +276,8 @@ private ImmutableArray GetParameterNames(
ImmutableArray