diff --git a/.vsts-ci.yml b/.vsts-ci.yml index 54d5fffebe4acfd43452a0ad5b0903161cacb950..3efb1259a4c8f0b3e6081abdca853dead67e61f0 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -32,37 +32,26 @@ steps: feed: '8f470c7e-ac49-4afe-a6ee-cf784e438b93' - task: CmdLine@1 + displayName: Create output directory inputs: filename: mkdir arguments: 'Binaries\$(BuildConfiguration)' -- task: VSBuild@1 +- script: build\scripts\cibuild.cmd + -configuration $(BuildConfiguration) -official -testDesktop -procdump + /p:OfficialBuildId=$(BUILD.BUILDNUMBER) + /p:DotNetSignType=$(PB_SignType) + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + displayName: Build + condition: succeeded() + +- task: PowerShell@2 + displayName: Publish Assets inputs: - solution: 'src/Tools/MicroBuild/Build.proj' - vsVersion: 15.0 - msbuildArgs: >- - /p:TreatWarningsAsErrors=true - /p:DeployExtension=false - /p:TrackFileAccess=false - /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - /p:VisualStudioVersion=14.0 - /flp1:Summary;Verbosity=diagnostic;Encoding=UTF-8;LogFile=$(Build.SourcesDirectory)\Binaries\$(BuildConfiguration)\Roslyn.log - /flp2:WarningsOnly;Verbosity=diagnostic;Encoding=UTF-8;LogFile=$(Build.SourcesDirectory)\Binaries\$(BuildConfiguration)\Roslyn.wrn - /flp3:ErrorsOnly;Verbosity=diagnostic;Encoding=UTF-8;LogFile=$(Build.SourcesDirectory)\Binaries\$(BuildConfiguration)\Roslyn.err - /p:RoslynMyGetApiKey=$(Roslyn.MyGetApiKey) - /p:RoslynNuGetApiKey=$(Roslyn.NuGetApiKey) - /p:RoslynGitHubEmail=$(Roslyn.GitHubEmail) - /p:RoslynGitHubToken=$(Roslyn.GitHubToken) - /p:RoslynGitHubUserName=$(Roslyn.GitHubUserName) - /p:PB_PublishBlobFeedKey=$(PB_PublishBlobFeedKey) - /p:PublishStableVersions=false - /p:VersionStampToPublish=prerelease - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - platform: '$(BuildPlatform)' - configuration: '$(BuildConfiguration)' - maximumCpuCount: true - logProjectEvents: false + arguments: '-config $(BuildConfiguration) -branchName "$(Build.SourceBranch)" -mygetApiKey $(Roslyn.MyGetApiKey) -nugetApiKey $(Roslyn.NuGetApiKey) -gitHubUserName $(Roslyn.GitHubUserName) -gitHubToken $(Roslyn.GitHubToken) -gitHubEmail $(Roslyn.GitHubEmail)' + filePath: 'build\scripts\publish-assets.ps1' + condition: succeeded() - task: PublishBuildArtifacts@1 displayName: Publish Logs @@ -86,7 +75,7 @@ steps: displayName: Upload VSTS Drop inputs: DropFolder: 'Binaries\VSSetup\$(BuildConfiguration)\Insertion' - condition: and(succeeded(), contains(variables['PB_PublishType'], 'vsts')) + condition: succeeded() - task: NuGetCommand@2 displayName: NuGet CoreXT publish @@ -96,7 +85,7 @@ steps: packagesToPush: '$(Build.SourcesDirectory)\Binaries\$(BuildConfiguration)\DevDivPackages\**\*.nupkg' publishVstsFeed: '97a41293-2972-4f48-8c0e-05493ae82010' allowPackageConflicts: true - condition: and(succeeded(), contains(variables['PB_PublishType'], 'vsts')) + condition: succeeded() # Publish VSTS artifact that the RoslynInsertionTool is able to find by its name. # The backing storage of the artifact is a file share. @@ -130,5 +119,5 @@ steps: ArtifactName: '$(Build.BuildNumber)' publishLocation: FilePath TargetPath: '$(DropRoot)\Roslyn-Signed\$(Build.SourceBranchName)\$(BuildConfiguration)' - condition: and(succeededOrFailed(), contains(variables['PB_PublishType'], 'vsts')) + condition: succeededOrFailed() diff --git a/.vsts-dnceng.yml b/.vsts-dnceng.yml index f51c07f7be31ec1e3a5b1a8a1ea4163c10fbf0d9..42d5b0989cb30f1e215e467e7d07fcabe05c4b10 100644 --- a/.vsts-dnceng.yml +++ b/.vsts-dnceng.yml @@ -1,7 +1,7 @@ phases: - phase: Windows_Desktop_Unit_Tests queue: - name: Helix + name: dotnet-external-temp timeoutInMinutes: 90 parallel: 4 matrix: @@ -19,7 +19,8 @@ phases: _testKind: Test64 steps: - - script: build/scripts/cibuild.cmd -$(_configuration) -testDesktop -$(_testKind) + - script: build/scripts/cibuild.cmd -configuration $(_configuration) -testDesktop -$(_testKind) + displayName: Build and Test - task: PublishTestResults@1 inputs: @@ -39,7 +40,7 @@ phases: - phase: Windows_CoreClr_Unit_Tests queue: - name: Helix + name: dotnet-external-temp timeoutInMinutes: 90 parallel: 2 matrix: @@ -49,7 +50,8 @@ phases: _configuration: Release steps: - - script: build/scripts/cibuild.cmd -$(_configuration) -testCoreClr -buildCoreClr + - script: build/scripts/cibuild.cmd -configuration $(_configuration) -testCoreClr -buildCoreClr + displayName: Build and Test - task: PublishTestResults@1 inputs: @@ -69,10 +71,11 @@ phases: - phase: Windows_Determinism_Test queue: - name: Helix + name: dotnet-external-temp timeoutInMinutes: 90 steps: - script: build/scripts/cibuild.cmd -testDeterminism + displayName: Build - Validate determinism - task: PublishBuildArtifacts@1 inputs: @@ -84,10 +87,11 @@ phases: - phase: Windows_Correctness_Test queue: - name: Helix + name: dotnet-external-temp timeoutInMinutes: 90 steps: - - script: build/scripts/test-build-correctness.cmd -cibuild -release + - script: build/scripts/test-build-correctness.cmd -configuration Release -cibuild + displayName: Build - Validate correctness - task: PublishBuildArtifacts@1 inputs: @@ -104,14 +108,16 @@ phases: parallel: 2 matrix: coreclr: - _args: --debug + _args: --configuration Debug _name: CoreClr mono: - _args: --debug --docker --mono + _args: --configuration Debug --docker --mono _name: Mono steps: - script: ./build/scripts/cibuild.sh $(_args) + displayName: Build and Test - script: ./build/scripts/dockerstop.sh + displayName: Stop Docker condition: eq(variables['_name'], 'Mono') - task: PublishTestResults@1 inputs: diff --git a/Compilers.sln b/Compilers.sln index 6215df65ff9e66b7f6b5b587aee36e781e62a43d..137403f2a2ab4710fe664866ea5635660aa38eb7 100644 --- a/Compilers.sln +++ b/Compilers.sln @@ -444,7 +444,6 @@ Global {1EE8CAD3-55F9-4D91-96B2-084641DA9A6C} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} {9508F118-F62E-4C16-A6F4-7C3B56E166AD} = {E35DA3D1-16C0-4318-9187-6B664F12A870} {F5CE416E-B906-41D2-80B9-0078E887A3F6} = {E35DA3D1-16C0-4318-9187-6B664F12A870} - {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {4B45CA0C-03A0-400F-B454-3D4BCB16AF38} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {B501A547-C911-4A05-AC6E-274A50DFF30E} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {50D26304-0961-4A51-ABF6-6CAD1A56D203} = {32A48625-F0AD-419D-828B-A50BDABA38EA} @@ -453,7 +452,6 @@ Global {B2C33A93-DB30-4099-903E-77D75C4C3F45} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {28026D16-EB0C-40B0-BDA7-11CAA2B97CCC} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {50D26304-0961-4A51-ABF6-6CAD1A56D202} = {32A48625-F0AD-419D-828B-A50BDABA38EA} - {C65C6143-BED3-46E6-869E-9F0BE6E84C37} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {7FE6B002-89D8-4298-9B1B-0B5C247DD1FD} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} {4371944A-D3BA-4B5B-8285-82E5FFC6D1F9} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {4371944A-D3BA-4B5B-8285-82E5FFC6D1F8} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37} @@ -465,7 +463,6 @@ Global {BDA5D613-596D-4B61-837C-63554151C8F5} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37} {91F6F646-4F6E-449A-9AB4-2986348F329D} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37} {AFDE6BEA-5038-4A4A-A88E-DBD2E4088EED} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} - {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {02459936-CD2C-4F61-B671-5C518F2A3DDC} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} {288089C5-8721-458E-BE3E-78990DAB5E2E} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} {288089C5-8721-458E-BE3E-78990DAB5E2D} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} @@ -475,25 +472,20 @@ Global {FCFA8808-A1B6-48CC-A1EA-0B8CA8AEDA8E} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {E58EE9D7-1239-4961-A0C1-F9EC3952C4C1} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37} {1DFEA9C5-973C-4179-9B1B-0F32288E1EF2} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} - {E35DA3D1-16C0-4318-9187-6B664F12A870} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {AD6F474E-E6D4-4217-91F3-B7AF1BE31CCC} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} - {6F016299-BA96-45BA-9BFF-6C0793979177} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {1A3941F1-1E1F-4EF7-8064-7729C4C2E2AA} = {6F016299-BA96-45BA-9BFF-6C0793979177} {CCBD3438-3E84-40A9-83AD-533F23BCFCA5} = {6F016299-BA96-45BA-9BFF-6C0793979177} - {3CDEA9FB-CD44-4AB4-98A8-5537AAA2169B} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {C1930979-C824-496B-A630-70F5369A636F} = {3CDEA9FB-CD44-4AB4-98A8-5537AAA2169B} {D73ADF7D-2C1C-42AE-B2AB-EDC9497E4B71} = {3CDEA9FB-CD44-4AB4-98A8-5537AAA2169B} {7AD4FE65-9A30-41A6-8004-AA8F89BCB7F3} = {A41D1B99-F489-4C43-BBDF-96D61B19A6B9} {2DAE4406-7A89-4B5F-95C3-BC5472CE47CE} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {2DAE4406-7A89-4B5F-95C3-BC5422CE47CE} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {ABC7262E-1053-49F3-B846-E3091BB92E8C} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} - {3FF38FD4-DF16-44B0-924F-0D5AE155495B} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {12A68549-4E8C-42D6-8703-A09335F97997} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {066F0DBD-C46C-4C20-AFEC-99829A172625} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {3E7DEA65-317B-4F43-A25D-62F18D96CFD7} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {21A01C2D-2501-4619-8144-48977DD22D9C} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} {14118347-ED06-4608-9C45-18228273C712} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B} - {D9591377-7868-4D64-9314-83E0C92A871B} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {5F8D2414-064A-4B3A-9B42-8E2A04246BE5} = {D9591377-7868-4D64-9314-83E0C92A871B} {21B239D0-D144-430F-A394-C066D58EE267} = {D9591377-7868-4D64-9314-83E0C92A871B} {57CA988D-F010-4BF2-9A2E-07D6DCD2FF2C} = {D9591377-7868-4D64-9314-83E0C92A871B} @@ -509,7 +501,6 @@ Global {54E08BF5-F819-404F-A18D-0AB9EA81EA04} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {E8F0BAA5-7327-43D1-9A51-644E81AE55F1} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37} {46B3E63A-C462-4133-9F27-3B85DA5E7D37} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} - {274B96B7-F815-47E3-9CA4-4024A57A478F} = {32A48625-F0AD-419D-828B-A50BDABA38EA} {15FEBD1B-55CE-4EBD-85E3-04898260A25B} = {274B96B7-F815-47E3-9CA4-4024A57A478F} {27B1EAE2-2E06-48EF-8A67-06D6FB3DC275} = {274B96B7-F815-47E3-9CA4-4024A57A478F} {E0756C89-603F-4B48-8E64-1D53E62654C8} = {274B96B7-F815-47E3-9CA4-4024A57A478F} diff --git a/build.sh b/build.sh index 5c3680bedd1fa0e17c055c0d697df1c1d28b6f71..7e3e6073b804f507f53990b01b62f6179e7109f9 100755 --- a/build.sh +++ b/build.sh @@ -1,209 +1,16 @@ #!/usr/bin/env bash -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -set -e -set -u +source="${BASH_SOURCE[0]}" -usage() -{ - echo "Main interface to running builds on Mac/Linux" - echo "Usage: build.sh [options]" - echo "" - echo "Options" - echo " --debug Build Debug (default)" - echo " --release Build Release" - echo " --restore Restore projects required to build" - echo " --build Build all projects" - echo " --pack Build nuget packages" - echo " --test Run unit tests" - echo " --mono Run unit tests with mono" - echo " --build-bootstrap Build the bootstrap compilers" - echo " --use-bootstrap Use the built bootstrap compilers when running main build" - echo " --bootstrap Implies --build-bootstrap and --use-bootstrap" -} +# resolve $SOURCE until the file is no longer a symlink +while [[ -h $source ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" -root_path="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -binaries_path="${root_path}"/Binaries -bootstrap_path="${binaries_path}"/Bootstrap - -args= -build_in_docker=false -build_configuration=Debug -restore=false -build=false -test_=false -pack=false -use_mono=false -build_bootstrap=false -use_bootstrap=false -stop_vbcscompiler=false - -# LTTNG is the logging infrastructure used by coreclr. Need this variable set -# so it doesn't output warnings to the console. -export LTTNG_HOME="$HOME" - -if [[ $# = 0 ]] -then - usage - echo "" - echo "To build and test this repo, try: ./build.sh --restore --build --test" - exit 1 -fi - -while [[ $# > 0 ]] -do - opt="$(echo "$1" | awk '{print tolower($0)}')" - case "$opt" in - -h|--help) - usage - exit 1 - ;; - --docker) - build_in_docker=true - shift - continue - ;; - --debug) - build_configuration=Debug - ;; - --release) - build_configuration=Release - ;; - --restore|-r) - restore=true - ;; - --build|-b) - build=true - ;; - --test|-t) - test_=true - ;; - --mono) - use_mono=true - ;; - --build-bootstrap) - build_bootstrap=true - ;; - --use-bootstrap) - use_bootstrap=true - ;; - --bootstrap) - build_bootstrap=true - use_bootstrap=true - ;; - --stop-vbcscompiler) - stop_vbcscompiler=true - ;; - --pack) - pack=true - ;; - *) - echo "$1" - usage - exit 1 - ;; - esac - args="$args $1" - shift + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" done -config_path=${binaries_path}/${build_configuration} -logs_path=${config_path}/Logs -mkdir -p ${binaries_path} -mkdir -p ${config_path} -mkdir -p ${logs_path} - -function stop_processes { - echo "Killing running build processes..." - pkill -9 "dotnet" || true - pkill -9 "vbcscompiler" || true -} - -if [[ "$build_in_docker" = true ]] -then - echo "Docker exec: $args" - BUILD_COMMAND=/opt/code/build.sh "$root_path"/build/scripts/dockerrun.sh $args - exit -fi - -source "${root_path}"/build/scripts/obtain_dotnet.sh - -if [[ "$restore" == true ]] -then - echo "Restoring RoslynToolset.csproj" - dotnet restore "${root_path}/build/ToolsetPackages/RoslynToolset.csproj" "/bl:${logs_path}/Restore-RoslynToolset.binlog" - echo "Restoring Compilers.sln" - dotnet restore "${root_path}/Compilers.sln" "/bl:${logs_path}/Restore-Compilers.binlog" -fi - -build_args="--no-restore -c ${build_configuration} /nologo" - -if [[ "$build_bootstrap" == true ]] -then - echo "Building bootstrap compiler" - - rm -rf ${bootstrap_path} - mkdir -p ${bootstrap_path} - - project_path=src/NuGet/Microsoft.NETCore.Compilers/Microsoft.NETCore.Compilers.Package.csproj - - dotnet pack -nologo ${project_path} /p:DotNetUseShippingVersions=true /p:InitialDefineConstants=BOOTSTRAP /p:PackageOutputPath=${bootstrap_path} - unzip ${bootstrap_path}/Microsoft.NETCore.Compilers.*.nupkg -d ${bootstrap_path} - chmod -R 755 ${bootstrap_path} - - echo "Cleaning Bootstrap compiler artifacts" - dotnet clean ${project_path} - - stop_processes -fi - -if [[ "${use_bootstrap}" == true ]] -then - build_args+=" /p:BootstrapBuildPath=${bootstrap_path}" -fi - -# https://github.com/dotnet/roslyn/issues/23736 -UNAME="$(uname)" -if [[ "$UNAME" == "Darwin" ]] -then - build_args+=" /p:UseRoslynAnalyzers=false" -fi - -if [[ "${build}" == true ]] -then - echo "Building Compilers.sln" - - if [[ "${pack}" == true ]] - then - build_args+=" /t:Pack" - fi - - dotnet build "${root_path}/Compilers.sln" ${build_args} "/bl:${binaries_path}/Build.binlog" -fi - -if [[ "${stop_vbcscompiler}" == true ]] -then - if [[ "${use_bootstrap}" == true ]] - then - dotnet build-server shutdown - else - echo "--stop-vbcscompiler requires --use-bootstrap. Aborting." - exit 1 - fi -fi - -if [[ "${test_}" == true ]] -then - if [[ "${use_mono}" == true ]] - then - test_runtime=mono - - # Echo out the mono version to the comamnd line so it's visible in CI logs. It's not fixed - # as we're using a feed vs. a hard coded package. - mono --version - else - test_runtime=dotnet - fi - "${root_path}"/build/scripts/tests.sh "${build_configuration}" "${test_runtime}" -fi +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" +"$scriptroot/build/scripts/build.sh" $@ diff --git a/build/Targets/RepoToolset/Publish.proj b/build/Targets/RepoToolset/Publish.proj index 17efc76d201ddbd07b8a15fc7b43b0e6ac1580a7..e2ca5c5993f0615cd788d3081b4a2edbb67d9215 100644 --- a/build/Targets/RepoToolset/Publish.proj +++ b/build/Targets/RepoToolset/Publish.proj @@ -1,21 +1,13 @@ - - $(ArtifactsPackagesDir)PerBuildPreRelease - $(ArtifactsPackagesDir)Release - $(ArtifactsPackagesDir)PreRelease + $(ArtifactsLogDir)AssetManifest\$(OS)-$(PlatformName).xml @@ -50,16 +36,20 @@ - + + - + + + $(SymbolPackagesDir)%(Filename).symbols.nupkg %(PackagesToPublish.Identity) + %(PackagesToPublish.IsShipping) @@ -72,13 +62,21 @@ + + + NonShipping=true + + + @@ -98,23 +96,28 @@ DryRunPTA - - + + + + + - false + false - - 0 ]] +do + opt="$(echo "$1" | awk '{print tolower($0)}')" + case "$opt" in + -h|--help) + usage + exit 1 + ;; + --docker) + build_in_docker=true + shift + continue + ;; + --configuration) + build_configuration=$2 + args="$args $1" + shift + ;; + --ci) + ci=true + ;; + --restore|-r) + restore=true + ;; + --build|-b) + build=true + ;; + --test|-t) + test_=true + ;; + --mono) + use_mono=true + ;; + --build-bootstrap) + build_bootstrap=true + ;; + --use-bootstrap) + use_bootstrap=true + ;; + --bootstrap) + build_bootstrap=true + use_bootstrap=true + ;; + --stop-vbcscompiler) + stop_vbcscompiler=true + ;; + --pack) + pack=true + ;; + *) + echo "$1" + usage + exit 1 + ;; + esac + args="$args $1" + shift +done + +config_path=${binaries_path}/${build_configuration} +logs_path=${config_path}/Logs +mkdir -p ${binaries_path} +mkdir -p ${config_path} +mkdir -p ${logs_path} + +function stop_processes { + echo "Killing running build processes..." + pkill -9 "dotnet" || true + pkill -9 "vbcscompiler" || true +} + +if [[ "$build_in_docker" = true ]] +then + echo "Docker exec: $args" + BUILD_COMMAND=/opt/code/build.sh "$scriptroot"/dockerrun.sh $args + exit +fi + +source "${scriptroot}"/obtain_dotnet.sh + +if [[ "$restore" == true ]] +then + echo "Restoring RoslynToolset.csproj" + dotnet restore "${root_path}/build/ToolsetPackages/RoslynToolset.csproj" "/bl:${logs_path}/Restore-RoslynToolset.binlog" + echo "Restoring Compilers.sln" + dotnet restore "${root_path}/Compilers.sln" "/bl:${logs_path}/Restore-Compilers.binlog" +fi + +build_args="--no-restore -c ${build_configuration} /nologo" + +if [[ "$build_bootstrap" == true ]] +then + echo "Building bootstrap compiler" + + rm -rf ${bootstrap_path} + mkdir -p ${bootstrap_path} + + project_path=src/NuGet/Microsoft.NETCore.Compilers/Microsoft.NETCore.Compilers.Package.csproj + + dotnet pack -nologo ${project_path} /p:DotNetUseShippingVersions=true /p:InitialDefineConstants=BOOTSTRAP /p:PackageOutputPath=${bootstrap_path} + unzip ${bootstrap_path}/Microsoft.NETCore.Compilers.*.nupkg -d ${bootstrap_path} + chmod -R 755 ${bootstrap_path} + + echo "Cleaning Bootstrap compiler artifacts" + dotnet clean ${project_path} + + stop_processes +fi + +if [[ "${use_bootstrap}" == true ]] +then + build_args+=" /p:BootstrapBuildPath=${bootstrap_path}" +fi + +if [[ "${ci}" == true ]] +then + build_args+=" /p:ContinuousIntegrationBuild=true" +fi + +# https://github.com/dotnet/roslyn/issues/23736 +UNAME="$(uname)" +if [[ "$UNAME" == "Darwin" ]] +then + build_args+=" /p:UseRoslynAnalyzers=false" +fi + +if [[ "${build}" == true ]] +then + echo "Building Compilers.sln" + + if [[ "${pack}" == true ]] + then + build_args+=" /t:Pack" + fi + + dotnet build "${root_path}/Compilers.sln" ${build_args} "/bl:${binaries_path}/Build.binlog" +fi + +if [[ "${stop_vbcscompiler}" == true ]] +then + if [[ "${use_bootstrap}" == true ]] + then + dotnet build-server shutdown + else + echo "--stop-vbcscompiler requires --use-bootstrap. Aborting." + exit 1 + fi +fi + +if [[ "${test_}" == true ]] +then + if [[ "${use_mono}" == true ]] + then + test_runtime=mono + + # Echo out the mono version to the comamnd line so it's visible in CI logs. It's not fixed + # as we're using a feed vs. a hard coded package. + mono --version + else + test_runtime=dotnet + fi + "${scriptroot}"/tests.sh "${build_configuration}" "${test_runtime}" +fi diff --git a/build/scripts/check-loc-status.cmd b/build/scripts/check-loc-status.cmd index 15878b8107620c87436f2e609d22e9ff52e93a46..91d2671032d472461c0bfa5f0881a014913df140 100644 --- a/build/scripts/check-loc-status.cmd +++ b/build/scripts/check-loc-status.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\build.ps1" -cibuild -restore -checkLoc -release -binaryLog %* +powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\build.ps1" -configuration Release -cibuild -restore -checkLoc -binaryLog %* diff --git a/build/scripts/cibuild.cmd b/build/scripts/cibuild.cmd index b4dc8daa4b4b5d887c8737f11777f4b9f9d37108..c2f318debe369c24ea3b8e95f7f982575accf8ce 100644 --- a/build/scripts/cibuild.cmd +++ b/build/scripts/cibuild.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\build.ps1" -cibuild -build -restore -bootstrap -pack -binaryLog %* +powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\build.ps1" -cibuild -build -restore -bootstrap -pack -sign -binaryLog %* diff --git a/build/scripts/cibuild.sh b/build/scripts/cibuild.sh index 320eff72559c3267cedd1a60435f290252dca683..3ddc9a98ad2bf6e8563c37c0d6e59e228259e565 100755 --- a/build/scripts/cibuild.sh +++ b/build/scripts/cibuild.sh @@ -1,11 +1,17 @@ #!/usr/bin/env bash -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -set -e -set -u +source="${BASH_SOURCE[0]}" -root_path="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +# resolve $SOURCE until the file is no longer a symlink +while [[ -h $source ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" + + # if $source was a relative symlink, we need to resolve it relative to the path where + # the symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" +done +scriptroot="$( cd -P "$( dirname "$source" )" && pwd)" # $HOME is unset when running the mac unit tests. if [[ -z "${HOME+x}" ]] @@ -24,4 +30,5 @@ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 echo "Building this commit:" git show --no-patch --pretty=raw HEAD -"${root_path}"/build.sh --restore --bootstrap --build --pack --stop-vbcscompiler --test "$@" + +. "$scriptroot/build.sh" --restore --bootstrap --build --pack --stop-vbcscompiler --test --ci "$@" \ No newline at end of file diff --git a/src/Tools/MicroBuild/publish-assets.ps1 b/build/scripts/publish-assets.ps1 similarity index 98% rename from src/Tools/MicroBuild/publish-assets.ps1 rename to build/scripts/publish-assets.ps1 index 03890d459e03d73f5c3df8c55653aae6147b91c0..3c9e4790a7ac2171ce7c868d8aed2df317d2e9fa 100644 --- a/src/Tools/MicroBuild/publish-assets.ps1 +++ b/build/scripts/publish-assets.ps1 @@ -143,7 +143,7 @@ function Normalize-BranchName([string]$branchName) { } try { - . (Join-Path $PSScriptRoot "..\..\..\build\scripts\build-utils.ps1") + . (Join-Path $PSScriptRoot "build-utils.ps1") $dotnet = Ensure-DotnetSdk $configDir = Join-Path $binariesDir $config $nugetDir = Join-Path $configDir "NuGet" diff --git a/build/scripts/run_perf.ps1 b/build/scripts/run_perf.ps1 index 9cf0b5a3cd7f4e3bfc1f78acfb99e3783b576a43..71c27fc8af05f7011b0f8c9d96cf4054b5d2ad1f 100644 --- a/build/scripts/run_perf.ps1 +++ b/build/scripts/run_perf.ps1 @@ -16,7 +16,7 @@ Invoke-WebRequest -Uri http://dotnetci.blob.core.windows.net/roslyn-perf/cpc.zip [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null [IO.Compression.ZipFile]::ExtractToDirectory('cpc.zip', $CPCLocation) -./build/scripts/cibuild.cmd -release -testPerfRun +./build/scripts/cibuild.cmd -configuration Release -testPerfRun if ( -not $? ) { diff --git a/build/scripts/test-build-correctness.ps1 b/build/scripts/test-build-correctness.ps1 index 74dab4e1ee55c58f5681d1c655124ad90b0f66cc..f62dd4c6393a0a778534edab506d0fd1dbf1f094 100644 --- a/build/scripts/test-build-correctness.ps1 +++ b/build/scripts/test-build-correctness.ps1 @@ -11,7 +11,7 @@ [CmdletBinding(PositionalBinding=$false)] param( - [switch]$release = $false, + [string]$configuration = "Debug", [switch]$cibuild = $false) Set-StrictMode -version 2.0 @@ -20,12 +20,11 @@ $ErrorActionPreference="Stop" try { . (Join-Path $PSScriptRoot "build-utils.ps1") Push-Location $repoDir - $buildConfiguration = if ($release) { "Release" } else { "Debug" } - $releaseArg = if ($release) { "-release" } else { "" } - $configDir = Join-Path $binariesDir $buildConfiguration + $releaseArg = if ($configuration -eq "Release") { "-release" } else { "" } + $configDir = Join-Path $binariesDir $configuration Write-Host "Building Roslyn" - Exec-Block { & (Join-Path $PSScriptRoot "build.ps1") -restore -build -cibuild:$cibuild -release:$release -pack -binaryLog } + Exec-Block { & (Join-Path $PSScriptRoot "build.ps1") -restore -build -cibuild:$cibuild -configuration:$configuration -pack -binaryLog } # Verify the state of our various build artifacts diff --git a/cibuild.sh b/cibuild.sh deleted file mode 100755 index c547a03bac910c0c6e7fb061ea32ee5a096ecbb3..0000000000000000000000000000000000000000 --- a/cibuild.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -# Temporary file until the netci.groovy change to use the new location propogates -exec ./build/scripts/cibuild.sh "$@" diff --git a/netci.groovy b/netci.groovy index 2b3e67fd24ad2701c5d693255fe65113680bb103..eda4ad4f74628290acc9333c3380dd9c13b28110 100644 --- a/netci.groovy +++ b/netci.groovy @@ -65,7 +65,7 @@ commitPullList.each { isPr -> def myJob = job(jobName) { description("Windows debug unit tests on unit32 using Spanish language") steps { - batchFile(""".\\build\\scripts\\cibuild.cmd -debug -test32 -testDesktop""") + batchFile(""".\\build\\scripts\\cibuild.cmd -configuration Debug -test32 -testDesktop""") } } def triggerPhraseOnly = false @@ -81,7 +81,7 @@ commitPullList.each { isPr -> def myJob = job(jobName) { description("Mac tests") steps { - shell("./build/scripts/cibuild.sh --debug") + shell("./build/scripts/cibuild.sh --configuration Debug") } } @@ -92,22 +92,6 @@ commitPullList.each { isPr -> addRoslynJob(myJob, jobName, branchName, isPr, triggerPhraseExtra, triggerPhraseOnly) } -// Microbuild -commitPullList.each { isPr -> - def jobName = Utilities.getFullJobName(projectName, "microbuild", isPr) - def myJob = job(jobName) { - description('MicroBuild test') - steps { - batchFile(""".\\src\\Tools\\MicroBuild\\cibuild.cmd""") - } - } - - def triggerPhraseOnly = false - def triggerPhraseExtra = "microbuild" - Utilities.setMachineAffinity(myJob, windowsUnitTestMachine) - addRoslynJob(myJob, jobName, branchName, isPr, triggerPhraseExtra, triggerPhraseOnly) -} - // VS Integration Tests commitPullList.each { isPr -> ['debug', 'release'].each { configuration -> @@ -116,7 +100,7 @@ commitPullList.each { isPr -> def myJob = job(jobName) { description("Windows ${configuration} tests on ${buildTarget}") steps { - batchFile(""".\\build\\scripts\\cibuild.cmd -${configuration} -testVsi""") + batchFile(""".\\build\\scripts\\cibuild.cmd -configuration ${configuration} -testVsi""") } } diff --git a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs index 870ef5788a3f2024e014352f80667b8ccc397fe0..3f6c915364cd251973f5ec158eca798fdec374c6 100644 --- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs +++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs @@ -46,6 +46,8 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar /// a commandlinearguments object representing the parsed command line. public new CSharpCommandLineArguments Parse(IEnumerable args, string baseDirectory, string sdkDirectory, string additionalReferenceDirectories = null) { + Debug.Assert(baseDirectory == null || PathUtilities.IsAbsolute(baseDirectory)); + List diagnostics = new List(); List flattenedArgs = new List(); List scriptArgs = IsScriptCommandLineParser ? new List() : null; @@ -1214,7 +1216,7 @@ public new CSharpCommandLineArguments Parse(IEnumerable args, string bas } // add additional reference paths if specified - if (!string.IsNullOrWhiteSpace(additionalReferenceDirectories)) + if (!string.IsNullOrEmpty(additionalReferenceDirectories)) { ParseAndResolveReferencePaths(null, additionalReferenceDirectories, baseDirectory, libPaths, MessageID.IDS_LIB_ENV, diagnostics); } @@ -1225,14 +1227,18 @@ public new CSharpCommandLineArguments Parse(IEnumerable args, string bas // Dev11 searches for the key file in the current directory and assembly output directory. // We always look to base directory and then examine the search paths. - keyFileSearchPaths.Add(baseDirectory); - if (baseDirectory != outputDirectory) + if (!string.IsNullOrEmpty(baseDirectory)) + { + keyFileSearchPaths.Add(baseDirectory); + } + + if (!string.IsNullOrEmpty(outputDirectory) && baseDirectory != outputDirectory) { keyFileSearchPaths.Add(outputDirectory); } // Public sign doesn't use the legacy search path settings - if (publicSign && !string.IsNullOrWhiteSpace(keyFileSetting)) + if (publicSign && !string.IsNullOrEmpty(keyFileSetting)) { keyFileSetting = ParseGenericPathToFile(keyFileSetting, diagnostics, baseDirectory); } diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 007859039ff11a872f6d5a9b9d40812e5bead2ea..fdac9e251f203b2db8fc51fa3075ace81229117f 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -243,6 +243,13 @@ public void ResponseFiles_RelativePaths() Assert.Equal(basePath, args.BaseDirectory); } + [Fact] + public void NullBaseDirectoryNotAddedToKeyFileSearchPaths() + { + var parser = CSharpCommandLineParser.Default.Parse(new string[0], null, SdkDirectory); + AssertEx.Equal(ImmutableArray.Create(), parser.KeyFileSearchPaths); + } + [ConditionalFact(typeof(WindowsOnly))] public void SourceFiles_Patterns() { @@ -542,7 +549,7 @@ public void Win32IconContainsGarbage() CleanupAllGeneratedFiles(tmpFileName); } - [Fact] + [ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30289")] public void Win32ResQuotes() { string[] responseFile = new string[] { diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAnonymousFunctionExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAnonymousFunctionExpression.cs index 662f7cd32dc1541a16ac314d0c0cc6e2a8dc9cf4..98fb11846731130627fdf05f4b9f6b7a0e743d60 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAnonymousFunctionExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAnonymousFunctionExpression.cs @@ -753,24 +753,91 @@ void M(System.Action d1, System.Action d2) var graphM = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType().Single())); Assert.NotNull(graphM); + Assert.Null(graphM.Parent); IFlowAnonymousFunctionOperation lambdaD1 = getLambda(graphM); Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(null)); Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(lambdaD1.Symbol)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(null)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(lambdaD1.Symbol)); var graphD1 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD1); Assert.NotNull(graphD1); + Assert.Same(graphM, graphD1.Parent); + var graphD1_FromExtension = graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD1); + Assert.Same(graphD1, graphD1_FromExtension); IFlowAnonymousFunctionOperation lambdaD2 = getLambda(graphD1); + var graphD2 = graphD1.GetAnonymousFunctionControlFlowGraph(lambdaD2); + Assert.NotNull(graphD2); + Assert.Same(graphD1, graphD2.Parent); Assert.Throws(() => graphM.GetAnonymousFunctionControlFlowGraph(null)); Assert.Throws(() => graphM.GetAnonymousFunctionControlFlowGraph(lambdaD2)); + Assert.Throws(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(null)); + Assert.Throws(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD2)); IFlowAnonymousFunctionOperation getLambda(ControlFlowGraph graph) { return graph.Blocks.SelectMany(b => b.Operations.SelectMany(o => o.DescendantsAndSelf())).OfType().Single(); } } + + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] + [Fact] + public void LambdaFlow_05() + { + string source = @" +struct C +{ + void M(System.Action d1, System.Action d2) +/**/{ + d1 = () => { }; + d2 = () => + { + d1(); + }; + }/**/ +} +"; + + var compilation = CreateCompilation(source); + var tree = compilation.SyntaxTrees.Single(); + var semanticModel = compilation.GetSemanticModel(tree); + var graphM = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType().Single())); + + Assert.NotNull(graphM); + Assert.Null(graphM.Parent); + + IFlowAnonymousFunctionOperation lambdaD1 = getLambda(graphM, index: 0); + Assert.NotNull(lambdaD1); + IFlowAnonymousFunctionOperation lambdaD2 = getLambda(graphM, index: 1); + Assert.NotNull(lambdaD2); + + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(null)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(lambdaD1.Symbol)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(null)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(lambdaD1.Symbol)); + + var graphD1 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD1); + Assert.NotNull(graphD1); + Assert.Same(graphM, graphD1.Parent); + var graphD2 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD2); + Assert.NotNull(graphD2); + Assert.Same(graphM, graphD2.Parent); + + var graphD1_FromExtension = graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD1); + Assert.Same(graphD1, graphD1_FromExtension); + + Assert.Throws(() => graphD2.GetAnonymousFunctionControlFlowGraph(lambdaD1)); + graphD1_FromExtension = graphD2.GetAnonymousFunctionControlFlowGraphInScope(lambdaD1); + Assert.Same(graphD1, graphD1_FromExtension); + + IFlowAnonymousFunctionOperation getLambda(ControlFlowGraph graph, int index) + { + return graph.Blocks.SelectMany(b => b.Operations.SelectMany(o => o.DescendantsAndSelf())).OfType().ElementAt(index); + } + } } } diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_ILocalFunctionStatement.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_ILocalFunctionStatement.cs index 8ff00a36f926ee77933973292dc4f55b8c47ddd2..f2d567dd0d809c948c9efc9ffe7762b301ba2650 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_ILocalFunctionStatement.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_ILocalFunctionStatement.cs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.FlowAnalysis; +using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -1629,5 +1633,113 @@ void local2(C result2, C input21, C input22) VerifyFlowGraphAndDiagnosticsForTest(source, expectedGraph, expectedDiagnostics); } + + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] + [Fact] + public void LocalFunctionFlow_11() + { + string source = @" +struct C +{ + void M() +/**/{ + void d1() + { + void d2(bool result1, bool input1) + { + result1 = input1; + } + }; + }/**/ +} +"; + + var compilation = CreateCompilation(source); + var tree = compilation.SyntaxTrees.Single(); + var semanticModel = compilation.GetSemanticModel(tree); + var graphM = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType().First())); + + Assert.NotNull(graphM); + Assert.Null(graphM.Parent); + + IMethodSymbol localFunctionD1 = getLocalFunction(graphM); + Assert.NotNull(localFunctionD1); + Assert.Equal("d1", localFunctionD1.Name); + + var graphD1 = graphM.GetLocalFunctionControlFlowGraph(localFunctionD1); + Assert.NotNull(graphD1); + Assert.Same(graphM, graphD1.Parent); + var graphD1_FromExtension = graphM.GetLocalFunctionControlFlowGraphInScope(localFunctionD1); + Assert.Same(graphD1, graphD1_FromExtension); + + IMethodSymbol localFunctionD2 = getLocalFunction(graphD1); + Assert.NotNull(localFunctionD2); + Assert.Equal("d2", localFunctionD2.Name); + + var graphD2 = graphD1.GetLocalFunctionControlFlowGraph(localFunctionD2); + Assert.NotNull(graphD2); + Assert.Same(graphD1, graphD2.Parent); + + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(null)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraph(localFunctionD2)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(null)); + Assert.Throws(() => graphM.GetLocalFunctionControlFlowGraphInScope(localFunctionD2)); + + IMethodSymbol getLocalFunction(ControlFlowGraph graph) + { + return graph.LocalFunctions.Single(); + } + } + + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] + [Fact] + public void LocalFunctionFlow_12() + { + string source = @" +struct C +{ + void M() +/**/{ + void d1() { } + void d2() + { + d1(); + } + }/**/ +} +"; + + var compilation = CreateCompilation(source); + var tree = compilation.SyntaxTrees.Single(); + var semanticModel = compilation.GetSemanticModel(tree); + var graphM = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType().First())); + + Assert.NotNull(graphM); + Assert.Null(graphM.Parent); + + IMethodSymbol localFunctionD1 = getLocalFunction(graphM, "d1"); + Assert.NotNull(localFunctionD1); + IMethodSymbol localFunctionD2 = getLocalFunction(graphM, "d2"); + Assert.NotNull(localFunctionD2); + + var graphD1 = graphM.GetLocalFunctionControlFlowGraph(localFunctionD1); + Assert.NotNull(graphD1); + Assert.Same(graphM, graphD1.Parent); + var graphD2 = graphM.GetLocalFunctionControlFlowGraph(localFunctionD2); + Assert.NotNull(graphD2); + Assert.Same(graphM, graphD2.Parent); + + var graphD1_FromExtension = graphM.GetLocalFunctionControlFlowGraphInScope(localFunctionD1); + Assert.Same(graphD1, graphD1_FromExtension); + + Assert.Throws(() => graphD2.GetLocalFunctionControlFlowGraph(localFunctionD1)); + graphD1_FromExtension = graphD2.GetLocalFunctionControlFlowGraphInScope(localFunctionD1); + Assert.Same(graphD1, graphD1_FromExtension); + + IMethodSymbol getLocalFunction(ControlFlowGraph graph, string name) + { + return graph.LocalFunctions.Single(l => l.Name == name); + } + } } } diff --git a/src/Compilers/Core/MSBuildTask/ValidateBootstrap.cs b/src/Compilers/Core/MSBuildTask/ValidateBootstrap.cs index e5e6f49b45221c4beb34c5faf5233c99a0347ce1..9684e512a2d1faa320ebc47a054c8ea2c4d7aafa 100644 --- a/src/Compilers/Core/MSBuildTask/ValidateBootstrap.cs +++ b/src/Compilers/Core/MSBuildTask/ValidateBootstrap.cs @@ -26,7 +26,7 @@ public sealed partial class ValidateBootstrap : Task public string BootstrapPath { get { return _bootstrapPath; } - set { _bootstrapPath = NormalizePath(value); } + set { _bootstrapPath = NormalizePath(Path.GetFullPath(value)); } } public ValidateBootstrap() diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraph.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraph.cs index a631a5e6ff48003ae5cc00ec393f9deb8e8764cd..326b6b40aa7ed789df80d9732cd49cc16397ff30 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraph.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraph.cs @@ -26,12 +26,14 @@ public sealed partial class ControlFlowGraph private ControlFlowGraph[] _lazyAnonymousFunctionsGraphs; internal ControlFlowGraph(IOperation originalOperation, + ControlFlowGraph parent, ControlFlowGraphBuilder.CaptureIdDispenser captureIdDispenser, ImmutableArray blocks, ControlFlowRegion root, ImmutableArray localFunctions, ImmutableDictionary localFunctionsMap, ImmutableDictionary anonymousFunctionsMap) { + Debug.Assert(parent != null == (originalOperation.Kind == OperationKind.LocalFunction || originalOperation.Kind == OperationKind.AnonymousFunction)); Debug.Assert(captureIdDispenser != null); Debug.Assert(!blocks.IsDefault); Debug.Assert(blocks.First().Kind == BasicBlockKind.Entry); @@ -54,6 +56,7 @@ public sealed partial class ControlFlowGraph #endif OriginalOperation = originalOperation; + Parent = parent; Blocks = blocks; Root = root; LocalFunctions = localFunctions; @@ -193,6 +196,13 @@ internal static ControlFlowGraph CreateCore(IOperation operation, string argumen /// public IOperation OriginalOperation { get; } + /// + /// Optional parent control flow graph for this graph. + /// Non-null for a control flow graph generated for a local function or a lambda. + /// Null otherwise. + /// + public ControlFlowGraph Parent { get; } + /// /// Basic blocks for the control flow graph. /// @@ -220,11 +230,22 @@ public ControlFlowGraph GetLocalFunctionControlFlowGraph(IMethodSymbol localFunc throw new ArgumentNullException(nameof(localFunction)); } - if (!_localFunctionsMap.TryGetValue(localFunction, out (ControlFlowRegion enclosing, ILocalFunctionOperation operation, int ordinal) info)) + if (!TryGetLocalFunctionControlFlowGraph(localFunction, cancellationToken, out var controlFlowGraph)) { throw new ArgumentOutOfRangeException(nameof(localFunction)); } + return controlFlowGraph; + } + + internal bool TryGetLocalFunctionControlFlowGraph(IMethodSymbol localFunction, CancellationToken cancellationToken, out ControlFlowGraph controlFlowGraph) + { + if (!_localFunctionsMap.TryGetValue(localFunction, out (ControlFlowRegion enclosing, ILocalFunctionOperation operation, int ordinal) info)) + { + controlFlowGraph = null; + return false; + } + Debug.Assert(localFunction == LocalFunctions[info.ordinal]); if (_lazyLocalFunctionsGraphs == null) @@ -235,12 +256,14 @@ public ControlFlowGraph GetLocalFunctionControlFlowGraph(IMethodSymbol localFunc if (_lazyLocalFunctionsGraphs[info.ordinal] == null) { Debug.Assert(localFunction == info.operation.Symbol); - ControlFlowGraph graph = ControlFlowGraphBuilder.Create(info.operation, info.enclosing, _captureIdDispenser); + ControlFlowGraph graph = ControlFlowGraphBuilder.Create(info.operation, this, info.enclosing, _captureIdDispenser); Debug.Assert(graph.OriginalOperation == info.operation); Interlocked.CompareExchange(ref _lazyLocalFunctionsGraphs[info.ordinal], graph, null); } - return _lazyLocalFunctionsGraphs[info.ordinal]; + controlFlowGraph = _lazyLocalFunctionsGraphs[info.ordinal]; + Debug.Assert(controlFlowGraph.Parent == this); + return true; } /// @@ -255,11 +278,22 @@ public ControlFlowGraph GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunct throw new ArgumentNullException(nameof(anonymousFunction)); } - if (!_anonymousFunctionsMap.TryGetValue(anonymousFunction, out (ControlFlowRegion enclosing, int ordinal) info)) + if (!TryGetAnonymousFunctionControlFlowGraph(anonymousFunction, cancellationToken, out ControlFlowGraph controlFlowGraph)) { throw new ArgumentOutOfRangeException(nameof(anonymousFunction)); } + return controlFlowGraph; + } + + internal bool TryGetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation anonymousFunction, CancellationToken cancellationToken, out ControlFlowGraph controlFlowGraph) + { + if (!_anonymousFunctionsMap.TryGetValue(anonymousFunction, out (ControlFlowRegion enclosing, int ordinal) info)) + { + controlFlowGraph = null; + return false; + } + if (_lazyAnonymousFunctionsGraphs == null) { Interlocked.CompareExchange(ref _lazyAnonymousFunctionsGraphs, new ControlFlowGraph[_anonymousFunctionsMap.Count], null); @@ -268,12 +302,14 @@ public ControlFlowGraph GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunct if (_lazyAnonymousFunctionsGraphs[info.ordinal] == null) { var anonymous = (FlowAnonymousFunctionOperation)anonymousFunction; - ControlFlowGraph graph = ControlFlowGraphBuilder.Create(anonymous.Original, info.enclosing, _captureIdDispenser, in anonymous.Context); + ControlFlowGraph graph = ControlFlowGraphBuilder.Create(anonymous.Original, this, info.enclosing, _captureIdDispenser, in anonymous.Context); Debug.Assert(graph.OriginalOperation == anonymous.Original); Interlocked.CompareExchange(ref _lazyAnonymousFunctionsGraphs[info.ordinal], graph, null); } - return _lazyAnonymousFunctionsGraphs[info.ordinal]; + controlFlowGraph = _lazyAnonymousFunctionsGraphs[info.ordinal]; + Debug.Assert(controlFlowGraph.Parent == this); + return true; } } } diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 57a6277f197e395163bc81fdba674323fd729bef..6478b18b04002499ce4cf081834914a4ca32e43e 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -55,7 +55,7 @@ private bool IsImplicit(IOperation operation) return _forceImplicit || operation.IsImplicit; } - public static ControlFlowGraph Create(IOperation body, ControlFlowRegion enclosing = null, CaptureIdDispenser captureIdDispenser = null, in Context context = default) + public static ControlFlowGraph Create(IOperation body, ControlFlowGraph parent = null, ControlFlowRegion enclosing = null, CaptureIdDispenser captureIdDispenser = null, in Context context = default) { Debug.Assert(body != null); Debug.Assert(((Operation)body).OwningSemanticModel != null); @@ -71,10 +71,12 @@ public static ControlFlowGraph Create(IOperation body, ControlFlowRegion enclosi body.Kind == OperationKind.PropertyInitializer || body.Kind == OperationKind.ParameterInitializer, $"Unexpected root operation kind: {body.Kind}"); + Debug.Assert(parent == null); } else { Debug.Assert(body.Kind == OperationKind.LocalFunction || body.Kind == OperationKind.AnonymousFunction); + Debug.Assert(parent != null); } #endif @@ -135,7 +137,7 @@ public static ControlFlowGraph Create(IOperation body, ControlFlowRegion enclosi builder._regionMap.Free(); builder._labeledBlocks?.Free(); - return new ControlFlowGraph(body, builder._captureIdDispenser, ToImmutableBlocks(blocks), region, + return new ControlFlowGraph(body, parent, builder._captureIdDispenser, ToImmutableBlocks(blocks), region, localFunctions.ToImmutableAndFree(), localFunctionsMap.ToImmutable(), anonymousFunctionsMapOpt?.ToImmutable() ?? ImmutableDictionary.Empty); } diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphExtensions.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..fe1b57bd1341956b48e6e741fff51586859693f9 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphExtensions.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading; + +namespace Microsoft.CodeAnalysis.FlowAnalysis +{ + public static partial class ControlFlowGraphExtensions + { + /// + /// Gets or creates a control flow graph for the given defined in + /// the given or any of it's parent control flow graphs. + /// + public static ControlFlowGraph GetLocalFunctionControlFlowGraphInScope(this ControlFlowGraph controlFlowGraph, IMethodSymbol localFunction, CancellationToken cancellationToken = default) + { + if (controlFlowGraph == null) + { + throw new ArgumentNullException(nameof(controlFlowGraph)); + } + + if (localFunction == null) + { + throw new ArgumentNullException(nameof(localFunction)); + } + + do + { + if (controlFlowGraph.TryGetLocalFunctionControlFlowGraph(localFunction, cancellationToken, out ControlFlowGraph localFunctionControlFlowGraph)) + { + return localFunctionControlFlowGraph; + } + } + while ((controlFlowGraph = controlFlowGraph.Parent) != null); + + throw new ArgumentOutOfRangeException(nameof(localFunction)); + } + + /// + /// Gets or creates a control flow graph for the given defined in + /// the given or any of it's parent control flow graphs. + /// + public static ControlFlowGraph GetAnonymousFunctionControlFlowGraphInScope(this ControlFlowGraph controlFlowGraph, IFlowAnonymousFunctionOperation anonymousFunction, CancellationToken cancellationToken = default) + { + if (controlFlowGraph == null) + { + throw new ArgumentNullException(nameof(controlFlowGraph)); + } + + if (anonymousFunction == null) + { + throw new ArgumentNullException(nameof(anonymousFunction)); + } + + do + { + if (controlFlowGraph.TryGetAnonymousFunctionControlFlowGraph(anonymousFunction, cancellationToken, out ControlFlowGraph localFunctionControlFlowGraph)) + { + return localFunctionControlFlowGraph; + } + } + while ((controlFlowGraph = controlFlowGraph.Parent) != null); + + throw new ArgumentOutOfRangeException(nameof(anonymousFunction)); + } + } +} diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index ce4c37e295ef8de920a12d8a9493183b40e6cdb5..e14b83c4cdda7215b94b863234ce65fa64271f59 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -20,6 +20,8 @@ Microsoft.CodeAnalysis.Diagnostics.Telemetry.AnalyzerTelemetryInfo.SymbolStartAc Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.GetAnonymousFunctionControlFlowGraph(Microsoft.CodeAnalysis.FlowAnalysis.IFlowAnonymousFunctionOperation anonymousFunction, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.GetLocalFunctionControlFlowGraph(Microsoft.CodeAnalysis.IMethodSymbol localFunction, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.LocalFunctions.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.Parent.get -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph +Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraphExtensions Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowRegion.CaptureIds.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowRegion.LocalFunctions.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.FlowAnalysis.ICaughtExceptionOperation @@ -145,6 +147,8 @@ static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.Create(Microsoft.Cod static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.Create(Microsoft.CodeAnalysis.Operations.IParameterInitializerOperation initializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.Create(Microsoft.CodeAnalysis.Operations.IPropertyInitializerOperation initializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph.Create(Microsoft.CodeAnalysis.SyntaxNode node, Microsoft.CodeAnalysis.SemanticModel semanticModel, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph +static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraphExtensions.GetAnonymousFunctionControlFlowGraphInScope(this Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph controlFlowGraph, Microsoft.CodeAnalysis.FlowAnalysis.IFlowAnonymousFunctionOperation anonymousFunction, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph +static Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraphExtensions.GetLocalFunctionControlFlowGraphInScope(this Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph controlFlowGraph, Microsoft.CodeAnalysis.IMethodSymbol localFunction, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph static Microsoft.CodeAnalysis.Operations.OperationExtensions.GetCorrespondingOperation(this Microsoft.CodeAnalysis.Operations.IBranchOperation operation) -> Microsoft.CodeAnalysis.IOperation virtual Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterSymbolStartAction(System.Action action, Microsoft.CodeAnalysis.SymbolKind symbolKind) -> void virtual Microsoft.CodeAnalysis.Diagnostics.CompilationStartAnalysisContext.RegisterSymbolStartAction(System.Action action, Microsoft.CodeAnalysis.SymbolKind symbolKind) -> void diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index 1e4f5689c9aa285220423a0ba5506b53b2ee4e37..f2daec80d11156f7275252069d35304fa53952bd 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -73,6 +73,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' A string representing additional reference paths. ''' A CommandLineArguments object representing the parsed command line. Public Shadows Function Parse(args As IEnumerable(Of String), baseDirectory As String, sdkDirectory As String, Optional additionalReferenceDirectories As String = Nothing) As VisualBasicCommandLineArguments + Debug.Assert(baseDirectory Is Nothing OrElse PathUtilities.IsAbsolute(baseDirectory)) + Const GenerateFileNameForDocComment As String = "USE-OUTPUT-NAME" Dim diagnostics As List(Of Diagnostic) = New List(Of Diagnostic)() @@ -1252,7 +1254,7 @@ lVbRuntimePlus: End If ' add additional reference paths if specified - If Not String.IsNullOrWhiteSpace(additionalReferenceDirectories) Then + If Not String.IsNullOrEmpty(additionalReferenceDirectories) Then libPaths.AddRange(ParseSeparatedPaths(additionalReferenceDirectories)) End If @@ -1260,7 +1262,7 @@ lVbRuntimePlus: Dim searchPaths As ImmutableArray(Of String) = BuildSearchPaths(baseDirectory, sdkPaths, responsePaths, libPaths) ' Public sign doesn't use legacy search path settings - If publicSign AndAlso Not String.IsNullOrWhiteSpace(keyFileSetting) Then + If publicSign AndAlso Not String.IsNullOrEmpty(keyFileSetting) Then keyFileSetting = ParseGenericPathToFile(keyFileSetting, diagnostics, baseDirectory) End If @@ -1291,8 +1293,11 @@ lVbRuntimePlus: ' Dev10 searches for the keyfile in the current directory and assembly output directory. ' We always look to base directory and then examine the search paths. - keyFileSearchPaths.Add(baseDirectory) - If baseDirectory <> outputDirectory Then + If Not String.IsNullOrEmpty(baseDirectory) Then + keyFileSearchPaths.Add(baseDirectory) + End If + + If Not String.IsNullOrEmpty(outputDirectory) AndAlso baseDirectory <> outputDirectory Then keyFileSearchPaths.Add(outputDirectory) End If diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index c64eb5c25bee3efc9a1bf3e3252ccc11cb1492a2..a9ae111f82fd1534cfea5c544c366e9e077b4bfe 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -3188,6 +3188,12 @@ print Goodbye, World" Assert.Equal(New KeyValuePair(Of String, String)("/temp/", "/bar/"), doublemap(1)) End Sub + + Public Sub NothingBaseDirectoryNotAddedToKeyFileSearchPaths() + Dim args As VisualBasicCommandLineArguments = VisualBasicCommandLineParser.Default.Parse(New String() {}, Nothing, RuntimeEnvironment.GetRuntimeDirectory()) + AssertEx.Equal(ImmutableArray.Create(Of String)(), args.KeyFileSearchPaths) + End Sub + Public Sub PathMapPdbDeterminism() diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 3efec157fa4bf8087da88ddebc74ef93219537fb..16dc70616022e009b15b0658fe3d9642d53133bc 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; @@ -3989,6 +3990,80 @@ static void Main() }"); } + [WorkItem(29264, "https://github.com/dotnet/roslyn/issues/29264")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] + public async Task DontRemoveCastOnDictionaryIndexer() + { + await TestMissingInRegularAndScriptAsync( +@" +using System; +using System.Reflection; +using System.Collections.Generic; + +static class Program +{ + enum TestEnum + { + Test, + } + + static void Main() + { + Dictionary Icons = new Dictionary + { + [[|(int)|] TestEnum.Test] = null, + }; + } +}"); + } + + [WorkItem(29264, "https://github.com/dotnet/roslyn/issues/29264")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] + public async Task RemoveCastOnDictionaryIndexer() + { + await TestInRegularAndScriptAsync( + @" +using System; +using System.Reflection; +using System.Collections.Generic; + +static class Program +{ + enum TestEnum + { + Test, + } + + static void Main() + { + Dictionary Icons = new Dictionary + { + [[|(int)|] 0] = null, + }; + } +}", + @" +using System; +using System.Reflection; +using System.Collections.Generic; + +static class Program +{ + enum TestEnum + { + Test, + } + + static void Main() + { + Dictionary Icons = new Dictionary + { + [0] = null, + }; + } +}"); + } + [WorkItem(20630, "https://github.com/dotnet/roslyn/issues/20630")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] public async Task DontRemoveCastOnCallToAttributeWithParamsArgsAndProperty() diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxUtilitiesTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxUtilitiesTests.cs index 90dcde076e3f3de2b3f82a7020aca0340cfa1ac0..f9546b8125e0f609ae1a5e22f20a66d0dcfcc6d6 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxUtilitiesTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxUtilitiesTests.cs @@ -2,6 +2,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Xunit; using SyntaxUtilities = Microsoft.CodeAnalysis.CSharp.EditAndContinue.SyntaxUtilities; @@ -59,5 +60,96 @@ static void Main(string[] args) "; VerifySyntaxMap(source1, source2); } + + [Fact] + public void FindLeafNodeAndPartner1() + { + var leftRoot = SyntaxFactory.ParseSyntaxTree(@" +using System; + +class C +{ + public void M() + { + if (0 == 1) + { + Console.WriteLine(0); + } + } +} +").GetRoot(); + var leftPosition = leftRoot.DescendantNodes().OfType().ElementAt(2).SpanStart; // 0 within Console.WriteLine(0) + var rightRoot = SyntaxFactory.ParseSyntaxTree(@" +using System; + +class C +{ + public void M() + { + if (0 == 1) + { + if (2 == 3) + { + Console.WriteLine(0); + } + } + } +} +").GetRoot(); + + SyntaxUtilities.FindLeafNodeAndPartner(leftRoot, leftPosition, rightRoot, out SyntaxNode leftNode, out SyntaxNode rightNodeOpt); + Assert.Equal("0", leftNode.ToString()); + Assert.Null(rightNodeOpt); + } + + [Fact] + public void FindLeafNodeAndPartner2() + { + // Check that the method does not fail even if the index of the child (4) + // is greater than the count of children on the corresponding (from the upper side) node (3). + var leftRoot = SyntaxFactory.ParseSyntaxTree(@" +using System; + +class C +{ + public void M() + { + if (0 == 1) + { + Console.WriteLine(0); + Console.WriteLine(1); + Console.WriteLine(2); + Console.WriteLine(3); + } + } +} +").GetRoot(); + + var leftPosition = leftRoot.DescendantNodes().OfType().ElementAt(5).SpanStart; // 3 within Console.WriteLine(3) + var rightRoot = SyntaxFactory.ParseSyntaxTree(@" +using System; + +class C +{ + public void M() + { + if (0 == 1) + { + if (2 == 3) + { + Console.WriteLine(0); + Console.WriteLine(1); + Console.WriteLine(2); + Console.WriteLine(3); + } + } + } +} +").GetRoot(); + + SyntaxUtilities.FindLeafNodeAndPartner(leftRoot, leftPosition, rightRoot, out SyntaxNode leftNode, out SyntaxNode rightNodeOpt); + Assert.Equal("3", leftNode.ToString()); + Assert.Null(rightNodeOpt); + } } } diff --git a/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersCompilerErrorTests.cs b/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersCompilerErrorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..bcc3db7fe4a8fb9bd523e0bf5238ef3601d27edd --- /dev/null +++ b/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersCompilerErrorTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.OrderModifiers; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.OrderModifiers +{ + public sealed class OrderModifiersCompilerErrorTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) + => (null, new CSharpOrderModifiersCodeFixProvider()); + + [WorkItem(30352, "https://github.com/dotnet/roslyn/issues/30352")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEnd() + { + // Verify that the code fix claims it fixes the compiler error (CS0267) in addition to the analyzer diagnostic. + await TestInRegularAndScript1Async( +@"[|partial|] public class C { }", +@"public partial class C { }"); + } + } +} diff --git a/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersTests.cs b/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersTests.cs index 1b4bd014b85bd642c1296f92002fc476500e4692..2b4636bb681e7feab5151e95467704722f8a5b17 100644 --- a/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/OrderModifiers/OrderModifiersTests.cs @@ -274,5 +274,97 @@ internal static class C #endif "); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndClass1() + { + await TestInRegularAndScript1Async( +@"[|partial|] public class C { }", +@"public partial class C { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndClass2() + { + await TestInRegularAndScript1Async( +@"[|partial|] abstract class C { }", +@"abstract partial class C { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndClass3() + { + await TestInRegularAndScript1Async( +@"[|partial|] sealed class C { }", +@"sealed partial class C { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndClass4() + { + await TestInRegularAndScript1Async( +@"[|partial|] static class C { }", +@"static partial class C { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndClass5() + { + await TestInRegularAndScript1Async( +@"[|partial|] unsafe class C { }", +@"unsafe partial class C { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndStruct1() + { + await TestInRegularAndScript1Async( +@"[|partial|] public struct S { }", +@"public partial struct S { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndStruct2() + { + await TestInRegularAndScript1Async( +@"[|partial|] unsafe struct S { }", +@"unsafe partial struct S { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndInterface() + { + await TestInRegularAndScript1Async( +@"[|partial|] public interface I { }", +@"public partial interface I { }"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndMethod1() + { + await TestInRegularAndScript1Async( +@"partial class C +{ + [|partial|] static void M(); +}", +@"partial class C +{ + static partial void M(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsOrderModifiers)] + public async Task PartialAtTheEndMethod2() + { + await TestInRegularAndScript1Async( +@"partial class C +{ + [|partial|] unsafe void M(); +}", +@"partial class C +{ + unsafe partial void M(); +}"); + } } } diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index c1f326a030facd0e5044b00edb84050953dd14c1..9835ea2001bacf2d6aa1887fce09587cd79b25fc 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -1243,6 +1243,22 @@ public async Task TestFalseKeyword() MainDescription("struct System.Boolean")); } + [WorkItem(26027, "https://github.com/dotnet/roslyn/issues/26027")] + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestNullLiteral() + { + await TestInMethodAsync(@"string f = null$$", + MainDescription("class System.String")); + } + + [WorkItem(26027, "https://github.com/dotnet/roslyn/issues/26027")] + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestDefaultLiteral() + { + await TestInMethodAsync(@"string f = default$$", + MainDescription("class System.String")); + } + [WorkItem(756226, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/756226")] [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] public async Task TestAwaitKeywordOnGenericTaskReturningAsync() diff --git a/src/EditorFeatures/Test2/Workspaces/SymbolDescriptionServiceTests.vb b/src/EditorFeatures/Test2/Workspaces/SymbolDescriptionServiceTests.vb index ee8e1137bc7a36a934667501edd57ef8b3c0cd9b..d490b5c1f7bf620f9514360504c29e3089e148f4 100644 --- a/src/EditorFeatures/Test2/Workspaces/SymbolDescriptionServiceTests.vb +++ b/src/EditorFeatures/Test2/Workspaces/SymbolDescriptionServiceTests.vb @@ -108,6 +108,44 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Await TestCSharpAsync(workspace, $"({FeaturesResources.local_constant}) int x = 2") End Function + + Public Async Function TestCSharpNullLiteralVar() As Task + Dim workspace = + + + + class Goo + { + void Method() + { + var x = nu$$ll + } + } + + + + Await TestCSharpAsync(workspace, "") + End Function + + + Public Async Function TestCSharpNullLiteralString() As Task + Dim workspace = + + + + class Goo + { + void Method() + { + string x = nu$$ll + } + } + + + + Await TestCSharpAsync(workspace, "class System.String") + End Function + #End Region #Region "Basic SymbolDescription Tests" @@ -508,9 +546,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Await TestBasicAsync(workspace, "Structure System.DateTime") End Function - ''' Design change from Dev10 - Public Async Function TestNothingLiteral() As Task + Public Async Function TestNothingLiteralDim() As Task Dim workspace = @@ -523,7 +560,40 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces - Await TestBasicAsync(workspace, "") + Await TestBasicAsync(workspace, "Class System.Object") + End Function + + + Public Async Function TestNothingLiteralDimAsString() As Task + Dim workspace = + + + + Class Goo + Sub Method() + Dim x As String = Nothin$$g + End Sub + End Class + + + + Await TestBasicAsync(workspace, "Class System.String") + End Function + + + Public Async Function TestNothingLiteralFieldDimOptionStrict() As Task + Dim workspace = + + + + Option Strict On + Class Goo + Dim x = Nothin$$g + End Class + + + + Await TestBasicAsync(workspace, "Class System.Object") End Function diff --git a/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxUtilitiesTests.vb b/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxUtilitiesTests.vb index 74778d3e2267fe7df1bfd2dc137a63144755799d..d1686cf5043a21df43fabcbfdcbd7f4aa553c947 100644 --- a/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxUtilitiesTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxUtilitiesTests.vb @@ -1,5 +1,6 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports SyntaxUtilities = Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.SyntaxUtilities Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EditAndContinue @@ -47,5 +48,84 @@ End Class " VerifySyntaxMap(source1, source2) End Sub + + + Public Sub FindLeafNodeAndPartner1() + Dim leftRoot = SyntaxFactory.ParseSyntaxTree(" +Imports System; + +Class C + Public Sub M() + If 0 = 1 Then + Console.WriteLine(0) + End If + End Sub +End Class +").GetRoot() + Dim leftPosition = leftRoot.DescendantNodes().OfType(Of LiteralExpressionSyntax).ElementAt(2).SpanStart '0 within Console.WriteLine(0) + Dim rightRoot = SyntaxFactory.ParseSyntaxTree(" +Imports System; + +Class C + Public Sub M() + If 0 = 1 Then + If 2 = 3 Then + Console.WriteLine(0) + End If + End If + End Sub +End Class +").GetRoot() + + Dim leftNode As SyntaxNode = Nothing + Dim rightNodeOpt As SyntaxNode = Nothing + SyntaxUtilities.FindLeafNodeAndPartner(leftRoot, leftPosition, rightRoot, leftNode, rightNodeOpt) + Assert.Equal("0", leftNode.ToString()) + Assert.Null(rightNodeOpt) + End Sub + + + Public Sub FindLeafNodeAndPartner2() + ' Check that the method does Not fail even if the index of the child (4) + ' is greater than the count of children on the corresponding (from the upper side) node (3). + Dim leftRoot = SyntaxFactory.ParseSyntaxTree(" +Imports System; + +Class C + Public Sub M() + If 0 = 1 Then + Console.WriteLine(0) + Console.WriteLine(1) + Console.WriteLine(2) + Console.WriteLine(3) + End If + End Sub +End Class +").GetRoot() + + Dim leftPosition = leftRoot.DescendantNodes().OfType(Of LiteralExpressionSyntax).ElementAt(5).SpanStart '3 within Console.WriteLine(3) + Dim rightRoot = SyntaxFactory.ParseSyntaxTree(" +Imports System; + +Class C + Public Sub M() + If 0 = 1 Then + If 2 = 3 Then + Console.WriteLine(0) + Console.WriteLine(1) + Console.WriteLine(2) + Console.WriteLine(3) + End If + End If + End Sub +End Class +").GetRoot() + + Dim leftNode As SyntaxNode = Nothing + Dim rightNodeOpt As SyntaxNode = Nothing + SyntaxUtilities.FindLeafNodeAndPartner(leftRoot, leftPosition, rightRoot, leftNode, rightNodeOpt) + Assert.Equal("3", leftNode.ToString()) + Assert.Null(rightNodeOpt) + End Sub End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb b/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb index 1ef393eda43cc46cd292b90e54523219247b1972..a1e1dc9118cea2e9729297238fa91f4c9e17e5c4 100644 --- a/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb @@ -1745,6 +1745,31 @@ End Class]]>.NormalizedValue(), Text("cref.")))) End Function + + Public Async Function TestIntegerLiteral() As Task + Await TestInMethodAsync("Dim f = 37$$", + MainDescription("Structure System.Int32")) + End Function + + + Public Async Function TestTrueKeyword() As Task + Await TestInMethodAsync("Dim f = True$$", + MainDescription("Structure System.Boolean")) + End Function + + + Public Async Function TestFalseKeyword() As Task + Await TestInMethodAsync("Dim f = False$$", + MainDescription("Structure System.Boolean")) + End Function + + + + Public Async Function TestNothingLiteral() As Task + Await TestInMethodAsync("Dim f As String = Nothing$$", + MainDescription("Class System.String")) + End Function + ''' ''' As a part of fix for 756226, quick info for VB Await keyword now displays the type inferred from the AwaitExpression. This is C# behavior. ''' In Dev12, quick info for VB Await keyword was the syntactic help "Await <expression>". diff --git a/src/Features/CSharp/Portable/EditAndContinue/SyntaxUtilities.cs b/src/Features/CSharp/Portable/EditAndContinue/SyntaxUtilities.cs index f056d9ab1032f268b747303654f8d6b9e9cc5a6e..8e66bb432f1c6b11864d48c8bf4d67f7ad3e68ee 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/SyntaxUtilities.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/SyntaxUtilities.cs @@ -114,20 +114,36 @@ public static void AssertIsBody(SyntaxNode syntax, bool allowLambda) Debug.Assert(false); } - public static void FindLeafNodeAndPartner(SyntaxNode leftRoot, int leftPosition, SyntaxNode rightRoot, out SyntaxNode leftNode, out SyntaxNode rightNode) + public static void FindLeafNodeAndPartner(SyntaxNode leftRoot, int leftPosition, SyntaxNode rightRoot, out SyntaxNode leftNode, out SyntaxNode rightNodeOpt) { leftNode = leftRoot; - rightNode = rightRoot; + rightNodeOpt = rightRoot; while (true) { - Debug.Assert(leftNode.RawKind == rightNode.RawKind); + if (rightNodeOpt != null && leftNode.RawKind != rightNodeOpt.RawKind) + { + rightNodeOpt = null; + } + var leftChild = leftNode.ChildThatContainsPosition(leftPosition, out var childIndex); if (leftChild.IsToken) { return; } - rightNode = rightNode.ChildNodesAndTokens()[childIndex].AsNode(); + if (rightNodeOpt != null) + { + var rightNodeChildNodesAndTokens = rightNodeOpt.ChildNodesAndTokens(); + if (childIndex >= 0 && childIndex < rightNodeChildNodesAndTokens.Count) + { + rightNodeOpt = rightNodeChildNodesAndTokens[childIndex].AsNode(); + } + else + { + rightNodeOpt = null; + } + } + leftNode = leftChild.AsNode(); } } diff --git a/src/Features/CSharp/Portable/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs b/src/Features/CSharp/Portable/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs index 78f9d36bd5251fa76ba5076243d8160f854d60ff..9999c6058a3ac4f2148512e2e9c314b07e59c974 100644 --- a/src/Features/CSharp/Portable/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Composition; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.CodeStyle; @@ -12,9 +13,13 @@ namespace Microsoft.CodeAnalysis.CSharp.OrderModifiers [ExportCodeFixProvider(LanguageNames.CSharp), Shared] internal class CSharpOrderModifiersCodeFixProvider : AbstractOrderModifiersCodeFixProvider { + private const string CS0267 = nameof(CS0267); // The 'partial' modifier can only appear immediately before 'class', 'struct', 'interface', or 'void' + public CSharpOrderModifiersCodeFixProvider() : base(CSharpSyntaxFactsService.Instance, CSharpCodeStyleOptions.PreferredModifierOrder, CSharpOrderModifiersHelper.Instance) { } + + protected override ImmutableArray FixableCompilerErrorIds { get; } = ImmutableArray.Create(CS0267); } } diff --git a/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs b/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs index 0c062bebe51b9206dfa0354477dcd7cd60445d9b..badae74a2a5cbb8e208aceaad1e2174ca284f319 100644 --- a/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs +++ b/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs @@ -33,15 +33,22 @@ internal abstract class AbstractOrderModifiersCodeFixProvider : SyntaxEditorBase _helpers = helpers; } - public override ImmutableArray FixableDiagnosticIds { get; } = - ImmutableArray.Create(IDEDiagnosticIds.OrderModifiersDiagnosticId); + protected abstract ImmutableArray FixableCompilerErrorIds { get; } - public override Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override ImmutableArray FixableDiagnosticIds + => FixableCompilerErrorIds.Add(IDEDiagnosticIds.OrderModifiersDiagnosticId); + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) { - context.RegisterCodeFix( - new MyCodeAction(c => FixAsync(context.Document, context.Diagnostics[0], c)), - context.Diagnostics); - return Task.CompletedTask; + var syntaxTree = await context.Document.GetSyntaxTreeAsync(context.CancellationToken).ConfigureAwait(false); + var syntaxNode = Location.Create(syntaxTree, context.Span).FindNode(context.CancellationToken); + + if (_syntaxFacts.GetModifiers(syntaxNode) != default) + { + context.RegisterCodeFix( + new MyCodeAction(c => FixAsync(context.Document, context.Diagnostics[0], c)), + context.Diagnostics); + } } protected override async Task FixAllAsync( diff --git a/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxUtilities.vb b/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxUtilities.vb index b6e7ec4bb56be856d7a36b86fbe938b36263f302..8b9574ef65126163a3dcad5200c6b1b83dbc9b4a 100644 --- a/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxUtilities.vb +++ b/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxUtilities.vb @@ -67,18 +67,29 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue leftPosition As Integer, rightRoot As SyntaxNode, ByRef leftNode As SyntaxNode, - ByRef rightNode As SyntaxNode) + ByRef rightNodeOpt As SyntaxNode) leftNode = leftRoot - rightNode = rightRoot + rightNodeOpt = rightRoot While True - Debug.Assert(leftNode.RawKind = rightNode.RawKind) + If rightNodeOpt IsNot Nothing AndAlso leftNode.RawKind <> rightNodeOpt.RawKind Then + rightNodeOpt = Nothing + End If + Dim childIndex As Integer = 0 Dim leftChild = leftNode.ChildThatContainsPosition(leftPosition, childIndex) If leftChild.IsToken Then Return End If - rightNode = rightNode.ChildNodesAndTokens()(childIndex).AsNode() + If rightNodeOpt IsNot Nothing Then + Dim rightNodeChildNodesAndTokens = rightNodeOpt.ChildNodesAndTokens() + If childIndex >= 0 AndAlso childIndex < rightNodeChildNodesAndTokens.Count Then + rightNodeOpt = rightNodeChildNodesAndTokens(childIndex).AsNode() + Else + rightNodeOpt = Nothing + End If + End If + leftNode = leftChild.AsNode() End While End Sub diff --git a/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb b/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb index ad28a5b566c5dc5b87eae11c6a44075c7e1cc1cc..bcd512c3b0b100c7e8473fd3a5501a1fc3dce2c1 100644 --- a/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb @@ -1,5 +1,6 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports System.Collections.Immutable Imports System.Composition Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.OrderModifiers @@ -15,5 +16,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.OrderModifiers VisualBasicCodeStyleOptions.PreferredModifierOrder, VisualBasicOrderModifiersHelper.Instance) End Sub + + Protected Overrides ReadOnly Property FixableCompilerErrorIds As ImmutableArray(Of String) = + ImmutableArray(Of String).Empty End Class End Namespace diff --git a/src/Test/Utilities/Portable/Compilation/ControlFlowGraphVerifier.cs b/src/Test/Utilities/Portable/Compilation/ControlFlowGraphVerifier.cs index 284d8b84aade2cde72401438a7d72fdc056f8342..06d586a3d5e75e241361cdc7d6060057a2fbda10 100644 --- a/src/Test/Utilities/Portable/Compilation/ControlFlowGraphVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/ControlFlowGraphVerifier.cs @@ -311,6 +311,8 @@ public static string GetFlowGraph(Compilation compilation, ControlFlowGraph grap { ControlFlowGraph g = localFunctionsMap[m]; Assert.Same(g, graph.GetLocalFunctionControlFlowGraph(m)); + Assert.Same(g, graph.GetLocalFunctionControlFlowGraphInScope(m)); + Assert.Same(graph, g.Parent); } Assert.Equal(graph.LocalFunctions.Length, localFunctionsMap.Count); @@ -318,6 +320,8 @@ public static string GetFlowGraph(Compilation compilation, ControlFlowGraph grap foreach (KeyValuePair pair in anonymousFunctionsMap) { Assert.Same(pair.Value, graph.GetAnonymousFunctionControlFlowGraph(pair.Key)); + Assert.Same(pair.Value, graph.GetAnonymousFunctionControlFlowGraphInScope(pair.Key)); + Assert.Same(graph, pair.Value.Parent); } bool doCaptureVerification = true; diff --git a/src/Tools/MicroBuild/Build.proj b/src/Tools/MicroBuild/Build.proj deleted file mode 100644 index dbaf0b36f3a697cf87fc6de7b9a627286d91afe8..0000000000000000000000000000000000000000 --- a/src/Tools/MicroBuild/Build.proj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - Debug - - -release - $(ScriptArgs) -branch $(BUILD_SOURCEBRANCH) - $(ScriptArgs) -myGetApiKey $(RoslynNuGetApiKey) - $(ScriptArgs) -gitHubUserName $(RoslynGitHubUserName) -gitHubToken $(RoslynGitHubToken) -gitHubEmail $(RoslynGitHubEmail) - $(ScriptArgs) -testDesktop - $(ScriptArgs) -signType "real" - $(ScriptArgs) -signType "test" - $(ScriptArgs) -publishType "vsts" - $(ScriptArgs) -publishType "blob" - $(ScriptArgs) -blobFeedUrl $(PB_PublishBlobFeedUrl) -blobFeedKey $(PB_PublishBlobFeedKey) - - - - - - - <_PublishProps Include="Configuration=$(Configuration)"/> - <_PublishProps Include="ContinuousIntegrationBuild=true"/> - <_PublishProps Include="AzureFeedUrl=$(PB_PublishBlobFeedUrl)" Condition="'$(PB_PublishType)' == 'blob'" /> - <_PublishProps Include="AzureAccountKey=$(PB_PublishBlobFeedKey)" Condition="'$(PB_PublishType)' == 'blob'" /> - - - - - - diff --git a/src/Tools/MicroBuild/cibuild.cmd b/src/Tools/MicroBuild/cibuild.cmd index 04f7575d0c57a83d676de3475fc7bf9d342bb5ff..550fc53fff3e929264b42b5d6300ae8545779f99 100644 --- a/src/Tools/MicroBuild/cibuild.cmd +++ b/src/Tools/MicroBuild/cibuild.cmd @@ -1 +1 @@ -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\microbuild.ps1" -release +REM stub file (remove once netci.groovy is updated) \ No newline at end of file diff --git a/src/Tools/MicroBuild/microbuild.ps1 b/src/Tools/MicroBuild/microbuild.ps1 deleted file mode 100644 index 2f673302bb51b71f24c407587f26c03e4a57c3d9..0000000000000000000000000000000000000000 --- a/src/Tools/MicroBuild/microbuild.ps1 +++ /dev/null @@ -1,99 +0,0 @@ -[CmdletBinding(PositionalBinding=$false)] -param ( - [switch]$release = $false, - [switch]$official = $false, - [string]$branchName = "master", - [switch]$testDesktop = $false, - [string]$publishType = "", - [switch]$help = $false, - [string]$signType = "", - - # Credentials - [string]$myGetApiKey = "", - [string]$nugetApiKey = "", - [string]$gitHubUserName = "", - [string]$gitHubToken = "", - [string]$gitHubEmail = "", - [string]$blobFeedUrl = "", - [string]$blobFeedKey = "", - [parameter(ValueFromRemainingArguments=$true)] $badArgs) - -Set-StrictMode -version 2.0 -$ErrorActionPreference = "Stop" - -function Print-Usage() { - Write-Host "Usage: build.ps1" - Write-Host " -release Perform release build (default is debug)" - Write-Host " -official Perform an official build" - Write-Host " -testDesktop Run unit tests" - Write-Host " -publishType Publish to run: vsts, blob or none (default is none)" - Write-Host " -branchName Branch being built" - Write-Host " -nugetApiKey Key for NuGet publishing" - Write-Host " -signType Signing type: real, test or public (default is public)" - Write-Host " -help Print this message" -} - -Push-Location $PSScriptRoot -try { - . (Join-Path $PSScriptRoot "..\..\..\build\scripts\build-utils.ps1") - if ($badArgs -ne $null) { - Write-Host "Unsupported argument $badArgs" - Print-Usage - exit 1 - } - - if ($help) { - Print-Usage - exit 1 - } - - # On Jenkins runs we deliberately run microbuild with a clean NuGet cache. This means at least - # one job runs with a clean cache and assures all packages we depend on are restored during - # the restore phase. As opposed to getting lucky based on a NuGet being available in the cache. - if (-not $official) { - Clear-PackageCache - } - - $scriptDir = Join-Path $repoDir "build\scripts" - $config = if ($release) { "Release" } else { "Debug" } - $configDir = Join-Path $binariesDir $config - $setupDir = Join-Path $repoDir "src\Setup" - - Exec-Block { & (Join-Path $scriptDir "build.ps1") -restore:$true -build -cibuild:$true -official:$official -release:$release -sign -signType $signType -pack -testDesktop:$testDesktop -binaryLog -procdump } - - Get-Process vbcscompiler -ErrorAction SilentlyContinue | Stop-Process - - switch ($publishType) { - "vsts" { - Exec-Block { & .\publish-assets.ps1 -config $config -branchName $branchName -mygetApiKey $mygetApiKey -nugetApiKey $nugetApiKey -gitHubUserName $githubUserName -gitHubToken $gitHubToken -gitHubEmail $gitHubEmail -test:$(-not $official) } - break; - } - "blob" { - # This is handled by the Build.proj file directly - break; - } - "" { - # Explicit don't publish - break; - } - default { - throw "Unexpected publish type: $publishType" - break; - } - } - - exit 0 -} -catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 -} -finally { - Pop-Location - if (-not $official) { - Get-Process msbuild -ErrorAction SilentlyContinue | Stop-Process - Get-Process vbcscompiler -ErrorAction SilentlyContinue | Stop-Process - } -} \ No newline at end of file diff --git a/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProjectOptionsHelper.vb b/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProjectOptionsHelper.vb index 99212dde0cbc49069b8deb1e549f91ce8dc45091..0a17dd37de22846fd0ccac960e0aea4b5e87e974 100644 --- a/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProjectOptionsHelper.vb +++ b/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProjectOptionsHelper.vb @@ -26,7 +26,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim Private Shared s_conditionalCompilationSymbolsCache As Dictionary(Of KeyValuePair(Of String, OutputKind), ImmutableArray(Of KeyValuePair(Of String, Object))) = New Dictionary(Of KeyValuePair(Of String, OutputKind), ImmutableArray(Of KeyValuePair(Of String, Object))) - Private Shared ReadOnly s_EmptyCommandLineArguments As VisualBasicCommandLineArguments = VisualBasicCommandLineParser.Default.Parse(SpecializedCollections.EmptyEnumerable(Of String)(), baseDirectory:="", sdkDirectory:=Nothing) + Private Shared ReadOnly s_EmptyCommandLineArguments As VisualBasicCommandLineArguments = VisualBasicCommandLineParser.Default.Parse(SpecializedCollections.EmptyEnumerable(Of String)(), baseDirectory:=Nothing, sdkDirectory:=Nothing) Public Shared Function CreateCompilationOptions(baseCompilationOptionsOpt As VisualBasicCompilationOptions, newParseOptions As VisualBasicParseOptions, diff --git a/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs b/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs index 9b944a872e50964433fcd71f9de94b42903b70d9..e4e6afdfc6756da7b21b3276130d2210ec3162e7 100644 --- a/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs +++ b/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs @@ -512,7 +512,8 @@ protected override bool ExpressionMightReferenceMember(SyntaxNode node) { return node.IsKind(SyntaxKind.InvocationExpression) || node.IsKind(SyntaxKind.ElementAccessExpression) || - node.IsKind(SyntaxKind.SimpleMemberAccessExpression); + node.IsKind(SyntaxKind.SimpleMemberAccessExpression) || + node.IsKind(SyntaxKind.ImplicitElementAccess); } protected override ImmutableArray GetArguments(ExpressionSyntax expression) diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs index 60a26e385ec6ff7da29938759bbd295b0370e3b4..2103b345f9bece1eefcba35b0ccfe6342a45ee9d 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs @@ -16,12 +16,13 @@ namespace Microsoft.CodeAnalysis.Shared.Extensions internal struct TokenSemanticInfo { public static readonly TokenSemanticInfo Empty = new TokenSemanticInfo( - null, null, ImmutableArray.Empty, null, default(TextSpan)); + null, null, ImmutableArray.Empty, null, null, default(TextSpan)); public readonly ISymbol DeclaredSymbol; public readonly IAliasSymbol AliasSymbol; public readonly ImmutableArray ReferencedSymbols; public readonly ITypeSymbol Type; + public readonly ITypeSymbol ConvertedType; public readonly TextSpan Span; public TokenSemanticInfo( @@ -29,12 +30,14 @@ internal struct TokenSemanticInfo IAliasSymbol aliasSymbol, ImmutableArray referencedSymbols, ITypeSymbol type, + ITypeSymbol convertedType, TextSpan span) { DeclaredSymbol = declaredSymbol; AliasSymbol = aliasSymbol; ReferencedSymbols = referencedSymbols; Type = type; + ConvertedType = convertedType; Span = span; } @@ -47,7 +50,7 @@ public ImmutableArray GetSymbols(bool includeType) if (includeType) { - result.AddIfNotNull(Type); + result.AddIfNotNull(Type ?? ConvertedType); } return result.ToImmutableAndFree(); @@ -179,6 +182,7 @@ private static ISymbol MapSymbol(ISymbol symbol, ITypeSymbol type) { IAliasSymbol aliasSymbol; ITypeSymbol type; + ITypeSymbol convertedType; ISymbol declaredSymbol; ImmutableArray allSymbols; @@ -192,6 +196,7 @@ private static ISymbol MapSymbol(ISymbol symbol, ITypeSymbol type) // on an "override" token, the overridden symbol is the only part of TokenSemanticInfo used by callers, so type doesn't matter type = null; + convertedType = null; declaredSymbol = null; allSymbols = overriddenSymbol is null ? ImmutableArray.Empty : ImmutableArray.Create(overriddenSymbol); } @@ -199,7 +204,9 @@ private static ISymbol MapSymbol(ISymbol symbol, ITypeSymbol type) { aliasSymbol = semanticModel.GetAliasInfo(token.Parent, cancellationToken); var bindableParent = syntaxFacts.GetBindableParent(token); - type = semanticModel.GetTypeInfo(bindableParent, cancellationToken).Type; + var typeInfo = semanticModel.GetTypeInfo(bindableParent, cancellationToken); + type = typeInfo.Type; + convertedType = typeInfo.ConvertedType; declaredSymbol = MapSymbol(semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken), type); var skipSymbolInfoLookup = declaredSymbol.IsKind(SymbolKind.RangeVariable); @@ -238,9 +245,10 @@ private static ISymbol MapSymbol(ISymbol symbol, ITypeSymbol type) if (allSymbols.Length == 0 && syntaxFacts.IsQueryKeyword(token)) { type = null; + convertedType = null; } - return new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type, token.Span); + return new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type, convertedType, token.Span); } public static SemanticModel GetOriginalSemanticModel(this SemanticModel semanticModel)