diff --git a/BuildAndTest.proj b/BuildAndTest.proj index 64b484d150ce9..b85c5aa0f5b76 100644 --- a/BuildAndTest.proj +++ b/BuildAndTest.proj @@ -99,18 +99,29 @@ /rootSuffix:RoslynDev /vsInstallDir:"$([System.IO.Path]::GetFullPath('$(MSBuildBinPath)\..\..\..'))" - + + - - - - - - - - - + + + + + + + + + + diff --git a/Compilers.sln b/Compilers.sln index 603ac6079f602..d22ba9ca90b41 100644 --- a/Compilers.sln +++ b/Compilers.sln @@ -26,8 +26,14 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSemanticTest", "src\Compilers\CSharp\Test\Semantic\CSharpCompilerSemanticTest.csproj", "{B2C33A93-DB30-4099-903E-77D75C4C3F45}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSymbolTest", "src\Compilers\CSharp\Test\Symbol\CSharpCompilerSymbolTest.csproj", "{28026D16-EB0C-40B0-BDA7-11CAA2B97CCC}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSyntaxTest", "src\Compilers\CSharp\Test\Syntax\CSharpCompilerSyntaxTest.csproj", "{50D26304-0961-4A51-ABF6-6CAD1A56D202}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VisualBasic", "VisualBasic", "{C65C6143-BED3-46E6-869E-9F0BE6E84C37}" EndProject @@ -108,10 +114,19 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSBuildTask", "src\Compilers\Core\MSBuildTask\MSBuildTask.csproj", "{7AD4FE65-9A30-41A6-8004-AA8F89BCB7F3}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingTest", "src\Scripting\CoreTest\ScriptingTest.csproj", "{2DAE4406-7A89-4B5F-95C3-BC5472CE47CE}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpScriptingTest", "src\Scripting\CSharpTest\CSharpScriptingTest.csproj", "{2DAE4406-7A89-4B5F-95C3-BC5422CE47CE}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicScriptingTest", "src\Scripting\VisualBasicTest\BasicScriptingTest.vbproj", "{ABC7262E-1053-49F3-B846-E3091BB92E8C}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripting", "Scripting", "{3FF38FD4-DF16-44B0-924F-0D5AE155495B}" EndProject @@ -144,18 +159,27 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeStyleFixes", "src\CodeStyle\Core\CodeFixes\CodeStyleFixes.csproj", "{5FF1E493-69CC-4D0B-83F2-039F469A04E1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeStyleTests", "src\CodeStyle\Core\Tests\CodeStyleTests.csproj", "{9FF1205F-1D7C-4EE4-B038-3456FE6EBEAF}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeStyle", "src\CodeStyle\CSharp\Analyzers\CSharpCodeStyle.csproj", "{AA87BFED-089A-4096-B8D5-690BDC7D5B24}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeStyleFixes", "src\CodeStyle\CSharp\CodeFixes\CSharpCodeStyleFixes.csproj", "{A07ABCF5-BC43-4EE9-8FD8-B2D77FD54D73}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeStyleTests", "src\CodeStyle\CSharp\Tests\CSharpCodeStyleTests.csproj", "{5018D049-5870-465A-889B-C742CE1E31CB}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeStyle", "src\CodeStyle\VisualBasic\Analyzers\BasicCodeStyle.vbproj", "{2531A8C4-97DD-47BC-A79C-B7846051E137}" EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeStyleFixes", "src\CodeStyle\VisualBasic\CodeFixes\BasicCodeStyleFixes.vbproj", "{0141285D-8F6C-42C7-BAF3-3C0CCD61C716}" EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeStyleTests", "src\CodeStyle\VisualBasic\Tests\BasicCodeStyleTests.vbproj", "{E512C6C1-F085-4AD7-B0D9-E8F1A0A2A510}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution diff --git a/README.md b/README.md index 4770c0bfadf0a..09374138191bd 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ |**dev15.0.x**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.0.x/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.0.x/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/windows_release_vs-integration/)| |**dev15.1.x**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.1.x/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.1.x/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/windows_release_vs-integration/)| |**dev15.2.x**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.2.x/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.2.x/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/windows_release_vs-integration/)| +|**dev15.3-preview1**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.3-preview1/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev15.3-preview1/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/windows_release_vs-integration/)| |**dev16**|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit32/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit32/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit64/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_unit64/)|[![Build Status](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_determinism/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_determinism/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev16/windows_debug_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_debug_vs-integration/)|[![Build Status](https://ci.dot.net/buildStatus/icon?job=dotnet_roslyn/dev16/windows_release_vs-integration)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/windows_release_vs-integration/)| ### Linux/Mac - Unit Tests @@ -18,6 +19,7 @@ |**dev15.0.x**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/linux_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/linux_debug/)||[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.0.x/job/mac_debug/)| |**dev15.1.x**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/linux_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/linux_debug/)||[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.1.x/job/mac_debug/)| |**dev15.2.x**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/linux_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/linux_debug/)||[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.2.x/job/mac_debug/)| +|**dev15.3-preview1**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/linux_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/linux_debug/)||[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev15.3-preview1/job/mac_debug/)| |**dev16**|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/ubuntu_14_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/ubuntu_14_debug/)|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/ubuntu_16_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/ubuntu_16_debug/)|[![BuildStatus](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/mac_debug/badge/icon)](https://ci.dot.net/job/dotnet_roslyn/job/dev16/job/mac_debug/)| [//]: # (End current test results) diff --git a/Roslyn.sln b/Roslyn.sln index ec802e0e67bcf..41f0b21ebc336 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -28,8 +28,14 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSemanticTest", "src\Compilers\CSharp\Test\Semantic\CSharpCompilerSemanticTest.csproj", "{B2C33A93-DB30-4099-903E-77D75C4C3F45}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSymbolTest", "src\Compilers\CSharp\Test\Symbol\CSharpCompilerSymbolTest.csproj", "{28026D16-EB0C-40B0-BDA7-11CAA2B97CCC}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCompilerSyntaxTest", "src\Compilers\CSharp\Test\Syntax\CSharpCompilerSyntaxTest.csproj", "{50D26304-0961-4A51-ABF6-6CAD1A56D202}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VisualBasic", "VisualBasic", "{C65C6143-BED3-46E6-869E-9F0BE6E84C37}" EndProject @@ -106,10 +112,16 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scripting", "src\Scripting\Core\Scripting.csproj", "{12A68549-4E8C-42D6-8703-A09335F97997}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingTest", "src\Scripting\CoreTest\ScriptingTest.csproj", "{2DAE4406-7A89-4B5F-95C3-BC5472CE47CE}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpScripting", "src\Scripting\CSharp\CSharpScripting.csproj", "{066F0DBD-C46C-4C20-AFEC-99829A172625}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpScriptingTest", "src\Scripting\CSharpTest\CSharpScriptingTest.csproj", "{2DAE4406-7A89-4B5F-95C3-BC5422CE47CE}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteractiveFeatures", "src\Interactive\Features\InteractiveFeatures.csproj", "{8E2A252E-A140-45A6-A81A-2652996EA589}" EndProject @@ -250,6 +262,9 @@ EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicScriptingTest.Desktop", "src\Scripting\VisualBasicTest.Desktop\BasicScriptingTest.Desktop.vbproj", "{24973B4C-FD09-4EE1-97F4-EA03E6B12040}" EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicScriptingTest", "src\Scripting\VisualBasicTest\BasicScriptingTest.vbproj", "{ABC7262E-1053-49F3-B846-E3091BB92E8C}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diagnostics", "src\Test\Diagnostics\Diagnostics.csproj", "{E2E889A5-2489-4546-9194-47C63E49EAEB}" EndProject @@ -371,10 +386,19 @@ EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeStyleFixes", "src\CodeStyle\VisualBasic\CodeFixes\BasicCodeStyleFixes.vbproj", "{0141285D-8F6C-42C7-BAF3-3C0CCD61C716}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeStyleTests", "src\CodeStyle\Core\Tests\CodeStyleTests.csproj", "{9FF1205F-1D7C-4EE4-B038-3456FE6EBEAF}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeStyleTests", "src\CodeStyle\CSharp\Tests\CSharpCodeStyleTests.csproj", "{5018D049-5870-465A-889B-C742CE1E31CB}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeStyleTests", "src\CodeStyle\VisualBasic\Tests\BasicCodeStyleTests.vbproj", "{E512C6C1-F085-4AD7-B0D9-E8F1A0A2A510}" + ProjectSection(ProjectDependencies) = postProject + {76C6F005-C89D-4348-BB4A-391898DBEB52} = {76C6F005-C89D-4348-BB4A-391898DBEB52} + EndProjectSection EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution diff --git a/build/Rulesets/Roslyn_BuildRules.ruleset b/build/Rulesets/Roslyn_BuildRules.ruleset index c2da92b629f26..80a582eb370aa 100644 --- a/build/Rulesets/Roslyn_BuildRules.ruleset +++ b/build/Rulesets/Roslyn_BuildRules.ruleset @@ -20,6 +20,7 @@ + @@ -35,9 +36,19 @@ + + + + + + + + + + @@ -45,6 +56,8 @@ + + @@ -110,4 +123,4 @@ - \ No newline at end of file + diff --git a/build/Targets/Dependencies.props b/build/Targets/Dependencies.props index d25f03b1feea3..f9a8a6fadf63d 100644 --- a/build/Targets/Dependencies.props +++ b/build/Targets/Dependencies.props @@ -2,6 +2,7 @@ + 0.9.2 3.0.0-unstable0085 1.9.4 0.2.0 @@ -21,7 +22,7 @@ 0.8.31-beta 1.0.35 1.1.0 - 1.0.0-beta1-61518-02 + 1.0.0-beta1-61618-01 1.5.0 1.2.0 1.0.0-beta1-61531-03 diff --git a/build/Targets/Imports.targets b/build/Targets/Imports.targets index 4ca1c5aa511d5..a41f3d1d7df7e 100644 --- a/build/Targets/Imports.targets +++ b/build/Targets/Imports.targets @@ -11,14 +11,14 @@ <_CopyReferences>false <_CopyProjectReferences>false false - $(OutDir)Exes\$(MSBuildProjectName)\ + $(OutputPath)Exes\$(MSBuildProjectName)\ <_IsAnyUnitTest>true true - $(OutDir)UnitTests\$(MSBuildProjectName)\ + $(OutputPath)UnitTests\$(MSBuildProjectName)\ @@ -39,21 +39,21 @@ <_IsAnyUnitTest>true <_IsAnyPortableUnitTest>true false - $(OutDir)Dlls\$(MSBuildProjectName)\ + $(OutputPath)Dlls\$(MSBuildProjectName)\ <_CopyReferences>false false - $(OutDir)Exes\ + $(OutputPath)Exes\ <_CopyReferences>false true - $(OutDir)Vsix\$(MSBuildProjectName)\ + $(OutputPath)Vsix\$(MSBuildProjectName)\ @@ -62,8 +62,8 @@ $(AllowedReferenceRelatedFileExtensions);.pdb true - $(OutDir)CoreClrTest - $(OutDir)UnitTests\Portable\ + $(OutputPath)CoreClrTest + $(OutputPath)UnitTests\Portable\ @@ -74,19 +74,19 @@ <_CopyReferences>false <_CopyProjectReferences>false false - $(OutDir)Dlls\$(MSBuildProjectName)\ + $(OutputPath)Dlls\$(MSBuildProjectName)\ true - $(OutDir)Exes\$(MSBuildProjectName)\ + $(OutputPath)Exes\$(MSBuildProjectName)\ true - $(OutDir)Exes\$(MSBuildProjectName)\ + $(OutputPath)Exes\$(MSBuildProjectName)\ @@ -114,7 +114,6 @@ - $(OutDir) 0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9 002400000480000094000000060200000024000052534131000400000100010055e0217eb635f69281051f9a823e0c7edd90f28063eb6c7a742a19b4f6139778ee0af438f47aed3b6e9f99838aa8dba689c7a71ddb860c96d923830b57bbd5cd6119406ddb9b002cf1c723bf272d6acbb7129e9d6dd5a5309c94e0ff4b2c884d45a55f475cd7dba59198086f61f5a8c8b5e601c0edbf269733f6f578fc8579c2 @@ -367,6 +366,7 @@ DeployPortableOnDeveloperBuild;$(PrepareResourcesDependsOn) + RemoveDuplicateXUnitContent;$(PrepareForBuildDependsOn) $(IntermediateOutputPath)$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension) $(IntermediateOutputPath)$(TargetFileName).pcbm $(NuGetPackageRoot)\RoslynDependencies.OptimizationData\2.0.0-rc-61101-16\content\OptimizationData @@ -464,10 +464,29 @@ Targets="GetTargetPath" BuildInParallel="true"> - + + + + + + + + diff --git a/build/Targets/Roslyn.Toolsets.Xunit.targets b/build/Targets/Roslyn.Toolsets.Xunit.targets index 4b837cd3fca06..39950a76c6cf7 100644 --- a/build/Targets/Roslyn.Toolsets.Xunit.targets +++ b/build/Targets/Roslyn.Toolsets.Xunit.targets @@ -32,7 +32,5 @@ app.config - - - \ No newline at end of file + diff --git a/build/Targets/Settings.props b/build/Targets/Settings.props index a702d4dd7508d..fce63778e6a8b 100644 --- a/build/Targets/Settings.props +++ b/build/Targets/Settings.props @@ -18,7 +18,7 @@ 2.0.1 RoslynTools.Microsoft.VSIXExpInstaller 0.2.1-beta - 1.2.0-beta2 + 2.0.0-beta1-61628-06 $(NuGetPackageRoot)\Microsoft.Net.RoslynDiagnostics\$(RoslynDiagnosticsNugetPackageVersion)\build\Microsoft.Net.RoslynDiagnostics.props $(NuGetPackageRoot)\Roslyn.Build.Util\0.9.4-portable\lib\dotnet\Roslyn.MSBuild.Util.dll $(AdditionalFileItemNames);PublicAPI @@ -27,7 +27,7 @@ true true $(RepoRoot)Binaries\ - $(BaseOutputPath)$(Configuration)\ + $(BaseOutputPath)$(Configuration)\ $(RepoRoot)Binaries\Obj\ $(BaseIntermediateOutputPath)$(Configuration)\$(MSBuildProjectName)\ @@ -47,7 +47,7 @@ $(VisualStudioVersion) false diff --git a/build/ToolsetPackages/project.json b/build/ToolsetPackages/project.json index 394e26814b195..cf83655a35253 100644 --- a/build/ToolsetPackages/project.json +++ b/build/ToolsetPackages/project.json @@ -7,7 +7,7 @@ "Microsoft.NETCore.Platforms": "1.1.0", "Microsoft.DiaSymReader.Native": "1.5.0", "Microsoft.Net.Compilers": "2.0.1", - "Microsoft.Net.RoslynDiagnostics": "1.2.0-beta2", + "Microsoft.Net.RoslynDiagnostics": "2.0.0-beta1-61628-06", "FakeSign": "0.9.2", "xunit": "2.2.0-beta4-build3444", "xunit.runner.console": "2.2.0-beta4-build3444", diff --git a/build/config/RepoUtilData.json b/build/config/RepoUtilData.json index ebd46ab5a2463..85ecd228dc5f7 100644 --- a/build/config/RepoUtilData.json +++ b/build/config/RepoUtilData.json @@ -50,7 +50,8 @@ "GitLink", "Microsoft.NETCore.Runtime.CoreCLR", "Microsoft.VSSDK.BuildTools", - "NETStandard.Library" + "NETStandard.Library", + "FakeSign" ] } }, diff --git a/build/config/SignToolData.json b/build/config/SignToolData.json index ce3c84e033ff4..e3e9589e83567 100644 --- a/build/config/SignToolData.json +++ b/build/config/SignToolData.json @@ -1,7 +1,7 @@ { "sign": [ { - "certificate": "Microsoft402", + "certificate": "MicrosoftSHA2", "strongName": "MsSharedLib72", "values": [ "Dlls\\BasicCodeAnalysis\\Microsoft.CodeAnalysis.VisualBasic.dll", diff --git a/build/scripts/build-utils.ps1 b/build/scripts/build-utils.ps1 index c8c66eb70a275..2f24e9b2055a3 100644 --- a/build/scripts/build-utils.ps1 +++ b/build/scripts/build-utils.ps1 @@ -9,43 +9,89 @@ $ErrorActionPreference="Stop" # Handy function for executing a command in powershell and throwing if it # fails. +# +# Use this when the full command is known at script authoring time and +# doesn't require any dynamic argument build up. Example: +# +# Exec-Block { & $msbuild Test.proj } # # Original sample came from: http://jameskovacs.com/2010/02/25/the-exec-problem/ -function Exec([scriptblock]$cmd, [switch]$echo = $false) { - if ($echo) { - & $cmd - } - else { - $output = & $cmd - } +function Exec-Block([scriptblock]$cmd) { + & $cmd # Need to check both of these cases for errors as they represent different items # - $?: did the powershell script block throw an error # - $lastexitcode: did a windows command executed by the script block end in error if ((-not $?) -or ($lastexitcode -ne 0)) { - if (-not $echo) { - Write-Host $output - } throw "Command failed to execute: $cmd" } } -function Exec-Echo([scriptblock]$cmd) { - Exec $cmd -echo:$true +# Handy function for executing a windows command which needs to go through +# windows command line parsing. +# +# Use this when the command arguments are stored in a variable. Particularly +# when the variable needs reparsing by the windows command line. Example: +# +# $args = "/p:ManualBuild=true Test.proj" +# Exec-Command $msbuild $args +# +function Exec-Command([string]$command, [string]$commandArgs) { + $startInfo = New-Object System.Diagnostics.ProcessStartInfo + $startInfo.FileName = $command + $startInfo.Arguments = $commandArgs + + $startInfo.RedirectStandardOutput = $true + $startInfo.UseShellExecute = $false + $startInfo.CreateNoWindow = $true + + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $startInfo + $process.StartInfo.RedirectStandardOutput = $true; + $process.Start() | Out-Null + + $finished = $false + try { + # The OutputDataReceived event doesn't fire as events are sent by the + # process in powershell. Possibly due to subtlties of how Powershell + # manages the thread pool that I'm not aware of. Using blocking + # reading here as an alternative which is fine since this blocks + # on completion already. + $out = $process.StandardOutput + while (-not $out.EndOfStream) { + $line = $out.ReadLine() + Write-Output $line + } + + while (-not $process.WaitForExit(100)) { + # Non-blocking loop done to allow ctr-c interrupts + } + + $finished = $true + if ($process.ExitCode -ne 0) { + throw "Command failed to execute: $command $commandArgs" + } + } + finally { + # If we didn't finish then an error occured or the user hit ctrl-c. Either + # way kill the process + if (-not $finished) { + $process.Kill() + } + } } -# Handy function for executing Invoke-Expression and reliably throwing an -# error if the expression, or the command it invoked, fails -# -# Original sample came from: http://jameskovacs.com/2010/02/25/the-exec-problem/ -function Exec-Expression([string]$expr) { - Exec { Invoke-Expression $expr } -echo:$true +# Handy function for executing a powershell script in a clean environment with +# arguments. Prefer this over & sourcing a script as it will both use a clean +# environment and do proper error checking +function Exec-Script([string]$script, [string]$scriptArgs = "") { + Exec-Command "powershell" "-noprofile -executionPolicy RemoteSigned -file `"$script`" $scriptArgs" } # Ensure that NuGet is installed and return the path to the # executable to use. function Ensure-NuGet() { - Exec { & (Join-Path $PSScriptRoot "download-nuget.ps1") } + Exec-Block { & (Join-Path $PSScriptRoot "download-nuget.ps1") } | Out-Host $nuget = Join-Path $repoDir "NuGet.exe" return $nuget } @@ -56,7 +102,7 @@ function Ensure-BasicTool([string]$name, [string]$version) { $p = Join-Path (Get-PackagesDir) "$($name).$($version)" if (-not (Test-Path $p)) { $nuget = Ensure-NuGet - Exec { & $nuget install $name -OutputDirectory (Get-PackagesDir) -Version $version } + Exec-Block { & $nuget install $name -OutputDirectory (Get-PackagesDir) -Version $version } | Out-Null } return $p @@ -206,14 +252,14 @@ function Get-VisualStudioDir() { # Clear out the NuGet package cache function Clear-PackageCache() { $nuget = Ensure-NuGet - Exec { & $nuget locals all -clear } + Exec-Block { & $nuget locals all -clear } | Out-Host } # Restore a single project function Restore-Project([string]$fileName, [string]$nuget, [string]$msbuildDir) { $nugetConfig = Join-Path $repoDir "nuget.config" $filePath = Join-Path $repoDir $fileName - Exec { & $nuget restore -verbosity quiet -configfile $nugetConfig -MSBuildPath $msbuildDir -Project2ProjectTimeOut 1200 $filePath } + Exec-Block { & $nuget restore -verbosity quiet -configfile $nugetConfig -MSBuildPath $msbuildDir -Project2ProjectTimeOut 1200 $filePath } | Out-Null } # Restore all of the projects that the repo consumes diff --git a/build/scripts/build.ps1 b/build/scripts/build.ps1 index b59fbd8b0b40b..0c53de2ab25be 100644 --- a/build/scripts/build.ps1 +++ b/build/scripts/build.ps1 @@ -4,6 +4,7 @@ param ( [switch]$build = $false, [switch]$restore = $false, [switch]$test = $false, + [switch]$test64 = $false, [switch]$clean = $false, [switch]$clearPackageCache = $false, [string]$project = "", @@ -17,7 +18,8 @@ function Print-Usage() { Write-Host "Build.ps1" Write-Host "`t-build Run a build operation (default false)" Write-Host "`t-restore Run a restore operation (default false)" - Write-Host "`t-test Run tests (default false)" + Write-Host "`t-test Run unit tests (default false)" + Write-Host "`t-test64 Run unit tests in 64 bit mode" Write-Host "`t-clean Do a clean build / restore (default false)" Write-Host "`t-clearPackageCache Clear package cache before restoring" Write-Host "`t-project Project the build or restore should target" @@ -33,12 +35,16 @@ function Run-Build() { $target = if ($project -ne "") { $project } else { Join-Path $repoDir "Roslyn.sln" } $buildArgs = "$buildArgs $target" - Exec-Expression "& `"$msbuild`" $buildArgs" + Exec-Command $msbuild $buildArgs | Out-Host } function Run-Test() { $proj = Join-Path $repoDir "BuildAndTest.proj" - Exec-Expression "& `"$msbuild`" /v:m /p:SkipCoreClr=true /t:Test $proj" + $args = "/v:m /p:SkipCoreClr=true /p:ManualTest=true /t:Test $proj" + if ($test64) { + $args += " /p:Test64=true" + } + Exec-Command $msbuild $args | Out-Host } try { @@ -68,7 +74,7 @@ try { Run-Build } - if ($test) { + if ($test -or $test64) { Run-Test } } diff --git a/build/scripts/check-toolset-insertion.ps1 b/build/scripts/check-toolset-insertion.ps1 index 8d1493aa66545..a5e4e15f790f3 100644 --- a/build/scripts/check-toolset-insertion.ps1 +++ b/build/scripts/check-toolset-insertion.ps1 @@ -21,6 +21,11 @@ try "Microsoft.Build.Utilities.Core.dll", "Microsoft.DiaSymReader.Native.arm.dll" ) + + $exludedFromVsix = @( + "Microsoft.DiaSymReader.Native.x86.dll", # installed by msbuild setup component + "Microsoft.DiaSymReader.Native.amd64.dll" # installed by msbuild setup component + ) $deploymentPath = join-path $binariesPath "Exes\Toolset" $deployedFiles = @@ -92,7 +97,7 @@ try foreach ($file in $deployedFiles) { write-host "`t$file" - if ($msbuildroslynfiles.Contains($file)) + if ($msbuildroslynfiles.Contains($file) -or $exludedFromVsix.Contains($file)) { continue; } diff --git a/build/scripts/cibuild.ps1 b/build/scripts/cibuild.ps1 index a7916ead7132c..75fe3f9fc00c4 100644 --- a/build/scripts/cibuild.ps1 +++ b/build/scripts/cibuild.ps1 @@ -11,6 +11,8 @@ param ( [switch]$skipRestore = $false, [switch]$skipCommitPrinting = $false, [switch]$release = $false, + [switch]$skipCoreClrTests = $false, + [switch]$skipDesktopTests = $false, [parameter(ValueFromRemainingArguments=$true)] $badArgs) Set-StrictMode -version 2.0 @@ -24,6 +26,8 @@ function Print-Usage() { Write-Host " -test64 Run units tests in the 64-bit runner." Write-Host " -$testVsi Run all integration tests." Write-Host " -$testVsiNetCore Run just dotnet core integration tests." + Write-Host " -skipCoreClrTests Skip running unit tests on CoreCLR" + Write-Host " -skipDesktopTests Skip running unit tests on Desktop" } function Run-MSBuild() { @@ -31,10 +35,12 @@ function Run-MSBuild() { # that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise, # we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211. # MSBuildAdditionalCommandLineArgs= - & $msbuild /warnaserror /nologo /m /nodeReuse:false /consoleloggerparameters:Verbosity=minimal /filelogger /fileloggerparameters:Verbosity=normal @args - if (-not $?) { - throw "Build failed" + $buildArgs = "/warnaserror /nologo /m /nodeReuse:false /consoleloggerparameters:Verbosity=minimal /filelogger /fileloggerparameters:Verbosity=normal" + foreach ($arg in $args) { + $buildArgs += " $arg" } + + Exec-Command $msbuild $buildArgs } # Kill any instances VBCSCompiler.exe to release locked files, ignoring stderr if process is not open @@ -87,14 +93,14 @@ try { Redirect-Temp if ($testBuildCorrectness) { - Exec-Echo { & ".\build\scripts\test-build-correctness.ps1" -config $buildConfiguration } + Exec-Block { & ".\build\scripts\test-build-correctness.ps1" -config $buildConfiguration } | Out-Host exit 0 } # Output the commit that we're building, for reference in Jenkins logs if (-not $skipCommitPrinting) { Write-Host "Building this commit:" - Exec { & git show --no-patch --pretty=raw HEAD } + Exec-Block { & git show --no-patch --pretty=raw HEAD } | Out-Host } # Build with the real assembly version, since that's what's contained in the bootstrap compiler redirects @@ -108,14 +114,14 @@ try { Terminate-BuildProcesses if ($testDeterminism) { - Exec { & ".\build\scripts\test-determinism.ps1" -buildDir $bootstrapDir } + Exec-Block { & ".\build\scripts\test-determinism.ps1" -buildDir $bootstrapDir } | Out-Host Terminate-BuildProcesses exit 0 } if ($testPerfCorrectness) { Run-MSBuild Roslyn.sln /p:Configuration=$buildConfiguration /p:DeployExtension=false - Exec { & ".\Binaries\$buildConfiguration\Exes\Perf.Runner\Roslyn.Test.Performance.Runner.exe" --ci-test } + Exec-Block { & ".\Binaries\$buildConfiguration\Exes\Perf.Runner\Roslyn.Test.Performance.Runner.exe" --ci-test } | Out-Host exit 0 } @@ -140,7 +146,7 @@ try { Create-Directory ".\Binaries\$buildConfiguration\tools\" # Get the benchview tools - Place alongside Roslyn.Test.Performance.Runner.exe - Exec { & ".\build\scripts\install_benchview_tools.cmd" ".\Binaries\$buildConfiguration\tools\" } + Exec-Block { & ".\build\scripts\install_benchview_tools.cmd" ".\Binaries\$buildConfiguration\tools\" } | Out-Host } Terminate-BuildProcesses @@ -154,13 +160,15 @@ try { $target = if ($skipTest) { "Build" } else { "BuildAndTest" } $test64Arg = if ($test64) { "true" } else { "false" } $testVsiArg = if ($testVsi) { "true" } else { "false" } + $skipCoreClrTestsArg = if ($skipCoreClrTests) { "true" } else { "false" } + $skipDesktopTestsArg = if ($skipDesktopTests) { "true" } else { "false" } $buildLog = Join-Path $binariesdir "Build.log" if ($testVsiNetCore) { - Run-MSBuild /p:BootstrapBuildPath="$bootstrapDir" BuildAndTest.proj /t:$target /p:Configuration=$buildConfiguration /p:Test64=$test64Arg /p:TestVsi=true /p:Trait="Feature=NetCore" /p:PathMap="$($repoDir)=q:\roslyn" /p:Feature=pdb-path-determinism /fileloggerparameters:LogFile="$buildLog"`;verbosity=diagnostic /p:DeployExtension=false + Run-MSBuild /p:BootstrapBuildPath="$bootstrapDir" BuildAndTest.proj /t:$target /p:Configuration=$buildConfiguration /p:Test64=$test64Arg /p:TestVsi=true /p:SkipCoreClrTest=$skipCoreClrTestsArg /p:SkipDesktopTest=$skipDesktopTestsArg /p:Trait="Feature=NetCore" /p:PathMap="$($repoDir)=q:\roslyn" /p:Feature=pdb-path-determinism /fileloggerparameters:LogFile="$buildLog"`;verbosity=diagnostic /p:DeployExtension=false } else { - Run-MSBuild /p:BootstrapBuildPath="$bootstrapDir" BuildAndTest.proj /t:$target /p:Configuration=$buildConfiguration /p:Test64=$test64Arg /p:TestVsi=$testVsiArg /p:PathMap="$($repoDir)=q:\roslyn" /p:Feature=pdb-path-determinism /fileloggerparameters:LogFile="$buildLog"`;verbosity=diagnostic /p:DeployExtension=false + Run-MSBuild /p:BootstrapBuildPath="$bootstrapDir" BuildAndTest.proj /t:$target /p:Configuration=$buildConfiguration /p:Test64=$test64Arg /p:TestVsi=$testVsiArg /p:SkipCoreClrTest=$skipCoreClrTestsArg /p:SkipDesktopTest=$skipDesktopTestsArg /p:PathMap="$($repoDir)=q:\roslyn" /p:Feature=pdb-path-determinism /fileloggerparameters:LogFile="$buildLog"`;verbosity=diagnostic /p:DeployExtension=false } exit 0 diff --git a/build/scripts/generate-compiler-code.ps1 b/build/scripts/generate-compiler-code.ps1 index 4ac3612f9f037..d9acdedfd0de1 100644 --- a/build/scripts/generate-compiler-code.ps1 +++ b/build/scripts/generate-compiler-code.ps1 @@ -14,10 +14,7 @@ function Run-Tool($tool, $toolArgs) { throw "$tool does not exist" } - Exec-Expression "& `"$coreRun`" `"$tool`" $toolArgs" - if ((-not $?) -or ($lastexitcode -ne 0)) { - throw "Failed" - } + Exec-Command "$coreRun" "`"$tool`" $toolArgs" | Out-Host } function Run-LanguageCore($language, $languageSuffix, $languageDir, $syntaxTool, $errorFactsTool, $generatedDir, $generatedTestDir) { diff --git a/build/scripts/test-build-correctness.ps1 b/build/scripts/test-build-correctness.ps1 index 85b00ec69ce99..dd2055da0f9ce 100644 --- a/build/scripts/test-build-correctness.ps1 +++ b/build/scripts/test-build-correctness.ps1 @@ -34,24 +34,24 @@ try { } Write-Host "Building Roslyn.sln with logging support" - Exec-Echo { & $msbuild /v:m /m /logger:StructuredLogger`,$structuredLoggerPath`;$logPath /nodeReuse:false /p:DeployExtension=false Roslyn.sln } + Exec-Command $msbuild "/v:m /m /logger:StructuredLogger,$structuredLoggerPath;$logPath /nodeReuse:false /p:DeployExtension=false Roslyn.sln" Write-Host "" # Verify the state of our various build artifacts Write-Host "Running BuildBoss" $buildBossPath = Join-Path $configDir "Exes\BuildBoss\BuildBoss.exe" - Exec-Echo { & $buildBossPath Roslyn.sln Compilers.sln src\Samples\Samples.sln CrossPlatform.sln "build\Targets" $logPath } + Exec-Command $buildBossPath "Roslyn.sln Compilers.sln src\Samples\Samples.sln CrossPlatform.sln build\Targets $logPath" Write-Host "" # Verify the state of our project.jsons Write-Host "Running RepoUtil" $repoUtilPath = Join-Path $configDir "Exes\RepoUtil\RepoUtil.exe" - Exec-Echo { & $repoUtilPath verify } + Exec-Command $repoUtilPath verify Write-Host "" # Verify the state of our generated syntax files Write-Host "Checking generated compiler files" - Exec-Echo { & (Join-Path $PSScriptRoot "generate-compiler-code.ps1") -test } + Exec-Block { & (Join-Path $PSScriptRoot "generate-compiler-code.ps1") -test } exit 0 } diff --git a/build/scripts/test-determinism.ps1 b/build/scripts/test-determinism.ps1 index 93d178d868a37..de59d2b6f71c2 100644 --- a/build/scripts/test-determinism.ps1 +++ b/build/scripts/test-determinism.ps1 @@ -37,12 +37,10 @@ function Run-Build() { # Clean out the previous run Write-Host "Cleaning the Binaries" - Remove-Item -re -fo $debugDir - Remove-Item -re -fo $objDir - Exec {& $msbuild /nologo /v:m /nodeReuse:false /t:clean $sln } + Exec-Command $msbuild "/nologo /v:m /nodeReuse:false /t:clean $sln" Write-Host "Building the Solution" - Exec { & $msbuild /nologo /v:m /nodeReuse:false /m /p:DebugDeterminism=true /p:BootstrapBuildPath=$script:buildDir '/p:Features="debug-determinism;pdb-path-determinism"' /p:UseRoslynAnalyzers=false $pathMapBuildOption $sln } + Exec-Command $msbuild "/nologo /v:m /nodeReuse:false /m /p:DebugDeterminism=true /p:BootstrapBuildPath=$script:buildDir /p:Features=`"debug-determinism;pdb-path-determinism`" /p:UseRoslynAnalyzers=false $pathMapBuildOption $sln" } finally { Pop-Location diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md index fdc296f49a43e..ab18ef653b598 100644 --- a/docs/Language Feature Status.md +++ b/docs/Language Feature Status.md @@ -1,7 +1,7 @@ Language Feature Status ===== -This document reflects the status, and planned work, for the compiler team. It is a live document +This document reflects the status, and planned work in progress, for the compiler team. It is a live document and will be updated as work progresses, features are added / removed, and as work on feature progresses. This is not an exhaustive list of our features but rather the ones which have active development efforts behind them. @@ -13,7 +13,8 @@ efforts behind them. | [Async Main](https://github.com/dotnet/csharplang/blob/master/proposals/async-main.md) | [async-main](https://github.com/dotnet/roslyn/tree/features/async-main) | Prototype | [tyoverby](https://github.com/tyoverby) | [vsadov](https://github.com/vsadov) | [stephentoub](https://github.com/stephentoub) | | [Default Expressions](https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-default.md) | master | Merged | [jcouv](https://github.com/jcouv) | [cston](https://github.com/cston) | [jcouv](https://github.com/jcouv) | | [Ref Assemblies](https://github.com/dotnet/roslyn/blob/features/refout/docs/features/refout.md) | [refout](https://github.com/dotnet/roslyn/tree/features/refout) | Integration & validation | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | N/A | -| [Infer tuple names](https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-default.md) | [tuple-names](https://github.com/dotnet/roslyn/tree/features/tuple-names) | Implementation | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) | +| [Infer tuple names](https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.1/infer-tuple-names.md) | master | Merged | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) | +| [Pattern-matching with generics](https://github.com/dotnet/csharplang/blob/master/proposals/generics-pattern-match.md) | https://github.com/dotnet/roslyn/pull/18784 | Implementation | [gafter](https://github.com/gafter) | [agocke](https://github.com/agocke) | [gafter](https://github.com/gafter) | # C# 7.2 @@ -27,8 +28,8 @@ efforts behind them. | Feature | Branch | State | Developers | Reviewer | LDM Champ | | ------- | ------ | ----- | ---------- | -------- | --------- | -| [Default Interface Methods](https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md) | [defaultInterfaceImplementation](https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation) | Proposal | [AlekseyTs](https://github.com/AlekseyTs) | [gafter](https://github.com/gafter) | [gafter](https://github.com/gafter) | -| [Nullable reference type](https://github.com/dotnet/roslyn/blob/features/NullableReferenceTypes/docs/features/NullableReferenceTypes/Nullable%20reference%20types.md) | none | Prototype | [cston](https://github.com/cston), [AlekseyTs](https://github.com/AlekseyTs) | | [gafter](https://github.com/gafter) | +| [Default Interface Methods](https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md) | [defaultInterfaceImplementation](https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation) | Prototype | [AlekseyTs](https://github.com/AlekseyTs) | [gafter](https://github.com/gafter) | [gafter](https://github.com/gafter) | +| [Nullable reference type](https://github.com/dotnet/roslyn/blob/features/NullableReferenceTypes/docs/features/NullableReferenceTypes/Nullable%20reference%20types.md) | [NullableReferenceTypes](https://github.com/dotnet/roslyn/tree/features/NullableReferenceTypes) | Prototype | [cston](https://github.com/cston), [AlekseyTs](https://github.com/AlekseyTs) | | [mattwar](https://github.com/mattwar) | # FAQ diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - post VS2017.md b/docs/compilers/CSharp/Compiler Breaking Changes - post VS2017.md index f324e453a2591..f35cbb494ee15 100644 --- a/docs/compilers/CSharp/Compiler Breaking Changes - post VS2017.md +++ b/docs/compilers/CSharp/Compiler Breaking Changes - post VS2017.md @@ -7,3 +7,10 @@ In C# 7, the compiler accepted a pattern of the form `dynamic identifier`, e.g. - https://github.com/dotnet/roslyn/issues/17674 In C# 7, the compiler accepted an assignment statement of the form `_ = M();` where M is a `void` method. The compiler now rejects that. - https://github.com/dotnet/roslyn/issues/17173 Before C# 7.1, `csc` would accept leading zeroes in the `/langversion` option. Now it should reject it. Example: `csc.exe source.cs /langversion:07`. + +- https://github.com/dotnet/csharplang/issues/415 +In C# 7.0, elements in tuple literals can be named explicitly, but in C# 7.1, elements that aren't named explicitly will get an inferred named. This uses the same rules as members in anonymous types which aren't named explicitly. +For instance, `var t = (a, b.c, this.d);` will produce a tuple with element names "a", "c" and "d". As a result, an invocation on a tuple member may result in a different result than it did in C# 7.0. +Consider the case where the type of `a` is `System.Func` and you write `var local = t.a();`. This will now find the first element of the tuple and invoke it, whereas previously it could only mean "invoke an extension method named 'a'". + +- https://github.com/dotnet/roslyn/issues/16870 In C# 7.0 and before C# 7.1, the compiler accepted self-assignments in deconstruction-assignment. The compiler now produces a warning for that. For instance, in `(x, y) = (x, 2);`. diff --git a/docs/compilers/Design/Closure Conversion.md b/docs/compilers/Design/Closure Conversion.md new file mode 100644 index 0000000000000..9f7574764ed6c --- /dev/null +++ b/docs/compilers/Design/Closure Conversion.md @@ -0,0 +1,175 @@ +Closure Conversion in C# +======================== + +This document describes the how the C# compiler turns closures (anonymous and local functions) into top-level functions (methods). + +If you aren't familiar with closure conversion, the introduction contains a walkthrough describing the transformations. Otherwise, you can skip to the Internals section to see how the actual transformations are done in Roslyn. + +# Introduction + +In the simplest case, this is trivial -- all closures are simply given new, unmentionable names and are lifted to the top level as static methods. The complexity comes when a closure captures a variable from its surrounding scope. At that point, we must not only move the closure to a method, we also have to create an "environment" to hold its captured variables and somehow deliver that environment into the context of the rewritten method. + +There are two possible strategies that are both employed in different situations in the compiler. The first strategy is to pass the environment as an extra parameter to all method calls to the closure. For example, + +```csharp +void M() +{ + int x = 0; + int Local() => x + 1; +} +``` + +becomes + +```csharp +void M() +{ + var env = new Environment(); + env.x = 0; + <>__Local(env); +} + +static int <>__Local(Environment env) +{ + return env.x + 1; +} + +struct Environment +{ + int x; +} +``` + +Instead of referring to local variables, the rewritten closure now references fields on the environment. A `struct` environment is used to prevent extra allocations, since `struct`s are normally allocated on the stack. However, the astute reader may notice a problem with this conversion -- `struct`s are always copied when passed as arguments to a function call! This means that writes to the environment field will not always propogate back to the local variable in the method `M`. To work around this flaw, all Environment variables are passed as `ref` arguments to the rewritten closures. + +The second strategy for rewriting closures is necessary when the closure interacts with external code. Consider the following program: + +```csharp +void M(IEnumerable e) +{ + int x = 0; + var positive = e.Where(n => n > 0); + ... +} +``` + +In this case we're passing a closure to the `IEnumerable.Where` function, which is expecting a delegate of type `Func`. Note that that delegate type is immutable -- it is defined in external code and cannot be changed. Therefore, rewriting external callsites to take an extra `Environment` argument is impossible. We have to choose a different strategy for acquiring the environment. + +What we do is use a `class` Environment for cases like this. With a `class` Environment, the previous environment can be rewritten as follows: + +```csharp +void M(IEnumerable e) +{ + var env = new Environment(); + env.x = 0; + var positive = e.Where(env.<>__Local); +} + +class Environment +{ + int x; + + bool <>__Local(int n) => n > 0; +} +``` + +Since the local variables are now fields in a class instance we can keep the same delegate signature and rely on field access to read and write the free variables. + +This covers the transformations C# performs at a high level. The following section covers how these transformations are performed in detail. + +# Internals + +There are two phases at the top level of closure conversion. The first phase, Analysis, is responsible for building an AnalysisResult data structure which contains all information necessary to rewrite all closures. The second phase, Rewriting, actually performs the aforementioned rewriting by replacing and adding BoundNodes to the Bound Tree. The most important contract between these two phases is that the Analysis phase performs no modifications to the Bound Tree and the Rewriting phase performs no computation and contains no logic aside from a simple mechanical modification of the Bound Tree based on the AnalysisResult. + +## Analysis + +In this phase we build an AnalysisResult, which is a tree structure that exactly represents the state mapping from the original program to the closure-converted form. + +For example, the following program + +```csharp +void M() +{ + int x = 0; + int Local() => x + 1; + { + int y = 0; + int z = 0; + int Local2() => Local() + y; + z++; + Local2(); + } + Local(); +} +``` + +Would produce a tree similar to + +``` + +-------------------------------------+ + |Captured: Closures: | + |int x int Local() | + |int Local() | + | | + | +--------------------------------+ | + | | Captured: Closures: | | + | | int y int Local2() | | + | | | | + | +--------------------------------+ | + +-------------------------------------+ + +``` + +To create this AnalysisResult there are multiple passes. The first pass gathers information by constructing a naive tree of scopes, closures, and captured variables. The result is a tree of nested scopes, where each scope lists the captured variables declared in the scope and the closures in that scope. The first pass must first gather information since most rewriting decisions, like what Environment type to use for the closures or what the rewritten closure signature will be, are dependent on context from the entire method. + +Information about captured variables are stored on instances of the `CapturedVariable` class, which holds information about the Symbol that was captured and rewriting information like the `SynthesizedLocal` that will replace the variable post-rewriting. Similarly, closures will be stored in instances of the `Closure` class, which contain both the original Symbol and the synthesized type or method created for the closure. All of these classes are mutable since it's expected that later passes will fill in more rewriting information using the structure gathered from the earlier passes. + +For instance, in the previous example we need to walk the tree to generate an Environment for the closures `Closure`, resulting in something like the following: + +``` +Closure +------- +Name: Local +Generated Sig: int <>_Local(ref <>_Env1) +Environment: + - Captures: 'int x' + - Name: <>_Env1 + - Type: Struct + +Name: Local2 +Generated Sig: int <>_Local(ref <>_Env2, ref <>_Env1) +Environment: + - Captures: 'int y', 'ref <>_Env1' + - Name: <>_Env2 + - Type: Struct +``` + +This result would be generated by each piece filling in required info: first filling in all the capture lists, then deciding the Environment type based on the capture list, then generating the end signature based on the environment type and final capture list. + +Some further details of analysis calculations can be found below: + +**TODO** _Add details for each analysis phase as implementation is fleshed out_ + + +* Deciding what environment type is necessary for each closure. An environment can be a struct unless one of the following things is true: + + 1. The closure is converted to delegate. + 2. The closure captures a variable which is captured by a closure that cannot have a `struct` Environment. + 3. A reference to the closure is captured by a closure that cannot have a `struct` Environment. + +* Creating `SynthesizedLocal`s for hoisted captured variables and captured Environment references +* Assigning rewritten names, signatures, and type parameters to each closure + +## Optimization + +The final passes are optimization passes. They attempt to simplify the tree by removing intermediate scopes with no captured variables and otherwise correcting the tree to create the most efficient rewritten form. Optimization opportunities could include running escape analysis to determine if capture hoisting could be done via copy or done in a narrower scope. + +## Rewriting + +The rewriting phase simply walks the bound tree and, at each new scope, checks to see if the AnalysisResult contains a scope with rewriting information to process. If so, locals and closures are replaced with the substitutions provided by the tree. Practically, this means that the tree contains: + +1. A list of synthesized locals to add to each scope. + +2. A set of proxies to replace existing symbols. + +3. A list of synthesized methods and types to add to the enclosing type. \ No newline at end of file diff --git a/docs/compilers/Visual Basic/CommandLine.md b/docs/compilers/Visual Basic/CommandLine.md index 7a05a9ef440e8..0a7afcefd67da 100644 --- a/docs/compilers/Visual Basic/CommandLine.md +++ b/docs/compilers/Visual Basic/CommandLine.md @@ -45,7 +45,7 @@ | **LANGUAGE** | `/define:`*symbol_list* | Declare global conditional compilation symbol(s). *symbol_list* is *name*`=`*value*`,`... (Short form: `/d`) | `/imports:`*import_list* | Declare global Imports for namespaces in referenced metadata files. *import_list* is *namespace*`,`... -| `/langversion:`*number* | Specify language version: `9`|`9.0`|`10`|`10.0`|`11`|`11.0`|`12`|`12.0`|`13`|`13.0`|`14`|`14.0`. The default is `14`. +| `/langversion:`*number* | Specify language version: `9`|`9.0`|`10`|`10.0`|`11`|`11.0`|`12`|`12.0`|`13`|`13.0`|`14`|`14.0`|`15`|`15.0`|`15.3`. The default is `15` and the latest is `15.3`. | `/optionexplicit`{`+`|`-`} | Require explicit declaration of variables. | `/optioninfer`{`+`|`-`} | Allow type inference of variables. | `/rootnamespace`:*string* | Specifies the root Namespace for all top-level type declarations. diff --git a/docs/compilers/Visual Basic/Compiler Breaking Changes - post VS2017.md b/docs/compilers/Visual Basic/Compiler Breaking Changes - post VS2017.md new file mode 100755 index 0000000000000..3346c7eb13ffb --- /dev/null +++ b/docs/compilers/Visual Basic/Compiler Breaking Changes - post VS2017.md @@ -0,0 +1,7 @@ +Changes since VS2017 (VB 15) +=========================== + +- https://github.com/dotnet/csharplang/issues/415 +In VB 15, elements in tuple literals can be named explicitly, but in VB 15.3, elements that aren't named explicitly will get an inferred named. This uses the same rules as members in anonymous types which aren't named explicitly. +For instance, `Dim t = (a, b.c, Me.d)` will produce a tuple with element names "a", "c" and "d". As a result, an invocation on a tuple member may result in a different result than it did in VB 15. +Consider the case where the type of `a` is `System.Func(Of Boolean)` and you write `Dim local = t.a()`. This will now find the first element of the tuple and invoke it, whereas previously it could only mean "invoke an extension method named 'a'". diff --git a/docs/contributing/Powershell Guidelines.md b/docs/contributing/Powershell Guidelines.md index 39e69363f6d93..bbdb1a1343c3e 100644 --- a/docs/contributing/Powershell Guidelines.md +++ b/docs/contributing/Powershell Guidelines.md @@ -88,26 +88,28 @@ to the invocation and removes the need for error prone if checking after every c # DO NOT & msbuild /v:m /m Roslyn.sln # DO -Exec { & msbuild /v:m /m Roslyn.sln } +Exec-Block { & msbuild /v:m /m Roslyn.sln } ``` Note this will not work for the rare Windows commands which use 0 as an exit code on failure. For example robocopy and corflags. In some cases windows commands need to have their argument list built up dynamically. When that -happens do not use Invoke-Expression to execute the command, instead use Exec-Expression. The former -does not fail when the windows command fails and can lead to silent errors. The Exec-Expression -will throw if the underlying expression or windows command fails. +happens do not use Invoke-Expression to execute the command, instead use Exec-Command. The former +does not fail when the windows command fails, can invoke powershell argument parsing and doesn't +have a mechanism for echoing output to console. The Exec-Command uses Process directly and can support +the major functionality needed. ``` powershell -$command = "& msbuild /v:m Roslyn.sln" +$command = "C:\Program Files (x86)\Microsoft Visual Studio\Preview\Dogfood\MSBuild\15.0\Bin\MSBuild.exe" +$args = "/v:m Roslyn.sln" if (...) { - $command += " /fl /flp:v=diag" + $args += " /fl /flp:v=diag" } # DO NOT -Invoke-Expression $command +Invoke-Expression "& $command $args" # DO -Exec-Expression $command +Exec-Command $command $args ``` diff --git a/docs/features/ExperimentalAttribute.md b/docs/features/ExperimentalAttribute.md new file mode 100644 index 0000000000000..bf050ff2b88aa --- /dev/null +++ b/docs/features/ExperimentalAttribute.md @@ -0,0 +1,142 @@ +ExperimentalAttribute +===================== +Report warnings for references to types and members marked with `Windows.Foundation.Metadata.ExperimentalAttribute`. +``` +namespace Windows.Foundation.Metadata +{ + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | + AttributeTargets.Interface | AttributeTargets.Delegate, + AllowMultiple = false)] + public sealed class ExperimentalAttribute : Attribute + { + } +} +``` + +## Warnings +The warning message is a specific message, where `'{0}'` is the fully-qualified type or member name. +``` +'{0}' is for evaluation purposes only and is subject to change or removal in future updates. +``` + +The warning is reported for any reference to a type or member marked with the attribute. +(The `AttributeUsage` is for types only so the attribute cannot be applied to non-type members from C# or VB, +but the attribute could be applied to non-type members outside of C# or VB.) +``` +[Experimental] +class A +{ + internal object F; + internal static object G; + internal class B { } +} +class C +{ + static void Main() + { + F(default(A)); // warning CS08305: 'A' is for evaluation purposes only ... + F(typeof(A)); // warning CS08305: 'A' is for evaluation purposes only ... + F(nameof(A)); // warning CS08305: 'A' is for evaluation purposes only ... + var a = new A(); // warning CS08305: 'A' is for evaluation purposes only ... + F(a.F); + F(A.G); // warning CS08305: 'A' is for evaluation purposes only ... + F(null); // warning CS08305: 'A' is for evaluation purposes only ... + } + static void F(T t) + { + } +} +``` + +The attribute is not inherited from base types or overridden members. +``` +[Experimental] +class A +{ + [Experimental] + internal virtual void F() + { + } +} +class B : A // warning CS08305: 'A' is for evaluation purposes only ... +{ + internal override void F() + { + base.F(); // warning CS08305: 'A.F' is for evaluation purposes only ... + } +} +class C +{ + static void F(A a, B b) // warning CS08305: 'A' is for evaluation purposes only ... + { + a.F(); // warning CS08305: 'A.F' is for evaluation purposes only ... + b.F(); + } +} +``` + +There is no automatic suppression of warnings: warnings are generated for all references, even within `[Experimental]` members. +Suppressing the warning requires an explicit compiler option or `#pragma`. +``` +[Experimental] enum E { } +[Experimental] +class C +{ + private C(E e) // warning CS08305: 'E' is for evaluation purposes only ... + { + } + internal static C Create() // warning CS08305: 'C' is for evaluation purposes only ... + { + return Create(0); + } +#pragma warning disable 8305 + internal static C Create(E e) + { + return new C(e); + } +} +``` + +## ObsoleteAttribute and DeprecatedAttribute +`ExperimentalAttribute` is independent of `System.ObsoleteAttribute` or `Windows.Framework.Metadata.DeprecatedAttribute`. + +Warnings for `[Experimental]` are reported within `[Obsolete]` or `[Deprecated]` members. +Warnings and errors for `[Obsolete]` and `[Deprecated]` are reported inside `[Experimental]` members. +``` +[Obsolete] +class A +{ + static object F() => new C(); // warning CS08305: 'C' is for evaluation purposes only ... +} +[Deprecated(null, DeprecationType.Deprecate, 0)] +class B +{ + static object F() => new C(); // warning CS08305: 'C' is for evaluation purposes only ... +} +[Experimental] +class C +{ + static object F() => new B(); // warning CS0612: 'B' is obsolete +} +``` + +Warnings and errors for `[Obsolete]` and `[Deprecated]` are reported instead of `[Experimental]` if there are multiple attributes. +``` +[Obsolete] +[Experimental] +class A +{ +} +[Experimental] +[Deprecated(null, DeprecationType.Deprecate, 0)] +class B +{ +} +class C +{ + static A F() => null; // warning CS0612: 'A' is obsolete + static B G() => null; // warning CS0612: 'B' is obsolete +} + +``` \ No newline at end of file diff --git a/netci.groovy b/netci.groovy index d53132101c48a..2d7e1e3048ccd 100644 --- a/netci.groovy +++ b/netci.groovy @@ -54,7 +54,7 @@ if (branchName.startsWith("features/")) { commitPullList = [true] } -// Windows +// Windows Desktop CLR commitPullList.each { isPr -> ['debug', 'release'].each { configuration -> ['unit32', 'unit64'].each { buildTarget -> @@ -62,7 +62,7 @@ commitPullList.each { isPr -> def myJob = job(jobName) { description("Windows ${configuration} tests on ${buildTarget}") steps { - batchFile(""".\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '/debug' : '/release'} ${(buildTarget == 'unit32') ? '/test32' : '/test64'}""") + batchFile(""".\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '/debug' : '/release'} ${(buildTarget == 'unit32') ? '/test32' : '/test64'} /skipCoreClrTests""") } } @@ -75,6 +75,25 @@ commitPullList.each { isPr -> } } +// Windows CoreCLR +commitPullList.each { isPr -> + ['debug', 'release'].each { configuration -> + def jobName = Utilities.getFullJobName(projectName, "windows_coreclr_test", isPr) + def myJob = job(jobName) { + description("Windows CoreCLR unit tests") + steps { + batchFile(""".\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '/debug' : '/release'} /skipDesktopTests""") + } + } + + def triggerPhraseOnly = false + def triggerPhraseExtra = "" + Utilities.setMachineAffinity(myJob, 'Windows_NT', 'win2016-base') + Utilities.addXUnitDotNETResults(myJob, '**/xUnitResults/*.xml') + addRoslynJob(myJob, jobName, branchName, isPr, triggerPhraseExtra, triggerPhraseOnly) + } +} + // Ubuntu 14.04 commitPullList.each { isPr -> def jobName = Utilities.getFullJobName(projectName, "ubuntu_14_debug", isPr) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs index 155b3e2192ba1..e40be9c0c6507 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs @@ -530,7 +530,7 @@ internal static void ReportDiagnosticsIfObsolete( leastOverriddenSymbol.GetAttributes(); } - ThreeState reportedOnOverridden = ReportDiagnosticsIfObsoleteInternal(diagnostics, leastOverriddenSymbol, node, containingMember, location); + var diagnosticKind = ReportDiagnosticsIfObsoleteInternal(diagnostics, leastOverriddenSymbol, node, containingMember, location); // CONSIDER: In place of hasBaseReceiver, dev11 also accepts cases where symbol.ContainingType is a "simple type" (e.g. int) // or a special by-ref type (e.g. ArgumentHandle). These cases are probably more important for other checks performed by @@ -540,74 +540,43 @@ internal static void ReportDiagnosticsIfObsolete( // If the overridden member was not definitely obsolete and this is a (non-virtual) base member // access, then check the overriding symbol as well. - if (reportedOnOverridden != ThreeState.True && checkOverridingSymbol) + switch (diagnosticKind) { - Debug.Assert(reportedOnOverridden != ThreeState.Unknown, "We forced attribute binding above."); - - ReportDiagnosticsIfObsoleteInternal(diagnostics, symbol, node, containingMember, location); + case ObsoleteDiagnosticKind.NotObsolete: + case ObsoleteDiagnosticKind.Lazy: + if (checkOverridingSymbol) + { + Debug.Assert(diagnosticKind != ObsoleteDiagnosticKind.Lazy, "We forced attribute binding above."); + ReportDiagnosticsIfObsoleteInternal(diagnostics, symbol, node, containingMember, location); + } + break; } } - /// - /// True if the symbol is definitely obsolete. - /// False if the symbol is definitely not obsolete. - /// Unknown if the symbol may be obsolete. - /// - /// NOTE: The return value reflects obsolete-ness, not whether or not the diagnostic was reported. - /// - internal static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diagnostics, Symbol symbol, SyntaxNodeOrToken node, Symbol containingMember, BinderFlags location) + internal static ObsoleteDiagnosticKind ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diagnostics, Symbol symbol, SyntaxNodeOrToken node, Symbol containingMember, BinderFlags location) { Debug.Assert(diagnostics != null); - if (symbol.ObsoleteState == ThreeState.False) - { - return ThreeState.False; - } - - var data = symbol.ObsoleteAttributeData; - if (data == null) - { - // Obsolete attribute has errors. - return ThreeState.False; - } - - // If we haven't cracked attributes on the symbol at all or we haven't - // cracked attribute arguments enough to be able to report diagnostics for - // ObsoleteAttribute, store the symbol so that we can report diagnostics at a - // later stage. - if (symbol.ObsoleteState == ThreeState.Unknown) - { - diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); - return ThreeState.Unknown; - } - - // After this point, always return True. - - var inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(containingMember); + var kind = ObsoleteAttributeHelpers.GetObsoleteDiagnosticKind(symbol, containingMember); - // If we are in a context that is already obsolete, there is no point reporting - // more obsolete diagnostics. - if (inObsoleteContext == ThreeState.True) + DiagnosticInfo info = null; + switch (kind) { - return ThreeState.True; - } - // If the context is unknown, then store the symbol so that we can do this check at a - // later stage - else if (inObsoleteContext == ThreeState.Unknown) - { - diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); - return ThreeState.True; + case ObsoleteDiagnosticKind.Diagnostic: + info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location); + break; + case ObsoleteDiagnosticKind.Lazy: + case ObsoleteDiagnosticKind.LazyPotentiallySuppressed: + info = new LazyObsoleteDiagnosticInfo(symbol, containingMember, location); + break; } - // We have all the information we need to report diagnostics right now. So do it. - var diagInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location); - if (diagInfo != null) + if (info != null) { - diagnostics.Add(diagInfo, node.GetLocation()); - return ThreeState.True; + diagnostics.Add(info, node.GetLocation()); } - return ThreeState.True; + return kind; } internal static bool IsSymbolAccessibleConditional( diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_AnonymousTypes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_AnonymousTypes.cs index dba04f102ec84..654983fb1c5a5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_AnonymousTypes.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_AnonymousTypes.cs @@ -47,10 +47,16 @@ private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpre } else { + if (!IsAnonymousTypeMemberExpression(expression)) + { + hasError = true; + diagnostics.Add(ErrorCode.ERR_InvalidAnonymousTypeMemberDeclarator, expression.GetLocation()); + } + nameToken = expression.ExtractAnonymousTypeMemberName(); } - hasError = hasError || expression.HasErrors; + hasError |= expression.HasErrors; boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue); // check the name to be unique @@ -131,6 +137,32 @@ private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpre hasError); } + private static bool IsAnonymousTypeMemberExpression(ExpressionSyntax expr) + { + while (true) + { + switch (expr.Kind()) + { + case SyntaxKind.QualifiedName: + expr = ((QualifiedNameSyntax)expr).Right; + continue; + case SyntaxKind.ConditionalAccessExpression: + expr = ((ConditionalAccessExpressionSyntax)expr).WhenNotNull; + if (expr.Kind() == SyntaxKind.MemberBindingExpression) + { + return true; + } + + continue; + case SyntaxKind.IdentifierName: + case SyntaxKind.SimpleMemberAccessExpression: + return true; + default: + return false; + } + } + } + /// /// Actually, defines if an error ERR_AnonymousTypeNotAvailable is to be generated; /// diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index 26670db57bafe..064045ec7866f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -13,8 +14,8 @@ namespace Microsoft.CodeAnalysis.CSharp { /// /// This portion of the binder converts deconstruction-assignment syntax (AssignmentExpressionSyntax nodes with the left - /// being a tuple expression or declaration expression) into a BoundAssignmentOperator (or bad node). - /// The BoundAssignmentOperator will have: + /// being a tuple expression or declaration expression) into a BoundDeconstructionAssignmentOperator (or bad node). + /// The BoundDeconstructionAssignmentOperator will have: /// - a BoundTupleLiteral as its Left, /// - a BoundConversion as its Right, holding: /// - a tree of Conversion objects with Kind=Deconstruction, information about a Deconstruct method (optional) and @@ -461,7 +462,8 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder), compilation: compilation, diagnostics: diagnostics, - shouldCheckConstraints: false); + shouldCheckConstraints: false, + errorPositions: default(ImmutableArray)); } private BoundTupleLiteral DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax, ArrayBuilder variables, DiagnosticBag diagnostics, bool hasErrors) @@ -470,6 +472,7 @@ private BoundTupleLiteral DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax var valuesBuilder = ArrayBuilder.GetInstance(count); var typesBuilder = ArrayBuilder.GetInstance(count); var locationsBuilder = ArrayBuilder.GetInstance(count); + var namesBuilder = ArrayBuilder.GetInstance(count); foreach (var variable in variables) { if (variable.HasNestedVariables) @@ -477,23 +480,47 @@ private BoundTupleLiteral DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax var nestedTuple = DeconstructionVariablesAsTuple(variable.Syntax, variable.NestedVariables, diagnostics, hasErrors); valuesBuilder.Add(nestedTuple); typesBuilder.Add(nestedTuple.Type); + namesBuilder.Add(null); } else { var single = variable.Single; valuesBuilder.Add(single); typesBuilder.Add(single.Type); + namesBuilder.Add(ExtractDeconstructResultElementName(single)); } locationsBuilder.Add(variable.Syntax.Location); } + var uniqueFieldNames = PooledHashSet.GetInstance(); + RemoveDuplicateInferredTupleNames(namesBuilder, uniqueFieldNames); + uniqueFieldNames.Free(); + ImmutableArray tupleNames = namesBuilder.ToImmutableAndFree(); + + bool disallowInferredNames = this.Compilation.LanguageVersion.DisallowInferredTupleElementNames(); + var inferredPositions = tupleNames.SelectAsArray(n => n != null); + var type = TupleTypeSymbol.Create(syntax.Location, typesBuilder.ToImmutableAndFree(), locationsBuilder.ToImmutableAndFree(), - elementNames: default(ImmutableArray), compilation: this.Compilation, - shouldCheckConstraints: !hasErrors, syntax: syntax, diagnostics: hasErrors ? null : diagnostics); + tupleNames, this.Compilation, + shouldCheckConstraints: !hasErrors, + errorPositions: disallowInferredNames ? inferredPositions : default(ImmutableArray), + syntax: syntax, diagnostics: hasErrors ? null : diagnostics); + + // Always track the inferred positions in the bound node, so that conversions don't produce a warning + // for "dropped names" on tuple literal when the name was inferred. + return new BoundTupleLiteral(syntax, tupleNames, inferredPositions, arguments: valuesBuilder.ToImmutableAndFree(), type: type); + } + + /// Extract inferred name from a single deconstruction variable. + private static string ExtractDeconstructResultElementName(BoundExpression expression) + { + if (expression.Kind == BoundKind.DiscardExpression) + { + return null; + } - return new BoundTupleLiteral(syntax: syntax, argumentNamesOpt: default(ImmutableArray), - arguments: valuesBuilder.ToImmutableAndFree(), type: type); + return InferTupleElementName(expression.Syntax); } /// diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index a7591f24219fb..7b3587c586de9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -742,23 +742,37 @@ private BoundExpression BindDeclarationVariables(TypeSymbol declType, VariableDe case SyntaxKind.ParenthesizedVariableDesignation: { var tuple = (ParenthesizedVariableDesignationSyntax)node; - var builder = ArrayBuilder.GetInstance(tuple.Variables.Count); + int count = tuple.Variables.Count; + var builder = ArrayBuilder.GetInstance(count); + var namesBuilder = ArrayBuilder.GetInstance(count); + foreach (var n in tuple.Variables) { builder.Add(BindDeclarationVariables(declType, n, n, diagnostics)); + namesBuilder.Add(InferTupleElementName(n)); } var subExpressions = builder.ToImmutableAndFree(); + var uniqueFieldNames = PooledHashSet.GetInstance(); + RemoveDuplicateInferredTupleNames(namesBuilder, uniqueFieldNames); + uniqueFieldNames.Free(); + + var tupleNames = namesBuilder.ToImmutableAndFree(); + var inferredPositions = tupleNames.SelectAsArray(n => n != null); + bool disallowInferredNames = this.Compilation.LanguageVersion.DisallowInferredTupleElementNames(); + // We will not check constraints at this point as this code path // is failure-only and the caller is expected to produce a diagnostic. var tupleType = TupleTypeSymbol.Create( null, subExpressions.SelectAsArray(e => e.Type), default(ImmutableArray), - default(ImmutableArray), + tupleNames, Compilation, - shouldCheckConstraints: false); - return new BoundTupleLiteral(syntax, default(ImmutableArray), subExpressions, tupleType); + shouldCheckConstraints: false, + errorPositions: disallowInferredNames ? inferredPositions : default(ImmutableArray)); + + return new BoundTupleLiteral(syntax, default(ImmutableArray), inferredPositions, subExpressions, tupleType); } default: throw ExceptionUtilities.UnexpectedValue(node.Kind()); @@ -780,41 +794,30 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost return BadExpression(node, args); } - bool hasErrors = false; bool hasNaturalType = true; - // set of names already used - var uniqueFieldNames = PooledHashSet.GetInstance(); - var boundArguments = ArrayBuilder.GetInstance(arguments.Count); var elementTypes = ArrayBuilder.GetInstance(arguments.Count); var elementLocations = ArrayBuilder.GetInstance(arguments.Count); - ArrayBuilder elementNames = null; - // prepare and check element names and types + // prepare names + var (elementNames, inferredPositions, hasErrors) = ExtractTupleElementNames(arguments, diagnostics); + + // prepare types and locations for (int i = 0; i < numElements; i++) { ArgumentSyntax argumentSyntax = arguments[i]; - string name = null; IdentifierNameSyntax nameSyntax = argumentSyntax.NameColon?.Name; if (nameSyntax != null) { - name = nameSyntax.Identifier.ValueText; elementLocations.Add(nameSyntax.Location); - - if (!CheckTupleMemberName(name, i, argumentSyntax.NameColon.Name, diagnostics, uniqueFieldNames)) - { - hasErrors = true; - } } else { elementLocations.Add(argumentSyntax.Location); } - CollectTupleFieldMemberNames(name, i + 1, numElements, ref elementNames); - BoundExpression boundArgument = BindValue(argumentSyntax.Expression, diagnostics, BindValueKind.RValue); if (boundArgument.Type?.SpecialType == SpecialType.System_Void) { @@ -835,26 +838,151 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost } } - uniqueFieldNames.Free(); - - var elementNamesArray = elementNames == null ? - default(ImmutableArray) : - elementNames.ToImmutableAndFree(); - NamedTypeSymbol tupleTypeOpt = null; var elements = elementTypes.ToImmutableAndFree(); var locations = elementLocations.ToImmutableAndFree(); if (hasNaturalType) { - tupleTypeOpt = TupleTypeSymbol.Create(node.Location, elements, locations, elementNamesArray, this.Compilation, syntax: node, diagnostics: diagnostics, shouldCheckConstraints: true); + bool disallowInferredNames = this.Compilation.LanguageVersion.DisallowInferredTupleElementNames(); + + tupleTypeOpt = TupleTypeSymbol.Create(node.Location, elements, locations, elementNames, + this.Compilation, syntax: node, diagnostics: diagnostics, shouldCheckConstraints: true, + errorPositions: disallowInferredNames ? inferredPositions : default(ImmutableArray)); } else { TupleTypeSymbol.VerifyTupleTypePresent(elements.Length, node, this.Compilation, diagnostics); } - return new BoundTupleLiteral(node, elementNamesArray, boundArguments.ToImmutableAndFree(), tupleTypeOpt, hasErrors); + // Always track the inferred positions in the bound node, so that conversions don't produce a warning + // for "dropped names" on tuple literal when the name was inferred. + return new BoundTupleLiteral(node, elementNames, inferredPositions, boundArguments.ToImmutableAndFree(), tupleTypeOpt, hasErrors); + } + + private static (ImmutableArray elementNamesArray, ImmutableArray inferredArray, bool hasErrors) ExtractTupleElementNames( + SeparatedSyntaxList arguments, DiagnosticBag diagnostics) + { + bool hasErrors = false; + int numElements = arguments.Count; + var uniqueFieldNames = PooledHashSet.GetInstance(); + ArrayBuilder elementNames = null; + ArrayBuilder inferredElementNames = null; + + for (int i = 0; i < numElements; i++) + { + ArgumentSyntax argumentSyntax = arguments[i]; + IdentifierNameSyntax nameSyntax = argumentSyntax.NameColon?.Name; + + string name = null; + string inferredName = null; + + if (nameSyntax != null) + { + name = nameSyntax.Identifier.ValueText; + + if (diagnostics != null && !CheckTupleMemberName(name, i, argumentSyntax.NameColon.Name, diagnostics, uniqueFieldNames)) + { + hasErrors = true; + } + } + else + { + inferredName = InferTupleElementName(argumentSyntax.Expression); + } + + CollectTupleFieldMemberName(name, i, numElements, ref elementNames); + CollectTupleFieldMemberName(inferredName, i, numElements, ref inferredElementNames); + } + + RemoveDuplicateInferredTupleNames(inferredElementNames, uniqueFieldNames); + uniqueFieldNames.Free(); + + var result = MergeTupleElementNames(elementNames, inferredElementNames); + elementNames?.Free(); + inferredElementNames?.Free(); + return (result.names, result.inferred, hasErrors); + } + + private static (ImmutableArray names, ImmutableArray inferred) MergeTupleElementNames( + ArrayBuilder elementNames, ArrayBuilder inferredElementNames) + { + if (elementNames == null) + { + if (inferredElementNames == null) + { + return (default(ImmutableArray), default(ImmutableArray)); + } + else + { + var finalNames = inferredElementNames.ToImmutable(); + return (finalNames, finalNames.SelectAsArray(n => n != null)); + } + } + + if (inferredElementNames == null) + { + return (elementNames.ToImmutable(), default(ImmutableArray)); + } + + Debug.Assert(elementNames.Count == inferredElementNames.Count); + var builder = ArrayBuilder.GetInstance(elementNames.Count); + for (int i = 0; i < elementNames.Count; i++) + { + string inferredName = inferredElementNames[i]; + if (elementNames[i] == null && inferredName != null) + { + elementNames[i] = inferredName; + builder.Add(true); + } + else + { + builder.Add(false); + } + } + + return (elementNames.ToImmutable(), builder.ToImmutableAndFree()); + } + + private static void RemoveDuplicateInferredTupleNames(ArrayBuilder inferredElementNames, HashSet uniqueFieldNames) + { + if (inferredElementNames == null) + { + return; + } + + // Inferred names that duplicate an explicit name or a previous inferred name are tagged for removal + var toRemove = PooledHashSet.GetInstance(); + foreach (var name in inferredElementNames) + { + if (name != null && !uniqueFieldNames.Add(name)) + { + toRemove.Add(name); + } + } + + for (int i = 0; i < inferredElementNames.Count; i++) + { + var inferredName = inferredElementNames[i]; + if (inferredName != null && toRemove.Contains(inferredName)) + { + inferredElementNames[i] = null; + } + } + toRemove.Free(); + } + + private static string InferTupleElementName(SyntaxNode syntax) + { + string name = syntax.TryGetInferredMemberName(); + + // Reserved names are never candidates to be inferred names, at any position + if (name == null || TupleTypeSymbol.IsElementNameReserved(name) != -1) + { + return null; + } + + return name; } private BoundExpression BindRefValue(RefValueExpressionSyntax node, DiagnosticBag diagnostics) @@ -3565,7 +3693,7 @@ private BoundExpression BindClassCreationExpression(ObjectCreationExpressionSynt } else if (node.Type.Kind() == SyntaxKind.TupleType) { - Debug.Assert(node.HasErrors, "new should be a syntax error"); + diagnostics.Add(ErrorCode.ERR_NewWithTupleTypeSyntax, node.Type.GetLocation()); return MakeBadExpressionForObjectCreation(node, type, boundInitializerOpt, analyzedArguments); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 15bd156c13e0f..d02e32d22e28e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -442,7 +442,7 @@ private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnosti locations.Add(argumentSyntax.Location); } - CollectTupleFieldMemberNames(name, i + 1, numElements, ref elementNames); + CollectTupleFieldMemberName(name, i, numElements, ref elementNames); } uniqueFieldNames.Free(); @@ -480,11 +480,12 @@ private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnosti elementNames.ToImmutableAndFree(), this.Compilation, this.ShouldCheckConstraints, - syntax, - diagnostics); + errorPositions: default(ImmutableArray), + syntax: syntax, + diagnostics: diagnostics); } - private static void CollectTupleFieldMemberNames(string name, int position, int tupleSize, ref ArrayBuilder elementNames) + private static void CollectTupleFieldMemberName(string name, int elementIndex, int tupleSize, ref ArrayBuilder elementNames) { // add the name to the list // names would typically all be there or none at all @@ -498,7 +499,7 @@ private static void CollectTupleFieldMemberNames(string name, int position, int if (name != null) { elementNames = ArrayBuilder.GetInstance(tupleSize); - for (int j = 1; j < position; j++) + for (int j = 0; j < elementIndex; j++) { elementNames.Add(null); } diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index e983843d28939..65f01d851c992 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -649,7 +649,7 @@ private bool GetEnumeratorInfo(ref ForEachEnumeratorInfo.Builder builder, BoundE if (!string.IsNullOrEmpty(collectionExprType.Name) || !collectionExpr.HasErrors) { - diagnostics.Add(ErrorCode.ERR_ForEachMissingMember, _syntax.Expression.Location, collectionExprType.ToDisplayString(), GetEnumeratorMethodName); + diagnostics.Add(ErrorCode.ERR_ForEachMissingMember, _syntax.Expression.Location, collectionExprType, GetEnumeratorMethodName); } return false; } diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 3f6fe70b8906d..e4962d7696bee 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -3,6 +3,8 @@ + + + + + + - + - + - + - + - \ No newline at end of file + diff --git a/src/Setup/DevDivInsertionFiles/BuildDevDivInsertionFiles.vb b/src/Setup/DevDivInsertionFiles/BuildDevDivInsertionFiles.vb index 3b07f411d10e4..07dc69a17c728 100644 --- a/src/Setup/DevDivInsertionFiles/BuildDevDivInsertionFiles.vb +++ b/src/Setup/DevDivInsertionFiles/BuildDevDivInsertionFiles.vb @@ -98,14 +98,15 @@ Public Class BuildDevDivInsertionFiles ' the src/NuGet/Microsoft.Net.Compilers.nuspec file, the ' src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swr file, ' and src/Compilers/Extension/CompilerExtension.csproj file. + ' + ' Note: Microsoft.DiaSymReader.Native.amd64.dll and Microsoft.DiaSymReader.Native.x86.dll + ' are installed by msbuild setup, not Roslyn. Private ReadOnly CompilerFiles As String() = { "Microsoft.CodeAnalysis.dll", "Microsoft.CodeAnalysis.CSharp.dll", "Microsoft.CodeAnalysis.Scripting.dll", "Microsoft.CodeAnalysis.CSharp.Scripting.dll", "Microsoft.CodeAnalysis.VisualBasic.dll", - "Microsoft.DiaSymReader.Native.amd64.dll", - "Microsoft.DiaSymReader.Native.x86.dll", "System.AppContext.dll", "System.Console.dll", "System.Diagnostics.FileVersionInfo.dll", diff --git a/src/Setup/DevDivPackages/Roslyn.proj b/src/Setup/DevDivPackages/Roslyn.proj index 7fd9635c5c66e..f7349818e07da 100644 --- a/src/Setup/DevDivPackages/Roslyn.proj +++ b/src/Setup/DevDivPackages/Roslyn.proj @@ -3,16 +3,16 @@ - $(OutDir)DevDivInsertionFiles + $(OutputPath)\DevDivInsertionFiles $(InsertionFilesDir)\VS.Tools.Roslyn - $(OutDir)DevDivPackages\Roslyn + $(OutputPath)\DevDivPackages\Roslyn $(NuGetPerBuildPreReleaseVersion) $(NuGetReleaseVersion)-cibuild - $(OutDir) + $(OutputPath) $(NuGetPerBuildPreReleaseVersion) @@ -30,4 +30,4 @@ - \ No newline at end of file + diff --git a/src/Setup/DevDivPackages/Roslyn/project.json b/src/Setup/DevDivPackages/Roslyn/project.json index af8c16a0b197f..142bc9394495f 100644 --- a/src/Setup/DevDivPackages/Roslyn/project.json +++ b/src/Setup/DevDivPackages/Roslyn/project.json @@ -1,7 +1,6 @@ { "dependencies": { "Microsoft.DiaSymReader": "1.1.0", - "Microsoft.DiaSymReader.Native": "1.5.0", "Microsoft.CodeAnalysis.Elfie": "0.10.6-rc2", "System.Collections.Immutable": "1.3.1", "System.Reflection.Metadata": "1.4.2", diff --git a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swixproj b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swixproj index 03f9fc4b50c60..1be98515de706 100644 --- a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swixproj +++ b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swixproj @@ -6,7 +6,8 @@ neutral false - $(OutDir)Insertion + $(OutputPath) + $(OutputPath)\Insertion true vsix @@ -14,7 +15,7 @@ - $(PackagePreprocessorDefinitions);Version=$(VsixVersion);OutputPath=$(OutDir) + $(PackagePreprocessorDefinitions);Version=$(VsixVersion);OutputPath=$(RoslynOutputPath) $(BaseIntermediateOutputPath)$(Configuration)\ @@ -23,4 +24,4 @@ - \ No newline at end of file + diff --git a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swr b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swr index 890e3bf4aa6f0..7900402e91a30 100644 --- a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swr +++ b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.swr @@ -34,9 +34,6 @@ folder InstallDir:\MSBuild\15.0\Bin\Roslyn file source=$(OutputPath)\Vsix\CompilerExtension\System.Reflection.Metadata.dll vs.file.ngenArchitecture=all file source=$(OutputPath)\Exes\csi\System.ValueTuple.dll vs.file.ngenArchitecture=all - file source=$(OutputPath)\Vsix\CompilerExtension\Microsoft.DiaSymReader.Native.amd64.dll - file source=$(OutputPath)\Vsix\CompilerExtension\Microsoft.DiaSymReader.Native.x86.dll - file source=$(OutputPath)\Vsix\CompilerExtension\System.AppContext.dll vs.file.ngenArchitecture=all file source=$(OutputPath)\Vsix\CompilerExtension\System.Console.dll vs.file.ngenArchitecture=all file source=$(OutputPath)\Vsix\CompilerExtension\System.Diagnostics.FileVersionInfo.dll vs.file.ngenArchitecture=all diff --git a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.vsmanproj b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.vsmanproj index d17ac1dd62634..2436b6d3b4ba0 100644 --- a/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.vsmanproj +++ b/src/Setup/DevDivVsix/CompilersPackage/Microsoft.CodeAnalysis.Compilers.vsmanproj @@ -6,7 +6,7 @@ true true - $(OutDir)Insertion\ + $(OutputPath)Insertion\ true false false @@ -29,4 +29,4 @@ - \ No newline at end of file + diff --git a/src/Setup/DevDivVsix/MicrosoftCodeAnalysisLanguageServices/Microsoft.CodeAnalysis.LanguageServices.vsmanproj b/src/Setup/DevDivVsix/MicrosoftCodeAnalysisLanguageServices/Microsoft.CodeAnalysis.LanguageServices.vsmanproj index f1e02c2793255..bd502c3f9e81c 100644 --- a/src/Setup/DevDivVsix/MicrosoftCodeAnalysisLanguageServices/Microsoft.CodeAnalysis.LanguageServices.vsmanproj +++ b/src/Setup/DevDivVsix/MicrosoftCodeAnalysisLanguageServices/Microsoft.CodeAnalysis.LanguageServices.vsmanproj @@ -6,7 +6,7 @@ true true - $(OutDir)Insertion + $(OutputPath)\Insertion true false false @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/src/Setup/DevDivVsix/PortableFacades/PortableFacades.swixproj b/src/Setup/DevDivVsix/PortableFacades/PortableFacades.swixproj index f931f13551c3f..9163ec5a36dbc 100644 --- a/src/Setup/DevDivVsix/PortableFacades/PortableFacades.swixproj +++ b/src/Setup/DevDivVsix/PortableFacades/PortableFacades.swixproj @@ -6,7 +6,7 @@ neutral false - $(OutDir)Insertion + $(OutputPath)\Insertion true vsix @@ -23,4 +23,4 @@ - \ No newline at end of file + diff --git a/src/Setup/DevDivVsix/PortableFacades/PortableFacades.vsmanproj b/src/Setup/DevDivVsix/PortableFacades/PortableFacades.vsmanproj index a6fecdc827d36..89dc8b22de47e 100644 --- a/src/Setup/DevDivVsix/PortableFacades/PortableFacades.vsmanproj +++ b/src/Setup/DevDivVsix/PortableFacades/PortableFacades.vsmanproj @@ -6,7 +6,7 @@ true true - $(OutDir)Insertion\ + $(OutputPath)\Insertion\ true false false @@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/src/Setup/SetupStep1.proj b/src/Setup/SetupStep1.proj index 04f418a8306cf..2a5d8d0393e03 100644 --- a/src/Setup/SetupStep1.proj +++ b/src/Setup/SetupStep1.proj @@ -25,7 +25,7 @@ where building multiple projects that produce VSIXes larger than 10MB will race against each other --> - + @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/src/Setup/SetupStep2.proj b/src/Setup/SetupStep2.proj index 4f6b35d31de34..aa04243ae80dd 100644 --- a/src/Setup/SetupStep2.proj +++ b/src/Setup/SetupStep2.proj @@ -8,7 +8,7 @@ - + @@ -23,4 +23,4 @@ - \ No newline at end of file + diff --git a/src/Setup/Vsix/Vsix.proj b/src/Setup/Vsix/Vsix.proj index 1b53f56703549..21b7f52dfded6 100644 --- a/src/Setup/Vsix/Vsix.proj +++ b/src/Setup/Vsix/Vsix.proj @@ -6,7 +6,7 @@ - + - \ No newline at end of file + diff --git a/src/Test/Utilities/Portable/Compilation/CompilationDifference.cs b/src/Test/Utilities/Portable/Compilation/CompilationDifference.cs index b4d272c2a632a..40bfaa8f37286 100644 --- a/src/Test/Utilities/Portable/Compilation/CompilationDifference.cs +++ b/src/Test/Utilities/Portable/Compilation/CompilationDifference.cs @@ -118,7 +118,7 @@ public void VerifyPdb( [CallerLineNumber]int expectedValueSourceLine = 0, [CallerFilePath]string expectedValueSourcePath = null) { - VerifyPdb(methodTokens, XElement.Parse(expectedPdb), format, expectedValueSourceLine, expectedValueSourcePath, expectedIsXmlLiteral: false); + VerifyPdb(methodTokens, expectedPdb, format, expectedValueSourceLine, expectedValueSourcePath, expectedIsXmlLiteral: false); } public void VerifyPdb( @@ -128,12 +128,12 @@ public void VerifyPdb( [CallerLineNumber]int expectedValueSourceLine = 0, [CallerFilePath]string expectedValueSourcePath = null) { - VerifyPdb(methodTokens, expectedPdb, format, expectedValueSourceLine, expectedValueSourcePath, expectedIsXmlLiteral: true); + VerifyPdb(methodTokens, expectedPdb.ToString(), format, expectedValueSourceLine, expectedValueSourcePath, expectedIsXmlLiteral: true); } private void VerifyPdb( IEnumerable methodTokens, - XElement expectedPdb, + string expectedPdb, DebugInformationFormat format, int expectedValueSourceLine, string expectedValueSourcePath, @@ -142,15 +142,10 @@ private void VerifyPdb( Assert.NotEqual(default(DebugInformationFormat), format); Assert.NotEqual(DebugInformationFormat.Embedded, format); - var actualXml = XElement.Parse(PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(PdbDelta), methodTokens)); - - PdbValidation.AdjustToPdbFormat( - actualPdb: actualXml, - actualIsPortable: NextGeneration.InitialBaseline.HasPortablePdb, - expectedPdb: expectedPdb, - expectedIsPortable: format != DebugInformationFormat.Pdb); + string actualPdb = PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(PdbDelta), methodTokens); + var (actualXml, expectedXml) = PdbValidation.AdjustToPdbFormat(actualPdb, expectedPdb, actualIsPortable: NextGeneration.InitialBaseline.HasPortablePdb); - AssertXml.Equal(expectedPdb, actualXml, $"Format: {format}{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); + AssertXml.Equal(expectedXml, actualXml, $"Format: {format}{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); } internal string GetMethodIL(string qualifiedMethodName) @@ -196,5 +191,12 @@ public void VerifySynthesizedFields(string typeName, params string[] expectedSyn var actual = EmitResult.Baseline.SynthesizedMembers.Single(e => e.Key.ToString() == typeName).Value.OfType().Select(f => f.Name + ": " + f.Type); AssertEx.SetEqual(expectedSynthesizedTypesAndMemberCounts, actual, itemSeparator: "\r\n"); } + + public void VerifyUpdatedMethods(params string[] expectedMethodTokens) + { + AssertEx.Equal( + expectedMethodTokens, + UpdatedMethods.Select(methodHandle => $"0x{MetadataTokens.GetToken(methodHandle):X8}")); + } } } diff --git a/src/Test/Utilities/Portable/Pdb/PdbValidation.cs b/src/Test/Utilities/Portable/Pdb/PdbValidation.cs index 23ab401a868e1..ef8158465840a 100644 --- a/src/Test/Utilities/Portable/Pdb/PdbValidation.cs +++ b/src/Test/Utilities/Portable/Pdb/PdbValidation.cs @@ -49,13 +49,11 @@ internal static void VerifyPdb( [CallerLineNumber]int expectedValueSourceLine = 0, [CallerFilePath]string expectedValueSourcePath = null) { - var expectedPdbXml = XElement.Parse(string.IsNullOrWhiteSpace(expectedPdb) ? "" : expectedPdb); - VerifyPdbImpl( compilation, debugEntryPoint, qualifiedMethodName, - expectedPdbXml, + string.IsNullOrWhiteSpace(expectedPdb) ? "" : expectedPdb, format, options, expectedValueSourceLine, @@ -89,7 +87,7 @@ internal static void VerifyPdb( compilation, debugEntryPoint, qualifiedMethodName, - expectedPdb, + expectedPdb.ToString(), format, options, expectedValueSourceLine, @@ -101,7 +99,7 @@ private static void VerifyPdbImpl( this Compilation compilation, IMethodSymbol debugEntryPoint, string qualifiedMethodName, - XElement expectedPdb, + string expectedPdb, DebugInformationFormat format, PdbToXmlOptions options, int expectedValueSourceLine, @@ -112,134 +110,125 @@ private static void VerifyPdbImpl( if (format == 0 || format == DebugInformationFormat.Pdb) { - var actualNativePdb = XElement.Parse(GetPdbXml(compilation, debugEntryPoint, options, qualifiedMethodName, portable: false)); - AssertXml.Equal(expectedPdb, actualNativePdb, $"PDB format: Windows{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); + var actualPdb = GetPdbXml(compilation, debugEntryPoint, options, qualifiedMethodName, portable: false); + var (actualXml, expectedXml) = AdjustToPdbFormat(actualPdb, expectedPdb, actualIsPortable: false); + + AssertXml.Equal(expectedXml, actualXml, $"PDB format: Windows{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); } if (format == 0 || format == DebugInformationFormat.PortablePdb) { - var actualPortablePdb = XElement.Parse(GetPdbXml(compilation, debugEntryPoint, options, qualifiedMethodName, portable: true)); - - // If format is not specified, we share expected output between portable and non-portable. - // The output is then non-portable since it contains more information (such as cdi). - AdjustToPdbFormat( - actualPdb: actualPortablePdb, - actualIsPortable: true, - expectedPdb: expectedPdb, - expectedIsPortable: format == DebugInformationFormat.PortablePdb); + string actualPdb = GetPdbXml(compilation, debugEntryPoint, options, qualifiedMethodName, portable: true); + var (actualXml, expectedXml) = AdjustToPdbFormat(actualPdb, expectedPdb, actualIsPortable: true); - AssertXml.Equal(expectedPdb, actualPortablePdb, $"PDB format: Portable{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); + AssertXml.Equal(expectedXml, actualXml, $"PDB format: Portable{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, expectedIsXmlLiteral); } } - internal static void AdjustToPdbFormat( - XElement actualPdb, - bool actualIsPortable, - XElement expectedPdb, - bool expectedIsPortable) + internal static (XElement Actual, XElement Expected) AdjustToPdbFormat(string actualPdb, string expectedPdb, bool actualIsPortable) { - if (actualIsPortable == expectedIsPortable) + var actualXml = XElement.Parse(actualPdb); + var expectedXml = XElement.Parse(expectedPdb); + + if (actualIsPortable) + { + // Windows SymWriter doesn't serialize empty scopes. + // In Portable PDB each method with a body (even with no locals) has a scope that points to the imports. Such scope appears as empty + // in the current XML representation. + RemoveEmptyScopes(actualXml); + + RemoveWindowsSpecificElements(expectedXml); + } + else { - return; + RemovePortableSpecificElements(expectedXml); } - // The test doesn't specify portable as expected PDB unless it's testing portable only in which case actual is also portable. - Assert.False(expectedIsPortable); - Assert.True(actualIsPortable); + RemoveEmptySequencePoints(expectedXml); + RemoveEmptyScopes(expectedXml); + RemoveEmptyCustomDebugInfo(expectedXml); + RemoveEmptyMethods(expectedXml); + RemoveFormatAttributes(expectedXml); - // SymWriter doesn't create empty scopes. When the C# compiler uses forwarding CDI instead of a NamespaceScope - // the scope is actually not empty - it logically contains the imports. Portable PDB does not use forwarding and thus - // creates the scope. When generating PDB XML for testing the Portable DiaSymReader returns empty namespaces. - RemoveEmptyScopes(actualPdb); + return (actualXml, expectedXml); + } - // if the actual format is portable and the expected is not, remove native-only artifacts: - RemoveNonPortablePdb(expectedPdb); + private static bool RemoveElements(IEnumerable elements) + { + var array = elements.ToArray(); - RemoveEmptySequencePoints(expectedPdb); + foreach (var e in array) + { + e.Remove(); + } - // remove scopes that only contained non-portable elements (namespace scopes) - RemoveEmptyScopes(expectedPdb); - RemoveMethodsWithNoSequencePoints(expectedPdb); - RemoveEmptyMethods(expectedPdb); + return array.Length > 0; } - private static void RemoveMethodsWithNoSequencePoints(XElement pdb) + private static void RemoveEmptyCustomDebugInfo(XElement pdb) { - var methods = (from e in pdb.DescendantsAndSelf() - where e.Name == "method" - select e).ToArray(); - foreach (var method in methods) - { - bool hasNoSequencePoints = method.DescendantsAndSelf().Where(node => node.Name == "entry").IsEmpty(); - if (hasNoSequencePoints) - { - method.Remove(); - } - } + RemoveElements(from e in pdb.DescendantsAndSelf() + where e.Name == "customDebugInfo" && !e.HasElements + select e); } private static void RemoveEmptyScopes(XElement pdb) { - XElement[] emptyScopes; - - do - { - emptyScopes = (from e in pdb.DescendantsAndSelf() - where e.Name == "scope" && !e.HasElements - select e).ToArray(); - - foreach (var e in emptyScopes) - { - e.Remove(); - } - } - while (emptyScopes.Any()); + while (RemoveElements(from e in pdb.DescendantsAndSelf() + where e.Name == "scope" && !e.HasElements + select e)); } private static void RemoveEmptySequencePoints(XElement pdb) { - var emptyScopes = from e in pdb.DescendantsAndSelf() - where e.Name == "sequencePoints" && !e.HasElements - select e; - - foreach (var e in emptyScopes.ToArray()) - { - e.Remove(); - } + RemoveElements(from e in pdb.DescendantsAndSelf() + where e.Name == "sequencePoints" && !e.HasElements + select e); } private static void RemoveEmptyMethods(XElement pdb) { - var emptyScopes = from e in pdb.DescendantsAndSelf() - where e.Name == "method" && !e.HasElements - select e; + RemoveElements(from e in pdb.DescendantsAndSelf() + where e.Name == "method" && !e.HasElements + select e); + } - foreach (var e in emptyScopes.ToArray()) - { - e.Remove(); - } + private static void RemoveWindowsSpecificElements(XElement expectedNativePdb) + { + RemoveElements(from e in expectedNativePdb.DescendantsAndSelf() + where e.Name == "forwardIterator" || + e.Name == "forwardToModule" || + e.Name == "forward" || + e.Name == "tupleElementNames" || + e.Name == "dynamicLocals" || + e.Name == "using" || + e.Name == "currentnamespace" || + e.Name == "defaultnamespace" || + e.Name == "importsforward" || + e.Name == "xmlnamespace" || + e.Name == "alias" || + e.Name == "namespace" || + e.Name == "type" || + e.Name == "defunct" || + e.Name == "extern" || + e.Name == "externinfo" || + e.Name == "local" && e.Attributes().Any(a => a.Name.LocalName == "name" && a.Value.StartsWith("$VB$ResumableLocal_")) || + e.Attributes().Any(a => a.Name.LocalName == "format" && a.Value == "windows") + select e); } - private static void RemoveNonPortablePdb(XElement expectedNativePdb) + private static void RemovePortableSpecificElements(XElement expectedNativePdb) { - var nonPortableElements = from e in expectedNativePdb.DescendantsAndSelf() - where e.Name == "customDebugInfo" || - e.Name == "currentnamespace" || - e.Name == "defaultnamespace" || - e.Name == "importsforward" || - e.Name == "xmlnamespace" || - e.Name == "alias" || - e.Name == "namespace" || - e.Name == "type" || - e.Name == "defunct" || - e.Name == "extern" || - e.Name == "externinfo" || - e.Name == "local" && e.Attributes().Any(a => a.Name.LocalName == "name" && a.Value.StartsWith("$VB$ResumableLocal_")) - select e; - - foreach (var e in nonPortableElements.ToArray()) + RemoveElements(from e in expectedNativePdb.DescendantsAndSelf() + where e.Attributes().Any(a => a.Name.LocalName == "format" && a.Value == "portable") + select e); + } + + private static void RemoveFormatAttributes(XElement pdb) + { + foreach (var element in pdb.DescendantsAndSelf()) { - e.Remove(); + element.Attributes().FirstOrDefault(a => a.Name.LocalName == "format")?.Remove(); } } diff --git a/src/Test/Utilities/Portable/TestBase.cs b/src/Test/Utilities/Portable/TestBase.cs index 9bdbe2b6bf663..e5ca5549f60cf 100644 --- a/src/Test/Utilities/Portable/TestBase.cs +++ b/src/Test/Utilities/Portable/TestBase.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; +using System.Threading; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -147,7 +148,12 @@ public static MetadataReference SystemCoreRef { if (s_systemCoreRef == null) { - s_systemCoreRef = AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System_Core).GetReference(display: "System.Core.v4_0_30319.dll"); + // We rely on reference equality in CreateSharedCompilation, so + // we must use a CompareExchange here. + Interlocked.CompareExchange( + ref s_systemCoreRef, + AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System_Core).GetReference(display: "System.Core.v4_0_30319.dll"), + null); } return s_systemCoreRef; @@ -414,7 +420,12 @@ public static MetadataReference SystemRef { if (s_systemRef == null) { - s_systemRef = AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System).GetReference(display: "System.v4_0_30319.dll"); + // We rely on reference equality in CreateSharedCompilation, so + // we must use a CompareExchange here. + Interlocked.CompareExchange( + ref s_systemRef, + AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System).GetReference(display: "System.v4_0_30319.dll"), + null); } return s_systemRef; diff --git a/src/Test/Utilities/Portable/project.json b/src/Test/Utilities/Portable/project.json index 2514bbdcbe11d..4d3cbef72331b 100644 --- a/src/Test/Utilities/Portable/project.json +++ b/src/Test/Utilities/Portable/project.json @@ -2,7 +2,7 @@ "dependencies": { "Microsoft.CodeAnalysis.Test.Resources.Proprietary": "2.0.0-pre-20160714", "Microsoft.CSharp": "4.3.0", - "Microsoft.DiaSymReader.Converter.Xml": "1.0.0-beta1-61518-02", + "Microsoft.DiaSymReader.Converter.Xml": "1.0.0-beta1-61618-01", "Microsoft.Metadata.Visualizer": "1.0.0-beta1-61531-03", "Microsoft.NETCore.Platforms": "1.1.0", "Microsoft.NETCore.Portable.Compatibility": "1.0.1", diff --git a/src/Tools/BuildBoss/StructuredLoggerCheckerUtil.cs b/src/Tools/BuildBoss/StructuredLoggerCheckerUtil.cs index c5d389d5b1a73..02ebd27531040 100644 --- a/src/Tools/BuildBoss/StructuredLoggerCheckerUtil.cs +++ b/src/Tools/BuildBoss/StructuredLoggerCheckerUtil.cs @@ -50,12 +50,6 @@ public bool Check(TextWriter textWriter) var allGood = true; foreach (var pair in _copyMap.OrderBy(x => x.Key)) { - // Issue https://github.com/dotnet/roslyn/issues/18753 - if (Path.GetFileName(pair.Key) == "xunit.abstractions.dll") - { - continue; - } - var list = pair.Value; if (list.Count > 1) { diff --git a/src/Tools/GenerateSdkPackages/README.md b/src/Tools/GenerateSdkPackages/README.md index 5d49c3b201f91..506b7420c27f6 100644 --- a/src/Tools/GenerateSdkPackages/README.md +++ b/src/Tools/GenerateSdkPackages/README.md @@ -1,8 +1,48 @@ # Generate SDK Packages -This is a collection of tools for generating a set of NuGet packages for the VS SDK and updating our repo to consume them. This is a temporary solution until we work with the VS SDK team to help address a couple of issues with how their packages are produced. +This is a collection of tools for generating a set of NuGet packages for the VS SDK and updating our repo to consume +them. This is a temporary solution until we work with the VS SDK team to help address a couple of issues with how their +packages are produced. - make-all.ps1: Generates all of the NuGet packages we need for the VS SDK - change-all.ps1: Changes all our project.json files to reference a new VS SDK version +## Example workflow + +Here is an example of building, testing and uploading the packages for the 26418.00 build of d15prerel. First step is +to make the packages for the build. + +``` powershell +> .\make-all.ps1 -version "26418.00" -branch "d15prerel" -outpath c:\users\jaredpar\temp\nuget +``` + +This will create all of the packages with the version string 15.0.26418-alpha. Next the build needs to be updated +to reflect this change in version for the packages we are consuming. + +``` powershell +> .\change-all.ps1 -version "26418.00" +``` + +Before uploading the packages to myget please do a local build to validate the changes. In order to do this the +following line needs to be added to NuGet.config. Do not merge this change, it is for testing only. + +``` xml + +``` + +Given this entry we can quickly run the following developer flow to validate the changes: + +``` cmd +> cd +> Restore.cmd +> Build.cmd +> Test.cmd +``` + +Assuming this all passes then revert the change to NuGet.config, upload the packages to the roslyn-tools feed of +myget and submit the result of `change-all.ps1` as a PR. + + + + diff --git a/src/Tools/GenerateSdkPackages/change-all.ps1 b/src/Tools/GenerateSdkPackages/change-all.ps1 index d1553c885180f..54c9491163200 100644 --- a/src/Tools/GenerateSdkPackages/change-all.ps1 +++ b/src/Tools/GenerateSdkPackages/change-all.ps1 @@ -1,45 +1,44 @@ -Param( - [string]$version = "" -) +[CmdletBinding(PositionalBinding=$false)] +Param([string]$version = "") -set-strictmode -version 2.0 -$ErrorActionPreference="Stop" +Set-StrictMode -version 2.0 +$ErrorActionPreference = "Stop" try { if ($version -eq "") { - write-host "Need a -version" + Write-Host "Need a -version" exit 1 } - $rootPath = resolve-path (join-path $PSScriptRoot "..\..\..\") - $repoUtil = join-path $rootPath "Binaries\Debug\Exes\RepoUtil\RepoUtil.exe" - if (-not (test-path $repoUtil)) { - write-host "RepoUtil not found $repoUtil" + $rootPath = Resolve-Path (Join-Path $PSScriptRoot "..\..\..\") + $repoUtil = Join-Path $rootPath "Binaries\Debug\Exes\RepoUtil\RepoUtil.exe" + if (-not (Test-Path $repoUtil)) { + Write-Host "RepoUtil not found $repoUtil" exit 1 } - $fileList = gc (join-path $PSScriptRoot "files.txt") + $fileList = Get-Content (Join-Path $PSScriptRoot "files.txt") $shortVersion = $version.Substring(0, $version.IndexOf('.')) $packageVersion = "15.0.$shortVersion-alpha" $changeList = @() - write-host "Moving version to $packageVersion" + Write-Host "Moving version to $packageVersion" foreach ($item in $fileList) { - $name = split-path -leaf $item + $name = Split-Path -leaf $item $simpleName = [IO.Path]::GetFileNameWithoutExtension($name) $changeList += "$simpleName $packageVersion" } $changeFilePath = [IO.Path]::GetTempFileName() - $changeList -join [Environment]::NewLine | out-file $changeFilePath - write-host (gc -raw $changeFilePath) + $changeList -join [Environment]::NewLine | Out-File $changeFilePath + Write-Host (gc -raw $changeFilePath) - $fullSln = join-path $rootPath "..\Roslyn.sln" - if (test-path $fullSln) { + $fullSln = Join-Path $rootPath "..\Roslyn.sln" + if (Test-Path $fullSln) { # Running as a part of the full enlisment. Need to add some extra paramteers - $sourcesPath = resolve-path (join-path $rootPath "..") + $sourcesPath = Resolve-Path (Join-Path $rootPath "..") $generatePath = $rootPath - $configPath = join-path $rootPath "build\config\RepoUtilData.json" + $configPath = Join-Path $rootPath "build\config\RepoUtilData.json" & $repoUtil -sourcesPath $sourcesPath -generatePath $generatePath -config $configPath change -version $changeFilePath } else { @@ -48,7 +47,8 @@ try { } } -catch [exception] { - write-host $_.Exception - exit -1 +catch { + Write-Host $_ + Write-Host $_.Exception + exit 1 } diff --git a/src/Tools/GenerateSdkPackages/engine.nuspec b/src/Tools/GenerateSdkPackages/engine.nuspec index 5925d34d4657a..ff23ae8a9ac23 100644 --- a/src/Tools/GenerateSdkPackages/engine.nuspec +++ b/src/Tools/GenerateSdkPackages/engine.nuspec @@ -17,8 +17,8 @@ VSSDK - - + + diff --git a/src/Tools/GenerateSdkPackages/make-all.ps1 b/src/Tools/GenerateSdkPackages/make-all.ps1 index 5724959b6b96e..f25f8ad000fed 100644 --- a/src/Tools/GenerateSdkPackages/make-all.ps1 +++ b/src/Tools/GenerateSdkPackages/make-all.ps1 @@ -1,113 +1,95 @@ -Param( +[CmdletBinding(PositionalBinding=$false)] +param( [string]$version = "26014.00", [string]$branch = "d15rel", - [string]$outPath = $null, - [string]$fakeSign = $null + [string]$outPath = $null ) -set-strictmode -version 2.0 -$ErrorActionPreference="Stop" +Set-StrictMode -version 2.0 +$ErrorActionPreference = "Stop" # Package a normal DLL into a nuget. Default used for packages that have a simple 1-1 # relationship between DLL and NuGet for only Net46. -function package-normal() { - $baseNuspecPath = join-path $PSScriptRoot "base.nuspec" - $sourceFilePath = join-path $dropPath $item - $filePath = join-path $dllPath $name - if (-not (test-path $sourceFilePath)) { - write-host "Could not locate $sourceFilePath" +function Package-Normal() { + $baseNuspecPath = Join-Path $PSScriptRoot "base.nuspec" + $sourceFilePath = Join-Path $dropPath $item + $filePath = Join-Path $dllPath $name + if (-not (Test-Path $sourceFilePath)) { + Write-Host "Could not locate $sourceFilePath" continue; } - cp $sourceFilePath $filePath + Copy-Item $sourceFilePath $filePath & $fakeSign -f $filePath & $nuget pack $baseNuspecPath -OutputDirectory $packagePath -Properties name=$simpleName`;version=$packageVersion`;filePath=$filePath } # The debugger DLLs have a more complex structure and it's easier to special case # copying them over. -function copy-debugger() { - $refRootPath = [IO.Path]::GetFullPath((join-path $dropPath "..\..\Debugger\ReferenceDLL")) - $debuggerDllPath = join-path $dllPath "debugger" - $net20Path = join-path $debuggerDllPath "net20" - $net45Path = join-path $debuggerDllPath "net45" - $portablePath = join-path $debuggerDllPath "portable" - - mkdir $debuggerDllPath -ErrorAction SilentlyContinue | out-null - mkdir $net20Path -ErrorAction SilentlyContinue | out-null - mkdir $net45Path -ErrorAction SilentlyContinue | out-null - mkdir $portablePath -ErrorAction SilentlyContinue | out-null - - pushd $debuggerDllPath - try { - $d = join-path $dropPath "..\..\Debugger" - cp (join-path $d "RemoteDebugger\Microsoft.VisualStudio.Debugger.Engine.dll") $net20Path - cp (join-path $d "IDE\Microsoft.VisualStudio.Debugger.Engine.dll") $net45Path - cp (join-path $d "x-plat\coreclr.windows\mcg\Microsoft.VisualStudio.Debugger.Engine.dll") $portablePath - cp (join-path $dropPath "Microsoft.VisualStudio.Debugger.Metadata.dll") $net20Path - cp (join-path $dropPath "Microsoft.VisualStudio.Debugger.Metadata.dll") $portablePath - gci -re -in *.dll | %{ & $fakeSign -f $_ } - } - finally { - popd - } +function Copy-Debugger() { + $refRootPath = [IO.Path]::GetFullPath((Join-Path $dropPath "..\..\Debugger\ReferenceDLL")) + $debuggerDllPath = Join-Path $dllPath "debugger" + Create-Directory $debuggerDllPath + Copy-Item -re -fo "$refRootPath\*" $debuggerDllPath } # Used to package debugger nugets -function package-debugger() { +function Package-Debugger() { param( [string]$kind ) - $debuggerPath = join-path $dllPath "debugger" - $nuspecPath = join-path $PSScriptRoot "$kind.nuspec" + $debuggerPath = Join-Path $dllPath "debugger" + $nuspecPath = Join-Path $PSScriptRoot "$kind.nuspec" & $nuget pack $nuspecPath -OutputDirectory $packagePath -Properties version=$packageVersion`;debuggerPath=$debuggerPath } try { if ($outPath -eq "") { - write-host "Need an -outPath value" + Write-Host "Need an -outPath value" exit 1 } - if ($fakeSign -eq "") { - write-host "Need a -fakeSign value" - exit 1 - } + . (Join-Path $PSScriptRoot "..\..\..\build\scripts\build-utils.ps1") - $list = gc (join-path $PSScriptRoot "files.txt") + $list = Get-Content (Join-Path $PSScriptRoot "files.txt") $dropPath = "\\cpvsbuild\drops\VS\$branch\raw\$version\binaries.x86ret\bin\i386" - $nuget = join-path $PSScriptRoot "..\..\..\nuget.exe" + $nuget = Join-Path $PSScriptRoot "..\..\..\nuget.exe" + $fakeSign = Join-Path (Get-PackageDir "FakeSign") "Tools\FakeSign.exe" $shortVersion = $version.Substring(0, $version.IndexOf('.')) $packageVersion = "15.0.$shortVersion-alpha" - $dllPath = join-path $outPath "Dlls" - $packagePath = join-path $outPath "Packages" + $dllPath = Join-Path $outPath "Dlls" + $packagePath = Join-Path $outPath "Packages" - write-host "Drop path is $dropPath" - write-host "Package version $packageVersion" - write-host "Out path is $outPath" + Write-Host "Drop path is $dropPath" + Write-Host "Package version $packageVersion" + Write-Host "Out path is $outPath" - mkdir $outPath -ErrorAction SilentlyContinue | out-null - mkdir $dllPath -ErrorAction SilentlyContinue | out-null - mkdir $packagePath -ErrorAction SilentlyContinue | out-null - pushd $outPath + Create-Directory $outPath + Create-Directory $dllPath + Create-Directory $packagePath + Push-Location $outPath try { - copy-debugger + Copy-Debugger foreach ($item in $list) { - $name = split-path -leaf $item + $name = Split-Path -leaf $item $simpleName = [IO.Path]::GetFileNameWithoutExtension($name) - write-host "Packing $simpleName" + Write-Host "Packing $simpleName" switch ($simpleName) { - "Microsoft.VisualStudio.Debugger.Engine" { package-debugger "engine" } - "Microsoft.VisualStudio.Debugger.Metadata" { package-debugger "metadata" } - default { package-normal } + "Microsoft.VisualStudio.Debugger.Engine" { Package-Debugger "engine" } + "Microsoft.VisualStudio.Debugger.Metadata" { Package-Debugger "metadata" } + default { Package-Normal } } } } finally { - popd + Pop-Location } } -catch [exception] { - write-host $_.Exception - exit -1 +catch { + Write-Host $_ + Write-Host $_.Exception + Get-PSCallstack + throw + + exit 1 } diff --git a/src/Tools/GenerateSdkPackages/metadata.nuspec b/src/Tools/GenerateSdkPackages/metadata.nuspec index 3f4d9fd992201..adee79778f849 100644 --- a/src/Tools/GenerateSdkPackages/metadata.nuspec +++ b/src/Tools/GenerateSdkPackages/metadata.nuspec @@ -17,7 +17,7 @@ VSSDK - + diff --git a/src/Tools/Github/GithubMergeTool/run.csx b/src/Tools/Github/GithubMergeTool/run.csx index ef7890cfaf247..bbc90c880298b 100644 --- a/src/Tools/Github/GithubMergeTool/run.csx +++ b/src/Tools/Github/GithubMergeTool/run.csx @@ -57,6 +57,7 @@ private static async Task RunAsync() await MakeRoslynPr("dev15.0.x", "dev15.1.x"); await MakeRoslynPr("dev15.1.x", "master"); await MakeRoslynPr("master", "dev16"); + await MakeRoslynPr("master", "features/ioperation"); // Roslyn-internal branches await MakeRoslynInternalPr("dev15.0.x", "dev15.1.x"); diff --git a/src/Tools/MicroBuild/cibuild.ps1 b/src/Tools/MicroBuild/cibuild.ps1 index 44d5c97b9eb6b..8a7fddf98638c 100644 --- a/src/Tools/MicroBuild/cibuild.ps1 +++ b/src/Tools/MicroBuild/cibuild.ps1 @@ -15,19 +15,17 @@ function Terminate-BuildProcesses() { } try { + Write-Host "${env:Userprofile}" . (Join-Path $PSScriptRoot "..\..\..\build\scripts\build-utils.ps1") Push-Location $PSScriptRoot $nuget = Ensure-NuGet - Exec { & $nuget locals all -clear } + Exec-Block { & $nuget locals all -clear } | Out-Host $msbuild = Ensure-MSBuild # The /nowarn exception can be removed once we fix https://github.com/dotnet/roslyn/issues/17325 - & $msbuild /nodereuse:false /p:Configuration=Release /p:SkipTest=true Build.proj /warnaserror /nowarn:MSB3277 - if (-not $?) { - throw "Build failed" - } + Exec-Block { & $msbuild /nodereuse:false /p:Configuration=Release /p:SkipTest=true Build.proj /warnaserror /nowarn:MSB3277 } | Out-Host exit 0 } diff --git a/src/Tools/MicroBuild/publish-assets.ps1 b/src/Tools/MicroBuild/publish-assets.ps1 index 3c0b56518c785..61db51110d528 100644 --- a/src/Tools/MicroBuild/publish-assets.ps1 +++ b/src/Tools/MicroBuild/publish-assets.ps1 @@ -40,6 +40,7 @@ try "dev15.0.x" { } "dev15.1.x" { } "dev15.2.x" { } + "dev15.3-preview1" { } "master" { } "post-dev15" { } "features/refout" { } diff --git a/src/VisualStudio/CSharp/Impl/CSharpVisualStudio.csproj b/src/VisualStudio/CSharp/Impl/CSharpVisualStudio.csproj index e45c1edd4defb..a91cb4f8e26b4 100644 --- a/src/VisualStudio/CSharp/Impl/CSharpVisualStudio.csproj +++ b/src/VisualStudio/CSharp/Impl/CSharpVisualStudio.csproj @@ -130,6 +130,7 @@ + diff --git a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs index 246f96ac0f4bc..f59aa21411022 100644 --- a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs +++ b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; @@ -18,22 +19,16 @@ internal partial class CSharpCodeModelService { protected override AbstractNodeLocator CreateNodeLocator() { - return new NodeLocator(this); + return new NodeLocator(); } private class NodeLocator : AbstractNodeLocator { - public NodeLocator(CSharpCodeModelService codeModelService) - : base(codeModelService) - { - } + protected override string LanguageName => LanguageNames.CSharp; - protected override EnvDTE.vsCMPart DefaultPart - { - get { return EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; } - } + protected override EnvDTE.vsCMPart DefaultPart => EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; - protected override VirtualTreePoint? GetStartPoint(SourceText text, SyntaxNode node, EnvDTE.vsCMPart part) + protected override VirtualTreePoint? GetStartPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { @@ -53,16 +48,16 @@ protected override EnvDTE.vsCMPart DefaultPart case SyntaxKind.DestructorDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: - return GetStartPoint(text, (BaseMethodDeclarationSyntax)node, part); + return GetStartPoint(text, options, (BaseMethodDeclarationSyntax)node, part); case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: case SyntaxKind.EventDeclaration: - return GetStartPoint(text, (BasePropertyDeclarationSyntax)node, part); + return GetStartPoint(text, options, (BasePropertyDeclarationSyntax)node, part); case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: - return GetStartPoint(text, (AccessorDeclarationSyntax)node, part); + return GetStartPoint(text, options, (AccessorDeclarationSyntax)node, part); case SyntaxKind.DelegateDeclaration: return GetStartPoint(text, (DelegateDeclarationSyntax)node, part); case SyntaxKind.NamespaceDeclaration: @@ -81,7 +76,7 @@ protected override EnvDTE.vsCMPart DefaultPart } } - protected override VirtualTreePoint? GetEndPoint(SourceText text, SyntaxNode node, EnvDTE.vsCMPart part) + protected override VirtualTreePoint? GetEndPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { @@ -141,7 +136,7 @@ private VirtualTreePoint GetBodyStartPoint(SourceText text, SyntaxToken openBrac : new VirtualTreePoint(openBrace.SyntaxTree, text, openBrace.Span.End); } - private VirtualTreePoint GetBodyStartPoint(SourceText text, SyntaxToken openBrace, SyntaxToken closeBrace, int memberStartColumn) + private VirtualTreePoint GetBodyStartPoint(SourceText text, OptionSet options, SyntaxToken openBrace, SyntaxToken closeBrace, int memberStartColumn) { Debug.Assert(!openBrace.IsMissing); Debug.Assert(!closeBrace.IsMissing); @@ -181,7 +176,7 @@ private VirtualTreePoint GetBodyStartPoint(SourceText text, SyntaxToken openBrac // If the line is all whitespace then place the caret at the first indent after the start // of the member. - var indentSize = GetTabSize(text); + var indentSize = GetTabSize(options); var lineText = lineAfterOpenBrace.ToString(); var lineEndColumn = lineText.GetColumnFromLineOffset(lineText.Length, indentSize); @@ -347,7 +342,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, BaseTypeDeclarationSynta return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } - private VirtualTreePoint GetStartPoint(SourceText text, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) + private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -380,9 +375,9 @@ private VirtualTreePoint GetStartPoint(SourceText text, BaseMethodDeclarationSyn if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(text)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); - return GetBodyStartPoint(text, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); + return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } else { @@ -436,7 +431,7 @@ private AccessorDeclarationSyntax FindFirstAccessorNode(BasePropertyDeclarationS return node.AccessorList.Accessors.FirstOrDefault(); } - private VirtualTreePoint GetStartPoint(SourceText text, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) + private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -467,17 +462,17 @@ private VirtualTreePoint GetStartPoint(SourceText text, BasePropertyDeclarationS if (firstAccessorNode != null) { var line = text.Lines.GetLineFromPosition(firstAccessorNode.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(text)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); if (firstAccessorNode.Body != null) { - return GetBodyStartPoint(text, firstAccessorNode.Body.OpenBraceToken, firstAccessorNode.Body.CloseBraceToken, indentation); + return GetBodyStartPoint(text, options, firstAccessorNode.Body.OpenBraceToken, firstAccessorNode.Body.CloseBraceToken, indentation); } else if (!firstAccessorNode.SemicolonToken.IsMissing) { // This is total weirdness from the old C# code model with auto props. // If there isn't a body, the semi-colon is used - return GetBodyStartPoint(text, firstAccessorNode.SemicolonToken, firstAccessorNode.SemicolonToken, indentation); + return GetBodyStartPoint(text, options, firstAccessorNode.SemicolonToken, firstAccessorNode.SemicolonToken, indentation); } } @@ -487,9 +482,9 @@ private VirtualTreePoint GetStartPoint(SourceText text, BasePropertyDeclarationS if (node.AccessorList != null && !node.AccessorList.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(text)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); - return GetBodyStartPoint(text, node.AccessorList.OpenBraceToken, node.AccessorList.CloseBraceToken, indentation); + return GetBodyStartPoint(text, options, node.AccessorList.OpenBraceToken, node.AccessorList.CloseBraceToken, indentation); } throw Exceptions.ThrowEFail(); @@ -501,7 +496,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, BasePropertyDeclarationS return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } - private VirtualTreePoint GetStartPoint(SourceText text, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) + private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -526,9 +521,9 @@ private VirtualTreePoint GetStartPoint(SourceText text, AccessorDeclarationSynta if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(text)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); - return GetBodyStartPoint(text, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); + return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } throw Exceptions.ThrowEFail(); diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml index bb02d9d38ec13..a365fc75093ac 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml @@ -100,6 +100,16 @@ x:Name="at_the_end" Content="{x:Static local:AdvancedOptionPageStrings.Option_at_the_end}"/> + +