diff --git a/.nuget/packages.config b/.nuget/packages.config
index be56510f9a04dd2a048d9b388e0265f0aebaa90e..055afc39827712ac9eaec92fe7d31f30f20928d3 100644
--- a/.nuget/packages.config
+++ b/.nuget/packages.config
@@ -10,4 +10,5 @@
+
diff --git a/build/Targets/VSL.Imports.targets b/build/Targets/VSL.Imports.targets
index 0b4c4999d5bcf362fa3556de55f25cc632bc7a45..339e2a2ae61251f2307f1105628744139e9dd59d 100644
--- a/build/Targets/VSL.Imports.targets
+++ b/build/Targets/VSL.Imports.targets
@@ -55,6 +55,17 @@
+
+
+ $(FinalDefineConstants.Replace('"', ''))
+
+
$(BuildDependsOn);
diff --git a/cibuild.sh b/cibuild.sh
index 8711c207ecec6ae3110d20599901923d47ff2901..647e7b3e709d4dd846f21d2875b500d95e0df87d 100755
--- a/cibuild.sh
+++ b/cibuild.sh
@@ -52,7 +52,7 @@ done
run_xbuild()
{
- xbuild /v:m /p:SignAssembly=false /p:DebugSymbols=false "$@"
+ mono packages/Microsoft.Build.Mono.Debug.14.1.0.0-prerelease/lib/MSBuild.exe /v:m /p:SignAssembly=false /p:DebugSymbols=false "$@"
if [ $? -ne 0 ]; then
echo Compilation failed
exit 1
@@ -115,7 +115,7 @@ save_toolset()
clean_roslyn()
{
echo Cleaning the enlistment
- xbuild /v:m /t:Clean build/Toolset.sln /p:Configuration=$BUILD_CONFIGURATION
+ mono packages/Microsoft.Build.Mono.Debug.14.1.0.0-prerelease/lib/MSBuild.exe /v:m /t:Clean build/Toolset.sln /p:Configuration=$BUILD_CONFIGURATION
rm -rf Binaries/$BUILD_CONFIGURATION
}
diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_Warnings.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_Warnings.cs
index a4a438bf8d4bec1ad9305f590175b9414e161dee..5d697aef15bf70e157036f3080da11f0b584b272 100644
--- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_Warnings.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_Warnings.cs
@@ -238,7 +238,16 @@ private void CheckBinaryOperator(BoundBinaryOperator node)
private void CheckCompoundAssignmentOperator(BoundCompoundAssignmentOperator node)
{
- CheckForBitwiseOrSignExtend(node, node.Operator.Kind, node.Left, node.Right);
+ BoundExpression left = node.Left;
+
+ if (!node.Operator.Kind.IsDynamic() && !node.LeftConversion.IsIdentity && node.LeftConversion.Exists)
+ {
+ // Need to represent the implicit conversion as a node in order to be able to produce correct diagnostics.
+ left = new BoundConversion(left.Syntax, left, node.LeftConversion, node.Operator.Kind.IsChecked(),
+ explicitCastInCode: false, constantValueOpt: null, type: node.Operator.LeftType);
+ }
+
+ CheckForBitwiseOrSignExtend(node, node.Operator.Kind, left, node.Right);
CheckLiftedCompoundAssignment(node);
if (_inExpressionLambda)
diff --git a/src/Compilers/CSharp/Test/CommandLine/CSharpCommandLineTest.csproj b/src/Compilers/CSharp/Test/CommandLine/CSharpCommandLineTest.csproj
index 352f200506d47404b114590a2ec1eb109729d6e9..3bf0586d1fe28d510d3d8b5b81c5e455dbd8997e 100644
--- a/src/Compilers/CSharp/Test/CommandLine/CSharpCommandLineTest.csproj
+++ b/src/Compilers/CSharp/Test/CommandLine/CSharpCommandLineTest.csproj
@@ -53,8 +53,12 @@
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTestResources.resx b/src/Compilers/CSharp/Test/CommandLine/CommandLineTestResources.resx
index 5548f2e7ba2beb9dbd66bfd952abace0fd347741..2315d56ec5c53e8687e35115dcbdcbe04286a267 100644
--- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTestResources.resx
+++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTestResources.resx
@@ -119,6 +119,6 @@
- ..\..\csc\csc.rsp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ ../../csc/csc.rsp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
\ No newline at end of file
+
diff --git a/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj b/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj
index 408e96b29c61cf910bdbc3b7ea1f360bb6704820..7011cdfdaf6d689d3402636e16d95be32db963f4 100644
--- a/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj
+++ b/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj
@@ -52,9 +52,15 @@
-
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ ..\..\..\..\..\packages\Microsoft.DiaSymReader.1.0.5\lib\net45\Microsoft.DiaSymReader.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
@@ -206,4 +212,4 @@
-
\ No newline at end of file
+
diff --git a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj
index 1ff0ba54003e2f9f936d6612d6f25c4e60a3ae37..f4899206a24e05f41cca2e2896626c9d4c152790 100644
--- a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj
+++ b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj
@@ -48,7 +48,9 @@
-
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs
index 16065dd8d5f907b68ffc8e2c423da80d2de7921a..e8cd779bb5e18d81844b2f9cdbac05b15cafaa2f 100644
--- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs
@@ -1105,6 +1105,20 @@ void Method()
TestGenericNameCore(source, new AnalyzerWithNoActions(), new CSharpGenericNameAnalyzer());
}
+ [Fact, WorkItem(4055, "https://github.com/dotnet/roslyn/issues/4055")]
+ public void TestAnalyzerWithNoSupportedDiagnostics()
+ {
+ var source = @"
+class MyClass
+{
+}";
+ // Ensure that adding a dummy analyzer with no supported diagnostics doesn't bring down entire analysis.
+ var analyzers = new DiagnosticAnalyzer[] { new AnalyzerWithNoSupportedDiagnostics() };
+ CreateCompilationWithMscorlib45(source)
+ .VerifyDiagnostics()
+ .VerifyAnalyzerDiagnostics(analyzers);
+ }
+
private static void TestEffectiveSeverity(
DiagnosticSeverity defaultSeverity,
ReportDiagnostic expectedEffectiveSeverity,
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
index 1af7d96bc178e1f42cedc2d1c49b558773cab407..27d6b222b643edf8ae2c639444bf0cbac149e6cb 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
@@ -8728,5 +8728,26 @@ operator int (IntHolder ih)
operator IntHolder(int i)
'y' is 5");
}
+
+ [Fact, WorkItem(4027, "https://github.com/dotnet/roslyn/issues/4027")]
+ public void NotSignExtendedOperand()
+ {
+ string source = @"
+class MainClass
+{
+ public static void Main ()
+ {
+ short a = 0;
+ int b = 0;
+ a |= (short)b;
+ a = (short)(a | (short)b);
+ }
+}
+";
+
+ var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll);
+
+ compilation.VerifyDiagnostics();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Symbol/CSharpCompilerSymbolTest.csproj b/src/Compilers/CSharp/Test/Symbol/CSharpCompilerSymbolTest.csproj
index adc4bdfef5d04a368d24691fd10ea9110d39788e..683e78cbfea589ffe010a3ac902f445cbb38f7d8 100644
--- a/src/Compilers/CSharp/Test/Symbol/CSharpCompilerSymbolTest.csproj
+++ b/src/Compilers/CSharp/Test/Symbol/CSharpCompilerSymbolTest.csproj
@@ -52,9 +52,15 @@
False
..\..\..\..\..\packages\Microsoft.CodeAnalysis.Test.Resources.Proprietary.1.1.0-beta1-20150716-08\lib\net45\Microsoft.CodeAnalysis.Test.Resources.Proprietary.dll
-
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ ..\..\..\..\..\packages\Microsoft.DiaSymReader.1.0.5\lib\net45\Microsoft.DiaSymReader.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/CSharp/Test/Syntax/CSharpCompilerSyntaxTest.csproj b/src/Compilers/CSharp/Test/Syntax/CSharpCompilerSyntaxTest.csproj
index 065203645410506cfec94eaec267f54e74d6f1c5..82a7d226a64f025516b621dec5d8dcc18584c549 100644
--- a/src/Compilers/CSharp/Test/Syntax/CSharpCompilerSyntaxTest.csproj
+++ b/src/Compilers/CSharp/Test/Syntax/CSharpCompilerSyntaxTest.csproj
@@ -22,7 +22,9 @@
-
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/Core/CodeAnalysisTest/CodeAnalysisTest.csproj b/src/Compilers/Core/CodeAnalysisTest/CodeAnalysisTest.csproj
index 0aff7e6c42c62bdb37caed05cd2d718fd34e56cb..9f010880f136e38603e8715e2097fb331a99596c 100644
--- a/src/Compilers/Core/CodeAnalysisTest/CodeAnalysisTest.csproj
+++ b/src/Compilers/Core/CodeAnalysisTest/CodeAnalysisTest.csproj
@@ -70,8 +70,12 @@
-
-
+
+ ..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
@@ -174,10 +178,10 @@
-
-
-
-
+
+
+
+
@@ -187,4 +191,4 @@
-
\ No newline at end of file
+
diff --git a/src/Compilers/Core/CodeAnalysisTest/Resources.resx b/src/Compilers/Core/CodeAnalysisTest/Resources.resx
index cccb42b13904444576b512ef20c9c26ff4110ebf..092240b59238d75c309aa65bc3c0c47507931ad1 100644
--- a/src/Compilers/Core/CodeAnalysisTest/Resources.resx
+++ b/src/Compilers/Core/CodeAnalysisTest/Resources.resx
@@ -121,15 +121,15 @@
- Resources\default.win32manifest;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ Resources/default.win32manifest;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Resources\VerResourceBuiltByRC.RES;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ Resources/VerResourceBuiltByRC.RES;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Resources\nativeWithStringIDsAndTypesAndIntTypes.res;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ Resources/nativeWithStringIDsAndTypesAndIntTypes.res;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Resources\Roslyn.ico.blah;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ Resources/Roslyn.ico.blah;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs
index 6782537f66e3c49a9e3c4e9633c3d79f74b0a7bd..6139e70ed3b7a4f51f5b26fa176b71b3efea59f3 100644
--- a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs
+++ b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs
@@ -308,6 +308,45 @@ private ImmutableArray CalculateAssemblyReferenceAli
#region Synthesized Members
+#if DEBUG
+ ///
+ /// The queue of synthesized members of a type should be deterministic, as the members are
+ /// emitted in the order in which they are added to the queue. Therefore for debug purposes
+ /// we have a custom version of ConcurrentQueue that detects attempted concurrent adds.
+ ///
+ ///
+ private class ConcurrentQueue : System.Collections.Concurrent.ConcurrentQueue
+ {
+ // A count of the number of concurrent queue operations in progress. Should always be zero or one,
+ // as synthetic members should be added by the compiler to a given type in a well-defined sequential
+ // order.
+ int queueing;
+
+ // A short delay to increase the chance that concurrent Enqueue operation will be diagnosed.
+ static readonly TimeSpan shortDelay = new TimeSpan(2);
+
+ ///
+ /// Adds an object to the end of the ConcurrentQueue.
+ ///
+ ///
+ /// The object to add to the end of the ConcurrentQueue.
+ /// The value can be a null reference for reference types.
+ ///
+ public new void Enqueue(T item)
+ {
+ if (Interlocked.Increment(ref queueing) != 1)
+ {
+ throw new System.InvalidOperationException("Concurrent use of " + nameof(SynthesizedDefinitions));
+ }
+ base.Enqueue(item);
+ // To increase the chance of catching concurrency issues, we add a delay to each queued item
+ // so that another thread has a chance to add at the same time.
+ System.Threading.Tasks.Task.Delay(shortDelay).Wait();
+ Interlocked.Decrement(ref queueing);
+ }
+ }
+#endif
+
///
/// Captures the set of synthesized definitions that should be added to a type
/// during emit process.
diff --git a/src/Compilers/Test/Utilities/Core2/CompilerTestUtilities2.csproj b/src/Compilers/Test/Utilities/Core2/CompilerTestUtilities2.csproj
index c1c233e969cf649fa45f37b8cacad53c4f14434f..15a0f4fbde31b19dc7eae8c3de864a362edf6ac0 100644
--- a/src/Compilers/Test/Utilities/Core2/CompilerTestUtilities2.csproj
+++ b/src/Compilers/Test/Utilities/Core2/CompilerTestUtilities2.csproj
@@ -27,8 +27,12 @@
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/VisualBasic/Portable/Errors/LocalizableErrorArgument.vb b/src/Compilers/VisualBasic/Portable/Errors/LocalizableErrorArgument.vb
index 586304f1b621cbefb0309d23d8256fe396649adc..26e5aae000035cac5efd83bd7ee073116926417a 100644
--- a/src/Compilers/VisualBasic/Portable/Errors/LocalizableErrorArgument.vb
+++ b/src/Compilers/VisualBasic/Portable/Errors/LocalizableErrorArgument.vb
@@ -21,7 +21,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
'''Creates a string representing the unformatted LocalizableErrorArgument instance.
'''
Public Overrides Function ToString() As String
- Return ToString(Nothing)
+ Return ToString_IFormattable(Nothing, Nothing)
End Function
'''
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/BasicCommandLineTest.vbproj b/src/Compilers/VisualBasic/Test/CommandLine/BasicCommandLineTest.vbproj
index 9cdee313b9ed373677758f6c82500bedbc09bfdc..f64d32968d9e4bf422141a6dd1727e53c74f4e38 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/BasicCommandLineTest.vbproj
+++ b/src/Compilers/VisualBasic/Test/CommandLine/BasicCommandLineTest.vbproj
@@ -58,8 +58,12 @@
False
..\..\..\..\..\packages\Microsoft.CodeAnalysis.Test.Resources.Proprietary.1.1.0-beta1-20150716-08\lib\net45\Microsoft.CodeAnalysis.Test.Resources.Proprietary.dll
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTestResources.resx b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTestResources.resx
index a6bf0ec678094b3d3a8e8a9de090567e8cb2fdc3..53f9b20569841116d12f321453dfca99d0ceca37 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTestResources.resx
+++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTestResources.resx
@@ -119,6 +119,6 @@
- ..\..\vbc\vbc.rsp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ ../../vbc/vbc.rsp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
\ No newline at end of file
+
diff --git a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
index 50380e3911867f16ab116b4a660bbe2d470c224c..08ba6bef891cad6ee2650b4f496c02314e46f80e 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
+++ b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj
@@ -46,9 +46,15 @@
-
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ ..\..\..\..\..\packages\Microsoft.DiaSymReader.1.0.5\lib\net45\Microsoft.DiaSymReader.dll
+
true
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
index e13951834685169053d1cbdead34389ff00fe0fa..6ae88d3dbf5f892377ca45b4ae406cac030f63b3 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
@@ -21,6 +21,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
Public Class CompilationAPITests
Inherits BasicTestBase
+
+ Public Sub LocalizableErrorArgumentToStringDoesntStackOverflow()
+ ' Error ID is arbitrary
+ Dim arg = New LocalizableErrorArgument(ERRID.IDS_ProjectSettingsLocationName)
+ Assert.NotNull(arg.ToString())
+ End Sub
+
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Resource.resx b/src/Compilers/VisualBasic/Test/Semantic/Resource.resx
index 27a695e1bf235b1acecf596fe006461fa677cc34..f332c999c9c04bb6ee786509ce6373060ebbc5dc 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Resource.resx
+++ b/src/Compilers/VisualBasic/Test/Semantic/Resource.resx
@@ -119,37 +119,37 @@
- Semantics\Async_Overload_Change_3.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/Async_Overload_Change_3.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestBaseline1.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestBaseline1.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestBaseline2.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestBaseline2.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestBaseline3.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestBaseline3.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestBaseline4.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestBaseline4.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestBaseline5.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestBaseline5.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestSource1.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestSource1.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestSource2.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestSource2.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestSource3.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestSource3.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestSource4.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestSource4.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\BinaryOperatorsTestSource5.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/BinaryOperatorsTestSource5.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
<Global>
@@ -182,21 +182,21 @@
</Global>
- Semantics\LongTypeNameNative.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/LongTypeNameNative.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\LongTypeName.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/LongTypeName.vb.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\OverloadResolutionTestSource.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/OverloadResolutionTestSource.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Semantics\PrintResultTestSource.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Semantics/PrintResultTestSource.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
- Binding\T_1247520.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+ Binding/T_1247520.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
- Binding\T_68086.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+ Binding/T_68086.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
diff --git a/src/Compilers/VisualBasic/Test/Symbol/BasicCompilerSymbolTest.vbproj b/src/Compilers/VisualBasic/Test/Symbol/BasicCompilerSymbolTest.vbproj
index fa99c04ac914d999060562ed6053ab2a0db0c9cb..f6152ad35e74420e75527e97b495c9e168c17d4a 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/BasicCompilerSymbolTest.vbproj
+++ b/src/Compilers/VisualBasic/Test/Symbol/BasicCompilerSymbolTest.vbproj
@@ -46,8 +46,12 @@
-
-
+
+ ..\..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
diff --git a/src/Compilers/VisualBasic/Test/Syntax/BasicCompilerSyntaxTest.vbproj b/src/Compilers/VisualBasic/Test/Syntax/BasicCompilerSyntaxTest.vbproj
index 33160ebab45d12436a78199e827f05d6124a4696..ef3343e61dc1c5b23078b3dbfdca38f690601636 100644
--- a/src/Compilers/VisualBasic/Test/Syntax/BasicCompilerSyntaxTest.vbproj
+++ b/src/Compilers/VisualBasic/Test/Syntax/BasicCompilerSyntaxTest.vbproj
@@ -20,7 +20,9 @@
-
+
+ ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
diff --git a/src/Compilers/VisualBasic/Test/Syntax/Resource.resx b/src/Compilers/VisualBasic/Test/Syntax/Resource.resx
index be56e337fe1818903a8bc4a9ec204ee630b4f4c9..512e357af6e427c40cc0c9ef57c997e0695da6f5 100644
--- a/src/Compilers/VisualBasic/Test/Syntax/Resource.resx
+++ b/src/Compilers/VisualBasic/Test/Syntax/Resource.resx
@@ -121,6 +121,6 @@
- Resources\VBAllInOne.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+ Resources/VBAllInOne.vb;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
diff --git a/src/Debugging/Microsoft.DiaSymReader.PortablePdb/Microsoft.DiaSymReader.PortablePdb.csproj b/src/Debugging/Microsoft.DiaSymReader.PortablePdb/Microsoft.DiaSymReader.PortablePdb.csproj
index 927f3c9be52883ea29913976e20aac511740dc6b..eb24fc9bb06c0af067e4efa342ae6e7ad1b32d7a 100644
--- a/src/Debugging/Microsoft.DiaSymReader.PortablePdb/Microsoft.DiaSymReader.PortablePdb.csproj
+++ b/src/Debugging/Microsoft.DiaSymReader.PortablePdb/Microsoft.DiaSymReader.PortablePdb.csproj
@@ -29,27 +29,21 @@
False
..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
-
-
+
+ ..\..\..\packages\Microsoft.DiaSymReader.1.0.5\lib\net45\Microsoft.DiaSymReader.dll
+
+
+ ..\..\..\packages\System.IO.FileSystem.4.0.0-beta-22816\lib\portable-wpa81+wp80+win80+net45+aspnetcore50\System.IO.FileSystem.dll
False
-
+
+ ..\..\..\packages\System.IO.FileSystem.Primitives.4.0.0-beta-22816\lib\portable-wpa81+wp80+win80+net45+aspnetcore50\System.IO.FileSystem.Primitives.dll
False
False
-
-
- PreserveNewest
- false
-
-
- PreserveNewest
- false
-
-
@@ -85,4 +79,4 @@
-
\ No newline at end of file
+
diff --git a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
index 2aafbb6a0b2cb7767e74b5157c1e903954924d14..aaa94efb96207eb8d14e3b96dfc479680998370e 100644
--- a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
+++ b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
@@ -794,6 +794,8 @@ class AnonymousFunctions
Using workspace = TestWorkspaceFactory.CreateWorkspace(test)
Dim project = workspace.CurrentSolution.Projects.Single()
+
+ ' Test partial type diagnostic reported on user file.
Dim analyzer = New PartialTypeDiagnosticAnalyzer(indexOfDeclToReportDiagnostic:=1)
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
@@ -813,6 +815,52 @@ class AnonymousFunctions
End Using
End Sub
+
+ Public Sub TestDiagnosticsReportedOnAllPartialDefinitions()
+ Dim test =
+
+
+ public partial class Foo { }
+
+
+ public partial class Foo { }
+
+
+
+
+ Using workspace = TestWorkspaceFactory.CreateWorkspace(test)
+ Dim project = workspace.CurrentSolution.Projects.Single()
+
+ ' Test partial type diagnostic reported on all source files.
+ Dim analyzer = New PartialTypeDiagnosticAnalyzer(indexOfDeclToReportDiagnostic:=Nothing)
+ Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
+ project = project.AddAnalyzerReference(analyzerReference)
+
+ Dim diagnosticService = New TestDiagnosticAnalyzerService()
+
+ Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
+ Assert.Equal(1, descriptorsMap.Count)
+
+ ' Verify project diagnostics contains diagnostics reported on both partial definitions.
+ Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
+ Dim diagnostics = diagnosticService.GetDiagnosticsAsync(project.Solution, project.Id).WaitAndGetResult(CancellationToken.None)
+ Assert.Equal(2, diagnostics.Count())
+ Dim file1HasDiag = False, file2HasDiag = False
+ For Each diagnostic In diagnostics
+ Assert.Equal(PartialTypeDiagnosticAnalyzer.DiagDescriptor.Id, diagnostic.Id)
+ Dim document = project.GetDocument(diagnostic.DocumentId)
+ If document.Name = "Test1.cs" Then
+ file1HasDiag = True
+ ElseIf document.Name = "Test2.cs"
+ file2HasDiag = True
+ End If
+ Next
+
+ Assert.True(file1HasDiag)
+ Assert.True(file2HasDiag)
+ End Using
+ End Sub
+
Private Sub TestCodeBlockAnalyzersForExpressionBody()
Dim test =
@@ -1228,8 +1276,8 @@ public class B
Private Class PartialTypeDiagnosticAnalyzer
Inherits DiagnosticAnalyzer
- Private ReadOnly _indexOfDeclToReportDiagnostic As Integer
- Public Sub New(indexOfDeclToReportDiagnostic As Integer)
+ Private ReadOnly _indexOfDeclToReportDiagnostic As Integer?
+ Public Sub New(indexOfDeclToReportDiagnostic As Integer?)
Me._indexOfDeclToReportDiagnostic = indexOfDeclToReportDiagnostic
End Sub
@@ -1246,7 +1294,15 @@ public class B
End Sub
Private Sub AnalyzeSymbol(context As SymbolAnalysisContext)
- context.ReportDiagnostic(Diagnostic.Create(DiagDescriptor, context.Symbol.Locations.ElementAt(Me._indexOfDeclToReportDiagnostic)))
+ Dim index = 0
+ For Each location In context.Symbol.Locations
+ If Not Me._indexOfDeclToReportDiagnostic.HasValue OrElse Me._indexOfDeclToReportDiagnostic.Value = index Then
+ context.ReportDiagnostic(Diagnostic.Create(DiagDescriptor, location))
+ End If
+
+ index += 1
+ Next
+
End Sub
End Class
@@ -1685,5 +1741,43 @@ namespace ConsoleApplication1
' See https//github.com/dotnet/roslyn/issues/2980 for details.
TestGenericNameCore(test, CSharpGenericNameAnalyzer.Message, CSharpGenericNameAnalyzer.DiagnosticId, New AnalyzerWithNoActions, New CSharpGenericNameAnalyzer)
End Sub
+
+
+ Public Sub TestAnalyzerWithNoSupportedDiagnostics()
+ Dim test =
+
+
+
+
+
+
+ ' Ensure that adding a dummy analyzer with no supported diagnostics doesn't bring down entire analysis.
+ Using workspace = TestWorkspaceFactory.CreateWorkspace(test)
+ Dim project = workspace.CurrentSolution.Projects.Single()
+
+ ' Add analyzer
+ Dim analyzer = New AnalyzerWithNoSupportedDiagnostics()
+ Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
+ project = project.AddAnalyzerReference(analyzerReference)
+
+ Dim diagnosticService = New TestDiagnosticAnalyzerService()
+ Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
+
+ ' Verify available diagnostic descriptors/analyzers
+ Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
+ Assert.Equal(1, descriptorsMap.Count)
+ Assert.Equal(0, descriptorsMap.First().Value.Length)
+
+ Dim document = project.Documents.Single()
+ Dim diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document,
+ document.GetSyntaxRootAsync().WaitAndGetResult(CancellationToken.None).FullSpan,
+ CancellationToken.None).WaitAndGetResult(CancellationToken.None)
+
+ Assert.Equal(0, diagnostics.Count())
+ End Using
+ End Sub
End Class
End Namespace
diff --git a/src/Features/Core/Completion/CompletionOptions.cs b/src/Features/Core/Completion/CompletionOptions.cs
index 971ab21c073f5c32cf8e12f3f14a4c000a71de0f..3bffded10c939765cecb321b1ca09ac57d6bca60 100644
--- a/src/Features/Core/Completion/CompletionOptions.cs
+++ b/src/Features/Core/Completion/CompletionOptions.cs
@@ -8,16 +8,9 @@ internal static class CompletionOptions
{
public const string FeatureName = "Completion";
- [ExportOption]
public static readonly PerLanguageOption HideAdvancedMembers = new PerLanguageOption(FeatureName, "HideAdvancedMembers", defaultValue: false);
-
- [ExportOption]
public static readonly PerLanguageOption IncludeKeywords = new PerLanguageOption(FeatureName, "IncludeKeywords", defaultValue: true);
-
- [ExportOption]
public static readonly PerLanguageOption TriggerOnTyping = new PerLanguageOption(FeatureName, "TriggerOnTyping", defaultValue: true);
-
- [ExportOption]
public static readonly PerLanguageOption TriggerOnTypingLetters = new PerLanguageOption(FeatureName, "TriggerOnTypingLetters", defaultValue: true);
}
}
diff --git a/src/Features/Core/Completion/CompletionOptionsProvider.cs b/src/Features/Core/Completion/CompletionOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..771c41b9c3fe80b917999be59ce88b4c5b92361c
--- /dev/null
+++ b/src/Features/Core/Completion/CompletionOptionsProvider.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.Completion
+{
+ [ExportOptionProvider, Shared]
+ internal class CompletionOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ CompletionOptions.HideAdvancedMembers,
+ CompletionOptions.IncludeKeywords,
+ CompletionOptions.TriggerOnTyping,
+ CompletionOptions.TriggerOnTypingLetters
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/Diagnostics/InternalDiagnosticsOptions.cs b/src/Features/Core/Diagnostics/InternalDiagnosticsOptions.cs
index 675dd1765572ae96c183b8554a6bc90bb185c14e..e6d1396de5329d89e1f1173df92b75105665f3e5 100644
--- a/src/Features/Core/Diagnostics/InternalDiagnosticsOptions.cs
+++ b/src/Features/Core/Diagnostics/InternalDiagnosticsOptions.cs
@@ -8,28 +8,13 @@ internal static class InternalDiagnosticsOptions
{
public const string OptionName = "InternalDiagnosticsOptions";
- [ExportOption]
public static readonly Option BlueSquiggleForBuildDiagnostic = new Option(OptionName, "Blue Squiggle For Build Diagnostic", defaultValue: false);
-
- [ExportOption]
public static readonly Option UseDiagnosticEngineV2 = new Option(OptionName, "Use Diagnostic Engine V2", defaultValue: false);
-
- [ExportOption]
public static readonly Option CompilationEndCodeFix = new Option(OptionName, "Enable Compilation End Code Fix", defaultValue: true);
-
- [ExportOption]
public static readonly Option UseCompilationEndCodeFixHeuristic = new Option(OptionName, "Enable Compilation End Code Fix With Heuristic", defaultValue: true);
-
- [ExportOption]
public static readonly Option BuildErrorIsTheGod = new Option(OptionName, "Make build errors to take over everything", defaultValue: false);
-
- [ExportOption]
public static readonly Option ClearLiveErrorsForProjectBuilt = new Option(OptionName, "Clear all live errors of projects that got built", defaultValue: false);
-
- [ExportOption]
public static readonly Option PreferLiveErrorsOnOpenedFiles = new Option(OptionName, "Live errors will be preferred over errors from build on opened files from same analyzer", defaultValue: true);
-
- [ExportOption]
public static readonly Option PreferBuildErrorsOverLiveErrors = new Option(OptionName, "Errors from build will be preferred over live errors from same analyzer", defaultValue: true);
}
}
diff --git a/src/Features/Core/Diagnostics/InternalDiagnosticsOptionsProvider.cs b/src/Features/Core/Diagnostics/InternalDiagnosticsOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a783f7cbe8464468fdafaeaad74bcc94d24a4b81
--- /dev/null
+++ b/src/Features/Core/Diagnostics/InternalDiagnosticsOptionsProvider.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.Diagnostics
+{
+ [ExportOptionProvider, Shared]
+ internal class InternalDiagnosticsOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ InternalDiagnosticsOptions.BlueSquiggleForBuildDiagnostic,
+ InternalDiagnosticsOptions.UseDiagnosticEngineV2,
+ InternalDiagnosticsOptions.CompilationEndCodeFix,
+ InternalDiagnosticsOptions.UseCompilationEndCodeFixHeuristic,
+ InternalDiagnosticsOptions.BuildErrorIsTheGod,
+ InternalDiagnosticsOptions.ClearLiveErrorsForProjectBuilt,
+ InternalDiagnosticsOptions.PreferLiveErrorsOnOpenedFiles,
+ InternalDiagnosticsOptions.PreferBuildErrorsOverLiveErrors
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/ExtractMethod/ExtractMethodOptions.cs b/src/Features/Core/ExtractMethod/ExtractMethodOptions.cs
index ec863d4244c6e9c1f6fe4c436f1728d767e24ea8..05ba16f83699865fcdac9cb8e8af173e24a125e4 100644
--- a/src/Features/Core/ExtractMethod/ExtractMethodOptions.cs
+++ b/src/Features/Core/ExtractMethod/ExtractMethodOptions.cs
@@ -8,13 +8,8 @@ internal static class ExtractMethodOptions
{
public const string FeatureName = "ExtractMethod";
- [ExportOption]
public static readonly PerLanguageOption AllowBestEffort = new PerLanguageOption(FeatureName, "Allow Best Effort", defaultValue: false);
-
- [ExportOption]
public static readonly PerLanguageOption DontPutOutOrRefOnStruct = new PerLanguageOption(FeatureName, "Don't Put Out Or Ref On Strcut", defaultValue: true);
-
- [ExportOption]
public static readonly PerLanguageOption AllowMovingDeclaration = new PerLanguageOption(FeatureName, "Allow Moving Declaration", defaultValue: false);
}
}
diff --git a/src/Features/Core/ExtractMethod/ExtractMethodOptionsProvider.cs b/src/Features/Core/ExtractMethod/ExtractMethodOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d009d4763f5219710243bce1c128b87706964bfc
--- /dev/null
+++ b/src/Features/Core/ExtractMethod/ExtractMethodOptionsProvider.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.ExtractMethod
+{
+ [ExportOptionProvider, Shared]
+ internal class ExtractMethodOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ ExtractMethodOptions.AllowBestEffort,
+ ExtractMethodOptions.DontPutOutOrRefOnStruct,
+ ExtractMethodOptions.AllowMovingDeclaration
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/Features.csproj b/src/Features/Core/Features.csproj
index eae56c20eabd91313a93d4411ed69ebf0b55ac20..73b2d3ccee136f3ddb07425ae424a4f7fc39bbec 100644
--- a/src/Features/Core/Features.csproj
+++ b/src/Features/Core/Features.csproj
@@ -47,10 +47,6 @@
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}
CodeAnalysis
-
- {2e87fa96-50bb-4607-8676-46521599f998}
- Workspaces.Desktop
-
{5F8D2414-064A-4B3A-9B42-8E2A04246BE5}
Workspaces
@@ -159,6 +155,7 @@
+
@@ -187,6 +184,7 @@
+
@@ -235,6 +233,7 @@
+
True
True
@@ -252,7 +251,10 @@
+
+
+
@@ -512,6 +514,7 @@
+
@@ -539,8 +542,6 @@
-
-
diff --git a/src/Features/Core/Shared/Options/OrganizerOptions.cs b/src/Features/Core/Shared/Options/OrganizerOptions.cs
index 2f6da3d9219f4f29505bc968d5a73cc1351f704a..fa5cf5d16dc3b285ef8dff25ab3c636230d27d63 100644
--- a/src/Features/Core/Shared/Options/OrganizerOptions.cs
+++ b/src/Features/Core/Shared/Options/OrganizerOptions.cs
@@ -11,7 +11,7 @@ internal partial class OrganizerOptions
public static PerLanguageOption PlaceSystemNamespaceFirst
{
- get { return Microsoft.CodeAnalysis.Editing.GenerationOptions.PlaceSystemNamespaceFirst; }
+ get { return Editing.GenerationOptions.PlaceSystemNamespaceFirst; }
}
///
@@ -20,7 +20,6 @@ public static PerLanguageOption PlaceSystemNamespaceFirst
/// maintain any customized value for this setting, even through versions that have not
/// implemented this feature yet.
///
- [ExportOption]
public static readonly PerLanguageOption WarnOnBuildErrors = new PerLanguageOption(FeatureName, "WarnOnBuildErrors", defaultValue: true);
}
}
diff --git a/src/Features/Core/Shared/Options/OrganizerOptionsProvider.cs b/src/Features/Core/Shared/Options/OrganizerOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8786fc18f1476ccfe6dbca3216f09d0215a86979
--- /dev/null
+++ b/src/Features/Core/Shared/Options/OrganizerOptionsProvider.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.Shared.Options
+{
+ [ExportOptionProvider, Shared]
+ internal class OrganizerOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ OrganizerOptions.WarnOnBuildErrors
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/Shared/Options/ServiceComponentOnOffOptions.cs b/src/Features/Core/Shared/Options/ServiceComponentOnOffOptions.cs
index 6fb708ac1caa527f4fa6bd38c2b0230ee0301091..fe20cbbde4157df9895fe849bc5fd3a020075cba 100644
--- a/src/Features/Core/Shared/Options/ServiceComponentOnOffOptions.cs
+++ b/src/Features/Core/Shared/Options/ServiceComponentOnOffOptions.cs
@@ -11,7 +11,6 @@ internal static class ServiceComponentOnOffOptions
{
public const string OptionName = "FeatureManager/Components";
- [ExportOption]
public static readonly Option DiagnosticProvider = new Option(OptionName, "Diagnostic Provider", defaultValue: true);
}
}
diff --git a/src/Features/Core/Shared/Options/ServiceComponentOnOffOptionsProvider.cs b/src/Features/Core/Shared/Options/ServiceComponentOnOffOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..673da97568c1a692c307aa8bac8f49f316d0b5bf
--- /dev/null
+++ b/src/Features/Core/Shared/Options/ServiceComponentOnOffOptionsProvider.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.Shared.Options
+{
+ [ExportOptionProvider, Shared]
+ internal class ServiceComponentOnOffOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ ServiceComponentOnOffOptions.DiagnosticProvider
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptions.cs b/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptions.cs
index 9368f9d34cf0e4b7bc826ae6dbf242f7bf13eb93..5f443e8162529e28a3afdf64588cfac26e429907 100644
--- a/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptions.cs
+++ b/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptions.cs
@@ -8,7 +8,6 @@ internal static class ServiceFeatureOnOffOptions
{
public const string OptionName = "ServiceFeaturesOnOff";
- [ExportOption]
public static readonly PerLanguageOption ClosedFileDiagnostic = new PerLanguageOption(OptionName, "Closed File Diagnostic", defaultValue: true);
}
}
diff --git a/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptionsProvider.cs b/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..50351f662f2dbef28c535e3271f65931b3ec9920
--- /dev/null
+++ b/src/Features/Core/Shared/Options/ServiceFeatureOnOffOptionsProvider.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.Shared.Options
+{
+ [ExportOptionProvider, Shared]
+ internal class ServiceFeatureOnOffOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ ServiceFeatureOnOffOptions.ClosedFileDiagnostic
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
index 312e87eb53b2a1adb7980ea7090c24ef07ebcb00..fbe63d865364d8bca851842a92818312b6faaf24 100644
--- a/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
+++ b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
@@ -8,25 +8,12 @@ internal static class InternalSolutionCrawlerOptions
{
public const string OptionName = "SolutionCrawler";
- [ExportOption]
public static readonly Option SolutionCrawler = new Option("FeatureManager/Components", "Solution Crawler", defaultValue: true);
-
- [ExportOption]
public static readonly Option ActiveFileWorkerBackOffTimeSpanInMS = new Option(OptionName, "Active file worker backoff timespan in ms", defaultValue: 800);
-
- [ExportOption]
public static readonly Option AllFilesWorkerBackOffTimeSpanInMS = new Option(OptionName, "All files worker backoff timespan in ms", defaultValue: 1500);
-
- [ExportOption]
public static readonly Option EntireProjectWorkerBackOffTimeSpanInMS = new Option(OptionName, "Entire project analysis worker backoff timespan in ms", defaultValue: 5000);
-
- [ExportOption]
public static readonly Option SemanticChangeBackOffTimeSpanInMS = new Option(OptionName, "Semantic change backoff timespan in ms", defaultValue: 100);
-
- [ExportOption]
public static readonly Option ProjectPropagationBackOffTimeSpanInMS = new Option(OptionName, "Project propagation backoff timespan in ms", defaultValue: 500);
-
- [ExportOption]
public static readonly Option PreviewBackOffTimeSpanInMS = new Option(OptionName, "Preview backoff timespan in ms", defaultValue: 500);
}
}
diff --git a/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptionsProvider.cs b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptionsProvider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..053cc1f283e863a065ea4f212060486dcd768539
--- /dev/null
+++ b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptionsProvider.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+
+namespace Microsoft.CodeAnalysis.SolutionCrawler
+{
+ [ExportOptionProvider, Shared]
+ internal class InternalSolutionCrawlerOptionsProvider : IOptionProvider
+ {
+ private readonly IEnumerable _options = new List
+ {
+ InternalSolutionCrawlerOptions.SolutionCrawler,
+ InternalSolutionCrawlerOptions.ActiveFileWorkerBackOffTimeSpanInMS,
+ InternalSolutionCrawlerOptions.AllFilesWorkerBackOffTimeSpanInMS,
+ InternalSolutionCrawlerOptions.EntireProjectWorkerBackOffTimeSpanInMS,
+ InternalSolutionCrawlerOptions.SemanticChangeBackOffTimeSpanInMS,
+ InternalSolutionCrawlerOptions.ProjectPropagationBackOffTimeSpanInMS,
+ InternalSolutionCrawlerOptions.PreviewBackOffTimeSpanInMS
+ }.ToImmutableArray();
+
+ public IEnumerable GetOptions()
+ {
+ return _options;
+ }
+ }
+}
diff --git a/src/Features/Core/Workspace/FileTracker.cs b/src/Features/Core/Workspace/FileTracker.cs
deleted file mode 100644
index a2869f67f4190f98e1aeb76807b6c4970bb80552..0000000000000000000000000000000000000000
--- a/src/Features/Core/Workspace/FileTracker.cs
+++ /dev/null
@@ -1,191 +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.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Roslyn.Utilities;
-
-namespace Microsoft.CodeAnalysis.Host
-{
- ///
- /// A class that tracks file changes on disk and invokes user actions
- /// when changes happen.
- ///
- internal class FileTracker
- {
- // guards watchers and actions
- private readonly NonReentrantLock _guard = new NonReentrantLock();
-
- private readonly Dictionary _watchers =
- new Dictionary();
-
- private readonly Dictionary _fileActionsMap =
- new Dictionary();
-
- public FileTracker()
- {
- }
-
- private FileActions GetFileActions_NoLock(string path)
- {
- _guard.AssertHasLock();
-
- FileActions actions;
-
- if (!_fileActionsMap.TryGetValue(path, out actions))
- {
- actions = new FileActions(this, path);
- _fileActionsMap.Add(path, actions);
- }
-
- return actions;
- }
-
- public bool IsTracking(string path)
- {
- if (path == null)
- {
- return false;
- }
-
- using (_guard.DisposableWait())
- {
- return _fileActionsMap.ContainsKey(path);
- }
- }
-
- public void Track(string path, Action action)
- {
- if (path == null)
- {
- throw new ArgumentNullException(nameof(path));
- }
-
- using (_guard.DisposableWait())
- {
- var fileActions = this.GetFileActions_NoLock(path);
- fileActions.AddAction_NoLock(action);
-
- var directory = Path.GetDirectoryName(path);
- if (!_watchers.ContainsKey(directory))
- {
- var watcher = new FileSystemWatcher(directory);
- watcher.Changed += OnFileChanged;
- watcher.EnableRaisingEvents = true;
- }
- }
- }
-
- public void StopTracking(string path)
- {
- if (path != null)
- {
- using (_guard.DisposableWait())
- {
- _fileActionsMap.Remove(path);
- }
- }
- }
-
- private void OnFileChanged(object sender, FileSystemEventArgs args)
- {
- FileActions actions;
-
- using (_guard.DisposableWait())
- {
- actions = this.GetFileActions_NoLock(args.FullPath);
- }
-
- actions.InvokeActions();
- }
-
- public void Dispose()
- {
- using (_guard.DisposableWait())
- {
- foreach (var watcher in _watchers.Values)
- {
- watcher.Dispose();
- }
-
- _watchers.Clear();
- _fileActionsMap.Clear();
- }
- }
-
- private class FileActions
- {
- private readonly FileTracker _tracker;
- private readonly string _path;
- private ImmutableArray _actions;
- private Task _invokeTask;
-
- public FileActions(FileTracker tracker, string path)
- {
- _tracker = tracker;
- _path = path;
- _actions = ImmutableArray.Create();
- }
-
- public void AddAction_NoLock(Action action)
- {
- _tracker._guard.AssertHasLock();
-
- _actions = _actions.Add(action);
- }
-
- public void InvokeActions()
- {
- using (_tracker._guard.DisposableWait())
- {
- // only start invoke task if one is not already running
- if (_invokeTask == null)
- {
- _invokeTask = Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);
- _invokeTask.ContinueWithAfterDelay(() => TryInvokeActions(_actions), CancellationToken.None, 100, TaskContinuationOptions.None, TaskScheduler.Current);
- }
- }
- }
-
- private void TryInvokeActions(ImmutableArray actions)
- {
- if (actions.Length == 0)
- {
- return;
- }
-
- // only invoke actions if the writer that caused the event is done
- // determine this by checking to see if we can read the file
- using (var stream = Kernel32File.Open(_path, FileAccess.Read, FileMode.Open, throwException: false))
- {
- if (stream != null)
- {
- stream.Close();
-
- foreach (var action in actions)
- {
- action();
- }
-
- // clear invoke task so any following changes get additional invocations
- using (_tracker._guard.DisposableWait())
- {
- _invokeTask = null;
- }
- }
- else
- {
- // try again after a short delay
- using (_tracker._guard.DisposableWait())
- {
- _invokeTask.ContinueWithAfterDelay(() => TryInvokeActions(_actions), CancellationToken.None, 100, TaskContinuationOptions.None, TaskScheduler.Current);
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/Features/Core/Workspace/Kernel32File.cs b/src/Features/Core/Workspace/Kernel32File.cs
deleted file mode 100644
index 311a360e6e041e89244413cc7e5f45b99c048af0..0000000000000000000000000000000000000000
--- a/src/Features/Core/Workspace/Kernel32File.cs
+++ /dev/null
@@ -1,93 +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.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-using IO = System.IO;
-
-namespace Microsoft.CodeAnalysis.Host
-{
- internal static class Kernel32File
- {
- internal static IO.FileStream Open(string path, IO.FileAccess access, IO.FileMode mode, IO.FileShare share = IO.FileShare.None, bool throwException = true)
- {
- var fileHandle = CreateFile(path, GetFileAccess(access), GetFileShare(share), default(IntPtr), GetFileMode(mode));
-
- if (fileHandle.IsInvalid)
- {
- if (throwException)
- {
- HandleCOMError(Marshal.GetLastWin32Error());
- }
- else
- {
- return null;
- }
- }
-
- return new IO.FileStream(fileHandle, access);
- }
-
- [Flags]
- private enum FileShare
- {
- FILE_SHARE_NONE = 0x00,
- FILE_SHARE_READ = 0x01,
- FILE_SHARE_WRITE = 0x02,
- FILE_SHARE_DELETE = 0x04
- }
-
- private enum FileMode
- {
- CREATE_NEW = 1,
- CREATE_ALWAYS = 2,
- OPEN_EXISTING = 3,
- OPEN_ALWAYS = 4,
- TRUNCATE_EXISTING = 5
- }
-
- private enum FileAccess
- {
- GENERIC_READ = unchecked((int)0x80000000),
- GENERIC_WRITE = 0x40000000
- }
-
- [DllImport("kernel32", SetLastError = true)]
- private static extern SafeFileHandle CreateFile(string filename,
- FileAccess desiredAccess,
- FileShare shareMode,
- IntPtr attributes,
- FileMode creationDisposition,
- uint flagsAndAttributes = 0,
- IntPtr templateFile = default(IntPtr));
-
- private static void HandleCOMError(int error)
- {
- throw new System.ComponentModel.Win32Exception(error);
- }
-
- private static FileMode GetFileMode(IO.FileMode mode)
- {
- if (mode != IO.FileMode.Append)
- {
- return (FileMode)(int)mode;
- }
- else
- {
- return (FileMode)(int)IO.FileMode.OpenOrCreate;
- }
- }
-
- private static FileAccess GetFileAccess(IO.FileAccess access)
- {
- return access == IO.FileAccess.Read ?
- FileAccess.GENERIC_READ :
- FileAccess.GENERIC_WRITE;
- }
-
- private static FileShare GetFileShare(IO.FileShare share)
- {
- return (FileShare)(int)share;
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/AsyncLambdaAnalyzer.cs b/src/Samples/CSharp/AsyncPackage/AsyncLambdaAnalyzer.cs
deleted file mode 100644
index bc6f8793da819ce03d367ebfe083375165716498..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/AsyncLambdaAnalyzer.cs
+++ /dev/null
@@ -1,101 +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.Immutable;
-using System.Linq;
-using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace AsyncPackage
-{
- ///
- /// Analyzer that examines async lambdas and checks if they are being passed or stored as void-returning delegate types.
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class AsyncLambdaAnalyzer : DiagnosticAnalyzer
- {
- internal const string AsyncLambdaId1 = "Async003";
- internal const string AsyncLambdaId2 = "Async004";
-
- internal static DiagnosticDescriptor Rule1 = new DiagnosticDescriptor(id: AsyncLambdaId1,
- title: "Don't Pass Async Lambdas as Void Returning Delegate Types",
- messageFormat: "This async lambda is passed as a void-returning delegate type",
- category: "Usage",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- internal static DiagnosticDescriptor Rule2 = new DiagnosticDescriptor(id: AsyncLambdaId2,
- title: "Don't Store Async Lambdas as Void Returning Delegate Types",
- messageFormat: "This async lambda is stored as a void-returning delegate type",
- category: "Usage",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- public override void Initialize(AnalysisContext context)
- {
- context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ParenthesizedLambdaExpression, SyntaxKind.SimpleLambdaExpression, SyntaxKind.AnonymousMethodExpression);
- }
-
- public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule1, Rule2); } }
-
- private void AnalyzeNode(SyntaxNodeAnalysisContext context)
- {
- var symbol = context.SemanticModel.GetSymbolInfo(context.Node).Symbol;
-
- var methodLambda = symbol as IMethodSymbol;
-
- if (methodLambda != null && methodLambda.IsAsync)
- {
- var type = context.SemanticModel.GetTypeInfo(context.Node);
- if (this.CheckIfVoidReturningDelegateType(type.ConvertedType))
- {
- // check if the lambda is being assigned to a variable. This has a code fix.
- var parent = context.Node.Parent;
-
- while (parent != null && !(parent is InvocationExpressionSyntax))
- {
- if (parent is VariableDeclarationSyntax)
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule2, parent.GetLocation()));
- return;
- }
-
- parent = parent.Parent;
- }
-
- // if not, add the normal diagnostic
- context.ReportDiagnostic(Diagnostic.Create(Rule1, context.Node.GetLocation()));
- return;
- }
- }
-
- return;
- }
-
- ///
- /// Check if the method is a void returning delegate type
- ///
- ///
- ///
- /// Returns false if analysis failed or if not a void-returning delegate type
- /// Returns true if the inputted node has a converted type that is a void-returning delegate type
- ///
- private bool CheckIfVoidReturningDelegateType(ITypeSymbol convertedType)
- {
- if (convertedType != null && convertedType.TypeKind.Equals(TypeKind.Delegate))
- {
- var invoke = convertedType.GetMembers("Invoke").FirstOrDefault() as IMethodSymbol;
-
- if (invoke != null)
- {
- return invoke.ReturnsVoid;
- }
- }
-
- return false;
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/AsyncLambdaVariableCodeFix.cs b/src/Samples/CSharp/AsyncPackage/AsyncLambdaVariableCodeFix.cs
deleted file mode 100644
index e7a8fa687c3e5d62d663c0c6c0d9b6326012bda0..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/AsyncLambdaVariableCodeFix.cs
+++ /dev/null
@@ -1,91 +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.Immutable;
-using System.Composition;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeActions;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.Simplification;
-
-namespace AsyncPackage
-{
- ///
- /// Codefix that changes the type of a variable to be Func of Task instead of a void-returning delegate type.
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = AsyncLambdaAnalyzer.AsyncLambdaId1), Shared]
- public class AsyncLambdaVariableCodeFix : CodeFixProvider
- {
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(AsyncLambdaAnalyzer.AsyncLambdaId1); }
- }
-
- public sealed override FixAllProvider GetFixAllProvider()
- {
- return null;
- }
-
- public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
- {
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-
- var diagnostic = context.Diagnostics.First();
- var diagnosticSpan = diagnostic.Location.SourceSpan;
-
- Debug.Assert(root != null);
- var parent = root.FindToken(diagnosticSpan.Start).Parent;
- if (parent != null)
- {
- // Find the type declaration identified by the diagnostic.
- var variableDeclaration = parent.FirstAncestorOrSelf();
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new AsyncLambdaVariableCodeAction("Async lambdas should not be stored in void-returning delegates",
- c => ChangeToFunc(context.Document, variableDeclaration, c)),
- diagnostic);
- }
- }
-
- private async Task ChangeToFunc(Document document, VariableDeclarationSyntax variableDeclaration, CancellationToken cancellationToken)
- {
- // Change the variable declaration
- var newDeclaration = variableDeclaration.WithType(SyntaxFactory.ParseTypeName("System.Func").WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation)
- .WithLeadingTrivia(variableDeclaration.Type.GetLeadingTrivia()).WithTrailingTrivia(variableDeclaration.Type.GetTrailingTrivia()));
-
- var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var newRoot = oldRoot.ReplaceNode(variableDeclaration, newDeclaration);
- var newDocument = document.WithSyntaxRoot(newRoot);
-
- // Return document with transformed tree.
- return newDocument;
- }
-
- private class AsyncLambdaVariableCodeAction : CodeAction
- {
- private Func> _generateDocument;
- private string _title;
-
- public AsyncLambdaVariableCodeAction(string title, Func> generateDocument)
- {
- _title = title;
- _generateDocument = generateDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _generateDocument(cancellationToken);
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj b/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj
deleted file mode 100644
index 21c408935b53ac9c4ece4e75df68340ff748b052..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj
+++ /dev/null
@@ -1,196 +0,0 @@
-
-
-
-
-
-
- Debug
- AnyCPU
- 2.0
- {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {68D3FDD2-DA02-453B-9DF9-022F65F9265E}
- Library
- Properties
- AsyncPackage
- AsyncPackage
- v4.6
- false
- true
- true
- false
- RoslynDev
- 14.0
-
-
- 4.0
-
- publish\
- true
- Disk
- false
- Foreground
- 7
- Days
- false
- false
- true
- 0
- 1.0.0.%2a
- false
- false
- true
- true
- ..\..\..\
- SAK
- SAK
- SAK
- SAK
-
-
- true
- full
- false
- bin\Debug\
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- prompt
- 4
-
-
- Program
- $(DevEnvDir)devenv.exe
- /rootsuffix RoslynDev /log
-
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.dll
- false
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.CSharp.dll
- false
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.CSharp.Workspaces.dll
- false
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.VisualBasic.dll
- false
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll
- false
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.Workspaces.dll
- false
-
-
-
-
- False
- ..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
-
-
-
- False
- ..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll
-
-
- False
- ..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll
-
-
- False
- ..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll
-
-
- False
- ..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll
-
-
- False
- ..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll
-
-
-
-
-
- False
- ..\..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
- Designer
-
-
-
-
- Designer
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
-
-
-
-
-
- False
- Microsoft .NET Framework 4.5 %28x86 and x64%29
- true
-
-
- False
- .NET Framework 3.5 SP1 Client Profile
- false
-
-
- False
- .NET Framework 3.5 SP1
- false
-
-
-
- 11.0
- $(VisualStudioVersion)
- $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
-
-
-
-
-
-
-
-
-
diff --git a/src/Samples/CSharp/AsyncPackage/AsyncVoidAnalyzer.cs b/src/Samples/CSharp/AsyncPackage/AsyncVoidAnalyzer.cs
deleted file mode 100644
index c019568b7e6bb13a3b2b935ed96f80fc4afcc5a9..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/AsyncVoidAnalyzer.cs
+++ /dev/null
@@ -1,78 +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.Immutable;
-using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace AsyncPackage
-{
- ///
- /// This Analyzer determines if a method is Async and needs to be returning a Task instead of having a void return type.
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
- public class AsyncVoidAnalyzer : DiagnosticAnalyzer
- {
- internal const string AsyncVoidId = "Async001";
-
- internal static DiagnosticDescriptor VoidReturnType = new DiagnosticDescriptor(id: AsyncVoidId,
- title: "Avoid Async Void",
- messageFormat: "This method has the async keyword but it returns void",
- category: "Usage",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- public override void Initialize(AnalysisContext context)
- {
- context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.Method);
- }
-
- public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(VoidReturnType); } }
-
- private void AnalyzeSymbol(SymbolAnalysisContext context)
- {
- // Filter out methods that do not use Async and that do not have exactly two parameters
- var methodSymbol = (IMethodSymbol)context.Symbol;
-
- var eventType = context.Compilation.GetTypeByMetadataName("System.EventArgs");
-
- if (methodSymbol.ReturnsVoid && methodSymbol.IsAsync)
- {
- if (methodSymbol.Parameters.Length == 2)
- {
- var firstParam = methodSymbol.Parameters[0];
- var secondParam = methodSymbol.Parameters[1];
-
- if (firstParam is object)
- {
- // Check each parameter for EventHandler shape and return if it matches.
- if (firstParam.Name.ToLower().Equals("sender") && secondParam.Type == eventType)
- {
- return;
- }
- else
- {
- // Check if the second parameter implements EventArgs. If it does; return.
- var checkForEventType = secondParam.Type.BaseType;
- while (checkForEventType.OriginalDefinition != context.Compilation.GetTypeByMetadataName("System.Object"))
- {
- if (checkForEventType == eventType)
- {
- return;
- }
-
- checkForEventType = checkForEventType.BaseType;
- }
- }
- }
- }
-
- context.ReportDiagnostic(Diagnostic.Create(VoidReturnType, methodSymbol.Locations[0], methodSymbol.Name));
- return;
- }
-
- return;
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/AsyncVoidCodeFix.cs b/src/Samples/CSharp/AsyncPackage/AsyncVoidCodeFix.cs
deleted file mode 100644
index 3c4c99652ce76926ee0e2f18b9336641012c0eb5..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/AsyncVoidCodeFix.cs
+++ /dev/null
@@ -1,85 +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.Immutable;
-using System.Composition;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeActions;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Simplification;
-
-namespace AsyncPackage
-{
- ///
- /// This codefix replaces the void return type with Task in any method declaration the AsyncVoidAnalyzer catches
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = AsyncVoidAnalyzer.AsyncVoidId), Shared]
- public class AsyncVoidCodeFix : CodeFixProvider
- {
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(AsyncVoidAnalyzer.AsyncVoidId); }
- }
-
- public sealed override FixAllProvider GetFixAllProvider()
- {
- return null;
- }
-
- public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
- {
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-
- var diagnostic = context.Diagnostics.First();
- var diagnosticSpan = diagnostic.Location.SourceSpan;
-
- // Find the type declaration identified by the diagnostic.
- var methodDeclaration = root.FindToken(diagnosticSpan.Start).Parent.FirstAncestorOrSelf();
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new AsyncVoidCodeAction("Async methods should not return void",
- c => VoidToTaskAsync(context.Document, methodDeclaration, c)),
- diagnostic);
- }
-
- private async Task VoidToTaskAsync(Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken)
- {
- // The Task object must be parsed from a string using the Syntax Factory
- var newType = SyntaxFactory.ParseTypeName("System.Threading.Tasks.Task").WithAdditionalAnnotations(Simplifier.Annotation).WithTrailingTrivia(methodDeclaration.ReturnType.GetTrailingTrivia());
-
- var newMethodDeclaration = methodDeclaration.WithReturnType(newType);
-
- var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var newRoot = oldRoot.ReplaceNode(methodDeclaration, newMethodDeclaration);
- var newDocument = document.WithSyntaxRoot(newRoot);
-
- // Return document with transformed tree.
- return newDocument;
- }
-
- private class AsyncVoidCodeAction : CodeAction
- {
- private Func> _createDocument;
- private string _title;
-
- public AsyncVoidCodeAction(string title, Func> createDocument)
- {
- _title = title;
- _createDocument = createDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _createDocument(cancellationToken);
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/BlockingAsyncAnalyzer.cs b/src/Samples/CSharp/AsyncPackage/BlockingAsyncAnalyzer.cs
deleted file mode 100644
index 3982a1ba127bcd6270cc2bf4550eeb7caa7a9cfc..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/BlockingAsyncAnalyzer.cs
+++ /dev/null
@@ -1,94 +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.Immutable;
-using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace AsyncPackage
-{
- ///
- /// This analyzer checks to see if asynchronous and synchronous code is mixed.
- /// This causes blocking and deadlocks. The analyzer will check when async
- /// methods are used and then checks if synchronous code is used within the method.
- /// A codefix will then change that synchronous code to its asynchronous counterpart.
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class BlockingAsyncAnalyzer : DiagnosticAnalyzer
- {
- internal const string BlockingAsyncId = "Async006";
-
- internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(id: BlockingAsyncId,
- title: "Don't Mix Blocking and Async",
- messageFormat: "This method is blocking on async code",
- category: "Usage",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- public override void Initialize(AnalysisContext context)
- {
- context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.SimpleMemberAccessExpression);
- }
-
- public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
-
- private void AnalyzeNode(SyntaxNodeAnalysisContext context)
- {
- var method = context.SemanticModel.GetEnclosingSymbol(context.Node.SpanStart) as IMethodSymbol;
-
- if (method != null && method.IsAsync)
- {
- var invokeMethod = context.SemanticModel.GetSymbolInfo(context.Node).Symbol as IMethodSymbol;
-
- if (invokeMethod != null && !invokeMethod.IsExtensionMethod)
- {
- // Checks if the Wait method is called within an async method then creates the diagnostic.
- if (invokeMethod.OriginalDefinition.Name.Equals("Wait"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.Parent.GetLocation()));
- return;
- }
-
- // Checks if the WaitAny method is called within an async method then creates the diagnostic.
- if (invokeMethod.OriginalDefinition.Name.Equals("WaitAny"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.Parent.GetLocation()));
- return;
- }
-
- // Checks if the WaitAll method is called within an async method then creates the diagnostic.
- if (invokeMethod.OriginalDefinition.Name.Equals("WaitAll"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.Parent.GetLocation()));
- return;
- }
-
- // Checks if the Sleep method is called within an async method then creates the diagnostic.
- if (invokeMethod.OriginalDefinition.Name.Equals("Sleep"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.Parent.GetLocation()));
- return;
- }
-
- // Checks if the GetResult method is called within an async method then creates the diagnostic.
- if (invokeMethod.OriginalDefinition.Name.Equals("GetResult"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.Parent.GetLocation()));
- return;
- }
- }
-
- var property = context.SemanticModel.GetSymbolInfo(context.Node).Symbol as IPropertySymbol;
-
- // Checks if the Result property is called within an async method then creates the diagnostic.
- if (property != null && property.OriginalDefinition.Name.Equals("Result"))
- {
- context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
- return;
- }
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/BlockingAsyncCodeFix.cs b/src/Samples/CSharp/AsyncPackage/BlockingAsyncCodeFix.cs
deleted file mode 100644
index 9bc0240388825c7be529f105eb93103eb28da3eb..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/BlockingAsyncCodeFix.cs
+++ /dev/null
@@ -1,259 +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.Immutable;
-using System.Composition;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeActions;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.Simplification;
-
-namespace AsyncPackage
-{
- ///
- /// Codefix changes the synchronous operations to it's asynchronous equivalent.
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = BlockingAsyncAnalyzer.BlockingAsyncId), Shared]
- public class BlockingAsyncCodeFix : CodeFixProvider
- {
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(BlockingAsyncAnalyzer.BlockingAsyncId); }
- }
-
- public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
- {
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-
- var diagnostic = context.Diagnostics.First();
- var diagnosticSpan = diagnostic.Location.SourceSpan;
-
- // Find the type declaration identified by the diagnostic.
- var invocation = root.FindToken(diagnosticSpan.Start).Parent.FirstAncestorOrSelf();
- var invokemethod = root.FindToken(diagnosticSpan.Start).Parent.FirstAncestorOrSelf();
-
- var semanticmodel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
-
- var method = semanticmodel.GetEnclosingSymbol(invocation.SpanStart) as IMethodSymbol;
-
- if (method != null && method.IsAsync)
- {
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("Wait"))
- {
- var name = invokemethod.Name.Identifier.Text;
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionChangetoAwaitAsync("Change synchronous operation to asynchronous counterpart",
- c => ChangetoAwaitAsync(context.Document, invocation, name, c)),
- diagnostic);
- return;
- }
-
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("GetAwaiter"))
- {
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionChangetoAwaitGetAwaiterAsync("Change synchronous operation to asynchronous counterpart",
- c => ChangetoAwaitGetAwaiterAsync(context.Document, invocation, c)),
- diagnostic);
- return;
- }
-
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("Result"))
- {
- var name = invokemethod.Name.Identifier.Text;
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionChangetoAwaitAsync("Change synchronous operation to asynchronous counterpart",
- c => ChangetoAwaitAsync(context.Document, invocation, name, c)),
- diagnostic);
- return;
- }
-
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("WaitAny"))
- {
- var name = invokemethod.Name.Identifier.Text;
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionToDelayWhenAnyWhenAllAsync("Change synchronous operation to asynchronous counterpart",
- c => ToDelayWhenAnyWhenAllAsync(context.Document, invocation, name, c)),
- diagnostic);
- return;
- }
-
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("WaitAll"))
- {
- var name = invokemethod.Name.Identifier.Text;
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionToDelayWhenAnyWhenAllAsync("Change synchronous operation to asynchronous counterpart",
- c => ToDelayWhenAnyWhenAllAsync(context.Document, invocation, name, c)),
- diagnostic);
- return;
- }
-
- if (invokemethod != null && invokemethod.Name.Identifier.Text.Equals("Sleep"))
- {
- var name = invokemethod.Name.Identifier.Text;
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CodeActionToDelayWhenAnyWhenAllAsync("Change synchronous operation to asynchronous counterpart",
- c => ToDelayWhenAnyWhenAllAsync(context.Document, invocation, name, c)),
- diagnostic);
- return;
- }
- }
- }
-
- private async Task ToDelayWhenAnyWhenAllAsync(Document document, InvocationExpressionSyntax invocation, string name, CancellationToken cancellationToken)
- {
- var simpleExpression = SyntaxFactory.ParseName("");
- if (name.Equals("WaitAny"))
- {
- simpleExpression = SyntaxFactory.ParseName("System.Threading.Tasks.Task.WhenAny").WithAdditionalAnnotations(Simplifier.Annotation);
- }
- else if (name.Equals("WaitAll"))
- {
- simpleExpression = SyntaxFactory.ParseName("System.Threading.Tasks.Task.WhenAll").WithAdditionalAnnotations(Simplifier.Annotation);
- }
- else if (name.Equals("Sleep"))
- {
- simpleExpression = SyntaxFactory.ParseName("System.Threading.Tasks.Task.Delay").WithAdditionalAnnotations(Simplifier.Annotation);
- }
-
- SyntaxNode oldExpression = invocation;
- var expression = invocation.WithExpression(simpleExpression).WithLeadingTrivia(invocation.GetLeadingTrivia()).WithTrailingTrivia(invocation.GetTrailingTrivia());
-
- var newExpression = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.AwaitExpression, expression.WithLeadingTrivia(SyntaxFactory.Space)).WithTrailingTrivia(invocation.GetTrailingTrivia()).WithLeadingTrivia(invocation.GetLeadingTrivia());
-
- var oldroot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var newroot = oldroot.ReplaceNode(oldExpression, newExpression);
-
- var newDocument = document.WithSyntaxRoot(newroot);
-
- return newDocument;
- }
-
- private async Task ChangetoAwaitAsync(Document document, InvocationExpressionSyntax invocation, string name, CancellationToken cancellationToken)
- {
- SyntaxNode oldExpression = invocation;
- SyntaxNode newExpression = null;
-
- if (name.Equals("Wait"))
- {
- oldExpression = invocation.FirstAncestorOrSelf();
- var identifier = (invocation.Expression as MemberAccessExpressionSyntax).Expression as IdentifierNameSyntax;
- newExpression = SyntaxFactory.PrefixUnaryExpression(
- SyntaxKind.AwaitExpression,
- identifier).WithAdditionalAnnotations(Formatter.Annotation);
- }
-
- if (name.Equals("Result"))
- {
- oldExpression = invocation.Parent.FirstAncestorOrSelf();
- newExpression = SyntaxFactory.PrefixUnaryExpression(
- SyntaxKind.AwaitExpression,
- invocation).WithAdditionalAnnotations(Formatter.Annotation);
- }
-
- var oldroot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var newroot = oldroot.ReplaceNode(oldExpression, newExpression);
-
- var newDocument = document.WithSyntaxRoot(newroot);
-
- return newDocument;
- }
-
- private async Task ChangetoAwaitGetAwaiterAsync(Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationTkn)
- {
- SyntaxNode expression = invocation;
- while (!(expression is ExpressionStatementSyntax))
- {
- expression = expression.Parent;
- }
-
- var oldExpression = expression as ExpressionStatementSyntax;
- var awaitedInvocation = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.AwaitExpression, invocation.WithLeadingTrivia(SyntaxFactory.Space)).WithLeadingTrivia(invocation.GetLeadingTrivia());
- var newExpression = oldExpression.WithExpression(awaitedInvocation);
-
- var oldroot = await document.GetSyntaxRootAsync(cancellationTkn).ConfigureAwait(false);
- var newroot = oldroot.ReplaceNode(oldExpression, newExpression);
- var newDocument = document.WithSyntaxRoot(newroot);
-
- return newDocument;
- }
-
- public sealed override FixAllProvider GetFixAllProvider()
- {
- return null;
- }
-
- private class CodeActionToDelayWhenAnyWhenAllAsync : CodeAction
- {
- private Func> _generateDocument;
- private string _title;
-
- public CodeActionToDelayWhenAnyWhenAllAsync(string title, Func> generateDocument)
- {
- _title = title;
- _generateDocument = generateDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _generateDocument(cancellationToken);
- }
- }
-
- private class CodeActionChangetoAwaitAsync : CodeAction
- {
- private Func> _generateDocument;
- private string _title;
-
- public CodeActionChangetoAwaitAsync(string title, Func> generateDocument)
- {
- _title = title;
- _generateDocument = generateDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _generateDocument(cancellationToken);
- }
- }
-
- private class CodeActionChangetoAwaitGetAwaiterAsync : CodeAction
- {
- private Func> _generateDocument;
- private string _title;
-
- public CodeActionChangetoAwaitGetAwaiterAsync(string title, Func> generateDocument)
- {
- _title = title;
- _generateDocument = generateDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _generateDocument(cancellationToken);
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/CancellationAnalyzer.cs b/src/Samples/CSharp/AsyncPackage/CancellationAnalyzer.cs
deleted file mode 100644
index 4ad1df5e1d881cd0c26fc40fd2a9f988d7e2a26b..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/CancellationAnalyzer.cs
+++ /dev/null
@@ -1,89 +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.Immutable;
-using System.Linq;
-using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace AsyncPackage
-{
- ///
- /// This analyzer check to see if there are Cancellation Tokens that can be propagated through async method calls
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class CancellationAnalyzer : DiagnosticAnalyzer
- {
- internal const string CancellationId = "Async005";
-
- internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(id: CancellationId,
- title: "Propagate CancellationTokens When Possible",
- messageFormat: "This method can take a CancellationToken",
- category: "Library",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- public override void Initialize(AnalysisContext context)
- {
- context.RegisterCodeBlockStartAction(CreateAnalyzerWithinCodeBlock);
- }
-
- public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
-
- private void CreateAnalyzerWithinCodeBlock(CodeBlockStartAnalysisContext context)
- {
- var methodDeclaration = context.OwningSymbol as IMethodSymbol;
-
- if (methodDeclaration != null)
- {
- ITypeSymbol cancellationTokenType = context.SemanticModel.Compilation.GetTypeByMetadataName("System.Threading.CancellationToken");
-
- var paramTypes = methodDeclaration.Parameters.Select(x => x.Type);
-
- if (paramTypes.Contains(cancellationTokenType))
- {
- // Analyze the inside of the code block for invocationexpressions
- context.RegisterSyntaxNodeAction(new CancellationAnalyzer_Inner().AnalyzeNode, SyntaxKind.InvocationExpression);
- }
- }
- }
-
- internal class CancellationAnalyzer_Inner
- {
- public void AnalyzeNode(SyntaxNodeAnalysisContext context)
- {
- var invokeMethod = context.SemanticModel.GetSymbolInfo(context.Node).Symbol as IMethodSymbol;
-
- if (invokeMethod != null)
- {
- ITypeSymbol cancellationTokenType = context.SemanticModel.Compilation.GetTypeByMetadataName("System.Threading.CancellationToken");
-
- var invokeParams = invokeMethod.Parameters.Select(x => x.Type);
-
- if (invokeParams.Contains(cancellationTokenType))
- {
- var passedToken = false;
-
- foreach (var arg in ((InvocationExpressionSyntax)context.Node).ArgumentList.Arguments)
- {
- var thisArgType = context.SemanticModel.GetTypeInfo(arg.Expression).Type;
-
- if (thisArgType != null && thisArgType.Equals(cancellationTokenType))
- {
- passedToken = true;
- }
- }
-
- if (!passedToken)
- {
- context.ReportDiagnostic(Diagnostic.Create(CancellationAnalyzer.Rule, context.Node.GetLocation()));
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/CancellationCodeFix.cs b/src/Samples/CSharp/AsyncPackage/CancellationCodeFix.cs
deleted file mode 100644
index 8fc2264c482b586e6a5ae42b29f7d5b0167789bb..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/CancellationCodeFix.cs
+++ /dev/null
@@ -1,120 +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.Immutable;
-using System.Composition;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeActions;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace AsyncPackage
-{
- ///
- /// Codefix that changes the type of a variable to be Func of Task instead of a void-returning delegate type.
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = CancellationAnalyzer.CancellationId), Shared]
- public class CancellationCodeFix : CodeFixProvider
- {
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(CancellationAnalyzer.CancellationId); }
- }
-
- public sealed override FixAllProvider GetFixAllProvider()
- {
- return null;
- }
-
- public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
- {
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-
- var diagnostic = context.Diagnostics.First();
- var diagnosticSpan = diagnostic.Location.SourceSpan;
-
- // Find the type declaration identified by the diagnostic.
- var invocation = root.FindToken(diagnosticSpan.Start).Parent.FirstAncestorOrSelf();
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new CancellationCodeAction("Propagate CancellationTokens when possible",
- c => AddCancellationTokenAsync(context.Document, invocation, c)),
- diagnostic);
- }
-
- private async Task AddCancellationTokenAsync(Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationToken)
- {
- var semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);
-
- ITypeSymbol cancellationTokenType = semanticModel.Compilation.GetTypeByMetadataName("System.Threading.CancellationToken");
-
- var invocationSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;
-
- // Step up through the syntax tree to get the Method Declaration of the invocation
- var parent = invocation.Parent;
- parent = parent.FirstAncestorOrSelf();
-
- var containingMethod = semanticModel.GetDeclaredSymbol(parent) as IMethodSymbol;
-
- // Get the CancellationToken from the containing method
- var tokens = containingMethod.Parameters.Where(x => x.Type.Equals(cancellationTokenType));
-
- var firstToken = tokens.FirstOrDefault();
-
- // Get what slot to put it in
- var cancelSlots = invocationSymbol.Parameters.Where(x => x.Type.Equals(cancellationTokenType));
-
- if (cancelSlots.FirstOrDefault() == null)
- {
- return document;
- }
-
- var firstSlotIndex = invocationSymbol.Parameters.IndexOf(cancelSlots.FirstOrDefault());
- var newIdentifier = SyntaxFactory.IdentifierName(firstToken.Name.ToString());
- var newArgs = invocation.ArgumentList.Arguments;
-
- if (firstSlotIndex == 0)
- {
- newArgs = newArgs.Insert(firstSlotIndex, SyntaxFactory.Argument(newIdentifier).WithLeadingTrivia());
- }
- else
- {
- newArgs = invocation.ArgumentList.Arguments.Insert(firstSlotIndex, SyntaxFactory.Argument(newIdentifier).WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ElasticSpace)));
- }
-
- var newArgsList = SyntaxFactory.ArgumentList(newArgs);
- var newInvocation = invocation.WithArgumentList(newArgsList);
-
- var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var newRoot = oldRoot.ReplaceNode(invocation, newInvocation);
- var newDocument = document.WithSyntaxRoot(newRoot);
-
- // Return document with transformed tree.
- return newDocument;
- }
-
- private class CancellationCodeAction : CodeAction
- {
- private Func> _createDocument;
- private string _title;
-
- public CancellationCodeAction(string title, Func> createDocument)
- {
- _title = title;
- _createDocument = createDocument;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
- {
- return _createDocument(cancellationToken);
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/Diagnostic.nuspec b/src/Samples/CSharp/AsyncPackage/Diagnostic.nuspec
deleted file mode 100644
index 2f44ea885aadae58eb0d73733d70b184c88797b8..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Diagnostic.nuspec
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- AsyncPackage
- 1.0.0.0
- AsyncPackage
- AsyncPackage
- AsyncPackage
- false
- AsyncPackage
- Summary of changes made in this release of the package.
- Copyright
- Tag1 Tag2
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Samples/CSharp/AsyncPackage/Properties/AssemblyInfo.cs b/src/Samples/CSharp/AsyncPackage/Properties/AssemblyInfo.cs
deleted file mode 100644
index 67888827ec575609a4eb96fb1e60ef0d7bf8b989..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,5 +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.Reflection;
-
-[assembly: AssemblyTitle("AsyncPackage")]
diff --git a/src/Samples/CSharp/AsyncPackage/ReadMe.txt b/src/Samples/CSharp/AsyncPackage/ReadMe.txt
deleted file mode 100644
index 3dbb3a23a15af423273686bbf6dc3b5326f8239c..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/ReadMe.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-
-Building this project will produce an analyzer .dll, as well as the
-following two ways you may wish to package that analyzer:
- * A NuGet package (.nupkg file) that will add your assembly as a
- project-local analyzer that participates in builds.
- * A VSIX extension (.vsix file) that will apply your analyzer to all projects
- and works just in the IDE.
-
-Starting this project will deploy the analyzer as a VSIX into another copy of
-Visual Studio, which is useful for debugging, even if you intend to produce a
-NuGet package.
-
-
-GETTING STARTED WITH NUGET
-
-Before you can produce a NuGet package, you must enable NuGet Package Restore:
- * Right-click the solution in Solution Explorer and choose Enable NuGet
- Package Restore.
-
-This downloads the NuGet binaries that will be used to pack your analyzer into
-a NuGet package. For more information, see
-http://go.microsoft.com/fwlink/?LinkID=322105.
-
-If you do not wish to produce a NuGet package, you can delete the
-Diagnostic.nuspec file to silence the Package Restore warning.
-
-
-TRYING OUT YOUR NUGET PACKAGE
-
-To try out the NuGet package:
- 1. Create a local NuGet feed by following the instructions here:
- > http://docs.nuget.org/docs/creating-packages/hosting-your-own-nuget-feeds
- 2. Copy the .nupkg file into that folder.
- 3. Open the target project in Visual Studio "14".
- 4. Right-click on the project node in Solution Explorer and choose Manage
- NuGet Packages.
- 5. Select the NuGet feed you created on the left.
- 6. Choose your analyzer from the list and click Install.
-
-If you want to automatically deploy the .nupkg file to the local feed folder
-when you build this project, follow these steps:
- 1. Right-click on this project in Solution Explorer and choose Properties.
- 2. Go to the Build Events tab.
- 3. In the "Post-build event command line" box, change the -OutputDirectory
- path to point to your local NuGet feed folder.
diff --git a/src/Samples/CSharp/AsyncPackage/RenameAsyncAnalyzer.cs b/src/Samples/CSharp/AsyncPackage/RenameAsyncAnalyzer.cs
deleted file mode 100644
index 01a29ef7a0acfdc8f42584647ea16c4aecde8ac6..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/RenameAsyncAnalyzer.cs
+++ /dev/null
@@ -1,52 +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.Immutable;
-using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace AsyncPackage
-{
- ///
- /// This analyzer will run a codefix on any method that qualifies as async that renames it to follow naming conventions
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
- public class RenameAsyncAnalyzer : DiagnosticAnalyzer
- {
- internal const string RenameAsyncId = "Async002";
-
- internal static DiagnosticDescriptor RenameAsyncMethod = new DiagnosticDescriptor(id: RenameAsyncId,
- title: "Async Method Names Should End in Async",
- messageFormat: "This method is async but the method name does not end in Async",
- category: "Naming",
- defaultSeverity: DiagnosticSeverity.Warning,
- isEnabledByDefault: true);
-
- public override void Initialize(AnalysisContext context)
- {
- context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.Method);
- }
-
- public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(RenameAsyncMethod); } }
-
- private static void AnalyzeSymbol(SymbolAnalysisContext context)
- {
- // Filter out methods that do not use Async and make sure to include methods that return a Task
- var methodSymbol = (IMethodSymbol)context.Symbol;
-
- // Check if method name is an override or virtual class. If it is disregard it.
- // (This assumes if a method is virtual the programmer will not want to change the name)
- // Check if the method returns a Task or Task
- if ((methodSymbol.ReturnType == context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task")
- || methodSymbol.ReturnType.OriginalDefinition == context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1").OriginalDefinition)
- && !methodSymbol.Name.EndsWith("Async") && !methodSymbol.IsOverride && !methodSymbol.IsVirtual)
- {
- context.ReportDiagnostic(Diagnostic.Create(RenameAsyncMethod, methodSymbol.Locations[0], methodSymbol.Name));
- return;
- }
-
- return;
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/RenameAsyncCodeFix.cs b/src/Samples/CSharp/AsyncPackage/RenameAsyncCodeFix.cs
deleted file mode 100644
index 313ce16332e5b69130ab48e79600b5b7d1dd6e54..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/RenameAsyncCodeFix.cs
+++ /dev/null
@@ -1,133 +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.Immutable;
-using System.Composition;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeActions;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Rename;
-
-namespace AsyncPackage
-{
- ///
- /// This codefix adds "Async" to the end of the Method Identifier and does a basic spellcheck in case the user had already tried to type Async
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = RenameAsyncAnalyzer.RenameAsyncId), Shared]
- public class RenameAsyncCodeFix : CodeFixProvider
- {
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(RenameAsyncAnalyzer.RenameAsyncId); }
- }
-
- public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
- {
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-
- var diagnostic = context.Diagnostics.First();
- var diagnosticSpan = diagnostic.Location.SourceSpan;
-
- // Find the type declaration identified by the diagnostic.
- var methodDeclaration = root.FindToken(diagnosticSpan.Start).Parent.FirstAncestorOrSelf();
-
- // Register a code action that will invoke the fix.
- context.RegisterCodeFix(
- new RenameAsyncCodeAction("Add Async to the end of the method name",
- c => RenameMethodAsync(context.Document, methodDeclaration, c)),
- diagnostic);
- }
-
- private async Task RenameMethodAsync(Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken)
- {
- var model = await document.GetSemanticModelAsync().ConfigureAwait(false);
- var oldSolution = document.Project.Solution;
-
- var symbol = model.GetDeclaredSymbol(methodDeclaration);
-
- var oldName = methodDeclaration.Identifier.ToString();
- var newName = string.Empty;
-
- // Check to see if name already contains Async at the end
- if (HasAsyncSuffix(oldName))
- {
- newName = oldName.Substring(0, oldName.Length - 5) + "Async";
- }
- else
- {
- newName = oldName + "Async";
- }
-
- var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, symbol, newName, document.Project.Solution.Workspace.Options).ConfigureAwait(false);
-
- // Gets all identifiers to check for renaming conflicts
- var syntaxTree = await document.GetSyntaxTreeAsync().ConfigureAwait(false);
- var descendentTokens = syntaxTree.GetRoot().DescendantTokens();
-
- var usedNames = descendentTokens.Where(token => token.IsKind(SyntaxKind.IdentifierToken)).Select(token => token.Value);
-
- while (usedNames.Contains(newName))
- {
- // No codefix should be offered if the name conflicts with another method.
- return oldSolution;
- }
-
- return newSolution;
- }
-
- ///
- /// This spellchecker obviously has limitations, but it may be helpful to some.
- ///
- ///
- /// Returns a boolean of whether or not "Async" may have been in the Method name already but was mispelled.
- public bool HasAsyncSuffix(string oldName)
- {
- if (oldName.Length >= 5)
- {
- var last5letters = oldName.Substring(oldName.Length - 5);
-
- // Check case. The A in Async must be capitalized
- if (last5letters.Contains("async") || last5letters.Contains("asinc"))
- {
- return true;
- }
- else if (((last5letters.Contains("A") || last5letters.Contains("a")) && last5letters.Contains("s") && last5letters.Contains("y")
- && last5letters.Contains("n") && last5letters.Contains("c")) && !last5letters.ToLower().Equals("scany"))
- {
- return true; // Basic spellchecker. This is obviously not conclusive, but it may catch a small error if the letters are simply switched around.
- }
- }
-
- return false;
- }
-
- public sealed override FixAllProvider GetFixAllProvider()
- {
- return null;
- }
-
- private class RenameAsyncCodeAction : CodeAction
- {
- private Func> _generateSolution;
- private string _title;
-
- public RenameAsyncCodeAction(string title, Func> generateSolution)
- {
- _title = title;
- _generateSolution = generateSolution;
- }
-
- public override string Title { get { return _title; } }
-
- protected override Task GetChangedSolutionAsync(CancellationToken cancellationToken)
- {
- return base.GetChangedSolutionAsync(cancellationToken);
- }
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/Test/AsyncPackage.Test.csproj b/src/Samples/CSharp/AsyncPackage/Test/AsyncPackage.Test.csproj
deleted file mode 100644
index c7159ea9ecff2c937f9c4beec051a5e049e1214c..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Test/AsyncPackage.Test.csproj
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
-
-
-
- Debug
- AnyCPU
- {0D9287FD-F17F-4CB8-B622-904E69994AC6}
- Library
- Properties
- Tests
- Tests
- v4.6
- 512
- {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- 10.0
- $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
- $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
- False
- UnitTest
- SAK
- SAK
- SAK
- SAK
- ..\..\..\
-
-
- true
- full
- false
- bin\Debug\
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- prompt
- 4
-
-
-
- $(VSLOutDir)\Microsoft.CodeAnalysis.dll
- false
-
-
- False
- (VSLOutDir)\Microsoft.CodeAnalysis.CSharp.dll
- false
-
-
- False
- (VSLOutDir)\Microsoft.CodeAnalysis.CSharp.Workspaces.dll
- false
-
-
- (VSLOutDir)\Microsoft.CodeAnalysis.VisualBasic.dll
- false
-
-
- (VSLOutDir)\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll
- false
-
-
- False
- (VSLOutDir)\Microsoft.CodeAnalysis.Workspaces.dll
- false
-
-
- False
- (VSLOutDir)\Microsoft.CodeAnalysis.Workspaces.Desktop.dll
- false
-
-
-
- False
- ..\..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
-
-
-
-
-
- false
-
-
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {68d3fdd2-da02-453b-9df9-022f65f9265e}
- AsyncPackage
-
-
-
-
-
-
-
-
-
- False
-
-
- False
-
-
- False
-
-
- False
-
-
-
-
-
-
-
-
-
diff --git a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncLambdaTests.cs b/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncLambdaTests.cs
deleted file mode 100644
index f6f75600630ad736b53233a810ca26a973088fc2..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncLambdaTests.cs
+++ /dev/null
@@ -1,313 +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 Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using TestTemplate;
-
-namespace AsyncPackage.Tests
-{
- ///
- /// Unit Tests for the AsyncLambdaDiagnosticAnalzer and AsyncLambdaVariableCodeFix
- ///
- [TestClass]
- public class AsyncLambdaTests : CodeFixVerifier
- {
- private const string DefaultHeader = @"
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics;
-
-namespace ConsoleApplication1
-{
- class Program
- { ";
-
- private const string DefaultFooter = @"
- }
-}";
-
- private DiagnosticResult expected003 = new DiagnosticResult
- {
- Id = "Async003",
- Message = "This async lambda is passed as a void-returning delegate type",
- Severity = DiagnosticSeverity.Warning,
-
- // Location should be changed within test methods
- Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 10) }
- };
-
- private DiagnosticResult expected004 = new DiagnosticResult
- {
- Id = "Async004",
- Message = "This async lambda is stored as a void-returning delegate type",
- Severity = DiagnosticSeverity.Warning,
-
- // Location should be changed within test methods
- Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 10) }
- };
-
- protected override CodeFixProvider GetCSharpCodeFixProvider()
- {
- return new AsyncLambdaVariableCodeFix();
- }
-
- protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
- {
- return new AsyncLambdaAnalyzer();
- }
-
- [TestMethod]
- public void AL001_None_NoMethodNoDiagnostics()
- {
- var test = @"";
-
- VerifyCSharpDiagnostic(test);
- }
-
- [TestMethod]
- public void AL002_DACF_AssignVoidableVariable()
- {
- var body = @"
- public void method()
- {
- //assign to voidable variable
- Action thing = async () =>
- {
- await Task.Delay(500);
- };
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected004.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 17) };
-
- VerifyCSharpDiagnostic(test, expected004);
-
- var fix = @"
- public void method()
- {
- //assign to voidable variable
- Func thing = async () =>
- {
- await Task.Delay(500);
- };
- }";
-
- var testfix = DefaultHeader + fix + DefaultFooter;
-
- // Causes new unused using directory error because the code is not using System.Action anymore
- VerifyCSharpFix(test, testfix, null, true);
- }
-
- // Task function assigned to lambda - no diagnostic should show
- [TestMethod]
- public void AL003_None_TaskReturningDelegateType()
- {
- var body = @"
- static void Main(string[] args)
- {
- //assign as correct variable
- Func thing2 = async () =>
- {
- await Task.Delay(666);
- };
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Method with void-returning delegate type - diagnostic should show on the lambda
- [TestMethod]
- public void AL004_DA_PassAsVoidReturningDelagateType()
- {
- var body = @"
- //bad implementation
- public static double BadMethod(Action action)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = BadMethod(async () =>
- {
- await Task.Delay(1000);
- });
- ";
- var test = DefaultHeader + body + DefaultFooter;
-
- expected003.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 20, 32) };
-
- VerifyCSharpDiagnostic(test, expected003);
- }
-
- // Method with correct delegate type - no diagnostic should show
- [TestMethod]
- public void AL005_None_PassAsTaskReturningDelagateType()
- {
- var body = @"
- //good implementation
- public static double GoodMethod(Func func)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = GoodMethod(async () =>
- {
- await Task.Delay(1000);
- });
- ";
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Lambda overrides a Task function - no diagnostic should show
- [TestMethod]
- public void AL006_None_TaskOverrideDelegateType()
- {
- var body = @"
- static void Main(string[] args)
- {
- //use correct override
- Task.Factory.StartNew(async () =>
- {
- await Task.Delay(12345);
- });
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Test delegate vs => correct - no diagnostic should show
- [TestMethod]
- public void AL007_None_DelegateLambdaTaskReturn()
- {
- var body = @"
- //good implementation
- public static double GoodMethod(Func func)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = GoodMethod(async delegate ()
- {
- await Task.Delay(222);
- });
- ";
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Test delegate vs => incorrect - 1 diagnostic should show
- [TestMethod]
- public void AL008_DA_DelegateLambdaVoidReturn()
- {
- var body = @"
- //good implementation
- public static double BadMethod(Action a)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = BadMethod(async delegate ()
- {
- await Task.Delay(100);
- });
- ";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected003.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 20, 32) };
-
- VerifyCSharpDiagnostic(test, expected003);
- }
-
- // Test simple lambda correct - no diagnostic should show
- [TestMethod]
- public void AL009_None_SimpleLambdaTaskReturn()
- {
- var body = @"
- //good implementation
- public static double GoodMethod(Func func)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = GoodMethod(async () => await Task.Delay(10));
- ";
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Test simple lambda incorrect - 1 diagnostic should show
- [TestMethod]
- public void AL010_DA_SimpleLambdaVoidReturn()
- {
- var body = @"
- //good implementation
- public static double BadMethod(Action a)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = BadMethod(async () => await Task.Delay(10));
- ";
- var test = DefaultHeader + body + DefaultFooter;
-
- expected003.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 20, 32) };
-
- VerifyCSharpDiagnostic(test, expected003);
- }
-
- // Missing necessary using directives - 1 diagnostic
- [TestMethod]
- public void AL011_DA_MissingUsings()
- {
- var body = @"
- using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-
-namespace ConsoleApplication1
-{
- class Program
- {
- //bad implementation
- public static double BadMethod(System.Action action)
- {
- return 0;
- }
-
- //pass as void-returning delegate type
- double num = BadMethod(async () =>
- {
- await System.Threading.Tasks.Task.Delay(1000);
- });
-
- }
-}";
- var test = body;
-
- expected003.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 18, 32) };
-
- VerifyCSharpDiagnostic(test, expected003);
- }
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncVoidTests.cs b/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncVoidTests.cs
deleted file mode 100644
index 0ab39ffb707485a14e2c60eb25e7e65681c1f398..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/AsyncVoidTests.cs
+++ /dev/null
@@ -1,688 +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 Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using TestTemplate;
-
-namespace AsyncPackage.Tests
-{
- ///
- /// Unit Tests for the AsyncVoidAnalyzer and AsyncVoidCodeFix
- ///
- [TestClass]
- public class AsyncVoidTests : CodeFixVerifier
- {
- private const string DefaultHeader = @"
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics;
-
-namespace ConsoleApplication1
-{
- class Program
- { ";
-
- private const string DefaultFooter = @"
- }
-}";
-
- private DiagnosticResult expected001 = new DiagnosticResult
- {
- Id = "Async001",
- Message = "This method has the async keyword but it returns void",
- Severity = DiagnosticSeverity.Warning,
-
- // Location should be changed within test methods
- Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 10) }
- };
-
- protected override CodeFixProvider GetCSharpCodeFixProvider()
- {
- return new AsyncVoidCodeFix();
- }
-
- protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
- {
- return new AsyncVoidAnalyzer();
- }
-
- protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
- {
- return new AsyncVoidAnalyzer();
- }
-
- // No methods - no diagnostic should show
- [TestMethod]
- public void AV001_None_NoMethodNoDiagnostics()
- {
- var body = @"";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - single request - should show no diagnostic
- [TestMethod]
- public void AV002_None_TaskReturnAsyncSingleRequest()
- {
- var body = @"
- public static async Task DelayAsync()
- {
- await Task.Delay(1000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - serial requests - should show no diagnostic
- [TestMethod]
- public void AV003_None_TaskReturnAsyncSerialRequests()
- {
- var body = @"
- public static async Task DelayMultipleTimesAsync()
- {
- await Task.Delay(1000);
- await Task.Delay(1000);
- await Task.Delay(1000);
- await Task.Delay(1000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - parallel requests - should show no diagnostic
- [TestMethod]
- public void AV004_None_TaskReturnAsyncParallelRequests()
- {
- var body = @"
- public async Task SomeAsyncTask()
- { int value = 708;
- await ValuePlusOne(value);
- await ValuePlusTwo(value);
- await ValuePlusThree(value);
- }
-
- public async Task ValuePlusOne(int num)
- {
- await Task.Delay(90);
-
- return num;
- }
-
- public async Task ValuePlusTwo(int num)
- {
- await Task.Delay(990);
-
- return num;
- }
-
- public async Task ValuePlusThree(int num)
- {
- await Task.Delay(9990);
-
- return num;
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - Single request - should show no diagnostic
- [TestMethod]
- public void AV005_None_TaskIntReturnAsyncSingleRequest()
- {
- var body = @"
- public static async Task MultiplyfactorsAsync(int factor1, int factor2)
- {
- await Task.Delay(5000);
- //delay once
-
- return (factor1 * factor2);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - serial requests - should show no diagnostic
- [TestMethod]
- public void AV006_None_TaskIntReturnWithAsync()
- {
- var body = @"
- private async Task MathAsync(int num1)
- {
- //delays
- await Task.Delay(3000);
- await Task.Delay(1000);
- await Task.Delay(num1 * 15);
-
- return (num1);
- } ";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - single request - should show no diagnostic
- [TestMethod]
- public void AV007_None_TaskStringReturnAsyncSingleRequest()
- {
- var body = @"
- public static Task ReturnAAAAsync()
- {
- return Task.Run(() =>
- { return (""AAA""); });
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - serial requests - should show no diagnostic
- [TestMethod]
- public void AV008_None_TaskStringReturnAsyncSerialRequests()
- {
- var body = @"
- public async static Task LongTaskAAsync()
- {
- await Task.Delay(2000);
- await Task.Delay(2000);
- await Task.Delay(2000);
- return await Task.Run(() =>
- {
- return (""AAA"");
- });
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - serial requests - should show no diagnostic
- [TestMethod]
- public void AV009_None_TaskIntReturnAsyncSerialRequests()
- {
- var body = @"
- public static async Task MultiplyAsync(int factor1, int factor2)
- {
- //delay three times
- await Task.Delay(100);
- await Task.Delay(100);
- await Task.Delay(100);
-
- return (factor1 * factor2);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - single request - should show no diagnostic
- [TestMethod]
- public void AV010_None_TaskReturnNoAsyncSingleRequest()
- {
- var body = @"
- public static async Task Delay()
- {
- await Task.Delay(1000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task Return Async Method - serial requests - should show no diagnostic
- [TestMethod]
- public void AV011_None_TaskIntReturnNoAsyncSerialRequests()
- {
- var body = @"
- public static async Task Multiply(int factor1, int factor2)
- {
- //delay three times
- await Task.Delay(100);
- await Task.Delay(100);
- await Task.Delay(100);
-
- return (factor1 * factor2);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Task async method - no diagnostic
- [TestMethod]
- public void AV012_None_TaskBoolReturnAsync()
- {
- var body = @"
- private async Task TrueorFalseAsync(bool trueorfalse)
- {
- await Task.Delay(700);
-
- return !(trueorfalse);
- } ";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Void Return Async Method with Event handling - should show no diagnostic
- [TestMethod]
- public void AV013_None_AsyncVoidWithEventHandling()
- {
- var body = @"
- private async void button1_Click(object sender, EventArgs e)
- {
- await Button1ClickAsync();
- }
- public async Task Button1ClickAsync()
- {
- // Do asynchronous work.
- await Task.Delay(1000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Void Return Async Method - parallel requests - should show 1 diagnostic
- [TestMethod]
- public void AV014_DACF_VoidReturnAsyncParallelRequests()
- {
- var body = @"
- public async void SomeAsyncTask()
- {
- int value = 708;
- await ValuePlusOne(value);
- await ValuePlusTwo(value);
- await ValuePlusThree(value);
- }
-
- public async Task ValuePlusOne(int num)
- {
- await Task.Delay(90);
-
- return num;
- }
-
- public async Task ValuePlusTwo(int num)
- {
- await Task.Delay(990);
-
- return num;
- }
-
- public async Task ValuePlusThree(int num)
- {
- await Task.Delay(9990);
-
- return num;
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected001.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 27) };
-
- VerifyCSharpDiagnostic(test, expected001);
-
- var fixbody = @"
- public async Task SomeAsyncTask()
- {
- int value = 708;
- await ValuePlusOne(value);
- await ValuePlusTwo(value);
- await ValuePlusThree(value);
- }
-
- public async Task ValuePlusOne(int num)
- {
- await Task.Delay(90);
-
- return num;
- }
-
- public async Task ValuePlusTwo(int num)
- {
- await Task.Delay(990);
-
- return num;
- }
-
- public async Task ValuePlusThree(int num)
- {
- await Task.Delay(9990);
-
- return num;
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest);
- }
-
- // No diagnostic shown during async void return when asynchronous event handler is used - parallel requests
- [TestMethod]
- public void AV015_None_VoidReturnaSyncWithEventParallel()
- {
- var body = @"
- private async void button1_Click(object sender, EventArgs e)
- {
- await Button1ClickAsync();
- await Button2ClickAsync();
- }
- public async Task Button1ClickAsync()
- {
- // Do asynchronous work.
- await Task.Delay(1000);
- }
- public async Task Button2ClickAsync()
- {
- //Do asynchronous work.
- await Task.Delay(3000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // No diagnostic shown during async void return when asynchronous event handler is used - serial requests
- [TestMethod]
- public void AV016_None_VoidReturnaSyncWithEventSerial()
- {
- var body = @"
- private async void button1_Click(object sender, EventArgs e)
- {
- await Button1ClickAsync();
- await Button1ClickAsync();
- await Button1ClickAsync();
- }
- public async Task Button1ClickAsync()
- {
- // Do asynchronous work.
- await Task.Delay(1000);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Void Return Async Method with no event handlers - 1 diagnostic should show
- [TestMethod]
- public void AV017_DACF_AsyncVoidWithOutEvent1()
- {
- var body = @"
- public async void AsyncVoidReturnTaskT()
- {
- Console.WriteLine(""Begin Program"");
- Console.WriteLine(await AsyncTaskReturnT());
- Console.WriteLine(""End Program"");
- }
-
- private async Task AsyncTaskReturnT()
- {
- await Task.Delay(65656565);
-
- return ""Program is processing...."";
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected001.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 27) };
-
- VerifyCSharpDiagnostic(test, expected001);
-
- var fixbody = @"
- public async Task AsyncVoidReturnTaskT()
- {
- Console.WriteLine(""Begin Program"");
- Console.WriteLine(await AsyncTaskReturnT());
- Console.WriteLine(""End Program"");
- }
-
- private async Task AsyncTaskReturnT()
- {
- await Task.Delay(65656565);
-
- return ""Program is processing...."";
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest);
- }
-
- // Void Return Async Method with no event handlers - 1 diagnostic should show
- [TestMethod]
- public void AV018_DACF_AsyncVoidWithOutEvent2()
- {
- var body = @"
- private async void WaitForIt(int value)
- {
- await Task.Delay(value);
- }
- private void DoSomethingSilent(int value)
- {
- WaitForIt(value);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected001.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 28) };
-
- VerifyCSharpDiagnostic(test, expected001);
-
- var fixbody = @"
- private async Task WaitForIt(int value)
- {
- await Task.Delay(value);
- }
- private void DoSomethingSilent(int value)
- {
- WaitForIt(value);
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest, null, true);
- }
-
- // Check to make sure the diagnostic still shows for methods with two parameters that are not Event Handlers
- [TestMethod]
- public void AV019_DACF_AsyncVoidTwoParams()
- {
- var body = @"
- private async void WaitForIt(int value, int value2)
- {
- await Task.Delay(value+value2);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected001.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 28) };
-
- VerifyCSharpDiagnostic(test, expected001);
-
- var fixbody = @"
- private async Task WaitForIt(int value, int value2)
- {
- await Task.Delay(value+value2);
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest);
- }
-
- // Check to make sure the diagnostic still shows for methods with a parameter that implements Event Handler
- [TestMethod]
- public void AV020_DA_AsyncVoidImplementsEvent()
- {
- var body = @"
- using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace TestingTemplate
-{
- [TestClass]
- public class UnitTest1
- {
- //Show no diagnostic for a param that implements an EventArgs
- public async void EventHandlerImplementAsync(object sender, ImplementsEvents e)
- {
- await Task.Delay(1000);
- }
- }
- public class ImplementsEvents : EventArgs
- {
- public ImplementsEvents() { }
- }
-}";
- var test = body;
- VerifyCSharpDiagnostic(test);
- }
-
- // Check to make sure the diagnostic still shows for methods with a parameter that implements Event Handler
- [TestMethod]
- public void AV021_DA_AsyncVoidParentImplementsEvent()
- {
- var body = @"
- using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace TestingTemplate
-{
- [TestClass]
- public class UnitTest1
- {
- //Show no diagnostic for a param that implements an EventArgs
- public async void EventHandlerImplementAsync(object sender, ParentImplementsEvents e)
- {
- await Task.Delay(1000);
- }
- }
- public class ImplementsEvents : EventArgs
- {
- public ImplementsEvents() { }
- }
-
- public class ParentImplementsEvents : ImplementsEvents
- {
- public ParentImplementsEvents() { }
- }
-}
-";
- var test = body;
- VerifyCSharpDiagnostic(test);
- }
-
- // Check to make sure the diagnostic still shows for methods with a parameter that implements Event Handler
- [TestMethod]
- public void AV022_DA_AsyncVoidGrandfatherImplementsEvent()
- {
- var body = @"
- using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace TestingTemplate
-{
- [TestClass]
- public class UnitTest1
- {
- //Show no diagnostic for a param that implements an EventArgs
- public async void EventHandlerImplementAsync(object sender, ParentParentImplementsEvents e)
- {
- await Task.Delay(1000);
- }
- }
- public class ImplementsEvents : EventArgs
- {
- public ImplementsEvents() { }
- }
-
- public class ParentImplementsEvents : ImplementsEvents
- {
- public ParentImplementsEvents() { }
- }
- public class ParentParentImplementsEvents : ParentImplementsEvents
- {
- public ParentParentImplementsEvents() { }
- }
-}";
- var test = body;
- VerifyCSharpDiagnostic(test);
- }
-
- #region VB Tests
-
- // Check to make sure the diagnostic appears for VB
- [TestMethod]
- public void AV023_DA_VBDiagnosticSimple()
- {
- var body = @"
-Module Module1
-
- Async Sub example()
- Await Task.Delay(100)
- End Sub
-
-End Module
-";
- var test = body;
-
- DiagnosticResult expected001vb = new DiagnosticResult
- {
- Id = "Async001",
- Message = "This method has the async keyword but it returns void",
- Severity = DiagnosticSeverity.Warning,
- Locations = new[] { new DiagnosticResultLocation("Test0.vb", 4, 15) }
- };
-
- VerifyBasicDiagnostic(test, expected001vb);
- }
-
- // Check to make sure the diagnostic does not appear for the case of VB event handlers
- [TestMethod]
- public void AV024_None_VBEventHandler()
- {
- var body = @"
-imports System
-
-Module Module1
-
- Async Sub event_method(sender As Object, e As EventArgs)
- Await Task.Delay(100)
- End Sub
-
-End Module
-";
- var test = body;
- VerifyBasicDiagnostic(test);
- }
-
- #endregion
- }
-}
diff --git a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/BlockingAsyncTests.cs b/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/BlockingAsyncTests.cs
deleted file mode 100644
index efa6cfc669b2ca1685ffc5cfedb1f9e4d3996fdf..0000000000000000000000000000000000000000
--- a/src/Samples/CSharp/AsyncPackage/Test/Async_Tests/BlockingAsyncTests.cs
+++ /dev/null
@@ -1,714 +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 Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using TestTemplate;
-
-namespace AsyncPackage.Tests
-{
- ///
- /// Unit Tests for the BlockingAsyncAnalyzer and BlockingAsyncCodeFix
- ///
- [TestClass]
- public class BlockingAsyncTests : CodeFixVerifier
- {
- private const string DefaultHeader = @"
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics;
-using System.Threading;
-
-namespace ConsoleApplication1
-{
- class Program
- { ";
-
- private const string DefaultFooter = @"
- }
-}";
-
- private DiagnosticResult expected = new DiagnosticResult
- {
- Id = "Async006",
- Message = "This method is blocking on async code",
- Severity = DiagnosticSeverity.Warning,
-
- // Location should be changed within test methods
- Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 10) }
- };
-
- protected override CodeFixProvider GetCSharpCodeFixProvider()
- {
- return new BlockingAsyncCodeFix();
- }
-
- protected override CodeFixProvider GetBasicCodeFixProvider()
- {
- return new BlockingAsyncCodeFix();
- }
-
- protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
- {
- return new BlockingAsyncAnalyzer();
- }
-
- protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
- {
- return new BlockingAsyncAnalyzer();
- }
-
- // No methods - no diagnostic should show
- [TestMethod]
- public void BA001_None_NoMethodNoDiagnostics()
- {
- var body = @"";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- VerifyCSharpDiagnostic(test);
- }
-
- // Wait block on async code - 1 diagnostic - code fix
- [TestMethod]
- public void BA002_DACF_WaitBlockAsyncCode()
- {
- var body = @"
- async Task fooAsync(int somenumber)
- {
- foo1Async(somenumber).Wait();
- return somenumber;
- }
-
- async Task foo1Async(int value)
- {
- await Task.Yield();
- return value;
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected.Id = "Async006";
- expected.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 13) };
-
- VerifyCSharpDiagnostic(test, expected);
-
- var fixbody = @"
- async Task fooAsync(int somenumber)
- {
- await foo1Async(somenumber);
- return somenumber;
- }
-
- async Task foo1Async(int value)
- {
- await Task.Yield();
- return value;
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest);
- }
-
- // Result block on async code - 1 diagnostic - code fix
- [TestMethod]
- public void BA003_DACF_ResultBlockAsyncCode()
- {
- var body = @"
- async Task foo2Async(int somenumber)
- {
- var temp = foo3Async(somenumber).Result;
- }
-
- async Task foo3Async(int value)
- {
- await Task.Yield();
- return value;
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected.Id = "Async006";
- expected.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 24) };
-
- VerifyCSharpDiagnostic(test, expected);
-
- var fixbody = @"
- async Task foo2Async(int somenumber)
- {
- var temp = await foo3Async(somenumber);
- }
-
- async Task foo3Async(int value)
- {
- await Task.Yield();
- return value;
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpFix(test, fixtest);
- }
-
- // Invocation expression assigned to variable - 1 diagnostic
- [TestMethod]
- public void BA004_DA_InvocationExpressionVariable()
- {
- var body = @"
- async Task> SomeMethodAsync()
- {
- var t = addAsync(25, 50);
- t.Wait();
-
- return t;
- }
-
- async Task addAsync(int num1, int num2)
- {
- await Task.Delay(29292);
- return (num1 + num2);
- }";
-
- var test = DefaultHeader + body + DefaultFooter;
-
- expected.Id = "Async006";
- expected.Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 13) };
-
- var fixbody = @"
- async Task> SomeMethodAsync()
- {
- var t = addAsync(25, 50);
- await t;
-
- return t;
- }
-
- async Task addAsync(int num1, int num2)
- {
- await Task.Delay(29292);
- return (num1 + num2);
- }";
-
- var fixtest = DefaultHeader + fixbody + DefaultFooter;
- VerifyCSharpDiagnostic(test, expected);
- VerifyCSharpFix(test, fixtest);
- }
-
- // Async method using waitall on task - 1 diagnostic - code fix
- [TestMethod]
- public void BA005_DACF_WaitAllBlockAsyncCode()
- {
- var body = @"
- async Task WaitAllAsync()
- //Source: http://msdn.microsoft.com/en-us/library/dd270695(v=vs.110).aspx
- {
- Func
-
-
-
+
+ ..\..\..\packages\System.Reflection.Metadata.$(SystemReflectionMetadataVersion)\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+
+ ..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ ..\..\..\packages\Microsoft.DiaSymReader.1.0.5\lib\net45\Microsoft.DiaSymReader.dll
+
true
@@ -214,4 +220,4 @@
-
\ No newline at end of file
+
diff --git a/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs b/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs
index 377976381a139f6361b973df3ea3597c0d956997..fb44161ae8cf18a3e1fb131bd72b13abfddbb288 100644
--- a/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs
+++ b/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs
@@ -1,7 +1,6 @@
// 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.Globalization;
using System.Linq;
using System.Text;
@@ -464,8 +463,19 @@ protected void GenerateNumber(object value, ITypeSymbol type)
{
using (NumberTag(GetTypeName(type)))
{
- // TODO(DustinCa): Add more unit tests to ensure that floats are correct.
- EncodedText(Convert.ToString(value, CultureInfo.InvariantCulture));
+ if (value is double)
+ {
+ // Note: use G17 for doubles to ensure that we roundtrip properly on 64-bit
+ EncodedText(((double)value).ToString("G17", CultureInfo.InvariantCulture));
+ }
+ else if (value is float)
+ {
+ EncodedText(((float)value).ToString("R", CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ EncodedText(Convert.ToString(value, CultureInfo.InvariantCulture));
+ }
}
}
diff --git a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_CSAssignments.vb b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_CSAssignments.vb
index b1051bc5e8e6c34f32c7c00958d654f336a60171..6b9f00afa7ca66694559b534085dc06b19197a44 100644
--- a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_CSAssignments.vb
+++ b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_CSAssignments.vb
@@ -1142,5 +1142,73 @@ class C
Test(definition, expected)
End Sub
+
+
+ Public Sub CSAssignments_RoundTrippedDoubles()
+ Dim definition =
+
+
+
+class C
+{
+ void $$M()
+ {
+ double d = 9.2233720368547758E+18D;
+ }
+}
+
+
+
+
+ Dim expected =
+
+
+ System.Double
+ d
+
+
+ 9.2233720368547758E+18
+
+
+
+
+
+ Test(definition, expected)
+ End Sub
+
+
+
+ Public Sub CSAssignments_RoundTrippedSingles()
+ Dim definition =
+
+
+
+class C
+{
+ void $$M()
+ {
+ float s = 0.333333343F;
+ }
+}
+
+
+
+
+ Dim expected =
+
+
+ System.Single
+ s
+
+
+ 0.333333343
+
+
+
+
+
+ Test(definition, expected)
+ End Sub
+
End Class
End Namespace
diff --git a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBAssignments.vb b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBAssignments.vb
index 8f34363fc724fae701f5a37bd764126e4bc6fd37..18a781a087a90a95687e3c7f757534412b185184 100644
--- a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBAssignments.vb
+++ b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBAssignments.vb
@@ -990,5 +990,69 @@ End Class
Test(definition, expected)
End Sub
+
+
+ Public Sub VBAssignments_RoundTrippedDoubles()
+ Dim definition =
+
+
+
+Class C
+ Sub $$M()
+ Dim d As Double = 9.2233720368547758E+18R
+ End Sub
+End Class
+
+
+
+
+ Dim expected =
+
+
+ System.Double
+ d
+
+
+ 9.2233720368547758E+18
+
+
+
+
+
+ Test(definition, expected)
+ End Sub
+
+
+
+ Public Sub VBAssignments_RoundTrippedSingles()
+ Dim definition =
+
+
+
+Class C
+ Sub $$M()
+ Dim s As Single = 0.333333343F
+ End Sub
+End Class
+
+
+
+
+ Dim expected =
+
+
+ System.Single
+ s
+
+
+ 0.333333343
+
+
+
+
+
+ Test(definition, expected)
+ End Sub
+
End Class
End Namespace
diff --git a/src/Workspaces/CSharp/Portable/Formatting/FormattingHelpers.cs b/src/Workspaces/CSharp/Portable/Formatting/FormattingHelpers.cs
index 3083e7d6700a39d9e074544385524a4ea6123f98..4db6394cc8945de4ceb56aefa71b496e6ce3602d 100644
--- a/src/Workspaces/CSharp/Portable/Formatting/FormattingHelpers.cs
+++ b/src/Workspaces/CSharp/Portable/Formatting/FormattingHelpers.cs
@@ -61,6 +61,16 @@ public static bool IsValidBracePair(this ValueTuple br
return true;
}
+ public static bool IsOpenParenInParameterListOfAConversionOperatorDeclaration(this SyntaxToken token)
+ {
+ return token.IsOpenParenInParameterList() && token.Parent.IsParentKind(SyntaxKind.ConversionOperatorDeclaration);
+ }
+
+ public static bool IsOpenParenInParameterListOfAOperationDeclaration(this SyntaxToken token)
+ {
+ return token.IsOpenParenInParameterList() && token.Parent.IsParentKind(SyntaxKind.OperatorDeclaration);
+ }
+
public static bool IsOpenParenInParameterList(this SyntaxToken token)
{
return token.Kind() == SyntaxKind.OpenParenToken && token.Parent.Kind() == SyntaxKind.ParameterList;
diff --git a/src/Workspaces/CSharp/Portable/Formatting/Rules/SpacingFormattingRule.cs b/src/Workspaces/CSharp/Portable/Formatting/Rules/SpacingFormattingRule.cs
index e461eff335bfb2c08db3ae7521dcdb1284290be5..39599ff8c1811ded50a0c0cb58a98b34e019ed66 100644
--- a/src/Workspaces/CSharp/Portable/Formatting/Rules/SpacingFormattingRule.cs
+++ b/src/Workspaces/CSharp/Portable/Formatting/Rules/SpacingFormattingRule.cs
@@ -31,6 +31,18 @@ public override AdjustSpacesOperation GetAdjustSpacesOperation(SyntaxToken previ
return AdjustSpacesOperationZeroOrOne(optionSet, CSharpFormattingOptions.SpacingAfterMethodDeclarationName);
}
+ // Case: public static implicit operator string(Program p) { return null; }
+ if (previousToken.IsKeyword() && currentToken.IsOpenParenInParameterListOfAConversionOperatorDeclaration())
+ {
+ return AdjustSpacesOperationZeroOrOne(optionSet, CSharpFormattingOptions.SpacingAfterMethodDeclarationName);
+ }
+
+ // Case: public static Program operator !(Program p) { return null; }
+ if (previousToken.Parent.IsKind(SyntaxKind.OperatorDeclaration) && currentToken.IsOpenParenInParameterListOfAOperationDeclaration())
+ {
+ return AdjustSpacesOperationZeroOrOne(optionSet, CSharpFormattingOptions.SpacingAfterMethodDeclarationName);
+ }
+
if (previousToken.IsOpenParenInParameterList() && currentToken.IsCloseParenInParameterList())
{
return AdjustSpacesOperationZeroOrOne(optionSet, CSharpFormattingOptions.SpaceBetweenEmptyMethodDeclarationParentheses);
diff --git a/src/Workspaces/CSharp/Portable/Formatting/Rules/TokenBasedFormattingRule.cs b/src/Workspaces/CSharp/Portable/Formatting/Rules/TokenBasedFormattingRule.cs
index bf6ae49bb7ceccca518336cbc8774fa685ae9299..427e4eb061ae84515c67ef003c109a7f7c088565 100644
--- a/src/Workspaces/CSharp/Portable/Formatting/Rules/TokenBasedFormattingRule.cs
+++ b/src/Workspaces/CSharp/Portable/Formatting/Rules/TokenBasedFormattingRule.cs
@@ -200,7 +200,6 @@ public override AdjustSpacesOperation GetAdjustSpacesOperation(SyntaxToken previ
previousToken.Kind() == SyntaxKind.BaseKeyword ||
previousToken.Kind() == SyntaxKind.ThisKeyword ||
previousToken.Kind() == SyntaxKind.NewKeyword ||
- previousToken.Parent.Kind() == SyntaxKind.OperatorDeclaration ||
previousToken.IsGenericGreaterThanToken() ||
currentToken.IsParenInArgumentList())
{
diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs
index 2fcacbd3167a96a20b4996e06b37f2415b6915e8..9afadc991634ff57bf4fc970c356223d2ce971de 100644
--- a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs
+++ b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs
@@ -6231,6 +6231,46 @@ void Main()
AssertFormat(expected, code);
}
+ [WorkItem(4240, "https://github.com/dotnet/roslyn/issues/4240")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
+ public void VerifySpacingAfterMethodDeclarationName_Default()
+ {
+ var code = @"class Program
+{
+ public static Program operator + (Program p1, Program p2) { return null; }
+ public static implicit operator string (Program p) { return null; }
+ public static void M () { }
+}";
+ var expected = @"class Program
+{
+ public static Program operator +(Program p1, Program p2) { return null; }
+ public static implicit operator string(Program p) { return null; }
+ public static void M() { }
+}";
+ AssertFormat(expected, code);
+ }
+
+ [WorkItem(4240, "https://github.com/dotnet/roslyn/issues/4240")]
+ [Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
+ public void VerifySpacingAfterMethodDeclarationName_NonDefault()
+ {
+ var changingOptions = new Dictionary();
+ changingOptions.Add(CSharpFormattingOptions.SpacingAfterMethodDeclarationName, true);
+ var code = @"class Program
+{
+ public static Program operator + (Program p1, Program p2) { return null; }
+ public static implicit operator string (Program p) { return null; }
+ public static void M () { }
+}";
+ var expected = @"class Program
+{
+ public static Program operator + (Program p1, Program p2) { return null; }
+ public static implicit operator string (Program p) { return null; }
+ public static void M () { }
+}";
+ AssertFormat(expected, code, changedOptionSet: changingOptions);
+ }
+
[WorkItem(939, "https://github.com/dotnet/roslyn/issues/939")]
[Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
public void DontFormatInsideArrayInitializers()
diff --git a/src/Workspaces/Core/Desktop/PublicAPI.txt b/src/Workspaces/Core/Desktop/PublicAPI.txt
index a2b9ac45a707c3000dbba084d6393b1c53e91088..f296949281930864eaf35fe83580e4231ad0f6ad 100644
--- a/src/Workspaces/Core/Desktop/PublicAPI.txt
+++ b/src/Workspaces/Core/Desktop/PublicAPI.txt
@@ -7,6 +7,16 @@ Microsoft.CodeAnalysis.Host.Mef.DesktopMefHostServices
Microsoft.CodeAnalysis.Host.Mef.MefV1HostServices
Microsoft.CodeAnalysis.Host.Mef.MefV1HostServices.GetExports() -> System.Collections.Generic.IEnumerable>
Microsoft.CodeAnalysis.Host.Mef.MefV1HostServices.GetExports() -> System.Collections.Generic.IEnumerable>
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.AssociateFileExtensionWithLanguage(string projectFileExtension, string language) -> void
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadMetadataForReferencedProjects.get -> bool
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadMetadataForReferencedProjects.set -> void
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(string projectFilePath, System.Collections.Generic.IReadOnlyDictionary projectPathToProjectIdMap = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task>
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadSolutionInfoAsync(string solutionFilePath, System.Collections.Generic.IReadOnlyDictionary projectPathToProjectIdMap = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.MSBuildProjectLoader(Microsoft.CodeAnalysis.Workspace workspace, System.Collections.Immutable.ImmutableDictionary properties = null) -> void
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Properties.get -> System.Collections.Immutable.ImmutableDictionary
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.SkipUnrecognizedProjects.get -> bool
+Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.SkipUnrecognizedProjects.set -> void
Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace
Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.AssociateFileExtensionWithLanguage(string projectFileExtension, string language) -> void
Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.CloseSolution() -> void
@@ -28,4 +38,4 @@ static Microsoft.CodeAnalysis.Host.Mef.MefV1HostServices.Create(System.Component
static Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create() -> Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace
static Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(System.Collections.Generic.IDictionary properties) -> Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace
static Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(System.Collections.Generic.IDictionary properties, Microsoft.CodeAnalysis.Host.HostServices hostServices) -> Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace
-virtual Microsoft.CodeAnalysis.FileTextLoader.CreateText(System.IO.Stream stream, Microsoft.CodeAnalysis.Workspace workspace) -> Microsoft.CodeAnalysis.Text.SourceText
+virtual Microsoft.CodeAnalysis.FileTextLoader.CreateText(System.IO.Stream stream, Microsoft.CodeAnalysis.Workspace workspace) -> Microsoft.CodeAnalysis.Text.SourceText
\ No newline at end of file
diff --git a/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildProjectLoader.cs b/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildProjectLoader.cs
new file mode 100644
index 0000000000000000000000000000000000000000..be933abc6e7408bcc94a5a6af021dd9f9d55282f
--- /dev/null
+++ b/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildProjectLoader.cs
@@ -0,0 +1,784 @@
+// 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.Reflection;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+#if !MSBUILD12
+using Microsoft.Build.Construction;
+#endif
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Host;
+using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.LanguageServices;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.MSBuild
+{
+ ///
+ /// An API for loading msbuild project files.
+ ///
+ public class MSBuildProjectLoader
+ {
+ // the workspace that the projects and solutions are intended to be loaded into.
+ private readonly Workspace _workspace;
+
+ // used to protect access to the following mutable state
+ private readonly NonReentrantLock _dataGuard = new NonReentrantLock();
+ private ImmutableDictionary _properties;
+ private readonly Dictionary _extensionToLanguageMap = new Dictionary(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ /// Create a new instance of an .
+ ///
+ public MSBuildProjectLoader(Workspace workspace, ImmutableDictionary properties = null)
+ {
+ _workspace = workspace;
+ _properties = properties ?? ImmutableDictionary.Empty;
+ }
+
+ ///
+ /// The MSBuild properties used when interpreting project files.
+ /// These are the same properties that are passed to msbuild via the /property:<n>=<v> command line argument.
+ ///
+ public ImmutableDictionary Properties
+ {
+ get { return _properties; }
+ }
+
+ ///
+ /// Determines if metadata from existing output assemblies is loaded instead of opening referenced projects.
+ /// If the referenced project is already opened, the metadata will not be loaded.
+ /// If the metadata assembly cannot be found the referenced project will be opened instead.
+ ///
+ public bool LoadMetadataForReferencedProjects { get; set; } = false;
+
+ ///
+ /// Determines if unrecognized projects are skipped when solutions or projects are opened.
+ ///
+ /// An project is unrecognized if it either has
+ /// a) an invalid file path,
+ /// b) a non-existent project file,
+ /// c) has an unrecognized file extension or
+ /// d) a file extension associated with an unsupported language.
+ ///
+ /// If unrecognized projects cannot be skipped a corresponding exception is thrown.
+ ///
+ public bool SkipUnrecognizedProjects { get; set; } = true;
+
+ ///
+ /// Associates a project file extension with a language name.
+ ///
+ public void AssociateFileExtensionWithLanguage(string projectFileExtension, string language)
+ {
+ if (language == null)
+ {
+ throw new ArgumentNullException(nameof(language));
+ }
+
+ if (projectFileExtension == null)
+ {
+ throw new ArgumentNullException(nameof(projectFileExtension));
+ }
+
+ using (_dataGuard.DisposableWait())
+ {
+ _extensionToLanguageMap[projectFileExtension] = language;
+ }
+ }
+
+ private const string SolutionDirProperty = "SolutionDir";
+
+ private void SetSolutionProperties(string solutionFilePath)
+ {
+ if (!string.IsNullOrEmpty(solutionFilePath))
+ {
+ // When MSBuild is building an individual project, it doesn't define $(SolutionDir).
+ // However when building an .sln file, or when working inside Visual Studio,
+ // $(SolutionDir) is defined to be the directory where the .sln file is located.
+ // Some projects out there rely on $(SolutionDir) being set (although the best practice is to
+ // use MSBuildProjectDirectory which is always defined).
+ if (!string.IsNullOrEmpty(solutionFilePath))
+ {
+ string solutionDirectory = Path.GetDirectoryName(solutionFilePath);
+ if (!solutionDirectory.EndsWith(@"\", StringComparison.Ordinal))
+ {
+ solutionDirectory += @"\";
+ }
+
+ if (Directory.Exists(solutionDirectory))
+ {
+ _properties = _properties.SetItem(SolutionDirProperty, solutionDirectory);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Loads the for the specified solution file, including all projects referenced by the solution file and
+ /// all the projects referenced by the project files.
+ ///
+ public async Task LoadSolutionInfoAsync(
+ string solutionFilePath,
+ IReadOnlyDictionary projectPathToProjectIdMap = null,
+ CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (solutionFilePath == null)
+ {
+ throw new ArgumentNullException(nameof(solutionFilePath));
+ }
+
+ var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory());
+ using (_dataGuard.DisposableWait(cancellationToken))
+ {
+ this.SetSolutionProperties(absoluteSolutionPath);
+ }
+
+ VersionStamp version = default(VersionStamp);
+
+#if !MSBUILD12
+ Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath);
+ var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
+
+ // a list to accumulate all the loaded projects
+ var loadedProjects = new LoadState(null);
+
+ // load all the projects
+ foreach (var project in solutionFile.ProjectsInOrder)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (project.ProjectType != SolutionProjectType.SolutionFolder)
+ {
+ var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode);
+ if (projectAbsolutePath != null)
+ {
+ IProjectFileLoader loader;
+ if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader))
+ {
+ // projects get added to 'loadedProjects' as side-effect
+ // never prefer metadata when loading solution, all projects get loaded if they can.
+ var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata: false, loadedProjects: loadedProjects, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+#else
+ SolutionFile solutionFile = null;
+
+ using (var reader = new StreamReader(absoluteSolutionPath))
+ {
+ version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath));
+ var text = await reader.ReadToEndAsync().ConfigureAwait(false);
+ solutionFile = SolutionFile.Parse(new StringReader(text));
+ }
+
+ var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath);
+
+ // a list to accumulate all the loaded projects
+ var loadedProjects = new LoadState(null);
+
+ var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
+
+ // load all the projects
+ foreach (var projectBlock in solutionFile.ProjectBlocks)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ string absoluteProjectPath;
+ if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath))
+ {
+ IProjectFileLoader loader;
+ if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader))
+ {
+ // projects get added to 'loadedProjects' as side-effect
+ // never prefer metadata when loading solution, all projects get loaded if they can.
+ var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata: false, loadedProjects: loadedProjects, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+#endif
+
+ // construct workspace from loaded project infos
+ return SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects.Projects);
+ }
+
+ internal string GetAbsoluteSolutionPath(string path, string baseDirectory)
+ {
+ string absolutePath;
+
+ try
+ {
+ absolutePath = GetAbsolutePath(path, baseDirectory);
+ }
+ catch (Exception)
+ {
+ throw new InvalidOperationException(string.Format(WorkspacesResources.InvalidSolutionFilePath, path));
+ }
+
+ if (!File.Exists(absolutePath))
+ {
+ throw new FileNotFoundException(string.Format(WorkspacesResources.SolutionFileNotFound, absolutePath));
+ }
+
+ return absolutePath;
+ }
+
+ ///
+ /// Loads the from the specified project file and all referenced projects.
+ /// The first in the result corresponds to the specified project file.
+ ///
+ public async Task> LoadProjectInfoAsync(
+ string projectFilePath,
+ IReadOnlyDictionary projectPathToProjectIdMap = null,
+ CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (projectFilePath == null)
+ {
+ throw new ArgumentNullException(nameof(projectFilePath));
+ }
+
+ string fullPath;
+ this.TryGetAbsoluteProjectPath(projectFilePath, Directory.GetCurrentDirectory(), ReportMode.Throw, out fullPath);
+
+ IProjectFileLoader loader;
+ this.TryGetLoaderFromProjectPath(projectFilePath, ReportMode.Throw, out loader);
+
+ var loadedProjects = new LoadState(projectPathToProjectIdMap);
+ var id = await this.LoadProjectAsync(fullPath, loader, this.LoadMetadataForReferencedProjects, loadedProjects, cancellationToken).ConfigureAwait(false);
+
+ var result = loadedProjects.Projects.Reverse().ToImmutableArray();
+ Debug.Assert(result[0].Id == id);
+ return result;
+ }
+
+ private class LoadState
+ {
+ private Dictionary _projetIdToProjectInfoMap
+ = new Dictionary();
+
+ private List _projectInfoList
+ = new List();
+
+ private readonly Dictionary _projectPathToProjectIdMap
+ = new Dictionary();
+
+ public LoadState(IReadOnlyDictionary projectPathToProjectIdMap)
+ {
+ if (projectPathToProjectIdMap != null)
+ {
+ _projectPathToProjectIdMap.AddRange(projectPathToProjectIdMap);
+ }
+ }
+
+ public void Add(ProjectInfo info)
+ {
+ _projetIdToProjectInfoMap.Add(info.Id, info);
+ _projectInfoList.Add(info);
+ }
+
+ public bool TryGetValue(ProjectId id, out ProjectInfo info)
+ {
+ return _projetIdToProjectInfoMap.TryGetValue(id, out info);
+ }
+
+ public IReadOnlyList Projects
+ {
+ get { return _projectInfoList; }
+ }
+
+ public ProjectId GetProjectId(string fullProjectPath)
+ {
+ ProjectId id;
+ _projectPathToProjectIdMap.TryGetValue(fullProjectPath, out id);
+ return id;
+ }
+
+ public ProjectId GetOrCreateProjectId(string fullProjectPath)
+ {
+ ProjectId id;
+ if (!_projectPathToProjectIdMap.TryGetValue(fullProjectPath, out id))
+ {
+ id = ProjectId.CreateNewId(debugName: fullProjectPath);
+ _projectPathToProjectIdMap.Add(fullProjectPath, id);
+ }
+
+ return id;
+ }
+ }
+
+ private async Task GetOrLoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, LoadState loadedProjects, CancellationToken cancellationToken)
+ {
+ var projectId = loadedProjects.GetProjectId(projectFilePath);
+ if (projectId == null)
+ {
+ projectId = await this.LoadProjectAsync(projectFilePath, loader, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
+ }
+
+ return projectId;
+ }
+
+ private async Task LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, LoadState loadedProjects, CancellationToken cancellationToken)
+ {
+ Debug.Assert(projectFilePath != null);
+ Debug.Assert(loader != null);
+
+ var projectId = loadedProjects.GetOrCreateProjectId(projectFilePath);
+
+ var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
+
+ var projectFile = await loader.LoadProjectFileAsync(projectFilePath, _properties, cancellationToken).ConfigureAwait(false);
+ var projectFileInfo = await projectFile.GetProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);
+
+ var projectDirectory = Path.GetDirectoryName(projectFilePath);
+ var outputFilePath = projectFileInfo.OutputFilePath;
+ var outputDirectory = Path.GetDirectoryName(outputFilePath);
+
+ VersionStamp version;
+ if (!string.IsNullOrEmpty(projectFilePath) && File.Exists(projectFilePath))
+ {
+ version = VersionStamp.Create(File.GetLastWriteTimeUtc(projectFilePath));
+ }
+ else
+ {
+ version = VersionStamp.Create();
+ }
+
+ // translate information from command line args
+ var commandLineParser = _workspace.Services.GetLanguageServices(loader.Language).GetService();
+ var metadataService = _workspace.Services.GetService();
+ var analyzerService = _workspace.Services.GetService();
+
+ var commandLineArgs = commandLineParser.Parse(
+ arguments: projectFileInfo.CommandLineArgs,
+ baseDirectory: projectDirectory,
+ isInteractive: false,
+ sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());
+
+ var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
+ var metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, metadataService.GetProvider()));
+
+ var analyzerLoader = analyzerService.GetLoader();
+ foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath))
+ {
+ analyzerLoader.AddDependencyLocation(path);
+ }
+
+ var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);
+
+ var defaultEncoding = commandLineArgs.Encoding;
+
+ // docs & additional docs
+ var docFileInfos = projectFileInfo.Documents.ToImmutableArrayOrEmpty();
+ var additionalDocFileInfos = projectFileInfo.AdditionalDocuments.ToImmutableArrayOrEmpty();
+
+ // check for duplicate documents
+ var allDocFileInfos = docFileInfos.AddRange(additionalDocFileInfos);
+ CheckDocuments(allDocFileInfos, projectFilePath, projectId);
+
+ var docs = new List();
+ foreach (var docFileInfo in docFileInfos)
+ {
+ string name;
+ ImmutableArray folders;
+ GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);
+
+ docs.Add(DocumentInfo.Create(
+ DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
+ name,
+ folders,
+ projectFile.GetSourceCodeKind(docFileInfo.FilePath),
+ new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
+ docFileInfo.FilePath,
+ docFileInfo.IsGenerated));
+ }
+
+ var additionalDocs = new List();
+ foreach (var docFileInfo in additionalDocFileInfos)
+ {
+ string name;
+ ImmutableArray folders;
+ GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);
+
+ additionalDocs.Add(DocumentInfo.Create(
+ DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
+ name,
+ folders,
+ SourceCodeKind.Regular,
+ new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
+ docFileInfo.FilePath,
+ docFileInfo.IsGenerated));
+ }
+
+ // project references
+ var resolvedReferences = await this.ResolveProjectReferencesAsync(
+ projectId, projectFilePath, projectFileInfo.ProjectReferences, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
+
+ // add metadata references for project refs converted to metadata refs
+ metadataReferences = metadataReferences.Concat(resolvedReferences.MetadataReferences);
+
+ // if the project file loader couldn't figure out an assembly name, make one using the project's file path.
+ var assemblyName = commandLineArgs.CompilationName;
+ if (string.IsNullOrWhiteSpace(assemblyName))
+ {
+ assemblyName = Path.GetFileNameWithoutExtension(projectFilePath);
+
+ // if this is still unreasonable, use a fixed name.
+ if (string.IsNullOrWhiteSpace(assemblyName))
+ {
+ assemblyName = "assembly";
+ }
+ }
+
+ // make sure that doc-comments at least get parsed.
+ var parseOptions = commandLineArgs.ParseOptions;
+ if (parseOptions.DocumentationMode == DocumentationMode.None)
+ {
+ parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Parse);
+ }
+
+ // add all the extra options that are really behavior overrides
+ var compOptions = commandLineArgs.CompilationOptions
+ .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
+ .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray.Empty, projectDirectory))
+ .WithMetadataReferenceResolver(
+ new AssemblyReferenceResolver(
+ new MetadataFileReferenceResolver(ImmutableArray.Empty, projectDirectory),
+ MetadataFileReferenceProvider.Default))
+ .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
+ .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
+
+ loadedProjects.Add(
+ ProjectInfo.Create(
+ projectId,
+ version,
+ projectName,
+ assemblyName,
+ loader.Language,
+ projectFilePath,
+ outputFilePath,
+ compilationOptions: compOptions,
+ parseOptions: parseOptions,
+ documents: docs,
+ projectReferences: resolvedReferences.ProjectReferences,
+ metadataReferences: metadataReferences,
+ analyzerReferences: analyzerReferences,
+ additionalDocuments: additionalDocs,
+ isSubmission: false,
+ hostObjectType: null));
+
+ return projectId;
+ }
+
+ private static readonly char[] s_directorySplitChars = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
+
+ private static void GetDocumentNameAndFolders(string logicalPath, out string name, out ImmutableArray folders)
+ {
+ var pathNames = logicalPath.Split(s_directorySplitChars, StringSplitOptions.RemoveEmptyEntries);
+ if (pathNames.Length > 0)
+ {
+ if (pathNames.Length > 1)
+ {
+ folders = pathNames.Take(pathNames.Length - 1).ToImmutableArray();
+ }
+ else
+ {
+ folders = ImmutableArray.Create();
+ }
+
+ name = pathNames[pathNames.Length - 1];
+ }
+ else
+ {
+ name = logicalPath;
+ folders = ImmutableArray.Create();
+ }
+ }
+
+ private void CheckDocuments(IEnumerable docs, string projectFilePath, ProjectId projectId)
+ {
+ var paths = new HashSet();
+ foreach (var doc in docs)
+ {
+ if (paths.Contains(doc.FilePath))
+ {
+ _workspace.OnWorkspaceFailed(new ProjectDiagnostic(WorkspaceDiagnosticKind.Warning, string.Format(WorkspacesResources.DuplicateSourceFileInProject, doc.FilePath, projectFilePath), projectId));
+ }
+
+ paths.Add(doc.FilePath);
+ }
+ }
+
+ private class ResolvedReferences
+ {
+ public readonly List ProjectReferences = new List();
+ public readonly List MetadataReferences = new List();
+ }
+
+ private async Task ResolveProjectReferencesAsync(
+ ProjectId thisProjectId,
+ string thisProjectPath,
+ IReadOnlyList projectFileReferences,
+ bool preferMetadata,
+ LoadState loadedProjects,
+ CancellationToken cancellationToken)
+ {
+ var resolvedReferences = new ResolvedReferences();
+ var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
+
+ foreach (var projectFileReference in projectFileReferences)
+ {
+ string fullPath;
+
+ if (TryGetAbsoluteProjectPath(projectFileReference.Path, Path.GetDirectoryName(thisProjectPath), reportMode, out fullPath))
+ {
+ // if the project is already loaded, then just reference the one we have
+ var existingProjectId = loadedProjects.GetProjectId(fullPath);
+ if (existingProjectId != null)
+ {
+ resolvedReferences.ProjectReferences.Add(new ProjectReference(existingProjectId, projectFileReference.Aliases));
+ continue;
+ }
+
+ IProjectFileLoader loader;
+ TryGetLoaderFromProjectPath(fullPath, ReportMode.Ignore, out loader);
+
+ // get metadata if preferred or if loader is unknown
+ if (preferMetadata || loader == null)
+ {
+ var projectMetadata = await this.GetProjectMetadata(fullPath, projectFileReference.Aliases, _properties, cancellationToken).ConfigureAwait(false);
+ if (projectMetadata != null)
+ {
+ resolvedReferences.MetadataReferences.Add(projectMetadata);
+ continue;
+ }
+ }
+
+ // must load, so we really need loader
+ if (TryGetLoaderFromProjectPath(fullPath, reportMode, out loader))
+ {
+ // load the project
+ var projectId = await this.GetOrLoadProjectAsync(fullPath, loader, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
+
+ // If that other project already has a reference on us, this will cause a circularity.
+ // This check doesn't need to be in the "already loaded" path above, since in any circularity this path
+ // must be taken at least once.
+ if (ProjectAlreadyReferencesProject(loadedProjects, projectId, targetProject: thisProjectId))
+ {
+ // We'll try to make this metadata if we can
+ var projectMetadata = await this.GetProjectMetadata(fullPath, projectFileReference.Aliases, _properties, cancellationToken).ConfigureAwait(false);
+ if (projectMetadata != null)
+ {
+ resolvedReferences.MetadataReferences.Add(projectMetadata);
+ }
+ continue;
+ }
+ else
+ {
+ resolvedReferences.ProjectReferences.Add(new ProjectReference(projectId, projectFileReference.Aliases));
+ continue;
+ }
+ }
+ }
+ else
+ {
+ fullPath = projectFileReference.Path;
+ }
+
+ // cannot find metadata and project cannot be loaded, so leave a project reference to a non-existent project.
+ var id = loadedProjects.GetOrCreateProjectId(fullPath);
+ resolvedReferences.ProjectReferences.Add(new ProjectReference(id, projectFileReference.Aliases));
+ }
+
+ return resolvedReferences;
+ }
+
+ ///
+ /// Returns true if the project identified by has a reference (even indirectly)
+ /// on the project identified by .
+ ///
+ private bool ProjectAlreadyReferencesProject(LoadState loadedProjects, ProjectId fromProject, ProjectId targetProject)
+ {
+ ProjectInfo info;
+
+ return loadedProjects.TryGetValue(fromProject, out info) && info.ProjectReferences.Any(pr => pr.ProjectId == targetProject ||
+ ProjectAlreadyReferencesProject(loadedProjects, pr.ProjectId, targetProject));
+ }
+
+ ///
+ /// Gets a MetadataReference to a project's output assembly.
+ ///
+ private async Task GetProjectMetadata(string projectFilePath, ImmutableArray aliases, IDictionary globalProperties, CancellationToken cancellationToken)
+ {
+ // use loader service to determine output file for project if possible
+ string outputFilePath = null;
+
+ try
+ {
+ outputFilePath = await ProjectFileLoader.GetOutputFilePathAsync(projectFilePath, globalProperties, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception e)
+ {
+ _workspace.OnWorkspaceFailed(new WorkspaceDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message));
+ }
+
+ if (outputFilePath != null && File.Exists(outputFilePath))
+ {
+ if (Workspace.TestHookStandaloneProjectsDoNotHoldReferences)
+ {
+ var documentationService = _workspace.Services.GetService();
+ var docProvider = documentationService.GetDocumentationProvider(outputFilePath);
+ var metadata = AssemblyMetadata.CreateFromImage(File.ReadAllBytes(outputFilePath));
+
+ return metadata.GetReference(
+ documentation: docProvider,
+ aliases: aliases,
+ display: outputFilePath);
+ }
+ else
+ {
+ var metadataService = _workspace.Services.GetService();
+ return metadataService.GetReference(outputFilePath, new MetadataReferenceProperties(MetadataImageKind.Assembly, aliases));
+ }
+ }
+
+ return null;
+ }
+
+ private string TryGetAbsolutePath(string path, ReportMode mode)
+ {
+ try
+ {
+ path = Path.GetFullPath(path);
+ }
+ catch (Exception)
+ {
+ ReportFailure(mode, string.Format(WorkspacesResources.InvalidProjectFilePath, path));
+ return null;
+ }
+
+ if (!File.Exists(path))
+ {
+ ReportFailure(
+ mode,
+ string.Format(WorkspacesResources.ProjectFileNotFound, path),
+ msg => new FileNotFoundException(msg));
+ return null;
+ }
+
+ return path;
+ }
+
+ internal bool TryGetLoaderFromProjectPath(string projectFilePath, out IProjectFileLoader loader)
+ {
+ return TryGetLoaderFromProjectPath(projectFilePath, ReportMode.Ignore, out loader);
+ }
+
+ private bool TryGetLoaderFromProjectPath(string projectFilePath, ReportMode mode, out IProjectFileLoader loader)
+ {
+ using (_dataGuard.DisposableWait())
+ {
+ // otherwise try to figure it out from extension
+ var extension = Path.GetExtension(projectFilePath);
+ if (extension.Length > 0 && extension[0] == '.')
+ {
+ extension = extension.Substring(1);
+ }
+
+ string language;
+ if (_extensionToLanguageMap.TryGetValue(extension, out language))
+ {
+ if (_workspace.Services.SupportedLanguages.Contains(language))
+ {
+ loader = _workspace.Services.GetLanguageServices(language).GetService();
+ }
+ else
+ {
+ loader = null;
+ this.ReportFailure(mode, string.Format(WorkspacesResources.CannotOpenProjectUnsupportedLanguage, projectFilePath, language));
+ return false;
+ }
+ }
+ else
+ {
+ loader = ProjectFileLoader.GetLoaderForProjectFileExtension(_workspace, extension);
+
+ if (loader == null)
+ {
+ this.ReportFailure(mode, string.Format(WorkspacesResources.CannotOpenProjectUnrecognizedFileExtension, projectFilePath, Path.GetExtension(projectFilePath)));
+ return false;
+ }
+ }
+
+ return loader != null;
+ }
+ }
+
+ private bool TryGetAbsoluteProjectPath(string path, string baseDirectory, ReportMode mode, out string absolutePath)
+ {
+ try
+ {
+ absolutePath = GetAbsolutePath(path, baseDirectory);
+ }
+ catch (Exception)
+ {
+ ReportFailure(mode, string.Format(WorkspacesResources.InvalidProjectFilePath, path));
+ absolutePath = null;
+ return false;
+ }
+
+ if (!File.Exists(absolutePath))
+ {
+ ReportFailure(
+ mode,
+ string.Format(WorkspacesResources.ProjectFileNotFound, absolutePath),
+ msg => new FileNotFoundException(msg));
+ return false;
+ }
+
+ return true;
+ }
+
+ private static string GetAbsolutePath(string path, string baseDirectoryPath)
+ {
+ return Path.GetFullPath(FileUtilities.ResolveRelativePath(path, baseDirectoryPath) ?? path);
+ }
+
+ private enum ReportMode
+ {
+ Throw,
+ Log,
+ Ignore
+ }
+
+ private void ReportFailure(ReportMode mode, string message, Func createException = null)
+ {
+ switch (mode)
+ {
+ case ReportMode.Throw:
+ if (createException != null)
+ {
+ throw createException(message);
+ }
+ else
+ {
+ throw new InvalidOperationException(message);
+ }
+
+ case ReportMode.Log:
+ _workspace.OnWorkspaceFailed(new WorkspaceDiagnostic(WorkspaceDiagnosticKind.Failure, message));
+ break;
+
+ case ReportMode.Ignore:
+ default:
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildWorkspace.cs b/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildWorkspace.cs
index 1f1d19072a2c8562315e0709ab253ddce741097a..f0000ccc0a80ba2228d6394722206b9cd7b7554f 100644
--- a/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildWorkspace.cs
+++ b/src/Workspaces/Core/Desktop/Workspace/MSBuild/MSBuildWorkspace.cs
@@ -32,26 +32,14 @@ public sealed class MSBuildWorkspace : Workspace
// used to serialize access to public methods
private readonly NonReentrantLock _serializationLock = new NonReentrantLock();
- // used to protect access to mutable state
- private readonly NonReentrantLock _dataGuard = new NonReentrantLock();
-
- private readonly Dictionary _extensionToLanguageMap = new Dictionary(StringComparer.OrdinalIgnoreCase);
- private readonly Dictionary _projectPathToProjectIdMap = new Dictionary(StringComparer.OrdinalIgnoreCase);
- private readonly Dictionary _projectPathToLoaderMap = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
- private string _solutionFilePath;
- private ImmutableDictionary _properties;
+ private MSBuildProjectLoader _loader;
private MSBuildWorkspace(
HostServices hostServices,
ImmutableDictionary properties)
: base(hostServices, "MSBuildWorkspace")
{
- // always make a copy of these build properties (no mutation please!)
- _properties = properties ?? ImmutableDictionary.Empty;
- this.SetSolutionProperties(solutionFilePath: null);
- this.LoadMetadataForReferencedProjects = false;
- this.SkipUnrecognizedProjects = true;
+ _loader = new MSBuildProjectLoader(this, properties);
}
///
@@ -99,7 +87,7 @@ public static MSBuildWorkspace Create(IDictionary properties, Ho
///
public ImmutableDictionary Properties
{
- get { return _properties; }
+ get { return _loader.Properties; }
}
///
@@ -107,7 +95,11 @@ public static MSBuildWorkspace Create(IDictionary properties, Ho
/// If the referenced project is already opened, the metadata will not be loaded.
/// If the metadata assembly cannot be found the referenced project will be opened instead.
///
- public bool LoadMetadataForReferencedProjects { get; set; }
+ public bool LoadMetadataForReferencedProjects
+ {
+ get { return _loader.LoadMetadataForReferencedProjects; }
+ set { _loader.LoadMetadataForReferencedProjects = value; }
+ }
///
/// Determines if unrecognized projects are skipped when solutions or projects are opened.
@@ -120,27 +112,18 @@ public static MSBuildWorkspace Create(IDictionary properties, Ho
///
/// If unrecognized projects cannot be skipped a corresponding exception is thrown.
///
- public bool SkipUnrecognizedProjects { get; set; }
+ public bool SkipUnrecognizedProjects
+ {
+ get { return _loader.SkipUnrecognizedProjects; }
+ set { _loader.SkipUnrecognizedProjects = value; }
+ }
///
/// Associates a project file extension with a language name.
///
public void AssociateFileExtensionWithLanguage(string projectFileExtension, string language)
{
- if (language == null)
- {
- throw new ArgumentNullException(nameof(language));
- }
-
- if (projectFileExtension == null)
- {
- throw new ArgumentNullException(nameof(projectFileExtension));
- }
-
- using (_dataGuard.DisposableWait())
- {
- _extensionToLanguageMap[projectFileExtension] = language;
- }
+ _loader.AssociateFileExtensionWithLanguage(projectFileExtension, language);
}
///
@@ -154,199 +137,6 @@ public void CloseSolution()
}
}
- protected override void ClearSolutionData()
- {
- base.ClearSolutionData();
-
- using (_dataGuard.DisposableWait())
- {
- this.SetSolutionProperties(solutionFilePath: null);
-
- // clear project related data
- _projectPathToProjectIdMap.Clear();
- _projectPathToLoaderMap.Clear();
- }
- }
-
- private const string SolutionDirProperty = "SolutionDir";
-
- private void SetSolutionProperties(string solutionFilePath)
- {
- _solutionFilePath = solutionFilePath;
-
- if (!string.IsNullOrEmpty(solutionFilePath))
- {
- // When MSBuild is building an individual project, it doesn't define $(SolutionDir).
- // However when building an .sln file, or when working inside Visual Studio,
- // $(SolutionDir) is defined to be the directory where the .sln file is located.
- // Some projects out there rely on $(SolutionDir) being set (although the best practice is to
- // use MSBuildProjectDirectory which is always defined).
- if (!string.IsNullOrEmpty(solutionFilePath))
- {
- string solutionDirectory = Path.GetDirectoryName(solutionFilePath);
- if (!solutionDirectory.EndsWith(@"\", StringComparison.Ordinal))
- {
- solutionDirectory += @"\";
- }
-
- if (Directory.Exists(solutionDirectory))
- {
- _properties = _properties.SetItem(SolutionDirProperty, solutionDirectory);
- }
- }
- }
- }
-
- private ProjectId GetProjectId(string fullProjectPath)
- {
- using (_dataGuard.DisposableWait())
- {
- ProjectId id;
- _projectPathToProjectIdMap.TryGetValue(fullProjectPath, out id);
- return id;
- }
- }
-
- private ProjectId GetOrCreateProjectId(string fullProjectPath)
- {
- using (_dataGuard.DisposableWait())
- {
- ProjectId id;
- if (!_projectPathToProjectIdMap.TryGetValue(fullProjectPath, out id))
- {
- id = ProjectId.CreateNewId(debugName: fullProjectPath);
- _projectPathToProjectIdMap.Add(fullProjectPath, id);
- }
-
- return id;
- }
- }
-
- private bool TryGetLoaderFromProjectPath(string projectFilePath, ReportMode mode, out IProjectFileLoader loader)
- {
- using (_dataGuard.DisposableWait())
- {
- // check to see if we already know the loader
- if (!_projectPathToLoaderMap.TryGetValue(projectFilePath, out loader))
- {
- // otherwise try to figure it out from extension
- var extension = Path.GetExtension(projectFilePath);
- if (extension.Length > 0 && extension[0] == '.')
- {
- extension = extension.Substring(1);
- }
-
- string language;
- if (_extensionToLanguageMap.TryGetValue(extension, out language))
- {
- if (this.Services.SupportedLanguages.Contains(language))
- {
- loader = this.Services.GetLanguageServices(language).GetService();
- }
- else
- {
- this.ReportFailure(mode, string.Format(WorkspacesResources.CannotOpenProjectUnsupportedLanguage, projectFilePath, language));
- return false;
- }
- }
- else
- {
- loader = ProjectFileLoader.GetLoaderForProjectFileExtension(this, extension);
-
- if (loader == null)
- {
- this.ReportFailure(mode, string.Format(WorkspacesResources.CannotOpenProjectUnrecognizedFileExtension, projectFilePath, Path.GetExtension(projectFilePath)));
- return false;
- }
- }
-
- if (loader != null)
- {
- _projectPathToLoaderMap[projectFilePath] = loader;
- }
- }
-
- return loader != null;
- }
- }
-
- private bool TryGetAbsoluteProjectPath(string path, string baseDirectory, ReportMode mode, out string absolutePath)
- {
- try
- {
- absolutePath = this.GetAbsolutePath(path, baseDirectory);
- }
- catch (Exception)
- {
- ReportFailure(mode, string.Format(WorkspacesResources.InvalidProjectFilePath, path));
- absolutePath = null;
- return false;
- }
-
- if (!File.Exists(absolutePath))
- {
- ReportFailure(
- mode,
- string.Format(WorkspacesResources.ProjectFileNotFound, absolutePath),
- msg => new FileNotFoundException(msg));
- return false;
- }
-
- return true;
- }
-
- private string GetAbsoluteSolutionPath(string path, string baseDirectory)
- {
- string absolutePath;
-
- try
- {
- absolutePath = GetAbsolutePath(path, baseDirectory);
- }
- catch (Exception)
- {
- throw new InvalidOperationException(string.Format(WorkspacesResources.InvalidSolutionFilePath, path));
- }
-
- if (!File.Exists(absolutePath))
- {
- throw new FileNotFoundException(string.Format(WorkspacesResources.SolutionFileNotFound, absolutePath));
- }
-
- return absolutePath;
- }
-
- private enum ReportMode
- {
- Throw,
- Log,
- Ignore
- }
-
- private void ReportFailure(ReportMode mode, string message, Func createException = null)
- {
- switch (mode)
- {
- case ReportMode.Throw:
- if (createException != null)
- {
- throw createException(message);
- }
- else
- {
- throw new InvalidOperationException(message);
- }
-
- case ReportMode.Log:
- this.OnWorkspaceFailed(new WorkspaceDiagnostic(WorkspaceDiagnosticKind.Failure, message));
- break;
-
- case ReportMode.Ignore:
- default:
- break;
- }
- }
-
private string GetAbsolutePath(string path, string baseDirectoryPath)
{
return Path.GetFullPath(FileUtilities.ResolveRelativePath(path, baseDirectoryPath) ?? path);
@@ -365,130 +155,10 @@ public async Task OpenSolutionAsync(string solutionFilePath, Cancellat
this.ClearSolution();
- var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory());
-
- using (_dataGuard.DisposableWait(cancellationToken))
- {
- this.SetSolutionProperties(absoluteSolutionPath);
- }
-
- VersionStamp version = default(VersionStamp);
-
-#if !MSBUILD12
- Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath);
- var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
- var invalidProjects = new List();
-
- // seed loaders from known project types
- using (_dataGuard.DisposableWait(cancellationToken))
- {
- foreach (var project in solutionFile.ProjectsInOrder)
- {
- if (project.ProjectType == SolutionProjectType.SolutionFolder)
- {
- continue;
- }
-
- var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode);
- if (projectAbsolutePath != null)
- {
- var extension = Path.GetExtension(projectAbsolutePath);
- if (extension.Length > 0 && extension[0] == '.')
- {
- extension = extension.Substring(1);
- }
-
- var loader = ProjectFileLoader.GetLoaderForProjectFileExtension(this, extension);
- if (loader != null)
- {
- _projectPathToLoaderMap[projectAbsolutePath] = loader;
- }
- }
- else
- {
- invalidProjects.Add(project);
- }
- }
- }
-
- // a list to accumulate all the loaded projects
- var loadedProjects = new Dictionary();
-
- // load all the projects
- foreach (var project in solutionFile.ProjectsInOrder)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (project.ProjectType != SolutionProjectType.SolutionFolder && !invalidProjects.Contains(project))
- {
- var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode);
- if (projectAbsolutePath != null)
- {
- IProjectFileLoader loader;
- if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader))
- {
- // projects get added to 'loadedProjects' as side-effect
- // never prefer metadata when loading solution, all projects get loaded if they can.
- var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata: false, loadedProjects: loadedProjects, cancellationToken: cancellationToken).ConfigureAwait(false);
- }
- }
- }
- }
-#else
- SolutionFile solutionFile = null;
-
- using (var reader = new StreamReader(absoluteSolutionPath))
- {
- version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath));
- var text = await reader.ReadToEndAsync().ConfigureAwait(false);
- solutionFile = SolutionFile.Parse(new StringReader(text));
- }
-
- var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath);
-
- // seed loaders from known project types
- using (_dataGuard.DisposableWait())
- {
- foreach (var projectBlock in solutionFile.ProjectBlocks)
- {
- string absoluteProjectPath;
- if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, ReportMode.Ignore, out absoluteProjectPath))
- {
- var loader = ProjectFileLoader.GetLoaderForProjectTypeGuid(this, projectBlock.ProjectTypeGuid);
- if (loader != null)
- {
- _projectPathToLoaderMap[absoluteProjectPath] = loader;
- }
- }
- }
- }
-
- // a list to accumulate all the loaded projects
- var loadedProjects = new Dictionary();
-
- var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
-
- // load all the projects
- foreach (var projectBlock in solutionFile.ProjectBlocks)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- string absoluteProjectPath;
- if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath))
- {
- IProjectFileLoader loader;
- if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader))
- {
- // projects get added to 'loadedProjects' as side-effect
- // never prefer metadata when loading solution, all projects get loaded if they can.
- var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata: false, loadedProjects: loadedProjects, cancellationToken: cancellationToken).ConfigureAwait(false);
- }
- }
- }
-#endif
+ var solutionInfo = await _loader.LoadSolutionInfoAsync(solutionFilePath, cancellationToken: cancellationToken).ConfigureAwait(false);
// construct workspace from loaded project infos
- this.OnSolutionAdded(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects.Values));
+ this.OnSolutionAdded(solutionInfo);
this.UpdateReferencesAfterAdd();
@@ -505,458 +175,26 @@ public async Task OpenProjectAsync(string projectFilePath, Cancellation
throw new ArgumentNullException(nameof(projectFilePath));
}
- string fullPath;
- if (this.TryGetAbsoluteProjectPath(projectFilePath, Directory.GetCurrentDirectory(), ReportMode.Throw, out fullPath))
- {
- IProjectFileLoader loader;
- if (this.TryGetLoaderFromProjectPath(projectFilePath, ReportMode.Throw, out loader))
- {
- var loadedProjects = new Dictionary();
- var projectId = await GetOrLoadProjectAsync(fullPath, loader, this.LoadMetadataForReferencedProjects, loadedProjects, cancellationToken).ConfigureAwait(false);
-
- // add projects to solution
- foreach (var project in loadedProjects.Values)
- {
- this.OnProjectAdded(project);
- }
-
- this.UpdateReferencesAfterAdd();
-
- return this.CurrentSolution.GetProject(projectId);
- }
- }
-
- // unreachable
- return null;
- }
-
- private string TryGetAbsolutePath(string path, ReportMode mode)
- {
- try
- {
- path = Path.GetFullPath(path);
- }
- catch (Exception)
- {
- ReportFailure(mode, string.Format(WorkspacesResources.InvalidProjectFilePath, path));
- return null;
- }
-
- if (!File.Exists(path))
- {
- ReportFailure(
- mode,
- string.Format(WorkspacesResources.ProjectFileNotFound, path),
- msg => new FileNotFoundException(msg));
- return null;
- }
-
- return path;
- }
-
- private void UpdateReferencesAfterAdd()
- {
- using (_serializationLock.DisposableWait())
- {
- var oldSolution = this.CurrentSolution;
- var newSolution = this.UpdateReferencesAfterAdd(oldSolution);
-
- if (newSolution != oldSolution)
- {
- newSolution = this.SetCurrentSolution(newSolution);
- var ignore = this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.SolutionChanged, oldSolution, newSolution);
- }
- }
- }
-
- // Updates all projects to properly reference other existing projects via project references instead of using references to built metadata.
- private Solution UpdateReferencesAfterAdd(Solution solution)
- {
- // Build map from output assembly path to ProjectId
- // Use explicit loop instead of ToDictionary so we don't throw if multiple projects have same output assembly path.
- var outputAssemblyToProjectIdMap = new Dictionary();
- foreach (var p in solution.Projects)
- {
- if (!string.IsNullOrEmpty(p.OutputFilePath))
- {
- outputAssemblyToProjectIdMap[p.OutputFilePath] = p.Id;
- }
- }
-
- // now fix each project if necessary
- foreach (var pid in solution.ProjectIds)
- {
- var project = solution.GetProject(pid);
-
- // convert metadata references to project references if the metadata reference matches some project's output assembly.
- foreach (var meta in project.MetadataReferences)
- {
- var pemeta = meta as PortableExecutableReference;
- if (pemeta != null)
- {
- ProjectId matchingProjectId;
+ var projects = await _loader.LoadProjectInfoAsync(projectFilePath, GetCurrentProjectMap(), cancellationToken).ConfigureAwait(false);
- // check both Display and FilePath. FilePath points to the actually bits, but Display should match output path if
- // the metadata reference is shadow copied.
- if ((!string.IsNullOrEmpty(pemeta.Display) && outputAssemblyToProjectIdMap.TryGetValue(pemeta.Display, out matchingProjectId)) ||
- (!string.IsNullOrEmpty(pemeta.FilePath) && outputAssemblyToProjectIdMap.TryGetValue(pemeta.FilePath, out matchingProjectId)))
- {
- var newProjRef = new ProjectReference(matchingProjectId, pemeta.Properties.Aliases, pemeta.Properties.EmbedInteropTypes);
-
- if (!project.ProjectReferences.Contains(newProjRef))
- {
- project = project.WithProjectReferences(project.ProjectReferences.Concat(newProjRef));
- }
-
- project = project.WithMetadataReferences(project.MetadataReferences.Where(mr => mr != meta));
- }
- }
- }
-
- solution = project.Solution;
- }
-
- return solution;
- }
-
- private async Task GetOrLoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, Dictionary loadedProjects, CancellationToken cancellationToken)
- {
- var projectId = GetProjectId(projectFilePath);
- if (projectId == null)
+ // add projects to solution
+ foreach (var project in projects)
{
- projectId = await this.LoadProjectAsync(projectFilePath, loader, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
+ this.OnProjectAdded(project);
}
- return projectId;
- }
-
- private async Task LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, Dictionary loadedProjects, CancellationToken cancellationToken)
- {
- Debug.Assert(projectFilePath != null);
- Debug.Assert(loader != null);
-
- var projectId = this.GetOrCreateProjectId(projectFilePath);
-
- var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
-
- var projectFile = await loader.LoadProjectFileAsync(projectFilePath, _properties, cancellationToken).ConfigureAwait(false);
- var projectFileInfo = await projectFile.GetProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);
-
- var projectDirectory = Path.GetDirectoryName(projectFilePath);
- var outputFilePath = projectFileInfo.OutputFilePath;
- var outputDirectory = Path.GetDirectoryName(outputFilePath);
-
- VersionStamp version;
- if (!string.IsNullOrEmpty(projectFilePath) && File.Exists(projectFilePath))
- {
- version = VersionStamp.Create(File.GetLastWriteTimeUtc(projectFilePath));
- }
- else
- {
- version = VersionStamp.Create();
- }
-
- // translate information from command line args
- var commandLineParser = this.Services.GetLanguageServices(loader.Language).GetService();
- var metadataService = this.Services.GetService();
- var analyzerService = this.Services.GetService();
-
- var commandLineArgs = commandLineParser.Parse(
- arguments: projectFileInfo.CommandLineArgs,
- baseDirectory: projectDirectory,
- isInteractive: false,
- sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());
-
- var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
- var metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, metadataService.GetProvider()));
-
- var analyzerLoader = analyzerService.GetLoader();
- foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath))
- {
- analyzerLoader.AddDependencyLocation(path);
- }
-
- var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);
-
- var defaultEncoding = commandLineArgs.Encoding;
-
- // docs & additional docs
- var docFileInfos = projectFileInfo.Documents.ToImmutableArrayOrEmpty();
- var additionalDocFileInfos = projectFileInfo.AdditionalDocuments.ToImmutableArrayOrEmpty();
-
- // check for duplicate documents
- var allDocFileInfos = docFileInfos.AddRange(additionalDocFileInfos);
- CheckDocuments(allDocFileInfos, projectFilePath, projectId);
-
- var docs = new List();
- foreach (var docFileInfo in docFileInfos)
- {
- string name;
- ImmutableArray folders;
- GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);
-
- docs.Add(DocumentInfo.Create(
- DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
- name,
- folders,
- projectFile.GetSourceCodeKind(docFileInfo.FilePath),
- new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
- docFileInfo.FilePath,
- docFileInfo.IsGenerated));
- }
-
- var additionalDocs = new List();
- foreach (var docFileInfo in additionalDocFileInfos)
- {
- string name;
- ImmutableArray folders;
- GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);
-
- additionalDocs.Add(DocumentInfo.Create(
- DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
- name,
- folders,
- SourceCodeKind.Regular,
- new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
- docFileInfo.FilePath,
- docFileInfo.IsGenerated));
- }
-
- // project references
- var resolvedReferences = await this.ResolveProjectReferencesAsync(
- projectId, projectFilePath, projectFileInfo.ProjectReferences, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
-
- // add metadata references for project refs converted to metadata refs
- metadataReferences = metadataReferences.Concat(resolvedReferences.MetadataReferences);
-
- // if the project file loader couldn't figure out an assembly name, make one using the project's file path.
- var assemblyName = commandLineArgs.CompilationName;
- if (string.IsNullOrWhiteSpace(assemblyName))
- {
- assemblyName = Path.GetFileNameWithoutExtension(projectFilePath);
-
- // if this is still unreasonable, use a fixed name.
- if (string.IsNullOrWhiteSpace(assemblyName))
- {
- assemblyName = "assembly";
- }
- }
-
- // make sure that doc-comments at least get parsed.
- var parseOptions = commandLineArgs.ParseOptions;
- if (parseOptions.DocumentationMode == DocumentationMode.None)
- {
- parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Parse);
- }
-
- // add all the extra options that are really behavior overrides
- var compOptions = commandLineArgs.CompilationOptions
- .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
- .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray.Empty, projectDirectory))
- .WithMetadataReferenceResolver(
- new AssemblyReferenceResolver(
- new MetadataFileReferenceResolver(ImmutableArray.Empty, projectDirectory),
- MetadataFileReferenceProvider.Default))
- .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
- .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
-
- loadedProjects.Add(
- projectId,
- ProjectInfo.Create(
- projectId,
- version,
- projectName,
- assemblyName,
- loader.Language,
- projectFilePath,
- outputFilePath,
- compilationOptions: compOptions,
- parseOptions: parseOptions,
- documents: docs,
- projectReferences: resolvedReferences.ProjectReferences,
- metadataReferences: metadataReferences,
- analyzerReferences: analyzerReferences,
- additionalDocuments: additionalDocs,
- isSubmission: false,
- hostObjectType: null));
-
- return projectId;
- }
-
- private static readonly char[] s_directorySplitChars = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
-
- private static void GetDocumentNameAndFolders(string logicalPath, out string name, out ImmutableArray folders)
- {
- var pathNames = logicalPath.Split(s_directorySplitChars, StringSplitOptions.RemoveEmptyEntries);
- if (pathNames.Length > 0)
- {
- if (pathNames.Length > 1)
- {
- folders = pathNames.Take(pathNames.Length - 1).ToImmutableArray();
- }
- else
- {
- folders = ImmutableArray.Create();
- }
-
- name = pathNames[pathNames.Length - 1];
- }
- else
- {
- name = logicalPath;
- folders = ImmutableArray.Create();
- }
- }
-
- private void CheckDocuments(IEnumerable docs, string projectFilePath, ProjectId projectId)
- {
- var paths = new HashSet();
- foreach (var doc in docs)
- {
- if (paths.Contains(doc.FilePath))
- {
- this.OnWorkspaceFailed(new ProjectDiagnostic(WorkspaceDiagnosticKind.Warning, string.Format(WorkspacesResources.DuplicateSourceFileInProject, doc.FilePath, projectFilePath), projectId));
- }
-
- paths.Add(doc.FilePath);
- }
- }
-
- private class ResolvedReferences
- {
- public readonly List ProjectReferences = new List();
- public readonly List MetadataReferences = new List();
- }
-
- private async Task ResolveProjectReferencesAsync(
- ProjectId thisProjectId,
- string thisProjectPath,
- IReadOnlyList projectFileReferences,
- bool preferMetadata,
- Dictionary loadedProjects,
- CancellationToken cancellationToken)
- {
- var resolvedReferences = new ResolvedReferences();
- var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw;
-
- foreach (var projectFileReference in projectFileReferences)
- {
- string fullPath;
-
- if (TryGetAbsoluteProjectPath(projectFileReference.Path, Path.GetDirectoryName(thisProjectPath), reportMode, out fullPath))
- {
- // if the project is already loaded, then just reference the one we have
- var existingProjectId = this.GetProjectId(fullPath);
- if (existingProjectId != null)
- {
- resolvedReferences.ProjectReferences.Add(new ProjectReference(existingProjectId, projectFileReference.Aliases));
- continue;
- }
-
- IProjectFileLoader loader;
- TryGetLoaderFromProjectPath(fullPath, ReportMode.Ignore, out loader);
-
- // get metadata if preferred or if loader is unknown
- if (preferMetadata || loader == null)
- {
- var projectMetadata = await this.GetProjectMetadata(fullPath, projectFileReference.Aliases, _properties, cancellationToken).ConfigureAwait(false);
- if (projectMetadata != null)
- {
- resolvedReferences.MetadataReferences.Add(projectMetadata);
- continue;
- }
- }
-
- // must load, so we really need loader
- if (TryGetLoaderFromProjectPath(fullPath, reportMode, out loader))
- {
- // load the project
- var projectId = await this.GetOrLoadProjectAsync(fullPath, loader, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);
-
- // If that other project already has a reference on us, this will cause a circularity.
- // This check doesn't need to be in the "already loaded" path above, since in any circularity this path
- // must be taken at least once.
- if (ProjectAlreadyReferencesProject(loadedProjects, projectId, targetProject: thisProjectId))
- {
- // We'll try to make this metadata if we can
- var projectMetadata = await this.GetProjectMetadata(fullPath, projectFileReference.Aliases, _properties, cancellationToken).ConfigureAwait(false);
- if (projectMetadata != null)
- {
- resolvedReferences.MetadataReferences.Add(projectMetadata);
- }
- continue;
- }
- else
- {
- resolvedReferences.ProjectReferences.Add(new ProjectReference(projectId, projectFileReference.Aliases));
- continue;
- }
- }
- }
- else
- {
- fullPath = projectFileReference.Path;
- }
-
- // cannot find metadata and project cannot be loaded, so leave a project reference to a non-existent project.
- var id = this.GetOrCreateProjectId(fullPath);
- resolvedReferences.ProjectReferences.Add(new ProjectReference(id, projectFileReference.Aliases));
- }
+ this.UpdateReferencesAfterAdd();
- return resolvedReferences;
+ return this.CurrentSolution.GetProject(projects[0].Id);
}
- ///
- /// Returns true if the project identified by has a reference (even indirectly)
- /// on the project identified by .
- ///
- private bool ProjectAlreadyReferencesProject(Dictionary loadedProjects, ProjectId fromProject, ProjectId targetProject)
+ private Dictionary GetCurrentProjectMap()
{
- ProjectInfo info;
-
- return loadedProjects.TryGetValue(fromProject, out info) && info.ProjectReferences.Any(pr => pr.ProjectId == targetProject ||
- ProjectAlreadyReferencesProject(loadedProjects, pr.ProjectId, targetProject));
+ return this.CurrentSolution.Projects
+ .Where(p => !string.IsNullOrEmpty(p.FilePath))
+ .ToDictionary(p => p.FilePath, p => p.Id);
}
- ///
- /// Gets a MetadataReference to a project's output assembly.
- ///
- private async Task GetProjectMetadata(string projectFilePath, ImmutableArray aliases, IDictionary globalProperties, CancellationToken cancellationToken)
- {
- // use loader service to determine output file for project if possible
- string outputFilePath = null;
-
- try
- {
- outputFilePath = await ProjectFileLoader.GetOutputFilePathAsync(projectFilePath, globalProperties, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception e)
- {
- this.OnWorkspaceFailed(new WorkspaceDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message));
- }
-
- if (outputFilePath != null && File.Exists(outputFilePath))
- {
- if (Workspace.TestHookStandaloneProjectsDoNotHoldReferences)
- {
- var documentationService = this.Services.GetService();
- var docProvider = documentationService.GetDocumentationProvider(outputFilePath);
- var metadata = AssemblyMetadata.CreateFromImage(File.ReadAllBytes(outputFilePath));
-
- return metadata.GetReference(
- documentation: docProvider,
- aliases: aliases,
- display: outputFilePath);
- }
- else
- {
- var metadataService = this.Services.GetService();
- return metadataService.GetReference(outputFilePath, new MetadataReferenceProperties(MetadataImageKind.Assembly, aliases));
- }
- }
-
- return null;
- }
#endregion
#region Apply Changes
@@ -1014,11 +252,11 @@ protected override void ApplyProjectChanges(ProjectChanges projectChanges)
{
var projectPath = project.FilePath;
IProjectFileLoader loader;
- if (this.TryGetLoaderFromProjectPath(projectPath, ReportMode.Ignore, out loader))
+ if (_loader.TryGetLoaderFromProjectPath(projectPath, out loader))
{
try
{
- _applyChangesProjectFile = loader.LoadProjectFileAsync(projectPath, _properties, CancellationToken.None).Result;
+ _applyChangesProjectFile = loader.LoadProjectFileAsync(projectPath, _loader.Properties, CancellationToken.None).Result;
}
catch (System.IO.IOException exception)
{
@@ -1096,7 +334,7 @@ protected override void ApplyDocumentAdded(DocumentInfo info, SourceText text)
var project = this.CurrentSolution.GetProject(info.Id.ProjectId);
IProjectFileLoader loader;
- if (this.TryGetLoaderFromProjectPath(project.FilePath, ReportMode.Ignore, out loader))
+ if (_loader.TryGetLoaderFromProjectPath(project.FilePath, out loader))
{
var extension = _applyChangesProjectFile.GetDocumentExtension(info.SourceCodeKind);
var fileName = Path.ChangeExtension(info.Name, extension);
@@ -1255,5 +493,5 @@ protected override void ApplyAnalyzerReferenceRemoved(ProjectId projectId, Analy
this.OnAnalyzerReferenceRemoved(projectId, analyzerReference);
}
}
- #endregion
+#endregion
}
diff --git a/src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj b/src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
index a68662b72671ca79d5c8d423ae5c63e2e84b8752..24f23e7b3a92c2bfece13496e9b2866ce824c236 100644
--- a/src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
+++ b/src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
@@ -127,6 +127,7 @@
+
diff --git a/src/Workspaces/Core/Portable/PublicAPI.txt b/src/Workspaces/Core/Portable/PublicAPI.txt
index f7187ff40f0197e6c2d5fb3eefc81c9b95fc5b51..a92579ef8b79233e712db106e86253f82cc22e1d 100644
--- a/src/Workspaces/Core/Portable/PublicAPI.txt
+++ b/src/Workspaces/Core/Portable/PublicAPI.txt
@@ -787,6 +787,7 @@ Microsoft.CodeAnalysis.Workspace.ScheduleTask(System.Func func, string tas
Microsoft.CodeAnalysis.Workspace.Services.get -> Microsoft.CodeAnalysis.Host.HostWorkspaceServices
Microsoft.CodeAnalysis.Workspace.SetCurrentSolution(Microsoft.CodeAnalysis.Solution solution) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.Workspace.UnregisterText(Microsoft.CodeAnalysis.Text.SourceTextContainer textContainer) -> void
+Microsoft.CodeAnalysis.Workspace.UpdateReferencesAfterAdd() -> void
Microsoft.CodeAnalysis.Workspace.Workspace(Microsoft.CodeAnalysis.Host.HostServices host, string workspaceKind) -> void
Microsoft.CodeAnalysis.Workspace.WorkspaceChanged -> System.EventHandler
Microsoft.CodeAnalysis.Workspace.WorkspaceFailed -> System.EventHandler
diff --git a/src/Workspaces/Core/Portable/Workspace/AdhocWorkspace.cs b/src/Workspaces/Core/Portable/Workspace/AdhocWorkspace.cs
index 1c56b68c72067c0efaac408b49de7f1871edffae..41a8048620f767b87ba031c015bb8fd417cae6ec 100644
--- a/src/Workspaces/Core/Portable/Workspace/AdhocWorkspace.cs
+++ b/src/Workspaces/Core/Portable/Workspace/AdhocWorkspace.cs
@@ -61,6 +61,8 @@ public Solution AddSolution(SolutionInfo solutionInfo)
this.OnSolutionAdded(solutionInfo);
+ this.UpdateReferencesAfterAdd();
+
return this.CurrentSolution;
}
@@ -85,6 +87,8 @@ public Project AddProject(ProjectInfo projectInfo)
this.OnProjectAdded(projectInfo);
+ this.UpdateReferencesAfterAdd();
+
return this.CurrentSolution.GetProject(projectInfo.Id);
}
@@ -103,6 +107,8 @@ public void AddProjects(IEnumerable projectInfos)
{
this.OnProjectAdded(info);
}
+
+ this.UpdateReferencesAfterAdd();
}
///
diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs
index 25e3e03ef30e3c455ee6b5d75dee23135bf69c46..ff80db0a212ccc1100fde57c3adaf650a716de71 100644
--- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs
+++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs
@@ -799,6 +799,73 @@ protected internal void OnAdditionalDocumentRemoved(DocumentId documentId)
}
}
+ ///
+ /// Updates all projects to properly reference other projects as project references instead of metadata references.
+ ///
+ protected void UpdateReferencesAfterAdd()
+ {
+ using (_serializationLock.DisposableWait())
+ {
+ var oldSolution = this.CurrentSolution;
+ var newSolution = this.UpdateReferencesAfterAdd(oldSolution);
+
+ if (newSolution != oldSolution)
+ {
+ newSolution = this.SetCurrentSolution(newSolution);
+ var ignore = this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.SolutionChanged, oldSolution, newSolution);
+ }
+ }
+ }
+
+ private Solution UpdateReferencesAfterAdd(Solution solution)
+ {
+ // Build map from output assembly path to ProjectId
+ // Use explicit loop instead of ToDictionary so we don't throw if multiple projects have same output assembly path.
+ var outputAssemblyToProjectIdMap = new Dictionary();
+ foreach (var p in solution.Projects)
+ {
+ if (!string.IsNullOrEmpty(p.OutputFilePath))
+ {
+ outputAssemblyToProjectIdMap[p.OutputFilePath] = p.Id;
+ }
+ }
+
+ // now fix each project if necessary
+ foreach (var pid in solution.ProjectIds)
+ {
+ var project = solution.GetProject(pid);
+
+ // convert metadata references to project references if the metadata reference matches some project's output assembly.
+ foreach (var meta in project.MetadataReferences)
+ {
+ var pemeta = meta as PortableExecutableReference;
+ if (pemeta != null)
+ {
+ ProjectId matchingProjectId;
+
+ // check both Display and FilePath. FilePath points to the actually bits, but Display should match output path if
+ // the metadata reference is shadow copied.
+ if ((!string.IsNullOrEmpty(pemeta.Display) && outputAssemblyToProjectIdMap.TryGetValue(pemeta.Display, out matchingProjectId)) ||
+ (!string.IsNullOrEmpty(pemeta.FilePath) && outputAssemblyToProjectIdMap.TryGetValue(pemeta.FilePath, out matchingProjectId)))
+ {
+ var newProjRef = new ProjectReference(matchingProjectId, pemeta.Properties.Aliases, pemeta.Properties.EmbedInteropTypes);
+
+ if (!project.ProjectReferences.Contains(newProjRef))
+ {
+ project = project.WithProjectReferences(project.ProjectReferences.Concat(newProjRef));
+ }
+
+ project = project.WithMetadataReferences(project.MetadataReferences.Where(mr => mr != meta));
+ }
+ }
+ }
+
+ solution = project.Solution;
+ }
+
+ return solution;
+ }
+
#endregion
#region Apply Changes
diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj
index 5c0673336df72c4b1bc96b881f825279ddbff92d..83dbc0ac96fd7542ee8c0ebf098aebf248652da3 100644
--- a/src/Workspaces/Core/Portable/Workspaces.csproj
+++ b/src/Workspaces/Core/Portable/Workspaces.csproj
@@ -19,7 +19,9 @@
{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
-
+
+ ..\..\..\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\\System.Collections.Immutable.dll
+
False
..\..\..\..\packages\Microsoft.Composition.$(MicrosoftCompositionVersion)\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll