diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index a1ba7ab156..6687fb4088 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -11,8 +11,7 @@ $(RepoRoot)src $(ArtifactsDir)\SymStore - $(ArtifactsDir)\Bootstrap - $(ArtifactsDir)/fsc/Proto/netcoreapp2.1 + $(ArtifactsDir)\Bootstrap 4.4.0 1182;0025;$(WarningsAsErrors) @@ -76,6 +75,7 @@ https://github.com/Microsoft/visualfsharp git + <_DotGitDir>$(RepoRoot).git <_HeadFileContent Condition="Exists('$(_DotGitDir)/HEAD')">$([System.IO.File]::ReadAllText('$(_DotGitDir)/HEAD').Trim()) @@ -88,7 +88,7 @@ $(NoWarn);FS2003 true - portable + embedded fs false true @@ -96,10 +96,10 @@ - $(ProtoOutputPath)\Microsoft.FSharp.Targets - $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.props - $(ProtoOutputPath)\Microsoft.FSharp.NetSdk.targets - $(ProtoOutputPath)\Microsoft.FSharp.Overrides.NetSdk.targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.Targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.NetSdk.props + $(ProtoOutputPath)\fsc\Microsoft.FSharp.NetSdk.targets + $(ProtoOutputPath)\fsc\Microsoft.FSharp.Overrides.NetSdk.targets diff --git a/FSharpTests.Directory.Build.props b/FSharpTests.Directory.Build.props new file mode 100644 index 0000000000..8a7a832a43 --- /dev/null +++ b/FSharpTests.Directory.Build.props @@ -0,0 +1,47 @@ + + + + true + + + + true + + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\net472 + fsc.exe + + + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\net472 + fsi.exe + + + + + true + + $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) + dotnet.exe + dotnet + $(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\netcoreapp2.1\fsc.exe + + $([System.IO.Path]::GetDirectoryName('$(DOTNET_HOST_PATH)')) + dotnet.exe + dotnet + $(MSBuildThisFileDirectory)artifacts\bin\fsi\$(Configuration)\netcoreapp2.1\fsi.exe + + + + + <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'!='Core'">net472 + <_FSharpBuildTargetFramework Condition="'$(MSBuildRuntimeType)'=='Core'">netcoreapp2.1 + <_FSharpBuildBinPath>$(MSBuildThisFileDirectory)artifacts\bin\fsc\$(Configuration)\$(_FSharpBuildTargetFramework) + + $(_FSharpBuildBinPath)\FSharp.Build.dll + + $(_FSharpBuildBinPath)/Microsoft.FSharp.Targets + $(_FSharpBuildBinPath)/Microsoft.FSharp.NetSdk.props + $(_FSharpBuildBinPath)/Microsoft.FSharp.NetSdk.targets + $(_FSharpBuildBinPath)/Microsoft.FSharp.Overrides.NetSdk.targets + + + diff --git a/NuGet.config b/NuGet.config index fdf6d3eda4..df85afb048 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,4 +1,4 @@ - + @@ -8,6 +8,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/RoslynPackageVersion.txt b/RoslynPackageVersion.txt index fd1d6f6d9b..2b54870d02 100644 --- a/RoslynPackageVersion.txt +++ b/RoslynPackageVersion.txt @@ -1 +1 @@ -3.1.0-beta3-19222-02 +3.2.0-beta4-19312-15 \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2207a4792e..0000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,306 +0,0 @@ -# CI and PR triggers -trigger: -- master -- dev16.1 -- feature/* -- release/* -pr: -- master -- dev16.1 -- feature/* -- release/* - -variables: - - name: _TeamName - value: FSharp - - name: _BuildConfig - value: Release - - name: _PublishUsingPipelines - value: true - - name: _DotNetArtifactsCategory - value: .NETCore - - name: VisualStudioDropName - value: Products/$(System.TeamProject)/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber) - -# Variables defined in yml cannot be overridden at queue time; instead overridable variables must be defined in the web UI. -# Commenting out until something like this is supported: https://github.com/Microsoft/azure-pipelines-yaml/pull/129 -#variables: -#- name: SkipTests -# defaultValue: false - -jobs: - -#---------------------------------------------------------------------------------------------------------------------# -# Signed build # -#---------------------------------------------------------------------------------------------------------------------# -- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - template: /eng/common/templates/jobs/jobs.yml - parameters: - enableMicrobuild: true - enablePublishBuildArtifacts: true - enablePublishTestResults: false - enablePublishBuildAssets: true - enablePublishUsingPipelines: $(_PublishUsingPipelines) - enableTelemetry: true - helixRepo: dotnet/fsharp - jobs: - - job: Full_Signed - pool: - name: NetCoreInternal-Int-Pool - queue: buildpool.windows.10.amd64.vs2019 - timeoutInMinutes: 300 - variables: - - group: DotNet-Blob-Feed - - group: DotNet-Symbol-Server-Pats - - name: _SignType - value: Real - - name: _DotNetPublishToBlobFeed - value: true - steps: - - checkout: self - clean: true - - script: eng\CIBuild.cmd - -configuration $(_BuildConfig) - -prepareMachine - -testAll - -officialSkipTests $(SkipTests) - /p:SignType=$(_SignType) - /p:DotNetSignType=$(_SignType) - /p:MicroBuild_SigningEnabled=true - /p:OverridePackageSource=https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json - /p:TeamName=$(_TeamName) - /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) - /p:DotNetPublishBlobFeedUrl=https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json - /p:DotNetPublishToBlobFeed=true - /p:DotNetPublishUsingPipelines=$(_PublishUsingPipelines) - /p:DotNetArtifactsCategory=$(_DotNetArtifactsCategory) - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - /p:PublishToSymbolServer=true - /p:VisualStudioDropName=$(VisualStudioDropName) - - task: PublishTestResults@2 - displayName: Publish Test Results - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - continueOnError: true - condition: ne(variables['SkipTests'], 'true') - - task: PublishBuildArtifacts@1 - displayName: Publish Test Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\artifacts\TestResults\$(_BuildConfig)' - ArtifactName: 'Test Logs' - publishLocation: Container - continueOnError: true - condition: ne(variables['SkipTests'], 'true') - - task: PublishBuildArtifacts@1 - displayName: Publish Artifact Packages - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\artifacts\packages\$(_BuildConfig)' - ArtifactName: 'Packages' - condition: succeeded() - - task: PublishBuildArtifacts@1 - displayName: Publish Artifact VSSetup - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\artifacts\VSSetup\$(_BuildConfig)\Insertion' - ArtifactName: 'VSSetup' - condition: succeeded() - - task: PublishBuildArtifacts@1 - displayName: Publish Artifact Nightly - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\artifacts\VSSetup\$(_BuildConfig)\VisualFSharpFull.vsix' - ArtifactName: 'Nightly' - condition: succeeded() - -#---------------------------------------------------------------------------------------------------------------------# -# PR builds # -#---------------------------------------------------------------------------------------------------------------------# -- ${{ if eq(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates/jobs/jobs.yml - parameters: - enableMicrobuild: true - enablePublishBuildArtifacts: true - enablePublishTestResults: false - enablePublishBuildAssets: true - enablePublishUsingPipelines: $(_PublishUsingPipelines) - enableTelemetry: true - helixRepo: dotnet/fsharp - jobs: - - # Windows - - job: Windows - pool: - vmImage: windows-2019 - timeoutInMinutes: 120 - strategy: - maxParallel: 4 - matrix: - desktop_release: - _configuration: Release - _testKind: testDesktop - coreclr_release: - _configuration: Release - _testKind: testCoreclr - fsharpqa_release: - _configuration: Release - _testKind: testFSharpQA - vs_release: - _configuration: Release - _testKind: testVs - steps: - - checkout: self - clean: true - - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) - displayName: Build / Test - - task: PublishTestResults@2 - displayName: Publish Test Results - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_configuration)' - continueOnError: true - condition: ne(variables['_testKind'], 'testFSharpQA') - - task: PublishBuildArtifacts@1 - displayName: Publish Test Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\artifacts\TestResults\$(_configuration)' - ArtifactName: 'Windows $(_configuration) $(_testKind) test logs' - publishLocation: Container - continueOnError: true - condition: eq(variables['_testKind'], 'testFSharpQA') - - # Linux - - job: Linux - pool: - vmImage: ubuntu-16.04 - variables: - - name: _SignType - value: Test - steps: - - checkout: self - clean: true - - script: ./eng/cibuild.sh --configuration $(_BuildConfig) --testcoreclr - displayName: Build / Test - - task: PublishTestResults@2 - displayName: Publish Test Results - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - continueOnError: true - condition: always() - - # MacOS - - job: MacOS - pool: - vmImage: macOS-10.13 - variables: - - name: _SignType - value: Test - steps: - - checkout: self - clean: true - - script: ./eng/cibuild.sh --configuration $(_BuildConfig) --testcoreclr - displayName: Build / Test - - task: PublishTestResults@2 - displayName: Publish Test Results - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - continueOnError: true - condition: always() - - # Source Build Linux - - job: SourceBuild_Linux - pool: - vmImage: ubuntu-16.04 - steps: - - checkout: self - clean: true - - script: ./eng/cibuild.sh --configuration Release /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true - displayName: Build - - # Source Build Windows - - job: SourceBuild_Windows - pool: - vmImage: windows-2019 - steps: - - checkout: self - clean: true - - script: eng\CIBuild.cmd -configuration Release -noSign /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true - displayName: Build - - # Up-to-date - - job: UpToDate_Windows - pool: - vmImage: windows-2019 - steps: - - checkout: self - clean: true - - task: PowerShell@2 - displayName: Run up-to-date build check - inputs: - filePath: eng\tests\UpToDate.ps1 - arguments: -configuration $(_BuildConfig) -ci -binaryLog - -#---------------------------------------------------------------------------------------------------------------------# -# FCS builds # -#---------------------------------------------------------------------------------------------------------------------# - -- ${{ if eq(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates/jobs/jobs.yml - parameters: - enableMicrobuild: true - enablePublishTestResults: false - enablePublishBuildAssets: true - enablePublishUsingPipelines: false - enableTelemetry: true - helixRepo: dotnet/fsharp - jobs: - - - job: Windows_FCS - pool: - vmImage: windows-2019 - variables: - - name: _SignType - value: Test - steps: - - checkout: self - clean: true - - script: fcs\build.cmd TestAndNuget - displayName: Build / Test - - task: PublishTestResults@2 - displayName: Publish Test Results - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' - continueOnError: true - condition: always() - - - job: Linux_FCS - pool: - vmImage: ubuntu-16.04 - variables: - - name: _SignType - value: Test - steps: - - checkout: self - clean: true - - script: ./fcs/build.sh Build - displayName: Build - - - job: MacOS_FCS - pool: - vmImage: macOS-10.13 - variables: - - name: _SignType - value: Test - steps: - - checkout: self - clean: true - - script: ./fcs/build.sh Build - displayName: Build diff --git a/eng/Build.ps1 b/eng/Build.ps1 index ac5675ae7e..75f0178b7d 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -69,6 +69,7 @@ function Print-Usage() { Write-Host "" Write-Host "Actions:" Write-Host " -restore Restore packages (short: -r)" + Write-Host " -norestore Don't restore packages" Write-Host " -build Build main solution (short: -b)" Write-Host " -rebuild Rebuild main solution" Write-Host " -pack Build NuGet packages, VS insertion manifests and installer" @@ -108,6 +109,7 @@ function Process-Arguments() { Print-Usage exit 0 } + $script:nodeReuse = $False; if ($testAll) { $script:testDesktop = $True @@ -172,7 +174,7 @@ function BuildSolution() { $officialBuildId = if ($official) { $env:BUILD_BUILDNUMBER } else { "" } $toolsetBuildProj = InitializeToolset $quietRestore = !$ci - $testTargetFrameworks = if ($testCoreClr) { "netcoreapp2.1" } else { "" } + $testTargetFrameworks = if ($testCoreClr) { "netcoreapp3.0" } else { "" } # Do not set the property to true explicitly, since that would override value projects might set. $suppressExtensionDeployment = if (!$deployExtensions) { "/p:DeployExtension=false" } else { "" } @@ -190,7 +192,6 @@ function BuildSolution() { /p:Publish=$publish ` /p:ContinuousIntegrationBuild=$ci ` /p:OfficialBuildId=$officialBuildId ` - /p:BootstrapBuildPath=$bootstrapDir ` /p:QuietRestore=$quietRestore ` /p:QuietRestoreBinaryLog=$binaryLog ` /p:TestTargetFrameworks=$testTargetFrameworks ` @@ -223,13 +224,14 @@ function UpdatePath() { TestAndAddToPath "$ArtifactsDir\bin\fsiAnyCpu\$configuration\net472" } -function VerifyAssemblyVersions() { - $fsiPath = Join-Path $ArtifactsDir "bin\fsi\Proto\net472\fsi.exe" +function VerifyAssemblyVersionsAndSymbols() { + $assemblyVerCheckPath = Join-Path $ArtifactsDir "Bootstrap\AssemblyCheck\AssemblyCheck.dll" # Only verify versions on CI or official build if ($ci -or $official) { - $asmVerCheckPath = "$RepoRoot\scripts" - Exec-Console $fsiPath """$asmVerCheckPath\AssemblyVersionCheck.fsx"" -- ""$ArtifactsDir""" + $dotnetPath = InitializeDotNetCli + $dotnetExe = Join-Path $dotnetPath "dotnet.exe" + Exec-Console $dotnetExe """$assemblyVerCheckPath"" ""$ArtifactsDir""" } } @@ -275,6 +277,25 @@ function Prepare-TempDir() { Copy-Item (Join-Path $RepoRoot "tests\Resources\Directory.Build.targets") $TempDir } +function EnablePreviewSdks() { + if (Test-Path variable:global:_MSBuildExe) { + return + } + $vsInfo = LocateVisualStudio + if ($vsInfo -eq $null) { + # Preview SDKs are allowed when no Visual Studio instance is installed + return + } + + $vsId = $vsInfo.instanceId + $vsMajorVersion = $vsInfo.installationVersion.Split('.')[0] + + $instanceDir = Join-Path ${env:USERPROFILE} "AppData\Local\Microsoft\VisualStudio\$vsMajorVersion.0_$vsId" + Create-Directory $instanceDir + $sdkFile = Join-Path $instanceDir "sdk.txt" + 'UsePreviews=True' | Set-Content $sdkFile +} + try { Process-Arguments @@ -286,8 +307,9 @@ try { if ($ci) { Prepare-TempDir + EnablePreviewSdks - # enable us to build netcoreapp2.1 binaries + # enable us to build netcoreapp2.1 product binaries $global:_DotNetInstallDir = Join-Path $RepoRoot ".dotnet" InstallDotNetSdk $global:_DotNetInstallDir $GlobalJson.tools.dotnet InstallDotNetSdk $global:_DotNetInstallDir "2.1.503" @@ -306,11 +328,11 @@ try { } if ($build) { - VerifyAssemblyVersions + VerifyAssemblyVersionsAndSymbols } $desktopTargetFramework = "net472" - $coreclrTargetFramework = "netcoreapp2.1" + $coreclrTargetFramework = "netcoreapp3.0" if ($testDesktop -and -not $noVisualStudio) { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 309516901a..848ec45335 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 9946534da4f73e6242ca105f6798ab58119c9ab0 + e2f5f0f5c20a1fef71845795b09066a5cd892a7e diff --git a/eng/Versions.props b/eng/Versions.props index 5b4d32757a..4a8ca4fbc4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,14 +23,14 @@ $(FSCorePackageVersion)-$(PreReleaseVersionLabel).* - 10.4 - $(FSPackageMajorVersion).3 + 10.5 + $(FSPackageMajorVersion).0 $(FSPackageVersion) $(FSPackageVersion).0 16 - 0 + 2 $(VSMajorVersion).0 $(VSMajorVersion).$(VSMinorVersion).0 $(VSAssemblyVersionPrefix).0 @@ -44,21 +44,6 @@ $(VersionPrefix).0 - - - <_BuildNumber>$(OfficialBuildId) - <_BuildNumber Condition="'$(OfficialBuildId)' == ''">$([System.DateTime]::Now.ToString(yyyyMMdd)).0 - $(_BuildNumber.Split('.')[0]) - $(VSMajorVersion).$(VSMinorVersion).$(VsixVersionDateStampFix) - @@ -70,6 +55,7 @@ https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json; https://api.nuget.org/v3/index.json; https://dotnet.myget.org/F/roslyn/api/v3/index.json; + https://dotnet.myget.org/F/roslyn-analyzers/api/v3/index.json; https://dotnet.myget.org/F/symreader-converter/api/v3/index.json; https://dotnet.myget.org/F/interactive-window/api/v3/index.json; https://myget.org/F/vs-devcore/api/v3/index.json; @@ -112,7 +98,10 @@ $(RoslynVersion) $(RoslynVersion) $(RoslynVersion) + $(RoslynVersion) $(RoslynVersion) + $(RoslynVersion) + 2.0.17 $(RoslynVersion) 16.0.461 @@ -179,7 +168,8 @@ 1.0.30 8.0.0-alpha 2.7.0 - 2.0.3 + 3.0.0-preview-27318-01 + 3.0.0-preview-27318-01 15.8.0 1.0.0 4.3.0 diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index efb7b761a5..772de110ca 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -178,7 +178,7 @@ function Get-PackageDir([string]$name, [string]$version = "") { return $p } -function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [switch]$parallel = $true, [switch]$summary = $true, [switch]$warnAsError = $true, [string]$configuration = $script:configuration) { +function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [switch]$parallel = $true, [switch]$summary = $true, [switch]$warnAsError = $true, [string]$configuration = $script:configuration, [string]$verbosity = $script:verbosity) { # Because we override the C#/VB toolset to build against our LKG package, it is important # that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise, # we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211. @@ -216,10 +216,6 @@ function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string] $args += " /p:ContinuousIntegrationBuild=true" } - if ($bootstrapDir -ne "") { - $args += " /p:BootstrapBuildPath=$bootstrapDir" - } - $args += " $buildArgs" $args += " $projectFilePath" $args += " $properties" @@ -240,10 +236,11 @@ function Make-BootstrapBuild() { Remove-Item -re $dir -ErrorAction SilentlyContinue Create-Directory $dir - # prepare FsLex and Fsyacc - Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Build" -logFileName "BuildTools" -configuration $bootstrapConfiguration - Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\*" -Destination $dir - Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\*" -Destination $dir + # prepare FsLex and Fsyacc and AssemblyCheck + Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration + Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fslex" -Force -Recurse + Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fsyacc" -Force -Recurse + Copy-Item "$ArtifactsDir\bin\AssemblyCheck\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\AssemblyCheck" -Force -Recurse # prepare compiler $projectPath = "$RepoRoot\proto.proj" diff --git a/eng/build.sh b/eng/build.sh index e1fa618cec..e806856c55 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -13,7 +13,9 @@ usage() echo " --binaryLog Create MSBuild binary log (short: -bl)" echo "" echo "Actions:" + echo " --bootstrap Force the build of the bootstrap compiler" echo " --restore Restore projects required to build (short: -r)" + echo " --norestore Don't restore projects required to build" echo " --build Build all projects (short: -b)" echo " --rebuild Rebuild all projects" echo " --pack Build nuget packages" @@ -54,6 +56,7 @@ test_core_clr=false configuration="Debug" verbosity='minimal' binary_log=false +force_bootstrap=false ci=false skip_analyzers=false prepare_machine=false @@ -88,6 +91,9 @@ while [[ $# > 0 ]]; do --binarylog|-bl) binary_log=true ;; + --bootstrap) + force_bootstrap=true + ;; --restore|-r) restore=true ;; @@ -209,17 +215,33 @@ function BuildSolution { quiet_restore=true fi + # Node reuse fails because multiple different versions of FSharp.Build.dll get loaded into MSBuild nodes + node_reuse=false + # build bootstrap tools bootstrap_config=Proto - MSBuild "$repo_root/src/buildtools/buildtools.proj" \ - /restore \ - /p:Configuration=$bootstrap_config \ - /t:Build - bootstrap_dir=$artifacts_dir/Bootstrap - mkdir -p "$bootstrap_dir" - cp $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir - cp $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.1/* $bootstrap_dir + if [[ "$force_bootstrap" == true ]]; then + rm -fr $bootstrap_dir + fi + if [ ! -f "$bootstrap_dir/fslex.dll" ]; then + MSBuild "$repo_root/src/buildtools/buildtools.proj" \ + /restore \ + /p:Configuration=$bootstrap_config \ + /t:Publish + + mkdir -p "$bootstrap_dir" + cp -pr $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fslex + cp -pr $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fsyacc + fi + if [ ! -f "$bootstrap_dir/fsc.exe" ]; then + MSBuild "$repo_root/proto.proj" \ + /restore \ + /p:Configuration=$bootstrap_config \ + /t:Publish + + cp -pr $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp2.1/publish $bootstrap_dir/fsc + fi # do real build MSBuild $toolset_build_proj \ @@ -247,7 +269,7 @@ InstallDotNetSdk $_InitializeDotNetCli 2.1.503 BuildSolution if [[ "$test_core_clr" == true ]]; then - coreclrtestframework=netcoreapp2.1 + coreclrtestframework=netcoreapp3.0 TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclrtestframework diff --git a/eng/common/SigningValidation.proj b/eng/common/SigningValidation.proj index 7045fb6fb9..3d0ac80af3 100644 --- a/eng/common/SigningValidation.proj +++ b/eng/common/SigningValidation.proj @@ -3,7 +3,7 @@ + + + $(WorkItemDirectory) + $(WorkItemCommand) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --artifacts $(ArtifactsDirectory) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" + 4:00 + + + + + $(WorkItemDirectory) + $(WorkItemCommand) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --artifacts $(ArtifactsDirectory)" + 4:00 + + + \ No newline at end of file diff --git a/eng/common/performance/performance-setup.ps1 b/eng/common/performance/performance-setup.ps1 new file mode 100644 index 0000000000..7e5441f797 --- /dev/null +++ b/eng/common/performance/performance-setup.ps1 @@ -0,0 +1,91 @@ +Param( + [string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY, + [string] $CoreRootDirectory, + [string] $Architecture="x64", + [string] $Framework="netcoreapp3.0", + [string] $CompilationMode="Tiered", + [string] $Repository=$env:BUILD_REPOSITORY_NAME, + [string] $Branch=$env:BUILD_SOURCEBRANCH, + [string] $CommitSha=$env:BUILD_SOURCEVERSION, + [string] $BuildNumber=$env:BUILD_BUILDNUMBER, + [string] $RunCategories="coreclr corefx", + [string] $Csproj="src\benchmarks\micro\MicroBenchmarks.csproj", + [string] $Kind="micro", + [switch] $Internal, + [string] $Configurations="CompilationMode=$CompilationMode" +) + +$RunFromPerformanceRepo = ($Repository -eq "dotnet/performance") +$UseCoreRun = ($CoreRootDirectory -ne [string]::Empty) + +$PayloadDirectory = (Join-Path $SourceDirectory "Payload") +$PerformanceDirectory = (Join-Path $PayloadDirectory "performance") +$WorkItemDirectory = (Join-Path $SourceDirectory "workitem") +$ExtraBenchmarkDotNetArguments = "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --stopOnFirstError true" +$Creator = $env:BUILD_DEFINITIONNAME +$PerfLabArguments = "" +$HelixSourcePrefix = "pr" + +$Queue = "Windows.10.Amd64.ClientRS4.DevEx.15.8.Open" + +if ($Framework.StartsWith("netcoreapp")) { + $Queue = "Windows.10.Amd64.ClientRS4.Open" +} + +if ($Internal) { + $Queue = "Windows.10.Amd64.ClientRS5.Perf" + $PerfLabArguments = "--upload-to-perflab-container" + $ExtraBenchmarkDotNetArguments = "" + $Creator = "" + $HelixSourcePrefix = "official" +} + +$CommonSetupArguments="--frameworks $Framework --queue $Queue --build-number $BuildNumber --build-configs $Configurations" +$SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments" + +if ($RunFromPerformanceRepo) { + $SetupArguments = "--perf-hash $CommitSha $CommonSetupArguments" + + robocopy $SourceDirectory $PerformanceDirectory /E /XD $PayloadDirectory $SourceDirectory\artifacts $SourceDirectory\.git +} +else { + git clone --branch master --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory +} + +if ($UseCoreRun) { + $NewCoreRoot = (Join-Path $PayloadDirectory "Core_Root") + Move-Item -Path $CoreRootDirectory -Destination $NewCoreRoot +} + +$DocsDir = (Join-Path $PerformanceDirectory "docs") +robocopy $DocsDir $WorkItemDirectory + +# Set variables that we will need to have in future steps +$ci = $true + +. "$PSScriptRoot\..\pipeline-logging-functions.ps1" + +# Directories +Write-PipelineSetVariable -Name 'PayloadDirectory' -Value "$PayloadDirectory" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'PerformanceDirectory' -Value "$PerformanceDirectory" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'WorkItemDirectory' -Value "$WorkItemDirectory" -IsMultiJobVariable $false + +# Script Arguments +Write-PipelineSetVariable -Name 'Python' -Value "py -3" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'ExtraBenchmarkDotNetArguments' -Value "$ExtraBenchmarkDotNetArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'SetupArguments' -Value "$SetupArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'PerfLabArguments' -Value "$PerfLabArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'BDNCategories' -Value "$RunCategories" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'TargetCsproj' -Value "$Csproj" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Kind' -Value "$Kind" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Architecture' -Value "$Architecture" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'UseCoreRun' -Value "$UseCoreRun" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'RunFromPerfRepo' -Value "$RunFromPerformanceRepo" -IsMultiJobVariable $false + +# Helix Arguments +Write-PipelineSetVariable -Name 'Creator' -Value "$Creator" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Queue' -Value "$Queue" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'HelixSourcePrefix' -Value "$HelixSourcePrefix" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name '_BuildConfig' -Value "$Architecture.$Kind.$Framework" -IsMultiJobVariable $false + +exit 0 \ No newline at end of file diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh new file mode 100755 index 0000000000..126da5f76d --- /dev/null +++ b/eng/common/performance/performance-setup.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +source_directory=$BUILD_SOURCESDIRECTORY +core_root_directory= +architecture=x64 +framework=netcoreapp3.0 +compilation_mode=tiered +repository=$BUILD_REPOSITORY_NAME +branch=$BUILD_SOURCEBRANCH +commit_sha=$BUILD_SOURCEVERSION +build_number=$BUILD_BUILDNUMBER +internal=false +kind="micro" +run_categories="coreclr corefx" +csproj="src\benchmarks\micro\MicroBenchmarks.csproj" +configurations= +run_from_perf_repo=false +use_core_run=true + +while (($# > 0)); do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in + --sourcedirectory) + source_directory=$2 + shift 2 + ;; + --corerootdirectory) + core_root_directory=$2 + shift 2 + ;; + --architecture) + architecture=$2 + shift 2 + ;; + --framework) + framework=$2 + shift 2 + ;; + --compilationmode) + compilation_mode=$2 + shift 2 + ;; + --repository) + repository=$2 + shift 2 + ;; + --branch) + branch=$2 + shift 2 + ;; + --commitsha) + commit_sha=$2 + shift 2 + ;; + --buildnumber) + build_number=$2 + shift 2 + ;; + --kind) + kind=$2 + shift 2 + ;; + --runcategories) + run_categories=$2 + shift 2 + ;; + --csproj) + csproj=$2 + shift 2 + ;; + --internal) + internal=true + shift 1 + ;; + --configurations) + configurations=$2 + shift 2 + ;; + --help) + echo "Common settings:" + echo " --corerootdirectory Directory where Core_Root exists, if running perf testing with --corerun" + echo " --architecture Architecture of the testing being run" + echo " --configurations List of key=value pairs that will be passed to perf testing infrastructure." + echo " ex: --configurations \"CompilationMode=Tiered OptimzationLevel=PGO\"" + echo " --help Print help and exit" + echo "" + echo "Advanced settings:" + echo " --framework The framework to run, if not running in master" + echo " --compliationmode The compilation mode if not passing --configurations" + echo " --sourcedirectory The directory of the sources. Defaults to env:BUILD_SOURCESDIRECTORY" + echo " --repository The name of the repository in the / format. Defaults to env:BUILD_REPOSITORY_NAME" + echo " --branch The name of the branch. Defaults to env:BUILD_SOURCEBRANCH" + echo " --commitsha The commit sha1 to run against. Defaults to env:BUILD_SOURCEVERSION" + echo " --buildnumber The build number currently running. Defaults to env:BUILD_BUILDNUMBER" + echo " --csproj The relative path to the benchmark csproj whose tests should be run. Defaults to src\benchmarks\micro\MicroBenchmarks.csproj" + echo " --kind Related to csproj. The kind of benchmarks that should be run. Defaults to micro" + echo " --runcategories Related to csproj. Categories of benchmarks to run. Defaults to \"coreclr corefx\"" + echo " --internal If the benchmarks are running as an official job." + echo "" + exit 0 + ;; + esac +done + +if [[ "$repository" == "dotnet/performance" ]]; then + run_from_perf_repo=true +fi + +if [ -z "$configurations" ]; then + configurations="CompliationMode=$compilation_mode" +fi + +if [ -z "$core_root_directory" ]; then + use_core_run=false +fi + +payload_directory=$source_directory/Payload +performance_directory=$payload_directory/performance +workitem_directory=$source_directory/workitem +extra_benchmark_dotnet_arguments="--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --stopOnFirstError true" +perflab_arguments= +queue=Ubuntu.1804.Amd64.Open +creator=$BUILD_DEFINITIONNAME +helix_source_prefix="pr" + +if [[ "$internal" == true ]]; then + perflab_arguments="--upload-to-perflab-container" + helix_source_prefix="official" + creator= + extra_benchmark_dotnet_arguments= + + if [[ "$architecture" = "arm64" ]]; then + queue=Ubuntu.1804.Arm64.Perf + else + queue=Ubuntu.1804.Amd64.Perf + fi +fi + +common_setup_arguments="--frameworks $framework --queue $queue --build-number $build_number --build-configs $configurations" +setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments" + +if [[ "$run_from_perf_repo" = true ]]; then + payload_directory= + workitem_directory=$source_directory + performance_directory=$workitem_directory + setup_arguments="--perf-hash $commit_sha $common_setup_arguments" +else + git clone --branch master --depth 1 --quiet https://github.com/dotnet/performance $performance_directory + + docs_directory=$performance_directory/docs + mv $docs_directory $workitem_directory +fi + +if [[ "$use_core_run" = true ]]; then + new_core_root=$payload_directory/Core_Root + mv $core_root_directory $new_core_root +fi + +# Make sure all of our variables are available for future steps +echo "##vso[task.setvariable variable=UseCoreRun]$use_core_run" +echo "##vso[task.setvariable variable=Architecture]$architecture" +echo "##vso[task.setvariable variable=PayloadDirectory]$payload_directory" +echo "##vso[task.setvariable variable=PerformanceDirectory]$performance_directory" +echo "##vso[task.setvariable variable=WorkItemDirectory]$workitem_directory" +echo "##vso[task.setvariable variable=Queue]$queue" +echo "##vso[task.setvariable variable=SetupArguments]$setup_arguments" +echo "##vso[task.setvariable variable=Python]python3" +echo "##vso[task.setvariable variable=PerfLabArguments]$perflab_arguments" +echo "##vso[task.setvariable variable=ExtraBenchmarkDotNetArguments]$extra_benchmark_dotnet_arguments" +echo "##vso[task.setvariable variable=BDNCategories]$run_categories" +echo "##vso[task.setvariable variable=TargetCsproj]$csproj" +echo "##vso[task.setvariable variable=RunFromPerfRepo]$run_from_perf_repo" +echo "##vso[task.setvariable variable=Creator]$creator" +echo "##vso[task.setvariable variable=HelixSourcePrefix]$helix_source_prefix" +echo "##vso[task.setvariable variable=Kind]$kind" +echo "##vso[task.setvariable variable=_BuildConfig]$architecture.$kind.$framework" \ No newline at end of file diff --git a/eng/common/pipeline-logging-functions.ps1 b/eng/common/pipeline-logging-functions.ps1 index 7b61376f8a..af5f48aace 100644 --- a/eng/common/pipeline-logging-functions.ps1 +++ b/eng/common/pipeline-logging-functions.ps1 @@ -77,13 +77,14 @@ function Write-PipelineTaskError { [string]$Name, [string]$Value, [switch]$Secret, - [switch]$AsOutput) - + [switch]$AsOutput, + [bool]$IsMultiJobVariable=$true) + if($ci) { Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data $Value -Properties @{ 'variable' = $Name 'isSecret' = $Secret - 'isOutput' = 'true' + 'isOutput' = $IsMultiJobVariable } -AsOutput:$AsOutput } } diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh old mode 100644 new mode 100755 index 6098f9a543..1c560a5061 --- a/eng/common/pipeline-logging-functions.sh +++ b/eng/common/pipeline-logging-functions.sh @@ -39,11 +39,11 @@ function Write-PipelineTaskError { return fi - message_type="error" - sourcepath='' - linenumber='' - columnnumber='' - error_code='' + local message_type="error" + local sourcepath='' + local linenumber='' + local columnnumber='' + local error_code='' while [[ $# -gt 0 ]]; do opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" @@ -76,7 +76,7 @@ function Write-PipelineTaskError { shift done - message="##vso[task.logissue" + local message="##vso[task.logissue" message="$message type=$message_type" @@ -100,3 +100,73 @@ function Write-PipelineTaskError { echo "$message" } +function Write-PipelineSetVariable { + if [[ "$ci" != true ]]; then + return + fi + + local name='' + local value='' + local secret=false + local as_output=false + local is_multi_job_variable=true + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -name|-n) + name=$2 + shift + ;; + -value|-v) + value=$2 + shift + ;; + -secret|-s) + secret=true + ;; + -as_output|-a) + as_output=true + ;; + -is_multi_job_variable|-i) + is_multi_job_variable=$2 + shift + ;; + esac + shift + done + + value=${value/;/%3B} + value=${value/\\r/%0D} + value=${value/\\n/%0A} + value=${value/]/%5D} + + local message="##vso[task.setvariable variable=$name;isSecret=$secret;isOutput=$is_multi_job_variable]$value" + + if [[ "$as_output" == true ]]; then + $message + else + echo "$message" + fi +} + +function Write-PipelinePrependPath { + local prepend_path='' + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -path|-p) + prepend_path=$2 + shift + ;; + esac + shift + done + + export PATH="$prepend_path:$PATH" + + if [[ "$ci" == true ]]; then + echo "##vso[task.prependpath]$prepend_path" + fi +} \ No newline at end of file diff --git a/eng/common/post-build/darc-gather-drop.ps1 b/eng/common/post-build/darc-gather-drop.ps1 new file mode 100644 index 0000000000..93a0bd8328 --- /dev/null +++ b/eng/common/post-build/darc-gather-drop.ps1 @@ -0,0 +1,35 @@ +param( + [Parameter(Mandatory=$true)][int] $BarBuildId, # ID of the build which assets should be downloaded + [Parameter(Mandatory=$true)][string] $DropLocation, # Where the assets should be downloaded to + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, # Token used to access Maestro API + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", # Maestro API URL + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" # Version of Maestro API to use +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + Write-Host "Installing DARC ..." + + . $PSScriptRoot\..\darc-init.ps1 + $exitCode = $LASTEXITCODE + + if ($exitCode -ne 0) { + Write-PipelineTaskError "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..." + ExitWithExitCode $exitCode + } + + darc gather-drop --non-shipping ` + --continue-on-error ` + --id $BarBuildId ` + --output-dir $DropLocation ` + --bar-uri $MaestroApiEndpoint ` + --password $MaestroApiAccessToken ` + --latest-location +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1 new file mode 100644 index 0000000000..78ed0d540f --- /dev/null +++ b/eng/common/post-build/nuget-validation.ps1 @@ -0,0 +1,25 @@ +# This script validates NuGet package metadata information using this +# tool: https://github.com/NuGet/NuGetGallery/tree/jver-verify/src/VerifyMicrosoftPackage + +param( + [Parameter(Mandatory=$true)][string] $PackagesPath, # Path to where the packages to be validated are + [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + $url = "https://raw.githubusercontent.com/NuGet/NuGetGallery/jver-verify/src/VerifyMicrosoftPackage/verify.ps1" + + New-Item -ItemType "directory" -Path ${ToolDestinationPath} -Force + + Invoke-WebRequest $url -OutFile ${ToolDestinationPath}\verify.ps1 + + & ${ToolDestinationPath}\verify.ps1 ${PackagesPath}\*.nupkg +} +catch { + Write-PipelineTaskError "NuGet package validation failed. Please check error logs." + Write-Host $_ + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/post-build-utils.ps1 b/eng/common/post-build/post-build-utils.ps1 new file mode 100644 index 0000000000..551ae113f8 --- /dev/null +++ b/eng/common/post-build/post-build-utils.ps1 @@ -0,0 +1,90 @@ +# Most of the functions in this file require the variables `MaestroApiEndPoint`, +# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available. + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 + +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +. $PSScriptRoot\..\tools.ps1 + +function Create-MaestroApiRequestHeaders([string]$ContentType = "application/json") { + Validate-MaestroVars + + $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $headers.Add('Accept', $ContentType) + $headers.Add('Authorization',"Bearer $MaestroApiAccessToken") + return $headers +} + +function Get-MaestroChannel([int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroBuild([int]$BuildId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion" + + $result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) { + Validate-MaestroVars + + $SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository) + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Trigger-Subscription([string]$SubscriptionId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion" + Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null +} + +function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion" + Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null +} + +function Validate-MaestroVars { + try { + Get-Variable MaestroApiEndPoint -Scope Global | Out-Null + Get-Variable MaestroApiVersion -Scope Global | Out-Null + Get-Variable MaestroApiAccessToken -Scope Global | Out-Null + + if (!($MaestroApiEndPoint -Match "^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$")) { + Write-PipelineTaskError "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'" + ExitWithExitCode 1 + } + + if (!($MaestroApiVersion -Match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")) { + Write-PipelineTaskError "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'" + ExitWithExitCode 1 + } + } + catch { + Write-PipelineTaskError "Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script." + Write-Host $_ + ExitWithExitCode 1 + } +} diff --git a/eng/common/post-build/promote-build.ps1 b/eng/common/post-build/promote-build.ps1 new file mode 100644 index 0000000000..e5ae85f251 --- /dev/null +++ b/eng/common/post-build/promote-build.ps1 @@ -0,0 +1,48 @@ +param( + [Parameter(Mandatory=$true)][int] $BuildId, + [Parameter(Mandatory=$true)][int] $ChannelId, + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + # Check that the channel we are going to promote the build to exist + $channelInfo = Get-MaestroChannel -ChannelId $ChannelId + + if (!$channelInfo) { + Write-Host "Channel with BAR ID $ChannelId was not found in BAR!" + ExitWithExitCode 1 + } + + # Get info about which channels the build has already been promoted to + $buildInfo = Get-MaestroBuild -BuildId $BuildId + + if (!$buildInfo) { + Write-Host "Build with BAR ID $BuildId was not found in BAR!" + ExitWithExitCode 1 + } + + # Find whether the build is already assigned to the channel or not + if ($buildInfo.channels) { + foreach ($channel in $buildInfo.channels) { + if ($channel.Id -eq $ChannelId) { + Write-Host "The build with BAR ID $BuildId is already on channel $ChannelId!" + ExitWithExitCode 0 + } + } + } + + Write-Host "Promoting build '$BuildId' to channel '$ChannelId'." + + Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId + + Write-Host "done." +} +catch { + Write-Host "There was an error while trying to promote build '$BuildId' to channel '$ChannelId'" + Write-Host $_ + Write-Host $_.ScriptStackTrace +} diff --git a/eng/common/post-build/setup-maestro-vars.ps1 b/eng/common/post-build/setup-maestro-vars.ps1 new file mode 100644 index 0000000000..d7f64dc63c --- /dev/null +++ b/eng/common/post-build/setup-maestro-vars.ps1 @@ -0,0 +1,26 @@ +param( + [Parameter(Mandatory=$true)][string] $ReleaseConfigsPath # Full path to ReleaseConfigs.txt asset +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + $Content = Get-Content $ReleaseConfigsPath + + $BarId = $Content | Select -Index 0 + + $Channels = "" + $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } + + $IsStableBuild = $Content | Select -Index 2 + + Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId + Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" + Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 84c97df1fc..41e01ae6e6 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -6,18 +6,15 @@ param( [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 +. $PSScriptRoot\post-build-utils.ps1 -. $PSScriptRoot\..\tools.ps1 - -# Cache/HashMap (File -> Exist flag) used to consult whether a file exist +# Cache/HashMap (File -> Exist flag) used to consult whether a file exist # in the repository at a specific commit point. This is populated by inserting # all files present in the repo at a specific commit point. $global:RepoFiles = @{} $ValidatePackage = { - param( + param( [string] $PackagePath # Full path to a Symbols.NuGet package ) @@ -32,7 +29,7 @@ $ValidatePackage = { # Extensions for which we'll look for SourceLink information # For now we'll only care about Portable & Embedded PDBs $RelevantExtensions = @(".dll", ".exe", ".pdb") - + Write-Host -NoNewLine "Validating" ([System.IO.Path]::GetFileName($PackagePath)) "... " $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) @@ -46,13 +43,13 @@ $ValidatePackage = { try { $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) - $zip.Entries | + $zip.Entries | Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | ForEach-Object { $FileName = $_.FullName $Extension = [System.IO.Path]::GetExtension($_.Name) $FakeName = -Join((New-Guid), $Extension) - $TargetFile = Join-Path -Path $ExtractPath -ChildPath $FakeName + $TargetFile = Join-Path -Path $ExtractPath -ChildPath $FakeName # We ignore resource DLLs if ($FileName.EndsWith(".resources.dll")) { @@ -62,7 +59,7 @@ $ValidatePackage = { [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile, $true) $ValidateFile = { - param( + param( [string] $FullPath, # Full path to the module that has to be checked [string] $RealPath, [ref] $FailedFiles @@ -83,7 +80,7 @@ $ValidatePackage = { ForEach-Object { $Link = $_ $CommitUrl = "https://raw.githubusercontent.com/${using:GHRepoName}/${using:GHCommit}/" - + $FilePath = $Link.Replace($CommitUrl, "") $Status = 200 $Cache = $using:RepoFiles @@ -91,7 +88,7 @@ $ValidatePackage = { if ( !($Cache.ContainsKey($FilePath)) ) { try { $Uri = $Link -as [System.URI] - + # Only GitHub links are valid if ($Uri.AbsoluteURI -ne $null -and ($Uri.Host -match "github" -or $Uri.Host -match "githubusercontent")) { $Status = (Invoke-WebRequest -Uri $Link -UseBasicParsing -Method HEAD -TimeoutSec 5).StatusCode @@ -128,15 +125,15 @@ $ValidatePackage = { } } } - + &$ValidateFile $TargetFile $FileName ([ref]$FailedFiles) } } catch { - + } finally { - $zip.Dispose() + $zip.Dispose() } if ($FailedFiles -eq 0) { @@ -163,13 +160,13 @@ function ValidateSourceLinkLinks { ExitWithExitCode 1 } - $RepoTreeURL = -Join("https://api.github.com/repos/", $GHRepoName, "/git/trees/", $GHCommit, "?recursive=1") + $RepoTreeURL = -Join("http://api.github.com/repos/", $GHRepoName, "/git/trees/", $GHCommit, "?recursive=1") $CodeExtensions = @(".cs", ".vb", ".fs", ".fsi", ".fsx", ".fsscript") try { # Retrieve the list of files in the repo at that particular commit point and store them in the RepoFiles hash $Data = Invoke-WebRequest $RepoTreeURL -UseBasicParsing | ConvertFrom-Json | Select-Object -ExpandProperty tree - + foreach ($file in $Data) { $Extension = [System.IO.Path]::GetExtension($file.path) @@ -183,7 +180,7 @@ function ValidateSourceLinkLinks { Write-Host $_ ExitWithExitCode 1 } - + if (Test-Path $ExtractPath) { Remove-Item $ExtractPath -Force -Recurse -ErrorAction SilentlyContinue } @@ -200,21 +197,27 @@ function ValidateSourceLinkLinks { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function InstallSourcelinkCli { + $sourcelinkCliPackageName = "sourcelink" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$sourcelinkCliPackageName*") -and ($toolList -like "*$sourcelinkCliVersion*")) { + Write-Host "SourceLink CLI version $sourcelinkCliVersion is already installed." + } + else { + Write-Host "Installing SourceLink CLI version $sourcelinkCliVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $sourcelinkCliPackageName --version $sourcelinkCliVersion --verbosity "minimal" --global } } try { - Write-Host "Installing SourceLink CLI..." - Get-Location - . $PSScriptRoot\sourcelink-cli-init.ps1 -sourcelinkCliVersion $SourcelinkCliVersion - CheckExitCode "Running sourcelink-cli-init" + InstallSourcelinkCli - Measure-Command { ValidateSourceLinkLinks } + ValidateSourceLinkLinks } catch { Write-Host $_ diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index 69456854e0..d5ec51b150 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -4,10 +4,7 @@ param( [Parameter(Mandatory=$true)][string] $DotnetSymbolVersion # Version of dotnet symbol to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 Add-Type -AssemblyName System.IO.Compression.FileSystem @@ -162,19 +159,25 @@ function CheckSymbolsAvailable { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function Installdotnetsymbol { + $dotnetsymbolPackageName = "dotnet-symbol" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$dotnetsymbolPackageName*") -and ($toolList -like "*$dotnetsymbolVersion*")) { + Write-Host "dotnet-symbol version $dotnetsymbolVersion is already installed." + } + else { + Write-Host "Installing dotnet-symbol version $dotnetsymbolVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $dotnetsymbolPackageName --version $dotnetsymbolVersion --verbosity "minimal" --global } } try { - Write-Host "Installing dotnet symbol ..." - Get-Location - . $PSScriptRoot\dotnetsymbol-init.ps1 -dotnetsymbolVersion $DotnetSymbolVersion - CheckExitCode "Running dotnetsymbol-init" + Installdotnetsymbol CheckSymbolsAvailable } diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 new file mode 100644 index 0000000000..926d5b4551 --- /dev/null +++ b/eng/common/post-build/trigger-subscriptions.ps1 @@ -0,0 +1,57 @@ +param( + [Parameter(Mandatory=$true)][string] $SourceRepo, + [Parameter(Mandatory=$true)][int] $ChannelId, + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" +) + +. $PSScriptRoot\post-build-utils.ps1 + +# Get all the $SourceRepo subscriptions +$normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') +$subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId + +if (!$subscriptions) { + Write-Host "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" + ExitWithExitCode 0 +} + +$subscriptionsToTrigger = New-Object System.Collections.Generic.List[string] +$failedTriggeredSubscription = $false + +# Get all enabled subscriptions that need dependency flow on 'everyBuild' +foreach ($subscription in $subscriptions) { + if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) { + Write-Host "Should trigger this subscription: $subscription.id" + [void]$subscriptionsToTrigger.Add($subscription.id) + } +} + +foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { + try { + Write-Host "Triggering subscription '$subscriptionToTrigger'." + + Trigger-Subscription -SubscriptionId $subscriptionToTrigger + + Write-Host "done." + } + catch + { + Write-Host "There was an error while triggering subscription '$subscriptionToTrigger'" + Write-Host $_ + Write-Host $_.ScriptStackTrace + $failedTriggeredSubscription = $true + } +} + +if ($subscriptionsToTrigger.Count -eq 0) { + Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'." +} +elseif ($failedTriggeredSubscription) { + Write-Host "At least one subscription failed to be triggered..." + ExitWithExitCode 1 +} +else { + Write-Host "All subscriptions were triggered successfully!" +} diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 index 0635f26fb6..aab7589f2c 100644 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ b/eng/common/sdl/execute-all-sdl-tools.ps1 @@ -22,7 +22,9 @@ Param( [string] $TsaCodebaseAdmin, # Optional: only needed if TsaOnboard is true; the aliases which are admins of the TSA codebase (e.g. DOMAIN\alias); TSA is the automated framework used to upload test results as bugs. [string] $TsaBugAreaPath, # Optional: only needed if TsaOnboard is true; the area path where TSA will file bugs in AzDO; TSA is the automated framework used to upload test results as bugs. [string] $TsaIterationPath, # Optional: only needed if TsaOnboard is true; the iteration path where TSA will file bugs in AzDO; TSA is the automated framework used to upload test results as bugs. - [string] $GuardianLoggerLevel="Standard" # Optional: the logger level for the Guardian CLI; options are Trace, Verbose, Standard, Warning, and Error + [string] $GuardianLoggerLevel="Standard", # Optional: the logger level for the Guardian CLI; options are Trace, Verbose, Standard, Warning, and Error + [string[]] $CrScanAdditionalRunConfigParams, # Optional: Additional Params to custom build a CredScan run config in the format @("xyz:abc","sdf:1") + [string[]] $PoliCheckAdditionalRunConfigParams # Optional: Additional Params to custom build a Policheck run config in the format @("xyz:abc","sdf:1") ) $ErrorActionPreference = "Stop" @@ -69,10 +71,10 @@ if ($TsaOnboard) { } if ($ArtifactToolsList -and $ArtifactToolsList.Count -gt 0) { - & $(Join-Path $PSScriptRoot "run-sdl.ps1") -GuardianCliLocation $guardianCliLocation -WorkingDirectory $ArtifactsDirectory -TargetDirectory $ArtifactsDirectory -GdnFolder $gdnFolder -ToolsList $ArtifactToolsList -AzureDevOpsAccessToken $AzureDevOpsAccessToken -UpdateBaseline $UpdateBaseline -GuardianLoggerLevel $GuardianLoggerLevel + & $(Join-Path $PSScriptRoot "run-sdl.ps1") -GuardianCliLocation $guardianCliLocation -WorkingDirectory $ArtifactsDirectory -TargetDirectory $ArtifactsDirectory -GdnFolder $gdnFolder -ToolsList $ArtifactToolsList -AzureDevOpsAccessToken $AzureDevOpsAccessToken -UpdateBaseline $UpdateBaseline -GuardianLoggerLevel $GuardianLoggerLevel -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams } if ($SourceToolsList -and $SourceToolsList.Count -gt 0) { - & $(Join-Path $PSScriptRoot "run-sdl.ps1") -GuardianCliLocation $guardianCliLocation -WorkingDirectory $ArtifactsDirectory -TargetDirectory $SourceDirectory -GdnFolder $gdnFolder -ToolsList $SourceToolsList -AzureDevOpsAccessToken $AzureDevOpsAccessToken -UpdateBaseline $UpdateBaseline -GuardianLoggerLevel $GuardianLoggerLevel + & $(Join-Path $PSScriptRoot "run-sdl.ps1") -GuardianCliLocation $guardianCliLocation -WorkingDirectory $ArtifactsDirectory -TargetDirectory $SourceDirectory -GdnFolder $gdnFolder -ToolsList $SourceToolsList -AzureDevOpsAccessToken $AzureDevOpsAccessToken -UpdateBaseline $UpdateBaseline -GuardianLoggerLevel $GuardianLoggerLevel -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams } if ($UpdateBaseline) { diff --git a/eng/common/sdl/extract-artifact-packages.ps1 b/eng/common/sdl/extract-artifact-packages.ps1 new file mode 100644 index 0000000000..1fdbb14329 --- /dev/null +++ b/eng/common/sdl/extract-artifact-packages.ps1 @@ -0,0 +1,70 @@ +param( + [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where artifact packages are stored + [Parameter(Mandatory=$true)][string] $ExtractPath # Full path to directory where the packages will be extracted +) + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 +$ExtractPackage = { + param( + [string] $PackagePath # Full path to a NuGet package + ) + + if (!(Test-Path $PackagePath)) { + Write-PipelineTaskError "Input file does not exist: $PackagePath" + ExitWithExitCode 1 + } + + $RelevantExtensions = @(".dll", ".exe", ".pdb") + Write-Host -NoNewLine "Extracting" ([System.IO.Path]::GetFileName($PackagePath)) "... " + + $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) + $ExtractPath = Join-Path -Path $using:ExtractPath -ChildPath $PackageId + + Add-Type -AssemblyName System.IO.Compression.FileSystem + + [System.IO.Directory]::CreateDirectory($ExtractPath); + + try { + $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) + + $zip.Entries | + Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | + ForEach-Object { + $TargetFile = Join-Path -Path $ExtractPath -ChildPath $_.Name + + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile, $true) + } + } + catch { + + } + finally { + $zip.Dispose() + } + } + function ExtractArtifacts { + if (!(Test-Path $InputPath)) { + Write-Host "Input Path does not exist: $InputPath" + ExitWithExitCode 0 + } + $Jobs = @() + Get-ChildItem "$InputPath\*.nupkg" | + ForEach-Object { + $Jobs += Start-Job -ScriptBlock $ExtractPackage -ArgumentList $_.FullName + } + + foreach ($Job in $Jobs) { + Wait-Job -Id $Job.Id | Receive-Job + } +} + +try { + Measure-Command { ExtractArtifacts } +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config index b054737df1..3f97ac2f16 100644 --- a/eng/common/sdl/packages.config +++ b/eng/common/sdl/packages.config @@ -1,4 +1,4 @@  - + diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 index e6a86d03a2..d7b8564458 100644 --- a/eng/common/sdl/run-sdl.ps1 +++ b/eng/common/sdl/run-sdl.ps1 @@ -5,7 +5,9 @@ Param( [string] $GdnFolder, [string[]] $ToolsList, [string] $UpdateBaseline, - [string] $GuardianLoggerLevel="Standard" + [string] $GuardianLoggerLevel="Standard", + [string[]] $CrScanAdditionalRunConfigParams, + [string[]] $PoliCheckAdditionalRunConfigParams ) $ErrorActionPreference = "Stop" @@ -29,8 +31,8 @@ foreach ($tool in $ToolsList) { Write-Host $tool # We have to manually configure tools that run on source to look at the source directory only if ($tool -eq "credscan") { - Write-Host "$GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args `" TargetDirectory : $TargetDirectory `"" - & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory : $TargetDirectory " + Write-Host "$GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args `" TargetDirectory : $TargetDirectory `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" + & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory : $TargetDirectory " $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) if ($LASTEXITCODE -ne 0) { Write-Host "Guardian configure for $tool failed with exit code $LASTEXITCODE." exit $LASTEXITCODE @@ -38,8 +40,8 @@ foreach ($tool in $ToolsList) { $config = $True } if ($tool -eq "policheck") { - Write-Host "$GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args `" Target : $TargetDirectory `"" - & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " Target : $TargetDirectory " + Write-Host "$GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args `" Target : $TargetDirectory `" $(If ($PoliCheckAdditionalRunConfigParams) {$PoliCheckAdditionalRunConfigParams})" + & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " Target : $TargetDirectory " $(If ($PoliCheckAdditionalRunConfigParams) {$PoliCheckAdditionalRunConfigParams}) if ($LASTEXITCODE -ne 0) { Write-Host "Guardian configure for $tool failed with exit code $LASTEXITCODE." exit $LASTEXITCODE diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index acb4c55d73..91621cf88f 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -10,6 +10,8 @@ jobs: displayName: Run SDL tool variables: - group: DotNet-VSTS-Bot + pool: + name: Hosted VS2017 steps: - checkout: self clean: true @@ -20,6 +22,16 @@ jobs: downloadType: specific files matchingPattern: "**" downloadPath: $(Build.SourcesDirectory)\artifacts + - powershell: eng/common/sdl/extract-artifact-packages.ps1 + -InputPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts + displayName: Extract Blob Artifacts + continueOnError: ${{ parameters.continueOnError }} + - powershell: eng/common/sdl/extract-artifact-packages.ps1 + -InputPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts + displayName: Extract Package Artifacts + continueOnError: ${{ parameters.continueOnError }} - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' - task: NuGetCommand@2 @@ -36,7 +48,7 @@ jobs: continueOnError: ${{ parameters.continueOnError }} - ${{ if eq(parameters.overrideParameters, '') }}: - powershell: eng/common/sdl/execute-all-sdl-tools.ps1 - -GuardianPackageName Microsoft.Guardian.Cli.0.3.2 + -GuardianPackageName Microsoft.Guardian.Cli.0.7.1 -NugetPackageDirectory $(Build.SourcesDirectory)\.packages -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) ${{ parameters.additionalParameters }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 1814e0ab61..8db456bb7f 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -37,6 +37,9 @@ parameters: # Optional: Enable publishing to the build asset registry enablePublishBuildAssets: false + # Optional: Prevent gather/push manifest from executing when using publishing pipelines + enablePublishUsingPipelines: false + # Optional: Include PublishTestResults task enablePublishTestResults: false @@ -187,7 +190,7 @@ jobs: continueOnError: true condition: always() - - ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(variables['_PublishUsingPipelines'], 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(parameters.enablePublishUsingPipelines, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: CopyFiles@2 displayName: Gather Asset Manifests inputs: @@ -195,6 +198,7 @@ jobs: TargetFolder: '$(Build.StagingDirectory)/AssetManifests' continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) + - task: PublishBuildArtifacts@1 displayName: Push Asset Manifests inputs: diff --git a/eng/common/templates/job/performance.yml b/eng/common/templates/job/performance.yml new file mode 100644 index 0000000000..ef809253d1 --- /dev/null +++ b/eng/common/templates/job/performance.yml @@ -0,0 +1,93 @@ +parameters: + steps: [] # optional -- any additional steps that need to happen before pulling down the performance repo and sending the performance benchmarks to helix (ie building your repo) + variables: [] # optional -- list of additional variables to send to the template + jobName: '' # required -- job name + displayName: '' # optional -- display name for the job. Will use jobName if not passed + pool: '' # required -- name of the Build pool + container: '' # required -- name of the container + extraSetupParameters: '' # optional -- extra arguments to pass to the setup script + frameworks: ['netcoreapp3.0'] # optional -- list of frameworks to run against + continueOnError: 'false' # optional -- determines whether to continue the build if the step errors + dependsOn: '' # optional -- dependencies of the job + timeoutInMinutes: 320 # optional -- timeout for the job + enableTelemetry: false # optional -- enable for telemetry + +jobs: +- template: ../jobs/jobs.yml + parameters: + dependsOn: ${{ parameters.dependsOn }} + enableTelemetry: ${{ parameters.enableTelemetry }} + enablePublishBuildArtifacts: true + continueOnError: ${{ parameters.continueOnError }} + + jobs: + - job: '${{ parameters.jobName }}' + + ${{ if ne(parameters.displayName, '') }}: + displayName: '${{ parameters.displayName }}' + ${{ if eq(parameters.displayName, '') }}: + displayName: '${{ parameters.jobName }}' + + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + variables: + + - ${{ each variable in parameters.variables }}: + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + - IsInternal: '' + - HelixApiAccessToken: '' + - HelixPreCommand: '' + + - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(variables['Agent.Os'], 'Windows_NT') }}: + - HelixPreCommand: 'set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - IsInternal: -Internal + - ${{ if ne(variables['Agent.Os'], 'Windows_NT') }}: + - HelixPreCommand: 'export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - IsInternal: --internal + - group: DotNet-HelixApi-Access + - group: dotnet-benchview + + workspace: + clean: all + pool: + ${{ parameters.pool }} + container: ${{ parameters.container }} + strategy: + matrix: + ${{ each framework in parameters.frameworks }}: + ${{ framework }}: + _Framework: ${{ framework }} + steps: + - checkout: self + clean: true + # Run all of the steps to setup repo + - ${{ each step in parameters.steps }}: + - ${{ step }} + - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) ${{ parameters.extraSetupParameters }} + displayName: Performance Setup (Windows) + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) ${{ parameters.extraSetupParameters }} + displayName: Performance Setup (Unix) + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) + displayName: Run ci setup script + # Run perf testing in helix + - template: /eng/common/templates/steps/perf-send-to-helix.yml + parameters: + HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'test/performance/$(Kind)/$(_Framework)/$(Architecture)' + HelixAccessToken: $(HelixApiAccessToken) + HelixTargetQueues: $(Queue) + HelixPreCommands: $(HelixPreCommand) + Creator: $(Creator) + WorkItemTimeout: 4:00 # 4 hours + WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy + CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions \ No newline at end of file diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index ff7346163f..9e77ef1b54 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -66,7 +66,6 @@ jobs: script: | Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId) Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)" - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsInternalBuild) Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild) - task: PublishBuildArtifacts@1 displayName: Publish ReleaseConfigs Artifact diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml new file mode 100644 index 0000000000..dc065ab308 --- /dev/null +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -0,0 +1,147 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: IS_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: Internal Servicing + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: publish_assets + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(InternalServicing_30_Channel_Id) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) + /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) + /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + - template: ../trigger-subscription.yml + parameters: + ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} + +- stage: IS_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-dev-5.yml b/eng/common/templates/post-build/channels/netcore-dev-5.yml new file mode 100644 index 0000000000..f2b0cfb269 --- /dev/null +++ b/eng/common/templates/post-build/channels/netcore-dev-5.yml @@ -0,0 +1,148 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: NetCore_Dev5_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: .NET Core 5 Dev Channel + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(NetCore_5_Dev_Channel_Id) + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + +- stage: NetCore_Dev5_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-tools-latest.yml b/eng/common/templates/post-build/channels/netcore-tools-latest.yml new file mode 100644 index 0000000000..fd6c09b227 --- /dev/null +++ b/eng/common/templates/post-build/channels/netcore-tools-latest.yml @@ -0,0 +1,148 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: NetCore_Tools_Latest_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: .NET Tools - Latest + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(NetCore_Tools_Latest_Channel_Id) + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + +- stage: NetCore_Tools_Latest_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index c61eaa927d..771dcf4ef8 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -13,24 +13,17 @@ stages: - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) variables: - group: DotNet-Symbol-Server-Pats pool: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts + displayName: Download Artifacts inputs: - buildType: current - artifactName: PDBArtifacts - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts + downloadType: specific files + matchingPattern: "*Artifacts*" - task: PowerShell@2 displayName: Publish @@ -44,14 +37,16 @@ stages: /p:Configuration=Release - job: - displayName: Publish to Static Feed + displayName: Publish Assets dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -74,22 +69,48 @@ stages: artifactName: AssetManifests - task: PowerShell@2 - displayName: Publish + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) inputs: filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToPackageFeed -restore -msbuildEngine dotnet - /p:AccountKeyToStaticFeed='$(dotnetfeed-storage-access-key-1)' + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(PublicDevRelease_30_Channel_Id) + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:ArtifactsCategory='$(_DotNetArtifactsCategory)' - /p:OverrideAssetsWithSameName=true - /p:PassIfExistingItemIdentical=true /p:Configuration=Release + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + - stage: PublishValidation displayName: Publish Validation @@ -102,7 +123,7 @@ stages: - job: displayName: Symbol Availability dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -118,28 +139,10 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location - - - template: ../promote-build.yml + - template: ../darc-gather-drop.yml parameters: ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml new file mode 100644 index 0000000000..00108bd3f8 --- /dev/null +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -0,0 +1,147 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: PubRel_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: Public Release + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: publish_assets + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Publish + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(PublicRelease_30_Channel_Id) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) + /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) + /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + - template: ../trigger-subscription.yml + parameters: + ChannelId: ${{ variables.PublicRelease_30_Channel_Id }} + +- stage: PubRel_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.PublicRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index 23725c6d62..f64184da9f 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -8,14 +8,16 @@ stages: - template: ../setup-maestro-vars.yml - job: - displayName: Publish to Static Feed + displayName: Publish Assets dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id) variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicValidationRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -38,22 +40,48 @@ stages: artifactName: AssetManifests - task: PowerShell@2 - displayName: Publish + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) inputs: filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToPackageFeed -restore -msbuildEngine dotnet - /p:AccountKeyToStaticFeed='$(dotnetfeed-storage-access-key-1)' + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(PublicValidationRelease_30_Channel_Id) + /p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:ArtifactsCategory='$(_DotNetArtifactsCategory)' - /p:OverrideAssetsWithSameName=true - /p:PassIfExistingItemIdentical=true + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' /p:Configuration=Release + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + - stage: PVR_PublishValidation displayName: Publish Validation @@ -62,30 +90,10 @@ stages: jobs: - template: ../setup-maestro-vars.yml - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id) - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - group: Publish-Build-Assets - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com --password $(MaestroAccessToken) --latest-location - - - template: ../promote-build.yml + - template: ../darc-gather-drop.yml parameters: ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 97b48d97fe..52a74487fd 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,9 +1,47 @@ variables: + - group: Publish-Build-Assets + # .NET Core 3 Dev - PublicDevRelease_30_Channel_Id: 3 + - name: PublicDevRelease_30_Channel_Id + value: 3 + + # .NET Core 5 Dev + - name: NetCore_5_Dev_Channel_Id + value: 131 # .NET Tools - Validation - PublicValidationRelease_30_Channel_Id: 9 + - name: PublicValidationRelease_30_Channel_Id + value: 9 + + # .NET Tools - Latest + - name: NetCore_Tools_Latest_Channel_Id + value: 2 + + # .NET Core 3.0 Internal Servicing + - name: InternalServicing_30_Channel_Id + value: 184 + + # .NET Core 3.0 Release + - name: PublicRelease_30_Channel_Id + value: 19 + + # Whether the build is internal or not + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + + # Storage account name for proxy-backed feeds + - name: ProxyBackedFeedsAccountName + value: dotnetfeed + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro-prod.westus2.cloudapp.azure.com" + - name: MaestroApiAccessToken + value: $(MaestroAccessToken) + - name: MaestroApiVersion + value: "2019-01-16" - SourceLinkCLIVersion: 3.0.0 - SymbolToolVersion: 1.0.1 + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 diff --git a/eng/common/templates/post-build/darc-gather-drop.yml b/eng/common/templates/post-build/darc-gather-drop.yml new file mode 100644 index 0000000000..3268ccaa55 --- /dev/null +++ b/eng/common/templates/post-build/darc-gather-drop.yml @@ -0,0 +1,23 @@ +parameters: + ChannelId: 0 + +jobs: +- job: gatherDrop + displayName: Gather Drop + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }})) + variables: + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + pool: + vmImage: 'windows-2019' + steps: + - task: PowerShell@2 + displayName: Darc gather-drop + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1 + arguments: -BarBuildId $(BARBuildId) + -DropLocation $(Agent.BuildDirectory)/Temp/Drop/ + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 2c411dd009..aba0b0fcaf 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -2,15 +2,38 @@ parameters: enableSourceLinkValidation: true enableSigningValidation: true enableSymbolValidation: true + enableNugetValidation: true SDLValidationParameters: enable: false params: '' + # Which stages should finish execution before post-build stages start + dependsOn: [build] + stages: - stage: validate - dependsOn: build + dependsOn: ${{ parameters.dependsOn }} displayName: Validate jobs: + - ${{ if eq(parameters.enableNugetValidation, 'true') }}: + - job: + displayName: NuGet Validation + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ + - ${{ if eq(parameters.enableSigningValidation, 'true') }}: - job: displayName: Signing Validation @@ -29,6 +52,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task SigningValidation -restore -msbuildEngine dotnet /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' /p:Configuration=Release - ${{ if eq(parameters.enableSourceLinkValidation, 'true') }}: @@ -60,8 +84,20 @@ stages: parameters: additionalParameters: ${{ parameters.SDLValidationParameters.params }} +- template: \eng\common\templates\post-build\channels\netcore-dev-5.yml + parameters: + enableSymbolValidation: ${{ parameters.enableSymbolValidation }} + - template: \eng\common\templates\post-build\channels\public-dev-release.yml parameters: enableSymbolValidation: ${{ parameters.enableSymbolValidation }} +- template: \eng\common\templates\post-build\channels\netcore-tools-latest.yml + parameters: + enableSymbolValidation: ${{ parameters.enableSymbolValidation }} + - template: \eng\common\templates\post-build\channels\public-validation-release.yml + +- template: \eng\common\templates\post-build\channels\public-release.yml + +- template: \eng\common\templates\post-build\channels\internal-servicing.yml diff --git a/eng/common/templates/post-build/promote-build.yml b/eng/common/templates/post-build/promote-build.yml index d00317003b..6b479c3b82 100644 --- a/eng/common/templates/post-build/promote-build.yml +++ b/eng/common/templates/post-build/promote-build.yml @@ -5,24 +5,21 @@ jobs: - job: displayName: Promote Build dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }}) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }})) variables: - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: ChannelId value: ${{ parameters.ChannelId }} - - group: Publish-Build-Assets pool: vmImage: 'windows-2019' steps: - task: PowerShell@2 displayName: Add Build to Channel inputs: - targetType: inline - script: | - $headers = @{ - "Accept" = "application/json" - "Authorization" = "Bearer $(MaestroAccessToken)" - } - Invoke-RestMethod -Method Post -Headers $headers -Uri https://maestro-prod.westus2.cloudapp.azure.com/api/channels/$(ChannelId)/builds/$(BARBuildId)?api-version=2019-01-16 - enabled: false + filePath: $(Build.SourcesDirectory)/eng/common/post-build/promote-build.ps1 + arguments: -BuildId $(BARBuildId) + -ChannelId $(ChannelId) + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 0eddd6cd3b..56242b068e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -14,24 +14,5 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - targetType: inline - script: | - # This is needed to make Write-PipelineSetVariable works in this context - $ci = $true - - . "$(Build.SourcesDirectory)/eng/common/tools.ps1" - - $Content = Get-Content "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - - $BarId = $Content | Select -Index 0 - - $Channels = "" - $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - - $IsInternalBuild = $Content | Select -Index 2 - $IsStableBuild = $Content | Select -Index 3 - - Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId - Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" - Write-PipelineSetVariable -Name 'IsInternalBuild' -Value $IsInternalBuild - Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild + filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 + arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml new file mode 100644 index 0000000000..da669030da --- /dev/null +++ b/eng/common/templates/post-build/trigger-subscription.yml @@ -0,0 +1,13 @@ +parameters: + ChannelId: 0 + +steps: +- task: PowerShell@2 + displayName: Triggering subscriptions + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 + arguments: -SourceRepo $(Build.Repository.Uri) + -ChannelId ${{ parameters.ChannelId }} + -MaestroApiAccessToken $(MaestroAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/steps/helix-publish.yml b/eng/common/templates/steps/helix-publish.yml deleted file mode 100644 index 470ab65da0..0000000000 --- a/eng/common/templates/steps/helix-publish.yml +++ /dev/null @@ -1,51 +0,0 @@ -parameters: - HelixSource: 'pr/dotnet-github-anon-kaonashi-bot' - HelixType: ̓'tests/default' - HelixBuild: $(Build.BuildNumber) - HelixTargetQueues: '' - HelixAccessToken: '' - HelixPreCommands: '' - HelixPostCommands: '' - WorkItemDirectory: '' - WorkItemCommand: '' - CorrelationPayloadDirectory: '' - XUnitProjects: '' - XUnitTargetFramework: '' - XUnitRunnerVersion: '' - IncludeDotNetCli: false - DotNetCliPackageType: '' - DotNetCliVersion: '' - EnableXUnitReporter: false - WaitForWorkItemCompletion: true - condition: succeeded() - continueOnError: false - -steps: - - task: DotNetCoreCLI@2 - inputs: - command: custom - projects: eng/common/helixpublish.proj - custom: msbuild - arguments: '/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog' - displayName: Send job to Helix - env: - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/templates/steps/perf-send-to-helix.yml b/eng/common/templates/steps/perf-send-to-helix.yml new file mode 100644 index 0000000000..b3ea9acf1f --- /dev/null +++ b/eng/common/templates/steps/perf-send-to-helix.yml @@ -0,0 +1,66 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk' or 'runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json + EnableXUnitReporter: false # optional -- true enables XUnit result reporting to Mission Control + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Send job to Helix' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: $(Build.SourcesDirectory)\eng\common\msbuild.ps1 $(Build.SourcesDirectory)\eng\common\performance\perfhelixpublish.proj /restore /t:Test /bl:$(Build.SourcesDirectory)\artifacts\log\$env:BuildConfig\SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/performance/perfhelixpublish.proj /restore /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 60741f0390..9c12b1b4fd 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -39,6 +39,10 @@ # installed on the machine instead of downloading one. [bool]$useInstalledDotNetCli = if (Test-Path variable:useInstalledDotNetCli) { $useInstalledDotNetCli } else { $true } +# Enable repos to use a particular version of the on-line dotnet-install scripts. +# default URL: https://dot.net/v1/dotnet-install.ps1 +[string]$dotnetInstallScriptVersion = if (Test-Path variable:dotnetInstallScriptVersion) { $dotnetInstallScriptVersion } else { "v1" } + # True to use global NuGet cache instead of restoring packages to repository-local directory. [bool]$useGlobalNuGetCache = if (Test-Path variable:useGlobalNuGetCache) { $useGlobalNuGetCache } else { !$ci } @@ -84,7 +88,7 @@ function Exec-Process([string]$command, [string]$commandArgs) { return $global:LASTEXITCODE = $process.ExitCode } finally { - # If we didn't finish then an error occured or the user hit ctrl-c. Either + # If we didn't finish then an error occurred or the user hit ctrl-c. Either # way kill the process if (-not $finished) { $process.Kill() @@ -147,7 +151,7 @@ function InitializeDotNetCli([bool]$install) { # It also ensures that VS msbuild will use the downloaded sdk targets. $env:PATH = "$dotnetRoot;$env:PATH" - # Make Sure that our bootstrapped dotnet cli is avaliable in future steps of the Azure Pipelines build + # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' @@ -159,7 +163,7 @@ function GetDotNetInstallScript([string] $dotnetRoot) { $installScript = Join-Path $dotnetRoot "dotnet-install.ps1" if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot - Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile $installScript + Invoke-WebRequest "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" -OutFile $installScript } return $installScript @@ -169,7 +173,7 @@ function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $arc InstallDotNet $dotnetRoot $version $architecture } -function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot +function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ Version = $version @@ -518,6 +522,9 @@ function MSBuild-Core() { if ($warnAsError) { $cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true" } + else { + $cmdArgs += " /p:TreatWarningsAsErrors=false" + } foreach ($arg in $args) { if ($arg -ne $null -and $arg.Trim() -ne "") { diff --git a/eng/common/tools.sh b/eng/common/tools.sh old mode 100644 new mode 100755 index 70d92cf85a..3af9be6157 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -45,6 +45,10 @@ warn_as_error=${warn_as_error:-true} # installed on the machine instead of downloading one. use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} +# Enable repos to use a particular version of the on-line dotnet-install scripts. +# default URL: https://dot.net/v1/dotnet-install.sh +dotnetInstallScriptVersion=${dotnetInstallScriptVersion:-'v1'} + # True to use global NuGet cache instead of restoring packages to repository-local directory. if [[ "$ci" == true ]]; then use_global_nuget_cache=${use_global_nuget_cache:-false} @@ -77,7 +81,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'InitializeTools' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -146,14 +150,10 @@ function InitializeDotNetCli { # Add dotnet to PATH. This prevents any bare invocation of dotnet in custom # build steps from using anything other than what we've downloaded. - export PATH="$dotnet_root:$PATH" + Write-PipelinePrependPath -path "$dotnet_root" - if [[ $ci == true ]]; then - # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build - echo "##vso[task.prependpath]$dotnet_root" - echo "##vso[task.setvariable variable=DOTNET_MULTILEVEL_LOOKUP]0" - echo "##vso[task.setvariable variable=DOTNET_SKIP_FIRST_TIME_EXPERIENCE]1" - fi + Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" + Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" # return value _InitializeDotNetCli="$dotnet_root" @@ -199,7 +199,7 @@ function InstallDotNet { function GetDotNetInstallScript { local root=$1 local install_script="$root/dotnet-install.sh" - local install_script_url="https://dot.net/v1/dotnet-install.sh" + local install_script_url="https://dot.net/$dotnetInstallScriptVersion/dotnet-install.sh" if [[ ! -a "$install_script" ]]; then mkdir -p "$root" @@ -249,7 +249,7 @@ function InitializeNativeTools() { then local nativeArgs="" if [[ "$ci" == true ]]; then - nativeArgs="-InstallDirectory $tools_dir" + nativeArgs="--installDirectory $tools_dir" fi "$_script_dir/init-tools-native.sh" $nativeArgs fi @@ -387,7 +387,8 @@ mkdir -p "$toolset_dir" mkdir -p "$temp_dir" mkdir -p "$log_dir" -if [[ $ci == true ]]; then - export TEMP="$temp_dir" - export TMP="$temp_dir" -fi +Write-PipelineSetVariable -name "Artifacts" -value "$artifacts_dir" +Write-PipelineSetVariable -name "Artifacts.Toolset" -value "$toolset_dir" +Write-PipelineSetVariable -name "Artifacts.Log" -value "$log_dir" +Write-PipelineSetVariable -name "Temp" -value "$temp_dir" +Write-PipelineSetVariable -name "TMP" -value "$temp_dir" diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index 5d145af11c..3290288182 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -2,13 +2,13 @@ MIT - Microsoft and F# Software Foundation Visual F# Compiler FSharp functional programming $(ArtifactsBinDir) - true + + false diff --git a/fcs/Directory.Build.props b/fcs/Directory.Build.props index dc1615654c..7988ee2f36 100644 --- a/fcs/Directory.Build.props +++ b/fcs/Directory.Build.props @@ -31,7 +31,6 @@ $(FSharpSourcesRoot)\..\packages\FSharp.Compiler.Tools.4.1.27\tools fsi.exe - $(ArtifactsBinDir)\FSharp.Build\Proto\net472 4.6.2 net461 diff --git a/fcs/FSharp.Compiler.Service.Tests/QuickInfoTests.fs b/fcs/FSharp.Compiler.Service.Tests/QuickInfoTests.fs index bfa6c7df72..415079942e 100644 --- a/fcs/FSharp.Compiler.Service.Tests/QuickInfoTests.fs +++ b/fcs/FSharp.Compiler.Service.Tests/QuickInfoTests.fs @@ -154,9 +154,9 @@ module Test = let quickInfo = GetQuickInfoTextFromCode code let expected = expectedLines [ "type MyEmployee =" - " {mutable Name: string;" - " mutable Age: int;" - " mutable IsFTE: bool;}" + " { mutable Name: string" + " mutable Age: int" + " mutable IsFTE: bool }" "Full name: FsTest.MyEmployee" ] Assert.AreEqual(expected, quickInfo) () diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 33188f095d..55b2ad535e 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -1,4 +1,4 @@ - + $(MSBuildProjectDirectory)\..\..\src diff --git a/fcs/RELEASE_NOTES.md b/fcs/RELEASE_NOTES.md index 35476348dd..73164bb892 100644 --- a/fcs/RELEASE_NOTES.md +++ b/fcs/RELEASE_NOTES.md @@ -1,3 +1,15 @@ +#### 31.0.0 + * Integrate dotnet/fsharp from 5a8f454a1 to 05c558a61 + * Notable changes include: + * Removal of the `Microsoft.FSharp.Compiler.SourceCodeServices` namespace + * A new API for determining if an identifier needs to be quoted is available: `FSharp.Compiler.LexHelp.Keywords.DoesIdentifierNeedQuotation` + * Enhancements to the correctness of PDBs + * Better string formatting of records and values + * More stack overflow fixes in the compiler + * Inline IL parsing error handling + * `LeafExpressionConverter` handles struct tuples + * `FSharpChecker` now can parse a file without caching: `ParseFileNoCache` + #### 30.0.0 * Integrate dotnet/fsharp from 25560f477 to 5a8f454a1 * Notable improvements include: @@ -5,7 +17,6 @@ * FCS APIs for FSComp and Implement Interface * line directive handling * improved performance when computing quick fix suggestions - #### 29.0.1 * Fix versioning of the assembly diff --git a/fcs/download-paket.ps1 b/fcs/download-paket.ps1 index 7aa8c5ef6f..4541168012 100644 --- a/fcs/download-paket.ps1 +++ b/fcs/download-paket.ps1 @@ -1,4 +1,4 @@ -$paketurl="https://github.com/fsprojects/Paket/releases/download/5.210.1/paket.exe" +$paketurl="https://github.com/fsprojects/Paket/releases/download/5.215.0/paket.exe" $paketdir = Join-Path $PSScriptRoot ".paket" $paketpath = Join-Path $paketdir "paket.exe" diff --git a/fcs/download-paket.sh b/fcs/download-paket.sh index d2bf8524a8..2825ac4d5a 100755 --- a/fcs/download-paket.sh +++ b/fcs/download-paket.sh @@ -12,7 +12,7 @@ while [[ -h "$source" ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -paketurl=https://github.com/fsprojects/Paket/releases/download/5.210.1/paket.exe +paketurl=https://github.com/fsprojects/Paket/releases/download/5.215.0/paket.exe paketdir=$scriptroot/.paket paketpath=$paketdir/paket.exe if [ ! -e "$paketpath" ]; then diff --git a/global.json b/global.json index 1f44c774f6..42b7fded08 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "3.0.100-preview5-011568", + "dotnet": "3.0.100-preview6-012264", "vs": { "version": "16.1", "components": [ @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19323.4", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19410.2", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } diff --git a/proto.proj b/proto.proj index b94fb70481..23d7525d13 100644 --- a/proto.proj +++ b/proto.proj @@ -25,6 +25,10 @@ + + + + diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index f1afa06c48..fa49d64c9e 100755 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -327,6 +327,8 @@ type cenv = generatePdb: bool resolveAssemblyRef: (ILAssemblyRef -> Choice option) } + override x.ToString() = "" + /// Convert an Abstract IL type reference to Reflection.Emit System.Type value. // This ought to be an adequate substitute for this whole function, but it needs // to be thoroughly tested. diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index e48c00eaf0..e9978c3de5 100755 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -605,6 +605,7 @@ type cenv = member cenv.GetCode() = cenv.codeChunks.Close() + override x.ToString() = "" let FindOrAddSharedRow (cenv: cenv) tbl x = cenv.GetTable(tbl).FindOrAddSharedEntry x @@ -3025,7 +3026,8 @@ let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : IL //===================================================================== // TABLES+BLOBS --> PHYSICAL METADATA+BLOBS //===================================================================== -let chunk sz next = ({addr=next; size=sz}, next + sz) +let chunk sz next = ({addr=next; size=sz}, next + sz) +let emptychunk next = ({addr=next; size=0}, next) let nochunk next = ({addr= 0x0;size= 0x0; }, next) let count f arr = @@ -3516,7 +3518,7 @@ let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Len let writeBinaryAndReportMappings (outfile, ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, - embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap) + embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap) modul normalizeAssemblyRefs = // Store the public key from the signer into the manifest. This means it will be written // to the binary and also acts as an indicator to leave space for delay sign @@ -3565,7 +3567,7 @@ let writeBinaryAndReportMappings (outfile, with e -> failwith ("Could not open file for writing (binary mode): " + outfile) - let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings = + let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings = try let imageBaseReal = modul.ImageBase // FIXED CHOICE @@ -3670,42 +3672,61 @@ let writeBinaryAndReportMappings (outfile, let pdbOpt = match portablePDB with | true -> - let (uncompressedLength, contentId, stream) as pdbStream = - generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap + let (uncompressedLength, contentId, stream, algorithmName, checkSum) as pdbStream = + generatePortablePdb embedAllSource embedSourceList sourceLink checksumAlgorithm showTimes pdbData pathMap - if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream) + if embeddedPDB then + let uncompressedLength, contentId, stream = compressPortablePdbStream uncompressedLength contentId stream + Some (uncompressedLength, contentId, stream, algorithmName, checkSum) else Some pdbStream | _ -> None - let debugDirectoryChunk, next = - chunk (if pdbfile = None then - 0x0 - else if embeddedPDB && portablePDB then - sizeof_IMAGE_DEBUG_DIRECTORY * 2 + let debugDirectoryChunk, next = + chunk (if pdbfile = None then + 0x0 else - sizeof_IMAGE_DEBUG_DIRECTORY + sizeof_IMAGE_DEBUG_DIRECTORY * 2 + + (if embeddedPDB then sizeof_IMAGE_DEBUG_DIRECTORY else 0) + + (if deterministic then sizeof_IMAGE_DEBUG_DIRECTORY else 0) ) next + // The debug data is given to us by the PDB writer and appears to // typically be the type of the data plus the PDB file name. We fill // this in after we've written the binary. We approximate the size according // to what PDB writers seem to require and leave extra space just in case... let debugDataJustInCase = 40 - let debugDataChunk, next = + let debugDataChunk, next = chunk (align 0x4 (match pdbfile with | None -> 0 | Some f -> (24 + System.Text.Encoding.Unicode.GetByteCount f // See bug 748444 + debugDataJustInCase))) next - let debugEmbeddedPdbChunk, next = - let streamLength = - match pdbOpt with - | Some (_, _, stream) -> int stream.Length - | None -> 0 - chunk (align 0x4 (match embeddedPDB with - | true -> 8 + streamLength - | _ -> 0 )) next + let debugChecksumPdbChunk, next = + chunk (align 0x4 (match pdbOpt with + | Some (_, _, _, algorithmName, checkSum) -> + let alg = System.Text.Encoding.UTF8.GetBytes(algorithmName) + let size = alg.Length + 1 + checkSum.Length + size + | None -> 0)) next + + let debugEmbeddedPdbChunk, next = + if embeddedPDB then + let streamLength = + match pdbOpt with + | Some (_, _, stream, _, _) -> int stream.Length + | None -> 0 + chunk (align 0x4 (match embeddedPDB with + | true -> 8 + streamLength + | _ -> 0 )) next + else + nochunk next + + let debugDeterministicPdbChunk, next = + if deterministic then emptychunk next + else nochunk next + let textSectionSize = next - textSectionAddr let nextPhys = align alignPhys (textSectionPhysLoc + textSectionSize) @@ -3804,35 +3825,39 @@ let writeBinaryAndReportMappings (outfile, if pCurrent <> pExpected then failwith ("warning: "+chunkName+" not where expected, pCurrent = "+string pCurrent+", p.addr = "+string pExpected) writeBytes os chunk - + let writePadding (os: BinaryWriter) _comment sz = if sz < 0 then failwith "writePadding: size < 0" for i = 0 to sz - 1 do os.Write 0uy - + // Now we've computed all the offsets, write the image - + write (Some msdosHeaderChunk.addr) os "msdos header" msdosHeader - + write (Some peSignatureChunk.addr) os "pe signature" [| |] - + writeInt32 os 0x4550 - + write (Some peFileHeaderChunk.addr) os "pe file header" [| |] - + if (modul.Platform = Some AMD64) then writeInt32AsUInt16 os 0x8664 // Machine - IMAGE_FILE_MACHINE_AMD64 elif isItanium then writeInt32AsUInt16 os 0x200 else writeInt32AsUInt16 os 0x014c // Machine - IMAGE_FILE_MACHINE_I386 - + writeInt32AsUInt16 os numSections - let pdbData = + let pdbData = + // Hash code, data and metadata if deterministic then - // Hash code, data and metadata - use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only + use sha = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + let hCode = sha.ComputeHash code let hData = sha.ComputeHash data let hMeta = sha.ComputeHash metadata @@ -3848,6 +3873,7 @@ let writeBinaryAndReportMappings (outfile, // Use last 4 bytes for timestamp - High bit set, to stop tool chains becoming confused let timestamp = int final.[16] ||| (int final.[17] <<< 8) ||| (int final.[18] <<< 16) ||| (int (final.[19] ||| 128uy) <<< 24) writeInt32 os timestamp + // Update pdbData with new guid and timestamp. Portable and embedded PDBs don't need the ModuleID // Full and PdbOnly aren't supported under deterministic builds currently, they rely on non-determinsitic Windows native code { pdbData with ModuleID = final.[0..15] ; Timestamp = timestamp } @@ -4133,10 +4159,14 @@ let writeBinaryAndReportMappings (outfile, if pdbfile.IsSome then write (Some (textV2P debugDirectoryChunk.addr)) os "debug directory" (Array.create debugDirectoryChunk.size 0x0uy) write (Some (textV2P debugDataChunk.addr)) os "debug data" (Array.create debugDataChunk.size 0x0uy) + write (Some (textV2P debugChecksumPdbChunk.addr)) os "debug checksum" (Array.create debugChecksumPdbChunk.size 0x0uy) if embeddedPDB then write (Some (textV2P debugEmbeddedPdbChunk.addr)) os "debug data" (Array.create debugEmbeddedPdbChunk.size 0x0uy) + if deterministic then + write (Some (textV2P debugDeterministicPdbChunk.addr)) os "debug deterministic" Array.empty + writePadding os "end of .text" (dataSectionPhysLoc - textSectionPhysLoc - textSectionSize) // DATA SECTION @@ -4182,7 +4212,7 @@ let writeBinaryAndReportMappings (outfile, FileSystemUtilites.setExecutablePermission outfile with _ -> () - pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings + pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings // Looks like a finally with e -> @@ -4207,11 +4237,11 @@ let writeBinaryAndReportMappings (outfile, try let idd = match pdbOpt with - | Some (originalLength, contentId, stream) -> + | Some (originalLength, contentId, stream, algorithmName, checkSum) -> if embeddedPDB then - embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk + embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic else - writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk + writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic | None -> #if FX_NO_PDB_WRITER Array.empty @@ -4232,16 +4262,17 @@ let writeBinaryAndReportMappings (outfile, writeInt32AsUInt16 os2 i.iddMajorVersion writeInt32AsUInt16 os2 i.iddMinorVersion writeInt32 os2 i.iddType - writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData - writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData - writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData + writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData + writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData + writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData // Write the Debug Data for i in idd do - // write the debug raw data as given us by the PDB writer - os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore - if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable" - writeBytes os2 i.iddData + if i.iddChunk.size <> 0 then + // write the debug raw data as given us by the PDB writer + os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore + if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable" + writeBytes os2 i.iddData os2.Dispose() with e -> failwith ("Error while writing debug directory entry: "+e.Message) @@ -4250,9 +4281,7 @@ let writeBinaryAndReportMappings (outfile, with e -> reraise() - end - ignore debugDataChunk - ignore debugEmbeddedPdbChunk + end reportTime showTimes "Finalize PDB" /// Sign the binary. No further changes to binary allowed past this point! @@ -4280,9 +4309,10 @@ type options = embedAllSource: bool embedSourceList: string list sourceLink: string + checksumAlgorithm: HashAlgorithm signer: ILStrongNameSigner option - emitTailcalls : bool - deterministic : bool + emitTailcalls: bool + deterministic: bool showTimes: bool dumpDebugInfo: bool pathMap: PathMap } @@ -4290,5 +4320,5 @@ type options = let WriteILBinary (outfile, (args: options), modul, normalizeAssemblyRefs) = writeBinaryAndReportMappings (outfile, args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource, - args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs + args.embedSourceList, args.sourceLink, args.checksumAlgorithm, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs |> ignore diff --git a/src/absil/ilwrite.fsi b/src/absil/ilwrite.fsi index f1955f82a2..9dba89c9b6 100755 --- a/src/absil/ilwrite.fsi +++ b/src/absil/ilwrite.fsi @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. /// The IL Binary writer. -module internal FSharp.Compiler.AbstractIL.ILBinaryWriter +module internal FSharp.Compiler.AbstractIL.ILBinaryWriter open Internal.Utilities -open FSharp.Compiler.AbstractIL -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILPdbWriter [] type ILStrongNameSigner = @@ -24,6 +25,7 @@ type options = embedAllSource: bool embedSourceList: string list sourceLink: string + checksumAlgorithm: HashAlgorithm signer : ILStrongNameSigner option emitTailcalls: bool deterministic: bool diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 260ccbe238..86b7ee9224 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -11,8 +11,9 @@ open System.Reflection open System.Reflection.Metadata open System.Reflection.Metadata.Ecma335 open System.Reflection.PortableExecutable +open System.Text open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Internal.Library @@ -125,6 +126,27 @@ type idd = iddData: byte[] iddChunk: BinaryChunk } +/// The specified Hash algorithm to use on portable pdb files. +type HashAlgorithm = + | Sha1 + | Sha256 + +// Document checksum algorithms +let guidSha1 = Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460") +let guidSha2 = Guid("8829d00f-11b8-4213-878b-770e8597ac16") + +let checkSum (url: string) (checksumAlgorithm: HashAlgorithm) = + try + use file = FileSystem.FileStreamReadShim url + let guid, alg = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> guidSha1, System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> guidSha2, System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + + let checkSum = alg.ComputeHash file + Some (guid, checkSum) + with _ -> None + //--------------------------------------------------------------------- // Portable PDB Writer //--------------------------------------------------------------------- @@ -153,7 +175,7 @@ let pdbGetCvDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvCh } let pdbMagicNumber= 0x4244504dL -let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) = +let pdbGetEmbeddedPdbDebugInfo (embeddedPdbChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) = let iddPdbBuffer = let buffer = Array.zeroCreate (sizeof + sizeof + int(stream.Length)) let (offset, size) = (0, sizeof) // Magic Number dword: 0x4244504dL @@ -164,33 +186,57 @@ let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int6 Buffer.BlockCopy(stream.ToArray(), 0, buffer, offset, size) buffer { iddCharacteristics = 0 // Reserved - iddMajorVersion = 0 // VersionMajor should be 0 + iddMajorVersion = 0x0100 // VersionMajor should be 0x0100 iddMinorVersion = 0x0100 // VersionMinor should be 0x0100 iddType = 17 // IMAGE_DEBUG_TYPE_EMBEDDEDPDB iddTimestamp = 0 iddData = iddPdbBuffer // Path name to the pdb file when built - iddChunk = embeddedPDBChunk + iddChunk = embeddedPdbChunk } -let pdbGetDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvChunk: BinaryChunk) (embeddedPDBChunk: BinaryChunk option) (uncompressedLength: int64) (stream: MemoryStream option) = - match stream, embeddedPDBChunk with - | None, _ | _, None -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk |] - | Some s, Some chunk -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk; pdbGetPdbDebugInfo chunk uncompressedLength s |] +let pdbChecksumDebugInfo timestamp (checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte[]) = + let iddBuffer = + let alg = Encoding.UTF8.GetBytes(algorithmName) + let buffer = Array.zeroCreate (alg.Length + 1 + checksum.Length) + Buffer.BlockCopy(alg, 0, buffer, 0, alg.Length) + Buffer.BlockCopy(checksum, 0, buffer, alg.Length + 1, checksum.Length) + buffer + { iddCharacteristics = 0 // Reserved + iddMajorVersion = 1 // VersionMajor should be 1 + iddMinorVersion = 0x0100 // VersionMinor should be 0x0100 + iddType = 19 // IMAGE_DEBUG_TYPE_CHECKSUMPDB + iddTimestamp = timestamp + iddData = iddBuffer // Path name to the pdb file when built + iddChunk = checksumPdbChunk + } -// Document checksum algorithms -let guidSourceHashMD5 = System.Guid(0x406ea660u, 0x64cfus, 0x4c82us, 0xb6uy, 0xf0uy, 0x42uy, 0xd4uy, 0x81uy, 0x72uy, 0xa7uy, 0x99uy) //406ea660-64cf-4c82-b6f0-42d48172a799 -let hashSizeOfMD5 = 16 +let pdbGetPdbDebugDeterministicInfo (deterministicPdbChunk: BinaryChunk) = + { iddCharacteristics = 0 // Reserved + iddMajorVersion = 0 // VersionMajor should be 0 + iddMinorVersion = 0 // VersionMinor should be 00 + iddType = 16 // IMAGE_DEBUG_TYPE_DETERMINISTIC + iddTimestamp = 0 + iddData = Array.empty // No DATA + iddChunk = deterministicPdbChunk + } -// If the FIPS algorithm policy is enabled on the computer (e.g., for US government employees and contractors) -// then obtaining the MD5 implementation in BCL will throw. -// In this case, catch the failure, and not set a checksum. -let checkSum (url: string) = - try - use file = FileSystem.FileStreamReadShim url - use md5 = System.Security.Cryptography.MD5.Create() - let checkSum = md5.ComputeHash file - Some (guidSourceHashMD5, checkSum) - with _ -> None +let pdbGetDebugInfo (contentId: byte[]) (timestamp: int32) (filepath: string) + (cvChunk: BinaryChunk) + (embeddedPdbChunk: BinaryChunk option) + (deterministicPdbChunk: BinaryChunk) + (checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte []) + (uncompressedLength: int64) (stream: MemoryStream option) + (embeddedPdb: bool) (deterministic: bool) = + [| yield pdbGetCvDebugInfo contentId timestamp filepath cvChunk + yield pdbChecksumDebugInfo timestamp checksumPdbChunk algorithmName checksum + if embeddedPdb then + match stream, embeddedPdbChunk with + | None, _ | _, None -> () + | Some s, Some chunk -> + yield pdbGetEmbeddedPdbDebugInfo chunk uncompressedLength s + if deterministic then + yield pdbGetPdbDebugDeterministicInfo deterministicPdbChunk + |] //------------------------------------------------------------------------------ // PDB Writer. The function [WritePdbInfo] abstracts the @@ -219,7 +265,7 @@ let getRowCounts tableRowCounts = tableRowCounts |> Seq.iter(fun x -> builder.Add x) builder.MoveToImmutable() -let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) showTimes (info: PdbData) isDeterministic (pathMap: PathMap) = +let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) checksumAlgorithm showTimes (info: PdbData) (pathMap: PathMap) = sortMethods showTimes info let externalRowCounts = getRowCounts info.TableRowCounts let docs = @@ -286,7 +332,7 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s metadata.SetCapacity(TableIndex.Document, docLength) for doc in docs do let handle = - match checkSum doc.File with + match checkSum doc.File checksumAlgorithm with | Some (hashAlg, checkSum) -> let dbgInfo = (serializeDocumentName doc.File, @@ -403,12 +449,17 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s if i < 1 || offsetDelta > 0 then builder.WriteCompressedInteger offsetDelta - // Hidden-sequence-point-record - if startLine = 0xfeefee || endLine = 0xfeefee || (startColumn = 0 && endColumn = 0) + // Check for hidden-sequence-point-record + if startLine = 0xfeefee || + endLine = 0xfeefee || + (startColumn = 0 && endColumn = 0) || + ((endLine - startLine) = 0 && (endColumn - startColumn) = 0) then + // Hidden-sequence-point-record builder.WriteCompressedInteger 0 builder.WriteCompressedInteger 0 - else // Non-hidden-sequence-point-record + else + // Non-hidden-sequence-point-record let deltaLines = endLine - startLine // lines builder.WriteCompressedInteger deltaLines @@ -476,25 +527,28 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s | None -> MetadataTokens.MethodDefinitionHandle 0 | Some x -> MetadataTokens.MethodDefinitionHandle x - let deterministicIdProvider isDeterministic : System.Func, BlobContentId> = - match isDeterministic with - | false -> null - | true -> - let convert (content: IEnumerable) = - use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only - let hash = content - |> Seq.collect (fun c -> c.GetBytes().Array |> sha.ComputeHash) - |> Array.ofSeq |> sha.ComputeHash - BlobContentId.FromHash hash - System.Func, BlobContentId>( convert ) - - let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, deterministicIdProvider isDeterministic) + // Compute the contentId for the pdb. Always do it deterministically, since we have to compute the anyway. + // The contentId is the hash of the ID using whichever algorithm has been specified to the compiler + let mutable contentHash = Array.empty + + let algorithmName, hashAlgorithm = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> "SHA1", System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> "SHA256", System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + let idProvider: System.Func, BlobContentId> = + let convert (content: IEnumerable) = + let contentBytes = content |> Seq.collect (fun c -> c.GetBytes()) |> Array.ofSeq + contentHash <- contentBytes |> hashAlgorithm.ComputeHash + BlobContentId.FromHash contentHash + System.Func, BlobContentId>(convert) + + let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, idProvider) let blobBuilder = new BlobBuilder() let contentId= serializer.Serialize blobBuilder let portablePdbStream = new MemoryStream() blobBuilder.WriteContentTo portablePdbStream reportTime showTimes "PDB: Created" - (portablePdbStream.Length, contentId, portablePdbStream) + (portablePdbStream.Length, contentId, portablePdbStream, algorithmName, contentHash) let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) = let compressedStream = new MemoryStream() @@ -502,17 +556,17 @@ let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobConten stream.WriteTo compressionStream (uncompressedLength, contentId, compressedStream) -let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk = +let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb = try FileSystem.FileDelete fpdb with _ -> () use pdbFile = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite) stream.WriteTo pdbFile reportTime showTimes "PDB: Closed" - pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None 0L None + pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None deterministicPdbChunk checksumPdbChunk algName checksum 0L None embeddedPdb deterministicPdb -let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk = +let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb = reportTime showTimes "PDB: Closed" let fn = Path.GetFileName fpdb - pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) uncompressedLength (Some stream) + pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) deterministicPdbChunk checksumPdbChunk algName checksum uncompressedLength (Some stream) embeddedPdb deterministicPdb #if !FX_NO_PDB_WRITER //--------------------------------------------------------------------- diff --git a/src/absil/ilwritepdb.fsi b/src/absil/ilwritepdb.fsi index 2713d9769b..748e178a46 100644 --- a/src/absil/ilwritepdb.fsi +++ b/src/absil/ilwritepdb.fsi @@ -4,7 +4,7 @@ module internal FSharp.Compiler.AbstractIL.ILPdbWriter open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range open System.Collections.Generic @@ -83,10 +83,14 @@ type idd = iddData: byte[]; iddChunk: BinaryChunk } -val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream) +type HashAlgorithm = + | Sha1 + | Sha256 + +val generatePortablePdb : embedAllSource: bool -> embedSourceList: string list -> sourceLink: string -> checksumAlgorithm: HashAlgorithm -> showTimes: bool -> info: PdbData -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream * string * byte[]) val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream) -val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[] -val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> pathMap:PathMap -> cvChunk:BinaryChunk -> idd[] +val embedPortablePdbInfo: uncompressedLength: int64 -> contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> cvChunk: BinaryChunk -> pdbChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[] +val writePortablePdbInfo: contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> pathMap: PathMap -> cvChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[] #if !FX_NO_PDB_WRITER val writePdbInfo : showTimes:bool -> f:string -> fpdb:string -> info:PdbData -> cvChunk:BinaryChunk -> idd[] diff --git a/scripts/AssemblyVersionCheck.fsx b/src/buildtools/AssemblyCheck/AssemblyCheck.fs similarity index 51% rename from scripts/AssemblyVersionCheck.fsx rename to src/buildtools/AssemblyCheck/AssemblyCheck.fs index 0f3816a2e6..c6bd035a67 100644 --- a/scripts/AssemblyVersionCheck.fsx +++ b/src/buildtools/AssemblyCheck/AssemblyCheck.fs @@ -1,22 +1,50 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. open System open System.Diagnostics open System.IO open System.Reflection +open System.Reflection.PortableExecutable open System.Text.RegularExpressions -module AssemblyVersionCheck = +module AssemblyCheck = let private versionZero = Version(0, 0, 0, 0) let private versionOne = Version(1, 0, 0, 0) let private commitHashPattern = new Regex(@"Commit Hash: ()|([0-9a-fA-F]{40})", RegexOptions.Compiled) let private devVersionPattern = new Regex(@"-(ci|dev)", RegexOptions.Compiled) - let verifyAssemblyVersions (binariesPath:string) = + let verifyEmbeddedPdb (filename:string) = + use fileStream = File.OpenRead(filename) + let reader = new PEReader(fileStream) + let mutable hasEmbeddedPdb = false + + try + for entry in reader.ReadDebugDirectory() do + match entry.Type with + | DebugDirectoryEntryType.CodeView -> + let _ = reader.ReadCodeViewDebugDirectoryData(entry) + () + + | DebugDirectoryEntryType.EmbeddedPortablePdb -> + let _ = reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry) + hasEmbeddedPdb <- true + () + + | DebugDirectoryEntryType.PdbChecksum -> + let _ = reader.ReadPdbChecksumDebugDirectoryData(entry) + () + + | _ -> () + with | e -> printfn "Error validating assembly %s\nMessage: %s" filename (e.ToString()) + hasEmbeddedPdb + + let verifyAssemblies (binariesPath:string) = + let excludedAssemblies = [ "FSharp.Data.TypeProviders.dll" ] |> Set.ofList + let fsharpAssemblies = [ "FSharp*.dll" "fsc.exe" @@ -28,12 +56,17 @@ module AssemblyVersionCheck = |> List.ofSeq |> List.filter (fun p -> (Set.contains (Path.GetFileName(p)) excludedAssemblies) |> not) + let fsharpExecutingWithEmbeddedPdbs = + fsharpAssemblies + |> List.filter (fun p -> not (p.Contains(@"\Proto\") || p.Contains(@"\Bootstrap\") || p.Contains(@".resources.") || p.Contains(@"\FSharpSdk\") || p.Contains(@"\tmp\") || p.Contains(@"\obj\"))) + // verify that all assemblies have a version number other than 0.0.0.0 or 1.0.0.0 let failedVersionCheck = fsharpAssemblies |> List.filter (fun a -> let assemblyVersion = AssemblyName.GetAssemblyName(a).Version assemblyVersion = versionZero || assemblyVersion = versionOne) + if failedVersionCheck.Length > 0 then printfn "The following assemblies had a version of %A or %A" versionZero versionOne printfn "%s\r\n" <| String.Join("\r\n", failedVersionCheck) @@ -43,27 +76,36 @@ module AssemblyVersionCheck = // verify that all assemblies have a commit hash let failedCommitHash = fsharpAssemblies + |> List.filter (fun p -> not (p.Contains(@"\FSharpSdk\"))) |> List.filter (fun a -> let fileProductVersion = FileVersionInfo.GetVersionInfo(a).ProductVersion not (commitHashPattern.IsMatch(fileProductVersion) || devVersionPattern.IsMatch(fileProductVersion))) + if failedCommitHash.Length > 0 then printfn "The following assemblies don't have a commit hash set" printfn "%s\r\n" <| String.Join("\r\n", failedCommitHash) else printfn "All shipping assemblies had an appropriate commit hash." + // verify that all assemblies have an embedded pdb + let failedVerifyEmbeddedPdb = + fsharpExecutingWithEmbeddedPdbs + |> List.filter (fun a -> not (verifyEmbeddedPdb a)) + + if failedVerifyEmbeddedPdb.Length > 0 then + printfn "The following assemblies don't have an embedded pdb" + printfn "%s\r\n" <| String.Join("\r\n", failedVerifyEmbeddedPdb) + else + printfn "All shipping assemblies had an embedded PDB." + // return code is the number of failures - failedVersionCheck.Length + failedCommitHash.Length + failedVersionCheck.Length + failedCommitHash.Length + failedVerifyEmbeddedPdb.Length + +[] let main (argv:string array) = if argv.Length <> 1 then - printfn "Usage: fsi.exe AssemblyVersionCheck.fsx -- path/to/binaries" + printfn "Usage: dotnet AssemblyCheck.dll -- path/to/binaries" 1 else - AssemblyVersionCheck.verifyAssemblyVersions argv.[0] - -Environment.GetCommandLineArgs() -|> Seq.skipWhile ((<>) "--") -|> Seq.skip 1 -|> Array.ofSeq -|> main + AssemblyCheck.verifyAssemblies argv.[0] diff --git a/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj b/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj new file mode 100644 index 0000000000..72f79d02f9 --- /dev/null +++ b/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp2.1 + true + + + + + + + + + + + diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 593f086dd0..7ac48ba2a3 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -2,31 +2,33 @@ Debug - + true + + - + - + - + - + - + diff --git a/src/buildtools/buildtools.targets b/src/buildtools/buildtools.targets index 303ab00825..185fd4d059 100644 --- a/src/buildtools/buildtools.targets +++ b/src/buildtools/buildtools.targets @@ -20,7 +20,7 @@ BeforeTargets="CoreCompile"> - $(ArtifactsDir)\Bootstrap\fslex.dll + $(ArtifactsDir)\Bootstrap\fslex\fslex.dll @@ -43,7 +43,7 @@ BeforeTargets="CoreCompile"> - $(ArtifactsDir)\Bootstrap\fsyacc.dll + $(ArtifactsDir)\Bootstrap\fsyacc\fsyacc.dll diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 85728909cf..5b75cf1077 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -17,6 +17,7 @@ open Internal.Utilities.Text open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Extensions.ILX @@ -2100,6 +2101,7 @@ type TcConfigBuilder = mutable maxErrors: int mutable abortOnError: bool (* intended for fsi scripts that should exit on first error *) mutable baseAddress: int32 option + mutable checksumAlgorithm: HashAlgorithm #if DEBUG mutable showOptimizationData: bool #endif @@ -2231,6 +2233,7 @@ type TcConfigBuilder = maxErrors = 100 abortOnError = false baseAddress = None + checksumAlgorithm = HashAlgorithm.Sha256 delaysign = false publicsign = false @@ -2740,6 +2743,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.flatErrors = data.flatErrors member x.maxErrors = data.maxErrors member x.baseAddress = data.baseAddress + member x.checksumAlgorithm = data.checksumAlgorithm #if DEBUG member x.showOptimizationData = data.showOptimizationData #endif diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 71bb7c6f8b..1262542cd9 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -10,6 +10,7 @@ open Internal.Utilities open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler open FSharp.Compiler.TypeChecker @@ -337,6 +338,7 @@ type TcConfigBuilder = mutable maxErrors: int mutable abortOnError: bool mutable baseAddress: int32 option + mutable checksumAlgorithm: HashAlgorithm #if DEBUG mutable showOptimizationData: bool #endif @@ -497,6 +499,7 @@ type TcConfig = member maxErrors: int member baseAddress: int32 option + member checksumAlgorithm: HashAlgorithm #if DEBUG member showOptimizationData: bool #endif diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 0c385cc367..e548a49e71 100755 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -9,6 +9,7 @@ open System open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics @@ -522,6 +523,7 @@ let tagFullPDBOnlyPortable = "{full|pdbonly|portable|embedded}" let tagWarnList = "" let tagSymbolList = "" let tagAddress = "
" +let tagAlgorithm = "{SHA1|SHA256}" let tagInt = "" let tagPathMap = "" let tagNone = "" @@ -933,6 +935,16 @@ let advancedFlagsFsc tcConfigB = OptionString (fun s -> tcConfigB.baseAddress <- Some(int32 s)), None, Some (FSComp.SR.optsBaseaddress())) + yield CompilerOption + ("checksumalgorithm", tagAlgorithm, + OptionString (fun s -> + tcConfigB.checksumAlgorithm <- + match s.ToUpperInvariant() with + | "SHA1" -> HashAlgorithm.Sha1 + | "SHA256" -> HashAlgorithm.Sha256 + | _ -> error(Error(FSComp.SR.optsUnknownChecksumAlgorithm s, rangeCmdArgs))), None, + Some (FSComp.SR.optsChecksumAlgorithm())) + yield noFrameworkFlag true tcConfigB yield CompilerOption diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 94c28b76e5..1cb860abae 100755 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -64,10 +64,10 @@ let compgenId = mkSynId range0 unassignedTyparName let NewCompGenTypar (kind, rigid, staticReq, dynamicReq, error) = NewTypar(kind, rigid, Typar(compgenId, staticReq, true), error, dynamicReq, [], false, false) -let anon_id m = mkSynId m unassignedTyparName +let AnonTyparId m = mkSynId m unassignedTyparName let NewAnonTypar (kind, m, rigid, var, dyn) = - NewTypar (kind, rigid, Typar(anon_id m, var, true), false, dyn, [], false, false) + NewTypar (kind, rigid, Typar(AnonTyparId m, var, true), false, dyn, [], false, false) let NewNamedInferenceMeasureVar (_m, rigid, var, id) = NewTypar(TyparKind.Measure, rigid, Typar(id, var, false), false, TyparDynamicReq.No, [], false, false) @@ -104,6 +104,7 @@ let FreshenAndFixupTypars m rigid fctps tinst tpsorig = tps, renaming, tinst let FreshenTypeInst m tpsorig = FreshenAndFixupTypars m TyparRigidity.Flexible [] [] tpsorig + let FreshMethInst m fctps tinst tpsorig = FreshenAndFixupTypars m TyparRigidity.Flexible fctps tinst tpsorig let FreshenTypars m tpsorig = @@ -126,62 +127,95 @@ let FreshenMethInfo m (minfo: MethInfo) = [] /// Information about the context of a type equation. type ContextInfo = + /// No context was given. | NoContext + /// The type equation comes from an IF expression. | IfExpression of range + /// The type equation comes from an omitted else branch. | OmittedElseBranch of range + /// The type equation comes from a type check of the result of an else branch. | ElseBranchResult of range + /// The type equation comes from the verification of record fields. | RecordFields + /// The type equation comes from the verification of a tuple in record fields. | TupleInRecordFields + /// The type equation comes from a list or array constructor | CollectionElement of bool * range + /// The type equation comes from a return in a computation expression. + | ReturnInComputationExpression + /// The type equation comes from a yield in a computation expression. | YieldInComputationExpression + /// The type equation comes from a runtime type test. | RuntimeTypeTest of bool + /// The type equation comes from an downcast where a upcast could be used. | DowncastUsedInsteadOfUpcast of bool + /// The type equation comes from a return type of a pattern match clause (not the first clause). | FollowingPatternMatchClause of range + /// The type equation comes from a pattern match guard. | PatternMatchGuard of range + /// The type equation comes from a sequence expression. | SequenceExpression of TType -exception ConstraintSolverTupleDiffLengths of displayEnv: DisplayEnv * TType list * TType list * range * range -exception ConstraintSolverInfiniteTypes of displayEnv: DisplayEnv * contextInfo: ContextInfo * TType * TType * range * range -exception ConstraintSolverTypesNotInEqualityRelation of displayEnv: DisplayEnv * TType * TType * range * range * ContextInfo +exception ConstraintSolverTupleDiffLengths of displayEnv: DisplayEnv * TType list * TType list * range * range + +exception ConstraintSolverInfiniteTypes of displayEnv: DisplayEnv * contextInfo: ContextInfo * TType * TType * range * range + +exception ConstraintSolverTypesNotInEqualityRelation of displayEnv: DisplayEnv * TType * TType * range * range * ContextInfo + exception ConstraintSolverTypesNotInSubsumptionRelation of displayEnv: DisplayEnv * TType * TType * range * range -exception ConstraintSolverMissingConstraint of displayEnv: DisplayEnv * Tast.Typar * Tast.TyparConstraint * range * range -exception ConstraintSolverError of string * range * range -exception ConstraintSolverRelatedInformation of string option * range * exn -exception ErrorFromApplyingDefault of tcGlobals: TcGlobals * displayEnv: DisplayEnv * Tast.Typar * TType * exn * range -exception ErrorFromAddingTypeEquation of tcGlobals: TcGlobals * displayEnv: DisplayEnv * TType * TType * exn * range +exception ConstraintSolverMissingConstraint of displayEnv: DisplayEnv * Tast.Typar * Tast.TyparConstraint * range * range + +exception ConstraintSolverError of string * range * range + +exception ConstraintSolverRelatedInformation of string option * range * exn + +exception ErrorFromApplyingDefault of tcGlobals: TcGlobals * displayEnv: DisplayEnv * Tast.Typar * TType * exn * range + +exception ErrorFromAddingTypeEquation of tcGlobals: TcGlobals * displayEnv: DisplayEnv * TType * TType * exn * range + exception ErrorsFromAddingSubsumptionConstraint of tcGlobals: TcGlobals * displayEnv: DisplayEnv * TType * TType * exn * ContextInfo * range -exception ErrorFromAddingConstraint of displayEnv: DisplayEnv * exn * range -exception PossibleOverload of displayEnv: DisplayEnv * string * exn * range -exception UnresolvedOverloading of displayEnv: DisplayEnv * exn list * string * range -exception UnresolvedConversionOperator of displayEnv: DisplayEnv * TType * TType * range + +exception ErrorFromAddingConstraint of displayEnv: DisplayEnv * exn * range + +exception PossibleOverload of displayEnv: DisplayEnv * string * exn * range + +exception UnresolvedOverloading of displayEnv: DisplayEnv * exn list * string * range + +exception UnresolvedConversionOperator of displayEnv: DisplayEnv * TType * TType * range let GetPossibleOverloads amap m denv (calledMethGroup: (CalledMeth<_> * exn) list) = - calledMethGroup |> List.map (fun (cmeth, e) -> PossibleOverload(denv, NicePrint.stringOfMethInfo amap m denv cmeth.Method, e, m)) + calledMethGroup |> List.map (fun (cmeth, e) -> + PossibleOverload(denv, NicePrint.stringOfMethInfo amap m denv cmeth.Method, e, m)) type TcValF = (ValRef -> ValUseFlag -> TType list -> range -> Expr * TType) type ConstraintSolverState = { g: TcGlobals + amap: Import.ImportMap + InfoReader: InfoReader + + /// The function used to freshen values we encounter during trait constraint solving TcVal: TcValF + /// This table stores all unsolved, ungeneralized trait constraints, indexed by free type variable. /// That is, there will be one entry in this table for each free type variable in /// each outstanding, unsolved, ungeneralized trait constraint. Constraints are removed from the table and resolved @@ -196,20 +230,29 @@ type ConstraintSolverState = InfoReader = infoReader TcVal = tcVal } - type ConstraintSolverEnv = { SolverState: ConstraintSolverState + eContextInfo: ContextInfo + MatchingOnly: bool + m: range + EquivEnv: TypeEquivEnv + DisplayEnv: DisplayEnv } + member csenv.InfoReader = csenv.SolverState.InfoReader + member csenv.g = csenv.SolverState.g + member csenv.amap = csenv.SolverState.amap + override csenv.ToString() = " @ " + csenv.m.ToString() + let MakeConstraintSolverEnv contextInfo css m denv = { SolverState = css m = m @@ -219,11 +262,6 @@ let MakeConstraintSolverEnv contextInfo css m denv = EquivEnv = TypeEquivEnv.Empty DisplayEnv = denv } - -//------------------------------------------------------------------------- -// Occurs check -//------------------------------------------------------------------------- - /// Check whether a type variable occurs in the r.h.s. of a type, e.g. to catch /// infinite equations such as /// 'a = list<'a> @@ -287,9 +325,13 @@ let isDecimalTy g ty = typeEquivAux EraseMeasures g g.decimal_ty ty let IsNonDecimalNumericOrIntegralEnumType g ty = isIntegerOrIntegerEnumTy g ty || isFpTy g ty + let IsNumericOrIntegralEnumType g ty = IsNonDecimalNumericOrIntegralEnumType g ty || isDecimalTy g ty + let IsNonDecimalNumericType g ty = isIntegerTy g ty || isFpTy g ty + let IsNumericType g ty = IsNonDecimalNumericType g ty || isDecimalTy g ty + let IsRelationalType g ty = IsNumericType g ty || isStringTy g ty || isCharTy g ty || isBoolTy g ty // Get measure of type, float<_> or float32<_> or decimal<_> but not float=float<1> or float32=float32<1> or decimal=decimal<1> @@ -386,8 +428,11 @@ let ShowAccessDomain ad = // Solve exception NonRigidTypar of displayEnv: DisplayEnv * string option * range * TType * TType * range + exception LocallyAbortOperationThatFailsToResolveOverload + exception LocallyAbortOperationThatLosesAbbrevs + let localAbortD = ErrorD LocallyAbortOperationThatLosesAbbrevs /// Return true if we would rather unify this variable v1 := v2 than vice versa @@ -652,7 +697,6 @@ let NormalizeExponentsInTypeScheme uvars ty = SubstMeasure v (Measure.RationalPower (Measure.Var v', DivRational OneRational expGcd)) v') - // We normalize unit-of-measure-polymorphic type schemes. There // are three reasons for doing this: // (1) to present concise and consistent type schemes to the programmer @@ -732,8 +776,6 @@ let rec SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optio // Record a entry in the undo trace if one is provided trace.Exec (fun () -> r.typar_solution <- Some ty) (fun () -> r.typar_solution <- None) - (* dprintf "setting typar %d to type %s at %a\n" r.Stamp ((DebugPrint.showType ty)) outputRange m; *) - // Only solve constraints if this is not an error var if r.IsFromError then () else // Check to see if this type variable is relevant to any trait constraints. @@ -745,15 +787,17 @@ let rec SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optio | _ -> failwith "SolveTyparEqualsType" } - /// Apply the constraints on 'typar' to the type 'ty' and solveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty (r: Typar) = trackErrors { let g = csenv.g + // Propagate compat flex requirements from 'tp' to 'ty' do! SolveTypIsCompatFlex csenv trace r.IsCompatFlex ty + // Propagate dynamic requirements from 'tp' to 'ty' do! SolveTypDynamicReq csenv trace r.DynamicReq ty + // Propagate static requirements from 'tp' to 'ty' do! SolveTypStaticReq csenv trace r.StaticReq ty @@ -899,6 +943,7 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional let amap = csenv.amap let aenv = csenv.EquivEnv let denv = csenv.DisplayEnv + match sty1, sty2 with | TType_var tp1, _ -> match aenv.EquivTypars.TryFind tp1 with @@ -914,15 +959,19 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 (* nb. can unify since no variance *) + | TType_anon (anonInfo1, l1), TType_anon (anonInfo2, l2) -> SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2 ++ (fun () -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2) (* nb. can unify since no variance *) + | TType_fun (d1, r1), TType_fun (d2, r2) -> SolveFunTypeEqn csenv ndeep m2 trace cxsln d1 d2 r1 r2 (* nb. can unify since no variance *) + | TType_measure ms1, TType_measure ms2 -> UnifyMeasures csenv trace ms1 ms2 // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1> | (_, TType_app (tc2, [ms])) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms (TType_measure Measure.One) + | (TType_app (tc2, [ms]), _) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms (TType_measure Measure.One) @@ -973,6 +1022,7 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional let ty2arg = destArrayTy g ty2 SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ty1arg ty2arg | _ -> error(InternalError("destArrayTy", m)) + | _ -> // D :> Head<_> --> C :> Head<_> for the // first interface or super-class C supported by D which @@ -991,7 +1041,6 @@ and SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace cxsln ty1 ty2 = // Solve and record non-equality constraints //------------------------------------------------------------------------- - and SolveTyparSubtypeOfType (csenv: ConstraintSolverEnv) ndeep m2 trace tp ty1 = let g = csenv.g if isObjTy g ty1 then CompleteD @@ -1052,7 +1101,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | _ -> do! ErrorD (ConstraintSolverError(FSComp.SR.csExpectedArguments(), m, m2)) // Trait calls are only supported on pseudo type (variables) for e in tys do - do! SolveTypStaticReq csenv trace HeadTypeStaticReq e + do! SolveTypStaticReq csenv trace HeadTypeStaticReq e let argtys = if memFlags.IsInstance then List.tail argtys else argtys @@ -1108,14 +1157,18 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 (mkAppTy tcref [TType_measure ms2]) do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) return TTraitBuiltIn + | _ -> + match GetMeasureOfType g argty2 with | Some (tcref, ms2) -> let ms1 = freshMeasure () do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty1 (mkAppTy tcref [TType_measure ms1]) do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) return TTraitBuiltIn + | _ -> + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn @@ -1931,7 +1984,7 @@ and SolveTypeIsNonNullableValueType (csenv: ConstraintSolverEnv) ndeep m2 trace | _ -> let underlyingTy = stripTyEqnsAndMeasureEqns g ty if isStructTy g underlyingTy then - if isAppTy g underlyingTy && tyconRefEq g g.system_Nullable_tcref (tcrefOfAppTy g underlyingTy) then + if isNullableTy g underlyingTy then return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeParameterCannotBeNullable(), m, m)) else return! ErrorD (ConstraintSolverError(FSComp.SR.csGenericConstructRequiresStructType(NicePrint.minimalStringOfType denv ty), m, m2)) diff --git a/src/fsharp/DetupleArgs.fs b/src/fsharp/DetupleArgs.fs index 8ae41acb31..b15bae8f24 100755 --- a/src/fsharp/DetupleArgs.fs +++ b/src/fsharp/DetupleArgs.fs @@ -644,17 +644,26 @@ let hasTransfrom penv f = Zmap.tryFind f penv.transforms *) type env = - { eg : TcGlobals - prefix : string - m : Range.range } + { + eg: TcGlobals + + prefix: string + + m: Range.range + } + + override __.ToString() = "" let suffixE env s = {env with prefix = env.prefix + s} + let rangeE env m = {env with m = m} let push b bs = b :: bs + let pushL xs bs = xs@bs let newLocal env ty = mkCompGenLocal env.m env.prefix ty + let newLocalN env i ty = mkCompGenLocal env.m (env.prefix + string i) ty let noEffectExpr env bindings x = @@ -712,7 +721,6 @@ and collapseArgs env bindings n (callPattern) args = | _ts :: _tss, [] -> internalError "collapseArgs: CallPattern longer than callsite args. REPORT BUG" - //------------------------------------------------------------------------- // pass - app fixup //------------------------------------------------------------------------- diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index ee2b41f2e9..831597c031 100755 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -878,6 +878,7 @@ optsUtf8output,"Output messages in UTF-8 encoding" optsFullpaths,"Output messages with fully qualified paths" optsLib,"Specify a directory for the include path which is used to resolve source files and assemblies (Short form: -I)" optsBaseaddress,"Base address for the library to be built" +optsChecksumAlgorithm,"Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)" optsNoframework,"Do not reference the default CLI assemblies by default" optsStandalone,"Statically link the F# library and all referenced DLLs that depend on it into the assembly being generated" optsStaticlink,"Statically link the given assembly and all referenced DLLs that depend on this assembly. Use an assembly name e.g. mylib, not a DLL name." @@ -900,6 +901,7 @@ optsHelpBannerLanguage,"- LANGUAGE -" optsHelpBannerErrsAndWarns,"- ERRORS AND WARNINGS -" 1063,optsUnknownArgumentToTheTestSwitch,"Unknown --test argument: '%s'" 1064,optsUnknownPlatform,"Unrecognized platform '%s', valid values are 'x86', 'x64', 'Itanium', 'anycpu32bitpreferred', and 'anycpu'" +1065,optsUnknownChecksumAlgorithm,"Algorithm '%s' is not supported" optsInternalNoDescription,"The command-line option '%s' is for test purposes only" optsDCLONoDescription,"The command-line option '%s' has been deprecated" optsDCLODeprecatedSuggestAlternative,"The command-line option '%s' has been deprecated. Use '%s' instead." diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/Directory.Build.props b/src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props similarity index 100% rename from src/fsharp/FSharp.Compiler.Interactive.Settings/Directory.Build.props rename to src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj b/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj new file mode 100644 index 0000000000..fd6e517e54 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj @@ -0,0 +1,50 @@ + + + + + Exe + .exe + net472;netcoreapp3.0 + netcoreapp3.0 + true + Implements the Language Server Protocol (LSP) for F#. + true + + + + + + + + + + + + + + + + + + + + + + + + + + <_PublishedProjectOutputGroupFiles Include="$(PublishDir)\**" /> + + + + + + + + + + diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/JsonDUConverter.fs b/src/fsharp/FSharp.Compiler.LanguageServer/JsonDUConverter.fs new file mode 100644 index 0000000000..ae8575195d --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/JsonDUConverter.fs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System +open FSharp.Reflection +open Newtonsoft.Json + +type JsonDUConverter() = + inherit JsonConverter() + override __.CanConvert(typ) = FSharpType.IsUnion(typ) + override __.WriteJson(writer, value, _serializer) = + writer.WriteValue(value.ToString().ToLowerInvariant()) + override __.ReadJson(reader, typ, x, serializer) = + let cases = FSharpType.GetUnionCases(typ) + let str = serializer.Deserialize(reader, typeof) :?> string + let case = cases |> Array.find (fun c -> String.Compare(c.Name, str, StringComparison.OrdinalIgnoreCase) = 0) + FSharpValue.MakeUnion(case, [||]) diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/JsonOptionConverter.fs b/src/fsharp/FSharp.Compiler.LanguageServer/JsonOptionConverter.fs new file mode 100644 index 0000000000..937dda00e4 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/JsonOptionConverter.fs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System +open FSharp.Reflection +open Newtonsoft.Json + +type JsonOptionConverter() = + inherit JsonConverter() + override __.CanConvert(typ) = typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof> + override __.WriteJson(writer, value, serializer) = + let value = match value with + | null -> null + | _ -> + let _, fields = FSharpValue.GetUnionFields(value, value.GetType()) + fields.[0] + serializer.Serialize(writer, value) + override __.ReadJson(reader, typ, _, serializer) = + let innerType = typ.GetGenericArguments().[0] + let innerType = + if innerType.IsValueType then (typedefof>).MakeGenericType([|innerType|]) + else innerType + let value = serializer.Deserialize(reader, innerType) + let cases = FSharpType.GetUnionCases(typ) + if value = null then FSharpValue.MakeUnion(cases.[0], [||]) + else FSharpValue.MakeUnion(cases.[1], [|value|]) diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/LspExternalAccess.fs b/src/fsharp/FSharp.Compiler.LanguageServer/LspExternalAccess.fs new file mode 100644 index 0000000000..e6fa760d1c --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/LspExternalAccess.fs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open StreamJsonRpc + +[] +module FunctionNames = + [] + let OptionsSet = "options/set" + +type Options = + { usePreviewTextHover: bool } + static member Default() = + { usePreviewTextHover = false } + +module Extensions = + type JsonRpc with + member jsonRpc.SetOptionsAsync (options: Options) = + async { + do! jsonRpc.InvokeAsync(OptionsSet, options) |> Async.AwaitTask + } diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/LspTypes.fs b/src/fsharp/FSharp.Compiler.LanguageServer/LspTypes.fs new file mode 100644 index 0000000000..97479eef26 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/LspTypes.fs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open Newtonsoft.Json.Linq +open Newtonsoft.Json + +// Interfaces as defined at https://microsoft.github.io/language-server-protocol/specification. The properties on +// these types are camlCased to match the underlying JSON properties to avoid attributes on every field: +// [] + +/// Represents a zero-based line and column of a text document. +type Position = + { line: int + character: int } + +type Range = + { start: Position + ``end``: Position } + +type DocumentUri = string + +type Location = + { uri: DocumentUri + range: Range } + +type DiagnosticRelatedInformation = + { location: Location + message: string } + +type Diagnostic = + { range: Range + severity: int option + code: string + source: string option // "F#" + message: string + relatedInformation: DiagnosticRelatedInformation[] option } + static member Error = 1 + static member Warning = 2 + static member Information = 3 + static member Hint = 4 + +type PublishDiagnosticsParams = + { uri: DocumentUri + diagnostics: Diagnostic[] } + +type ClientCapabilities = + { workspace: JToken option // TODO: WorkspaceClientCapabilities + textDocument: JToken option // TODO: TextDocumentCapabilities + experimental: JToken option + supportsVisualStudioExtensions: bool option } + +[)>] +type Trace = + | Off + | Messages + | Verbose + +type WorkspaceFolder = + { uri: DocumentUri + name: string } + +/// Note, this type has many more optional values that can be expanded as support is added. +type ServerCapabilities = + { hoverProvider: bool } + static member DefaultCapabilities() = + { ServerCapabilities.hoverProvider = true } + +type InitializeResult = + { capabilities: ServerCapabilities } + +[)>] +type MarkupKind = + | PlainText + | Markdown + +type MarkupContent = + { kind: MarkupKind + value: string } + +type Hover = + { contents: MarkupContent + range: Range option } + +type TextDocumentIdentifier = + { uri: DocumentUri } diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/Methods.fs b/src/fsharp/FSharp.Compiler.LanguageServer/Methods.fs new file mode 100644 index 0000000000..d1e614cb29 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/Methods.fs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System +open System.Runtime.InteropServices +open System.Threading +open Newtonsoft.Json.Linq +open StreamJsonRpc + +// https://microsoft.github.io/language-server-protocol/specification +type Methods(state: State) = + + /// Helper to run Async<'T> with a CancellationToken. + let runAsync (cancellationToken: CancellationToken) (computation: Async<'T>) = Async.StartAsTask(computation, cancellationToken=cancellationToken) + + member __.State = state + + //-------------------------------------------------------------------------- + // official LSP methods + //-------------------------------------------------------------------------- + + [] + member __.Initialize + ( + processId: Nullable, + [] rootPath: string, + [] rootUri: DocumentUri, + [] initializationOptions: JToken, + capabilities: ClientCapabilities, + [] trace: string, + [] workspaceFolders: WorkspaceFolder[] + ) = + { InitializeResult.capabilities = ServerCapabilities.DefaultCapabilities() } + + [] + member __.Initialized () = () + + [] + member __.Shutdown(): obj = state.DoShutdown(); null + + [] + member __.Exit() = state.DoExit() + + [] + member __.cancelRequest (id: JToken) = state.DoCancel() + + [] + member __.TextDocumentHover + ( + textDocument: TextDocumentIdentifier, + position: Position, + [] cancellationToken: CancellationToken + ) = + TextDocument.Hover state textDocument position |> runAsync cancellationToken + + //-------------------------------------------------------------------------- + // unofficial LSP methods that we implement separately + //-------------------------------------------------------------------------- + + [] + member __.OptionsSet + ( + options: Options + ) = + sprintf "got options %A" options |> Console.Error.WriteLine + state.Options <- options diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs b/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs new file mode 100644 index 0000000000..13d0c9709f --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System + +module Program = + + [] + let main(args: string[]) = + async { + let server = new Server(Console.OpenStandardOutput(), Console.OpenStandardInput()) + server.StartListening() + do! server.WaitForExitAsync() + return 0 + } |> Async.RunSynchronously diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/Server.fs b/src/fsharp/FSharp.Compiler.LanguageServer/Server.fs new file mode 100644 index 0000000000..071ad6b226 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/Server.fs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System +open System.IO +open StreamJsonRpc + +type Server(sendingStream: Stream, receivingStream: Stream) = + + let formatter = JsonMessageFormatter() + let converter = JsonOptionConverter() // special handler to convert between `Option<'T>` and `obj/null`. + do formatter.JsonSerializer.Converters.Add(converter) + let handler = new HeaderDelimitedMessageHandler(sendingStream, receivingStream, formatter) + let state = State() + let methods = Methods(state) + let rpc = new JsonRpc(handler, methods) + + member __.StartListening() = + rpc.StartListening() + + member __.WaitForExitAsync() = + async { + do! Async.AwaitEvent (state.Shutdown) + do! Async.AwaitEvent (state.Exit) + } + + interface IDisposable with + member __.Dispose() = + rpc.Dispose() diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/State.fs b/src/fsharp/FSharp.Compiler.LanguageServer/State.fs new file mode 100644 index 0000000000..5ca2d3f845 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/State.fs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +type State() = + + let shutdownEvent = new Event<_>() + let exitEvent = new Event<_>() + let cancelEvent = new Event<_>() + + [] + member __.Shutdown = shutdownEvent.Publish + + [] + member __.Exit = exitEvent.Publish + + [] + member __.Cancel = cancelEvent.Publish + + member __.DoShutdown() = shutdownEvent.Trigger() + + member __.DoExit() = exitEvent.Trigger() + + member __.DoCancel() = cancelEvent.Trigger() + + member val Options = Options.Default() with get, set diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs b/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs new file mode 100644 index 0000000000..0c73796505 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.LanguageServer + +open System + +module TextDocument = + + let Hover (state: State) (textDocument: TextDocumentIdentifier) (position: Position) = + async { + Console.Error.WriteLine("hover at " + position.line.ToString() + "," + position.character.ToString()) + if not state.Options.usePreviewTextHover then return None + else + let startCol, endCol = + if position.character = 0 then 0, 1 + else position.character, position.character + 1 + return Some { contents = { kind = MarkupKind.PlainText + value = "serving textDocument/hover from LSP" } + range = Some { start = { line = position.line; character = startCol } + ``end`` = { line = position.line; character = endCol } } + } + } + + let PublishDiagnostics(state: State) = + async { + return { + PublishDiagnosticsParams.uri = "" + diagnostics = [||] + } + } diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj index fd2d5162c7..512bfaad70 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuget.csproj @@ -6,7 +6,7 @@ FSharp.Core FSharp.Core.nuspec true - FSharp.Core redistributables from Visual F# Tools version $(FSPackageMajorVersion) For F# $(FSCoreMajorVersion) + FSharp.Core redistributables from Visual F# Tools version $(FSPackageMajorVersion) For F# $(FSCoreMajorVersion). Contains code from the F# Software Foundation. diff --git a/src/fsharp/FSharp.Core/Linq.fs b/src/fsharp/FSharp.Core/Linq.fs index 4663e6f79a..e4deedbf07 100644 --- a/src/fsharp/FSharp.Core/Linq.fs +++ b/src/fsharp/FSharp.Core/Linq.fs @@ -744,7 +744,12 @@ module LeafExpressionConverter = Expression.Lambda(dty, bodyP, vsP) |> asExpr | Patterns.NewTuple args -> - let tupTy = args |> List.map (fun arg -> arg.Type) |> Array.ofList |> Reflection.FSharpType.MakeTupleType + let tupTy = + let argTypes = args |> List.map (fun arg -> arg.Type) |> Array.ofList + if inp.Type.IsValueType then + Reflection.FSharpType.MakeStructTupleType(inp.Type.Assembly, argTypes) + else + Reflection.FSharpType.MakeTupleType(argTypes) let argsP = ConvExprsToLinq env args let rec build ty (argsP: Expression[]) = match Reflection.FSharpValue.PreComputeTupleConstructorInfo ty with diff --git a/src/fsharp/FindUnsolved.fs b/src/fsharp/FindUnsolved.fs index ac64aa6c1d..d11a128417 100755 --- a/src/fsharp/FindUnsolved.fs +++ b/src/fsharp/FindUnsolved.fs @@ -21,6 +21,8 @@ type cenv = denv: DisplayEnv mutable unsolved: Typars } + override x.ToString() = "" + /// Walk types, collecting type variables let accTy cenv _env ty = let normalizedTy = tryNormalizeMeasureInType cenv.g ty diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index c188b54807..5e61742fd9 100755 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -245,8 +245,16 @@ type cenv = /// Used to apply forced inlining optimizations to witnesses generated late during codegen mutable optimizeDuringCodeGen: (Expr -> Expr) + + /// What depth are we at when generating an expression? + mutable exprRecursionDepth: int + + /// Delayed Method Generation - prevents stack overflows when we need to generate methods that are split into many methods by the optimizer. + delayedGenMethods: Queue unit> } + override x.ToString() = "" + let mkTypeOfExpr cenv m ilty = let g = cenv.g @@ -765,17 +773,26 @@ and NamedLocalIlxClosureInfo = | NamedLocalIlxClosureInfoGenerator of (IlxGenEnv -> IlxClosureInfo) | NamedLocalIlxClosureInfoGenerated of IlxClosureInfo + override __.ToString() = "" + /// Indicates the overall representation decisions for all the elements of a namespace of module and ModuleStorage = - { Vals: Lazy> - SubModules: Lazy> } + { + Vals: Lazy> + + SubModules: Lazy> + } + + override __.ToString() = "" /// Indicate whether a call to the value can be implemented as /// a branch. At the moment these are only used for generating branch calls back to /// the entry label of the method currently being generated when a direct tailcall is /// made in the method itself. and BranchCallItem = + | BranchCallClosure of ArityInfo + | BranchCallMethod of // Argument counts for compiled form of F# method or value ArityInfo * @@ -787,6 +804,8 @@ and BranchCallItem = int * // num obj args int + + override __.ToString() = "" /// Represents a place we can branch to and Mark = @@ -826,8 +845,17 @@ and IlxGenEnv = /// Are we under the scope of a try, catch or finally? If so we can't tailcall. SEH = structured exception handling withinSEH: bool + + /// Are we inside of a recursive let binding, while loop, or a for loop? + isInLoop: bool } + override __.ToString() = "" + +let SetIsInLoop isInLoop eenv = + if eenv.isInLoop = isInLoop then eenv + else { eenv with isInLoop = isInLoop } + let ReplaceTyenv tyenv (eenv: IlxGenEnv) = {eenv with tyenv = tyenv } let EnvForTypars tps eenv = {eenv with tyenv = TypeReprEnv.ForTypars tps } @@ -2130,20 +2158,53 @@ let DoesGenExprStartWithSequencePoint g sp expr = FirstEmittedCodeWillBeSequencePoint g sp expr || EmitSequencePointForWholeExpr g sp expr +let ProcessSequencePointForExpr (cenv: cenv) (cgbuf: CodeGenBuffer) sp expr = + let g = cenv.g + if not (FirstEmittedCodeWillBeSequencePoint g sp expr) then + if EmitSequencePointForWholeExpr g sp expr then + CG.EmitSeqPoint cgbuf (RangeOfSequencePointForWholeExpr g expr) + elif EmitHiddenCodeMarkerForWholeExpr g sp expr then + cgbuf.EmitStartOfHiddenCode() + //------------------------------------------------------------------------- // Generate expressions //------------------------------------------------------------------------- -let rec GenExpr (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = +let rec GenExpr cenv cgbuf eenv sp (expr: Expr) sequel = + cenv.exprRecursionDepth <- cenv.exprRecursionDepth + 1 + + if cenv.exprRecursionDepth > 1 then + StackGuard.EnsureSufficientExecutionStack cenv.exprRecursionDepth + GenExprAux cenv cgbuf eenv sp expr sequel + else + GenExprWithStackGuard cenv cgbuf eenv sp expr sequel + + cenv.exprRecursionDepth <- cenv.exprRecursionDepth - 1 + + if cenv.exprRecursionDepth = 0 then + ProcessDelayedGenMethods cenv + +and ProcessDelayedGenMethods cenv = + while cenv.delayedGenMethods.Count > 0 do + let gen = cenv.delayedGenMethods.Dequeue () + gen cenv + +and GenExprWithStackGuard cenv cgbuf eenv sp expr sequel = + assert (cenv.exprRecursionDepth = 1) + try + GenExprAux cenv cgbuf eenv sp expr sequel + assert (cenv.exprRecursionDepth = 1) + with + | :? System.InsufficientExecutionStackException -> + error(InternalError("Expression is too large and/or complex to emit.", expr.Range)) + +and GenExprAux (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = let g = cenv.g let expr = stripExpr expr - if not (FirstEmittedCodeWillBeSequencePoint g sp expr) then - if EmitSequencePointForWholeExpr g sp expr then - CG.EmitSeqPoint cgbuf (RangeOfSequencePointForWholeExpr g expr) - elif EmitHiddenCodeMarkerForWholeExpr g sp expr then - cgbuf.EmitStartOfHiddenCode() + ProcessSequencePointForExpr cenv cgbuf sp expr + // A sequence expression will always match Expr.App. match (if compileSequenceExpressions then LowerCallsAndSeqs.LowerSeqExpr g cenv.amap expr else None) with | Some info -> GenSequenceExpr cenv cgbuf eenv info sequel @@ -2154,32 +2215,8 @@ let rec GenExpr (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = GenConstant cenv cgbuf eenv (c, m, ty) sequel | Expr.Match (spBind, exprm, tree, targets, m, ty) -> GenMatch cenv cgbuf eenv (spBind, exprm, tree, targets, m, ty) sequel - | Expr.Sequential (e1, e2, dir, spSeq, m) -> - GenSequential cenv cgbuf eenv sp (e1, e2, dir, spSeq, m) sequel | Expr.LetRec (binds, body, m, _) -> GenLetRec cenv cgbuf eenv (binds, body, m) sequel - | Expr.Let (bind, body, _, _) -> - // This case implemented here to get a guaranteed tailcall - // Make sure we generate the sequence point outside the scope of the variable - let startScope, endScope as scopeMarks = StartDelayedLocalScope "let" cgbuf - let eenv = AllocStorageForBind cenv cgbuf scopeMarks eenv bind - let spBind = GenSequencePointForBind cenv cgbuf bind - GenBindingAfterSequencePoint cenv cgbuf eenv spBind bind (Some startScope) - - // Work out if we need a sequence point for the body. For any "user" binding then the body gets SPAlways. - // For invisible compiler-generated bindings we just use "sp", unless its body is another invisible binding - // For sticky bindings arising from inlining we suppress any immediate sequence point in the body - let spBody = - match bind.SequencePointInfo with - | SequencePointAtBinding _ - | NoSequencePointAtLetBinding - | NoSequencePointAtDoBinding -> SPAlways - | NoSequencePointAtInvisibleBinding -> sp - | NoSequencePointAtStickyBinding -> SPSuppress - - // Generate the body - GenExpr cenv cgbuf eenv spBody body (EndLocalScope(sequel, endScope)) - | Expr.Lambda _ | Expr.TyLambda _ -> GenLambda cenv cgbuf eenv false None expr sequel | Expr.App (Expr.Val (vref, _, m) as v, _, tyargs, [], _) when @@ -2200,8 +2237,10 @@ let rec GenExpr (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = // Most generation of linear expressions is implemented routinely using tailcalls and the correct sequels. // This is because the element of expansion happens to be the final thing generated in most cases. However // for large lists we have to process the linearity separately + | Expr.Sequential _ + | Expr.Let _ | LinearOpExpr _ -> - GenLinearExpr cenv cgbuf eenv expr sequel id |> ignore + GenLinearExpr cenv cgbuf eenv sp expr sequel (* canProcessSequencePoint *) false id |> ignore | Expr.Op (op, tyargs, args, m) -> match op, args, tyargs with @@ -2515,16 +2554,64 @@ and GenAllocUnionCase cenv cgbuf eenv (c,tyargs,args,m) sequel = GenAllocUnionCaseCore cenv cgbuf eenv (c,tyargs,args.Length,m) GenSequel cenv eenv.cloc cgbuf sequel -and GenLinearExpr cenv cgbuf eenv expr sequel (contf: FakeUnit -> FakeUnit) = +and GenLinearExpr cenv cgbuf eenv sp expr sequel canProcessSequencePoint (contf: FakeUnit -> FakeUnit) = + let expr = stripExpr expr match expr with - | LinearOpExpr (TOp.UnionCase c, tyargs, argsFront, argLast, m) -> + | LinearOpExpr (TOp.UnionCase c, tyargs, argsFront, argLast, m) -> GenExprs cenv cgbuf eenv argsFront - GenLinearExpr cenv cgbuf eenv argLast Continue (contf << (fun Fake -> + GenLinearExpr cenv cgbuf eenv SPSuppress argLast Continue (* canProcessSequencePoint *) true (contf << (fun Fake -> GenAllocUnionCaseCore cenv cgbuf eenv (c, tyargs, argsFront.Length + 1, m) GenSequel cenv eenv.cloc cgbuf sequel Fake)) + + | Expr.Sequential (e1, e2, specialSeqFlag, spSeq, _) -> + if canProcessSequencePoint then + ProcessSequencePointForExpr cenv cgbuf sp expr + + // Compiler generated sequential executions result in suppressions of sequence points on both + // left and right of the sequence + let spAction, spExpr = + (match spSeq with + | SequencePointsAtSeq -> SPAlways, SPAlways + | SuppressSequencePointOnExprOfSequential -> SPSuppress, sp + | SuppressSequencePointOnStmtOfSequential -> sp, SPSuppress) + match specialSeqFlag with + | NormalSeq -> + GenExpr cenv cgbuf eenv spAction e1 discard + GenLinearExpr cenv cgbuf eenv spExpr e2 sequel (* canProcessSequencePoint *) true contf + | ThenDoSeq -> + GenExpr cenv cgbuf eenv spExpr e1 Continue + GenExpr cenv cgbuf eenv spAction e2 discard + GenSequel cenv eenv.cloc cgbuf sequel + contf Fake + + | Expr.Let (bind, body, _, _) -> + if canProcessSequencePoint then + ProcessSequencePointForExpr cenv cgbuf sp expr + + // This case implemented here to get a guaranteed tailcall + // Make sure we generate the sequence point outside the scope of the variable + let startScope, endScope as scopeMarks = StartDelayedLocalScope "let" cgbuf + let eenv = AllocStorageForBind cenv cgbuf scopeMarks eenv bind + let spBind = GenSequencePointForBind cenv cgbuf bind + GenBindingAfterSequencePoint cenv cgbuf eenv spBind bind (Some startScope) + + // Work out if we need a sequence point for the body. For any "user" binding then the body gets SPAlways. + // For invisible compiler-generated bindings we just use "sp", unless its body is another invisible binding + // For sticky bindings arising from inlining we suppress any immediate sequence point in the body + let spBody = + match bind.SequencePointInfo with + | SequencePointAtBinding _ + | NoSequencePointAtLetBinding + | NoSequencePointAtDoBinding -> SPAlways + | NoSequencePointAtInvisibleBinding -> sp + | NoSequencePointAtStickyBinding -> SPSuppress + + // Generate the body + GenLinearExpr cenv cgbuf eenv spBody body (EndLocalScope(sequel, endScope)) (* canProcessSequencePoint *) true contf + | _ -> - GenExpr cenv cgbuf eenv SPSuppress expr sequel + GenExpr cenv cgbuf eenv sp expr sequel contf Fake and GenAllocRecd cenv cgbuf eenv ctorInfo (tcref,argtys,args,m) sequel = @@ -3369,6 +3456,7 @@ and GenTryFinally cenv cgbuf eenv (bodyExpr, handlerExpr, m, resty, spTry, spFin //-------------------------------------------------------------------------- and GenForLoop cenv cgbuf eenv (spFor, v, e1, dir, e2, loopBody, m) sequel = + let eenv = SetIsInLoop true eenv let g = cenv.g // The JIT/NGen eliminate array-bounds checks for C# loops of form: @@ -3459,6 +3547,7 @@ and GenForLoop cenv cgbuf eenv (spFor, v, e1, dir, e2, loopBody, m) sequel = //-------------------------------------------------------------------------- and GenWhileLoop cenv cgbuf eenv (spWhile, e1, e2, m) sequel = + let eenv = SetIsInLoop true eenv let finish = CG.GenerateDelayMark cgbuf "while_finish" let startTest = CG.GenerateMark cgbuf "startTest" @@ -3475,28 +3564,6 @@ and GenWhileLoop cenv cgbuf eenv (spWhile, e1, e2, m) sequel = // SEQUENCE POINTS: Emit a sequence point to cover 'done' if present GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel -//-------------------------------------------------------------------------- -// Generate seq -//-------------------------------------------------------------------------- - -and GenSequential cenv cgbuf eenv spIn (e1, e2, specialSeqFlag, spSeq, _m) sequel = - - // Compiler generated sequential executions result in suppressions of sequence points on both - // left and right of the sequence - let spAction, spExpr = - (match spSeq with - | SequencePointsAtSeq -> SPAlways, SPAlways - | SuppressSequencePointOnExprOfSequential -> SPSuppress, spIn - | SuppressSequencePointOnStmtOfSequential -> spIn, SPSuppress) - match specialSeqFlag with - | NormalSeq -> - GenExpr cenv cgbuf eenv spAction e1 discard - GenExpr cenv cgbuf eenv spExpr e2 sequel - | ThenDoSeq -> - GenExpr cenv cgbuf eenv spExpr e1 Continue - GenExpr cenv cgbuf eenv spAction e2 discard - GenSequel cenv eenv.cloc cgbuf sequel - //-------------------------------------------------------------------------- // Generate IL assembly code. // Polymorphic IL/ILX instructions may be instantiated when polymorphic code is inlined. @@ -5083,6 +5150,7 @@ and GenLetRecFixup cenv cgbuf eenv (ilxCloSpec: IlxClosureSpec, e, ilField: ILFi /// Generate letrec bindings and GenLetRecBindings cenv (cgbuf: CodeGenBuffer) eenv (allBinds: Bindings, m) = + let eenv = SetIsInLoop true eenv // Fix up recursion for non-toplevel recursive bindings let bindsPossiblyRequiringFixup = allBinds |> List.filter (fun b -> @@ -5210,7 +5278,14 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s let tps, ctorThisValOpt, baseValOpt, vsl, body', bodyty = IteratedAdjustArityOfLambda g cenv.amap topValInfo rhsExpr let methodVars = List.concat vsl CommitStartScope cgbuf startScopeMarkOpt - GenMethodForBinding cenv cgbuf eenv (vspec, mspec, access, paramInfos, retInfo) (topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body', bodyty) + + let ilxMethInfoArgs = + (vspec, mspec, access, paramInfos, retInfo, topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body', bodyty) + // if we have any expression recursion depth, we should delay the generation of a method to prevent stack overflows + if cenv.exprRecursionDepth > 0 then + DelayGenMethodForBinding cenv cgbuf.mgbuf eenv ilxMethInfoArgs + else + GenMethodForBinding cenv cgbuf.mgbuf eenv ilxMethInfoArgs | StaticProperty (ilGetterMethSpec, optShadowLocal) -> @@ -5324,8 +5399,8 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s | _ -> let storage = StorageForVal cenv.g m vspec eenv match storage, rhsExpr with - // locals are zero-init, no need to initialize them - | Local (_, realloc, _), Expr.Const (Const.Zero, _, _) when not realloc -> + // locals are zero-init, no need to initialize them, except if you are in a loop and the local is mutable. + | Local (_, realloc, _), Expr.Const (Const.Zero, _, _) when not realloc && not (eenv.isInLoop && vspec.IsMutable) -> CommitStartScope cgbuf startScopeMarkOpt | _ -> GenBindingRhs cenv cgbuf eenv SPSuppress vspec rhsExpr @@ -5649,11 +5724,10 @@ and ComputeMethodImplAttribs cenv (_v: Val) attrs = let hasAggressiveInliningImplFlag = (implflags &&& 0x0100) <> 0x0 hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, hasAggressiveInliningImplFlag, attrs -and GenMethodForBinding - cenv cgbuf eenv - (v: Val, mspec, access, paramInfos, retInfo) - (topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body, returnTy) = +and DelayGenMethodForBinding cenv mgbuf eenv ilxMethInfoArgs = + cenv.delayedGenMethods.Enqueue (fun cenv -> GenMethodForBinding cenv mgbuf eenv ilxMethInfoArgs) +and GenMethodForBinding cenv mgbuf eenv (v, mspec, access, paramInfos, retInfo, topValInfo, ctorThisValOpt, baseValOpt, tps, methodVars, methodArgTys, body, returnTy) = let g = cenv.g let m = v.Range let selfMethodVars, nonSelfMethodVars, compileAsInstance = @@ -5714,7 +5788,7 @@ and GenMethodForBinding else body - let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) + let ilCode = CodeGenMethodForExpr cenv mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) // This is the main code generation for most methods false, MethodBody.IL ilCode, false @@ -5780,7 +5854,7 @@ and GenMethodForBinding else mdef CountMethodDef() - cgbuf.mgbuf.AddMethodDef(tref, mdef) + mgbuf.AddMethodDef(tref, mdef) match v.MemberInfo with @@ -5817,7 +5891,7 @@ and GenMethodForBinding let mdef = List.fold (fun mdef f -> f mdef) mdef flagFixups // fixup can potentially change name of reflected definition that was already recorded - patch it if necessary - cgbuf.mgbuf.ReplaceNameOfReflectedDefinition(v, mdef.Name) + mgbuf.ReplaceNameOfReflectedDefinition(v, mdef.Name) mdef else mkILGenericNonVirtualMethod (v.CompiledName g.CompilerGlobalState, access, ilMethTypars, ilParams, ilReturn, ilMethodBody) @@ -5844,7 +5918,7 @@ and GenMethodForBinding // Emit the pseudo-property as an event, but not if its a private method impl if mdef.Access <> ILMemberAccess.Private then let edef = GenEventForProperty cenv eenvForMeth mspec v ilAttrsThatGoOnPrimaryItem m returnTy - cgbuf.mgbuf.AddEventDef(tref, edef) + mgbuf.AddEventDef(tref, edef) // The method def is dropped on the floor here else @@ -5854,7 +5928,7 @@ and GenMethodForBinding let ilPropTy = GenType cenv.amap m eenvUnderMethTypeTypars.tyenv vtyp let ilArgTys = v |> ArgInfosOfPropertyVal g |> List.map fst |> GenTypes cenv.amap m eenvUnderMethTypeTypars.tyenv let ilPropDef = GenPropertyForMethodDef compileAsInstance tref mdef v memberInfo ilArgTys ilPropTy (mkILCustomAttrs ilAttrsThatGoOnPrimaryItem) compiledName - cgbuf.mgbuf.AddOrMergePropertyDef(tref, ilPropDef, m) + mgbuf.AddOrMergePropertyDef(tref, ilPropDef, m) // Add the special name flag for all properties let mdef = mdef.WithSpecialName.With(customAttrs= mkILCustomAttrs ((GenAttrs cenv eenv attrsAppliedToGetterOrSetter) @ sourceNameAttribs @ ilAttrsCompilerGenerated)) @@ -7463,7 +7537,8 @@ let GetEmptyIlxGenEnv (ilg: ILGlobals) ccu = liveLocals=IntMap.empty() innerVals = [] sigToImplRemapInfo = [] (* "module remap info" *) - withinSEH = false } + withinSEH = false + isInLoop = false } type IlxGenResults = { ilTypeDefs: ILTypeDef list @@ -7668,7 +7743,9 @@ type IlxAssemblyGenerator(amap: ImportMap, tcGlobals: TcGlobals, tcVal: Constrai casApplied = casApplied intraAssemblyInfo = intraAssemblyInfo opts = codeGenOpts - optimizeDuringCodeGen = (fun x -> x) } + optimizeDuringCodeGen = (fun x -> x) + exprRecursionDepth = 0 + delayedGenMethods = Queue () } GenerateCode (cenv, anonTypeTable, ilxGenEnv, typedAssembly, assemAttribs, moduleAttribs) /// Invert the compilation of the given value and clear the storage of the value diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 5a8d66c875..895f2d1f72 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -20,6 +20,7 @@ open FSharp.Compiler.Tastops.DebugPrint open FSharp.Compiler.TcGlobals open FSharp.Compiler.TypeRelations open FSharp.Compiler.AttributeChecking +open Internal.Utilities #if !NO_EXTENSIONTYPING open FSharp.Compiler.ExtensionTyping @@ -151,7 +152,9 @@ let AdjustCalledArgType (infoReader: InfoReader) isConstraint (calledArg: Called mkRefCellTy g (destByrefTy g calledArgTy) else - // If the called method argument is a delegate type, then the caller may provide a function + // If the called method argument is a delegate type, and the caller is known to be a function type, then the caller may provide a function + // If the called method argument is an Expression type, and the caller is known to be a function type, then the caller may provide a T + // If the called method argument is an [] Quotations.Expr, and the caller is not known to be a quoted expression type, then the caller may provide a T let calledArgTy = let adjustDelegateTy calledTy = let (SigOfFunctionForDelegate(_, delArgTys, _, fty)) = GetSigOfFunctionForDelegate infoReader calledTy m AccessibleFromSomewhere @@ -178,14 +181,18 @@ let AdjustCalledArgType (infoReader: InfoReader) isConstraint (calledArg: Called else calledArgTy // Adjust the called argument type to take into account whether the caller's argument is M(?arg=Some(3)) or M(arg=1) - // If the called method argument is optional with type Option, then the caller may provide a T, unless their argument is propagating-optional (i.e. isOptCallerArg) + // If the called method argument is Callee-side optional with type Option, and the caller argument is not explicitly optional (callerArg.IsOptional), then the caller may provide a T + // If the called method argument is Caller-side optional with type Nullable, and the caller argument is not explicitly optional (callerArg.IsOptional), then the caller may provide a T let calledArgTy = match calledArg.OptArgInfo with - | NotOptional -> calledArgTy + | NotOptional -> calledArgTy | CalleeSide when not callerArg.IsOptional && isOptionTy g calledArgTy -> destOptionTy g calledArgTy - | CalleeSide | CallerSide _ -> calledArgTy - calledArgTy - + // This will be added in https://github.com/dotnet/fsharp/pull/7276 + //| CallerSide _ when not callerArg.IsOptional && isNullableTy g calledArgTy -> destNullableTy g calledArgTy + | CalleeSide + | CallerSide _ -> calledArgTy + + calledArgTy //------------------------------------------------------------------------- // CalledMeth @@ -540,6 +547,351 @@ let ExamineMethodForLambdaPropagation (x: CalledMeth) = else None +//------------------------------------------------------------------------- +// Adjust caller arguments as part of building a method call +//------------------------------------------------------------------------- + +/// Build a call to the System.Object constructor taking no arguments, +let BuildObjCtorCall (g: TcGlobals) m = + let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object, [])).MethodRef + Expr.Op (TOp.ILCall (false, false, false, false, CtorValUsedAsSuperInit, false, true, ilMethRef, [], [], [g.obj_ty]), [], [], m) + +/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites +let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, invokeMethInfo: MethInfo, delArgTys, f, fty, m) = + let slotsig = invokeMethInfo.GetSlotSig(amap, m) + let delArgVals, expr = + let topValInfo = ValReprInfo([], List.replicate (max 1 (List.length delArgTys)) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) + + // Try to pull apart an explicit lambda and use it directly + // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler + let lambdaContents = + if Option.isSome eventInfoOpt then + None + else + tryDestTopLambda g amap topValInfo (f, fty) + + match lambdaContents with + | None -> + + if List.exists (isByrefTy g) delArgTys then + error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys), m)) + + let delArgVals = delArgTys |> List.mapi (fun i argty -> fst (mkCompGenLocal m ("delegateArg" + string i) argty)) + let expr = + let args = + match eventInfoOpt with + | Some einfo -> + match delArgVals with + | [] -> error(nonStandardEventError einfo.EventName m) + | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) + | h :: t -> [exprForVal m h; mkRefTupledVars g m t] + | None -> + if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals + mkApps g ((f, fty), [], args, m) + delArgVals, expr + + | Some _ -> + let _, _, _, vsl, body, _ = IteratedAdjustArityOfLambda g amap topValInfo f + List.concat vsl, body + + let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) + mkObjExpr(delegateTy, None, BuildObjCtorCall g m, [meth], [], m) + +let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = + let (SigOfFunctionForDelegate(invokeMethInfo, delArgTys, _, _)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad + BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) + +// Handle adhoc argument conversions +let AdjustCallerArgExprForCoercions (g: TcGlobals) amap infoReader ad isOutArg calledArgTy (reflArgInfo: ReflectedArgInfo) callerArgTy m callerArgExpr = + + if isByrefTy g calledArgTy && isRefCellTy g callerArgTy then + None, Expr.Op (TOp.RefAddrGet false, [destRefCellTy g callerArgTy], [callerArgExpr], m) + +#if IMPLICIT_ADDRESS_OF + elif isInByrefTy g calledArgTy && not (isByrefTy g callerArgTy) then + let wrap, callerArgExprAddress, _readonly, _writeonly = mkExprAddrOfExpr g true false NeverMutates callerArgExpr None m + Some wrap, callerArgExprAddress +#endif + + elif isDelegateTy g calledArgTy && isFunTy g callerArgTy then + None, CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr calledArgTy + + elif isLinqExpressionTy g calledArgTy && isDelegateTy g (destLinqExpressionTy g calledArgTy) && isFunTy g callerArgTy then + let delegateTy = destLinqExpressionTy g calledArgTy + let expr = CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy + None, mkCallQuoteToLinqLambdaExpression g m delegateTy (Expr.Quote (expr, ref None, false, m, mkQuotedExprTy g delegateTy)) + + // auto conversions to quotations (to match auto conversions to LINQ expressions) + elif reflArgInfo.AutoQuote && isQuotedExprTy g calledArgTy && not (isQuotedExprTy g callerArgTy) then + match reflArgInfo with + | ReflectedArgInfo.Quote true -> + None, mkCallLiftValueWithDefn g m calledArgTy callerArgExpr + | ReflectedArgInfo.Quote false -> + None, Expr.Quote (callerArgExpr, ref None, false, m, calledArgTy) + | ReflectedArgInfo.None -> failwith "unreachable" // unreachable due to reflArgInfo.AutoQuote condition + + // Note: out args do not need to be coerced + elif isOutArg then + None, callerArgExpr + + // Note: not all these casts are reported in quotations + else + None, mkCoerceIfNeeded g calledArgTy callerArgTy callerArgExpr + +// Handle CallerSide optional arguments. +// +// CallerSide optional arguments are largely for COM interop, e.g. to PIA assemblies for Word etc. +// As a result we follow the VB and C# behavior here. +// +// "1. If the parameter is statically typed as System.Object and does not have a value, then there are four cases: +// a. The parameter is marked with MarshalAs(IUnknown), MarshalAs(Interface), or MarshalAs(IDispatch). In this case we pass null. +// b. Else if the parameter is marked with IUnknownConstantAttribute. In this case we pass new System.Runtime.InteropServices.UnknownWrapper(null) +// c. Else if the parameter is marked with IDispatchConstantAttribute. In this case we pass new System.Runtime.InteropServices.DispatchWrapper(null) +// d. Else, we will pass Missing.Value. +// 2. Otherwise, if there is a value attribute, then emit the default value. +// 3. Otherwise, we emit default(T). +// 4. Finally, we apply conversions from the value to the parameter type. This is where the nullable conversions take place for VB. +// - VB allows you to mark ref parameters as optional. The semantics of this is that we create a temporary +// with type = type of parameter, load the optional value to it, and call the method. +// - VB also allows you to mark arrays with Nothing as the optional value. +// - VB also allows you to pass intrinsic values as optional values to parameters +// typed as Object. What we do in this case is we box the intrinsic value." +// +let AdjustOptionalCallerArgExprs tcFieldInit eCallerMemberName g (calledMeth: CalledMeth<_>) mItem mMethExpr = + + let assignedNamedArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.AssignedNamedArgs) + let unnamedCalledArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.UnnamedCalledArgs) + let unnamedCallerArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.UnnamedCallerArgs) + let unnamedArgs = + (unnamedCalledArgs, unnamedCallerArgs) ||> List.map2 (fun called caller -> + { NamedArgIdOpt = None; CalledArg=called; CallerArg=caller }) + + let emptyPreBinder (e: Expr) = e + + // Adjust all the optional arguments that require a default value to be inserted into the call + let optArgs, optArgPreBinder = + (emptyPreBinder, calledMeth.UnnamedCalledOptArgs) ||> List.mapFold (fun wrapper calledArg -> + let calledArgTy = calledArg.CalledArgumentType + let wrapper2, expr = + match calledArg.OptArgInfo with + | NotOptional -> + error(InternalError("Unexpected NotOptional", mItem)) + + | CallerSide dfltVal -> + + let rec build currCalledArgTy currDfltVal = + match currDfltVal with + | MissingValue -> + // Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr. + emptyPreBinder, mkAsmExpr ([ mkNormalLdsfld (fspec_Missing_Value g); AI_nop ], [], [], [currCalledArgTy], mMethExpr) + + | DefaultValue -> + emptyPreBinder, mkDefault(mMethExpr, currCalledArgTy) + + | Constant fieldInit -> + match currCalledArgTy with + | NullableTy g inst when fieldInit <> ILFieldInit.Null -> + let nullableTy = mkILNonGenericBoxedTy(g.FindSysILTypeRef "System.Nullable`1") + let ctor = mkILCtorMethSpecForTy(nullableTy, [ILType.TypeVar 0us]).MethodRef + let ctorArgs = [Expr.Const (tcFieldInit mMethExpr fieldInit, mMethExpr, inst)] + emptyPreBinder, Expr.Op (TOp.ILCall (false, false, true, true, NormalValUse, false, false, ctor, [inst], [], [currCalledArgTy]), [], ctorArgs, mMethExpr) + | ByrefTy g inst -> + build inst (PassByRef(inst, currDfltVal)) + | _ -> + match calledArg.CallerInfo, eCallerMemberName with + | CallerLineNumber, _ when typeEquiv g currCalledArgTy g.int_ty -> + emptyPreBinder, Expr.Const (Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) + | CallerFilePath, _ when typeEquiv g currCalledArgTy g.string_ty -> + let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply g.pathMap + emptyPreBinder, Expr.Const (Const.String fileName, mMethExpr, currCalledArgTy) + | CallerMemberName, Some callerName when (typeEquiv g currCalledArgTy g.string_ty) -> + emptyPreBinder, Expr.Const (Const.String callerName, mMethExpr, currCalledArgTy) + | _ -> + emptyPreBinder, Expr.Const (tcFieldInit mMethExpr fieldInit, mMethExpr, currCalledArgTy) + + | WrapperForIDispatch -> + match g.TryFindSysILTypeRef "System.Runtime.InteropServices.DispatchWrapper" with + | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) + | Some tref -> + let ty = mkILNonGenericBoxedTy tref + let mref = mkILCtorMethSpecForTy(ty, [g.ilg.typ_Object]).MethodRef + let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) + emptyPreBinder, expr + + | WrapperForIUnknown -> + match g.TryFindSysILTypeRef "System.Runtime.InteropServices.UnknownWrapper" with + | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) + | Some tref -> + let ty = mkILNonGenericBoxedTy tref + let mref = mkILCtorMethSpecForTy(ty, [g.ilg.typ_Object]).MethodRef + let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) + emptyPreBinder, expr + + | PassByRef (ty, dfltVal2) -> + let v, _ = mkCompGenLocal mMethExpr "defaultByrefArg" ty + let wrapper2, rhs = build currCalledArgTy dfltVal2 + (wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr false (mkLocalValRef v) + build calledArgTy dfltVal + + | CalleeSide -> + let calledNonOptTy = + if isOptionTy g calledArgTy then + destOptionTy g calledArgTy + else + calledArgTy // should be unreachable + + match calledArg.CallerInfo, eCallerMemberName with + | CallerLineNumber, _ when typeEquiv g calledNonOptTy g.int_ty -> + let lineExpr = Expr.Const(Const.Int32 mMethExpr.StartLine, mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy lineExpr mMethExpr + | CallerFilePath, _ when typeEquiv g calledNonOptTy g.string_ty -> + let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply g.pathMap + let filePathExpr = Expr.Const (Const.String(fileName), mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy filePathExpr mMethExpr + | CallerMemberName, Some(callerName) when typeEquiv g calledNonOptTy g.string_ty -> + let memberNameExpr = Expr.Const (Const.String callerName, mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy memberNameExpr mMethExpr + | _ -> + emptyPreBinder, mkNone g calledNonOptTy mMethExpr + + // Combine the variable allocators (if any) + let wrapper = (wrapper >> wrapper2) + let callerArg = CallerArg(calledArgTy, mMethExpr, false, expr) + { NamedArgIdOpt = None; CalledArg = calledArg; CallerArg = callerArg }, wrapper) + + // Adjust all the optional arguments + let wrapOptionalArg (assignedArg: AssignedCalledArg<_>) = + let (CallerArg(callerArgTy, m, isOptCallerArg, callerArgExpr)) = assignedArg.CallerArg + match assignedArg.CalledArg.OptArgInfo with + | NotOptional -> + if isOptCallerArg then errorR(Error(FSComp.SR.tcFormalArgumentIsNotOptional(), m)) + assignedArg + | _ -> + let callerArgExpr2 = + match assignedArg.CalledArg.OptArgInfo with + | CallerSide _ -> + if isOptCallerArg then + // M(?x=bopt) when M(A) --> M(?x=bopt.Value) for caller-side + // STRUCT OPTIONS: if we allow struct options as optional arguments then we should take + // the address correctly. + mkUnionCaseFieldGetUnprovenViaExprAddr (callerArgExpr, mkSomeCase g, [destOptionTy g callerArgTy], 0, m) + else + // M(x=b) when M(A) --> M(?x=b) for caller-side + callerArgExpr + + | CalleeSide -> + if isOptCallerArg then + // M(?x=bopt) when M(A) --> M(?x=Some(bopt.Value)) + callerArgExpr + else + // M(x=b) when M(A) --> M(?x=Some(b :> A)) + let calledArgTy = assignedArg.CalledArg.CalledArgumentType + if isOptionTy g calledArgTy then + let calledNonOptTy = destOptionTy g calledArgTy + mkSome g calledNonOptTy (mkCoerceIfNeeded g calledNonOptTy callerArgTy callerArgExpr) m + else + callerArgExpr // should be unreachable + + | _ -> failwith "Unreachable" + { assignedArg with CallerArg=CallerArg(tyOfExpr g callerArgExpr2, m, isOptCallerArg, callerArgExpr2) } + + let adjustedNormalUnnamedArgs = List.map wrapOptionalArg unnamedArgs + let adjustedAssignedNamedArgs = List.map wrapOptionalArg assignedNamedArgs + + optArgs, optArgPreBinder, adjustedNormalUnnamedArgs, adjustedAssignedNamedArgs + +/// Adjust any 'out' arguments, passing in the address of a mutable local +let AdjustOutCallerArgExprs g (calledMeth: CalledMeth<_>) mMethExpr = + calledMeth.UnnamedCalledOutArgs |> List.map (fun calledArg -> + let calledArgTy = calledArg.CalledArgumentType + let outArgTy = destByrefTy g calledArgTy + let outv, outArgExpr = mkMutableCompGenLocal mMethExpr PrettyNaming.outArgCompilerGeneratedName outArgTy // mutable! + let expr = mkDefault (mMethExpr, outArgTy) + let callerArg = CallerArg (calledArgTy, mMethExpr, false, mkValAddr mMethExpr false (mkLocalValRef outv)) + let outArg = { NamedArgIdOpt=None;CalledArg=calledArg;CallerArg=callerArg } + outArg, outArgExpr, mkCompGenBind outv expr) + |> List.unzip3 + +let AdjustParamArrayCallerArgExprs g amap infoReader ad (calledMeth: CalledMeth<_>) mMethExpr = + let argSets = calledMeth.ArgSets + + let paramArrayCallerArgs = argSets |> List.collect (fun argSet -> argSet.ParamArrayCallerArgs) + match calledMeth.ParamArrayCalledArgOpt with + | None -> + [], [] + | Some paramArrayCalledArg -> + let paramArrayCalledArgElementType = destArrayTy g paramArrayCalledArg.CalledArgumentType + + let paramArrayPreBinders, es = + paramArrayCallerArgs + |> List.map (fun callerArg -> + let (CallerArg(callerArgTy, m, isOutArg, callerArgExpr)) = callerArg + AdjustCallerArgExprForCoercions g amap infoReader ad isOutArg paramArrayCalledArgElementType paramArrayCalledArg.ReflArgInfo callerArgTy m callerArgExpr) + |> List.unzip + + let arg = + [ { NamedArgIdOpt = None + CalledArg=paramArrayCalledArg + CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op (TOp.Array, [paramArrayCalledArgElementType], es, mMethExpr)) } ] + paramArrayPreBinders, arg + +/// Build the argument list for a method call. Adjust for param array, optional arguments, byref arguments and coercions. +/// For example, if you pass an F# reference cell to a byref then we must get the address of the +/// contents of the ref. Likewise lots of adjustments are made for optional arguments etc. +let AdjustCallerArgExprs tcFieldInit eCallerMemberName g amap infoReader ad (calledMeth: CalledMeth<_>) objArgs lambdaVars mItem mMethExpr = + let calledMethInfo = calledMeth.Method + + // Some of the code below must allocate temporary variables or bind other variables to particular values. + // As usual we represent variable allocators by expr -> expr functions + // which we then use to wrap the whole expression. These will either do nothing or pre-bind a variable. It doesn't + // matter what order they are applied in as long as they are all composed together. + let emptyPreBinder (e: Expr) = e + + // For unapplied 'e.M' we first evaluate 'e' outside the lambda, i.e. 'let v = e in (fun arg -> v.M(arg))' + let objArgPreBinder, objArgs = + match objArgs, lambdaVars with + | [objArg], Some _ -> + if calledMethInfo.IsExtensionMember && calledMethInfo.ObjArgNeedsAddress(amap, mMethExpr) then + error(Error(FSComp.SR.tcCannotPartiallyApplyExtensionMethodForByref(calledMethInfo.DisplayName), mMethExpr)) + let objArgTy = tyOfExpr g objArg + let v, ve = mkCompGenLocal mMethExpr "objectArg" objArgTy + (fun body -> mkCompGenLet mMethExpr v objArg body), [ve] + | _ -> + emptyPreBinder, objArgs + + // Handle param array and optional arguments + let paramArrayPreBinders, paramArrayArgs = + AdjustParamArrayCallerArgExprs g amap infoReader ad calledMeth mMethExpr + + let optArgs, optArgPreBinder, adjustedNormalUnnamedArgs, adjustedFinalAssignedNamedArgs = + AdjustOptionalCallerArgExprs tcFieldInit eCallerMemberName g calledMeth mItem mMethExpr + + let outArgs, outArgExprs, outArgTmpBinds = + AdjustOutCallerArgExprs g calledMeth mMethExpr + + let allArgs = + adjustedNormalUnnamedArgs @ + adjustedFinalAssignedNamedArgs @ + paramArrayArgs @ + optArgs @ + outArgs + + let allArgs = + allArgs |> List.sortBy (fun x -> x.Position) + + let allArgsPreBinders, allArgsCoerced = + allArgs + |> List.map (fun assignedArg -> + let isOutArg = assignedArg.CalledArg.IsOutArg + let reflArgInfo = assignedArg.CalledArg.ReflArgInfo + let calledArgTy = assignedArg.CalledArg.CalledArgumentType + let (CallerArg(callerArgTy, m, _, e)) = assignedArg.CallerArg + + AdjustCallerArgExprForCoercions g amap infoReader ad isOutArg calledArgTy reflArgInfo callerArgTy m e) + |> List.unzip + + objArgPreBinder, objArgs, allArgsPreBinders, allArgs, allArgsCoerced, optArgPreBinder, paramArrayPreBinders, outArgExprs, outArgTmpBinds + //------------------------------------------------------------------------- // Additional helpers for building method calls and doing TAST generation //------------------------------------------------------------------------- @@ -573,27 +925,30 @@ let ComputeConstrainedCallInfo g amap m (objArgs, minfo: MethInfo) = | _ -> None - /// Adjust the 'this' pointer before making a call /// Take the address of a struct, and coerce to an interface/base/constraint type if necessary let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = let ccallInfo = ComputeConstrainedCallInfo g amap m (objArgs, minfo) let wrap, objArgs = + match objArgs with | [objArgExpr] -> + let hasCallInfo = ccallInfo.IsSome let mustTakeAddress = hasCallInfo || minfo.ObjArgNeedsAddress(amap, m) let objArgTy = tyOfExpr g objArgExpr - let wrap, objArgExpr', isReadOnly, _isWriteOnly = mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m + + let wrap, objArgExprAddr, isReadOnly, _isWriteOnly = + mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m // Extension members and calls to class constraints may need a coercion for their object argument - let objArgExpr' = + let objArgExprCoerced = if not hasCallInfo && not (TypeDefinitelySubsumesTypeNoCoercion 0 g amap m minfo.ApparentEnclosingType objArgTy) then - mkCoerceExpr(objArgExpr', minfo.ApparentEnclosingType, m, objArgTy) + mkCoerceExpr(objArgExprAddr, minfo.ApparentEnclosingType, m, objArgTy) else - objArgExpr' + objArgExprAddr // Check to see if the extension member uses the extending type as a byref. // If so, make sure we don't allow readonly/immutable values to be passed byref from an extension member. @@ -605,7 +960,7 @@ let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = errorR(Error(FSComp.SR.tcCannotCallExtensionMethodInrefToByref(minfo.DisplayName), m))) - wrap, [objArgExpr'] + wrap, [objArgExprCoerced] | _ -> id, objArgs @@ -616,11 +971,6 @@ let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = // Build method calls. //------------------------------------------------------------------------- -//------------------------------------------------------------------------- -// Build calls -//------------------------------------------------------------------------- - - /// Build an expression node that is a call to a .NET method. let BuildILMethInfoCall g amap m isProp (minfo: ILMethInfo) valUseFlags minst direct args = let valu = isStructTy g minfo.ApparentEnclosingType @@ -638,11 +988,6 @@ let BuildILMethInfoCall g amap m isProp (minfo: ILMethInfo) valUseFlags minst di Expr.Op (TOp.ILCall (useCallvirt, isProtected, valu, newobj, valUseFlags, isProp, isDllImport, ilMethRef, minfo.DeclaringTypeInst, minst, retTy), [], args, m), exprTy -/// Build a call to the System.Object constructor taking no arguments, -let BuildObjCtorCall (g: TcGlobals) m = - let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object, [])).MethodRef - Expr.Op (TOp.ILCall (false, false, false, false, CtorValUsedAsSuperInit, false, true, ilMethRef, [], [], [g.obj_ty]), [], [], m) - /// Build a call to an F# method. /// @@ -825,55 +1170,6 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m)) mkDefault (m, ty), ty) -//------------------------------------------------------------------------- -// Build delegate constructions (lambdas/functions to delegates) -//------------------------------------------------------------------------- - -/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites -let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, invokeMethInfo: MethInfo, delArgTys, f, fty, m) = - let slotsig = invokeMethInfo.GetSlotSig(amap, m) - let delArgVals, expr = - let topValInfo = ValReprInfo([], List.replicate (max 1 (List.length delArgTys)) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) - - // Try to pull apart an explicit lambda and use it directly - // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler - let lambdaContents = - if Option.isSome eventInfoOpt then - None - else - tryDestTopLambda g amap topValInfo (f, fty) - - match lambdaContents with - | None -> - - if List.exists (isByrefTy g) delArgTys then - error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys), m)) - - let delArgVals = delArgTys |> List.mapi (fun i argty -> fst (mkCompGenLocal m ("delegateArg" + string i) argty)) - let expr = - let args = - match eventInfoOpt with - | Some einfo -> - match delArgVals with - | [] -> error(nonStandardEventError einfo.EventName m) - | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) - | h :: t -> [exprForVal m h; mkRefTupledVars g m t] - | None -> - if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals - mkApps g ((f, fty), [], args, m) - delArgVals, expr - - | Some _ -> - let _, _, _, vsl, body, _ = IteratedAdjustArityOfLambda g amap topValInfo f - List.concat vsl, body - - let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) - mkObjExpr(delegateTy, None, BuildObjCtorCall g m, [meth], [], m) - -let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = - let (SigOfFunctionForDelegate(invokeMethInfo, delArgTys, _, _)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad - BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) - //------------------------------------------------------------------------- // Import provided expressions @@ -972,11 +1268,14 @@ module ProvidedMethodCalls = st loop inputType - let convertProvidedExpressionToExprAndWitness tcVal (thisArg: Expr option, - allArgs: Exprs, - paramVars: Tainted[], - g, amap, mut, isProp, isSuperInit, m, - expr: Tainted) = + let convertProvidedExpressionToExprAndWitness + tcVal + (thisArg: Expr option, + allArgs: Exprs, + paramVars: Tainted[], + g, amap, mut, isProp, isSuperInit, m, + expr: Tainted) = + let varConv = // note: using paramVars.Length as assumed initial size, but this might not // be the optimal value; this wasn't checked before obsoleting Dictionary.ofList diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index dd3b6c820f..6f03bbc1d4 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1584,7 +1584,7 @@ type TcResultsSinkImpl(g, ?sourceText: ISourceText) = // results in duplication of textual variables. So we ensure we never record two name resolutions // for the same identifier at the same location. if allowedRange m then - if replace then + if replace then capturedNameResolutions.RemoveAll(fun cnr -> Range.equals cnr.Range m) |> ignore capturedMethodGroupResolutions.RemoveAll(fun cnr -> Range.equals cnr.Range m) |> ignore else diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 5d56543e99..2d9ea197db 100644 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -32,8 +32,8 @@ module internal PrintUtilities = let bracketIfL x lyt = if x then bracketL lyt else lyt let squareAngleL x = LeftL.leftBracketAngle ^^ x ^^ RightL.rightBracketAngle let angleL x = sepL Literals.leftAngle ^^ x ^^ rightL Literals.rightAngle - let braceL x = leftL Literals.leftBrace ^^ x ^^ rightL Literals.rightBrace - let braceBarL x = leftL Literals.leftBraceBar ^^ x ^^ rightL Literals.rightBraceBar + let braceL x = wordL Literals.leftBrace ^^ x ^^ wordL Literals.rightBrace + let braceBarL x = wordL Literals.leftBraceBar ^^ x ^^ wordL Literals.rightBraceBar let comment str = wordL (tagText (sprintf "(* %s *)" str)) @@ -942,7 +942,7 @@ module private PrintTypes = // Layout a tuple type | TType_anon (anonInfo, tys) -> - let core = sepListL (wordL (tagPunctuation ";")) (List.map2 (fun nm ty -> wordL (tagField nm) ^^ wordL (tagPunctuation ":") ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) + let core = sepListL (rightL (tagPunctuation ";")) (List.map2 (fun nm ty -> wordL (tagField nm) ^^ rightL (tagPunctuation ":") ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) if evalAnonInfoIsStruct anonInfo then WordL.keywordStruct --- braceBarL core else @@ -1457,7 +1457,7 @@ module private TastDefinitionPrinting = let lhs = tagRecordField fld.Name |> mkNav fld.DefinitionRange - |> wordL + |> wordL let lhs = (if addAccess then layoutAccessibility denv fld.Accessibility lhs else lhs) let lhs = if fld.IsMutable then wordL (tagKeyword "mutable") --- lhs else lhs (lhs ^^ RightL.colon) --- layoutType denv fld.FormalType @@ -1738,8 +1738,15 @@ module private TastDefinitionPrinting = let denv = denv.AddAccessibility tycon.TypeReprAccessibility match repr with | TRecdRepr _ -> - let recdFieldRefL fld = layoutRecdField false denv fld ^^ rightL (tagPunctuation ";") - let recdL = tycon.TrueFieldsAsList |> List.map recdFieldRefL |> applyMaxMembers denv.maxMembers |> aboveListL |> braceL + let recdFieldRefL fld = layoutRecdField false denv fld + + let recdL = + tycon.TrueFieldsAsList + |> List.map recdFieldRefL + |> applyMaxMembers denv.maxMembers + |> aboveListL + |> braceL + Some (addMembersAsWithEnd (addReprAccessL recdL)) | TFSharpObjectRepr r -> @@ -1771,8 +1778,7 @@ module private TastDefinitionPrinting = | _ -> [] let vsprs = tycon.MembersOfFSharpTyconSorted - |> List.filter (fun v -> isNil (Option.get v.MemberInfo).ImplementedSlotSigs) - |> List.filter (fun v -> v.IsDispatchSlot) + |> List.filter (fun v -> isNil (Option.get v.MemberInfo).ImplementedSlotSigs && v.IsDispatchSlot) |> List.map (fun vref -> PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv vref.Deref) let staticValsLs = tycon.TrueFieldsAsList diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index ecc24b9131..cfa1a9a49d 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -380,6 +380,8 @@ type cenv = casApplied : Dictionary } + override x.ToString() = "" + type IncrementalOptimizationEnv = { /// An identifier to help with name generation latestBoundId: Ident option @@ -415,6 +417,8 @@ type IncrementalOptimizationEnv = localExternalVals = LayeredMap.Empty globalModuleInfos = LayeredMap.Empty } + override x.ToString() = "" + //------------------------------------------------------------------------- // IsPartialExprVal - is the expr fully known? //------------------------------------------------------------------------- diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index b6a286c5d7..d6ad0cdf64 100755 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -93,7 +93,10 @@ type env = returnScope : int /// Are we in an app expression (Expr.App)? - isInAppExpr: bool } + isInAppExpr: bool + } + + override __.ToString() = "" let BindTypar env (tp: Typar) = { env with @@ -183,23 +186,39 @@ let CombineLimits limits = type cenv = { boundVals: Dictionary // really a hash set + limitVals: Dictionary + mutable potentialUnboundUsesOfVals: StampMap + mutable anonRecdTypes: StampMap + g: TcGlobals + amap: Import.ImportMap + /// For reading metadata infoReader: InfoReader + internalsVisibleToPaths : CompilationPath list + denv: DisplayEnv + viewCcu : CcuThunk + reportErrors: bool + isLastCompiland : bool*bool + isInternalTestSpanStackReferring: bool + // outputs mutable usesQuotations : bool + mutable entryPointGiven: bool } + override x.ToString() = "" + /// Check if the value is an argument of a function let IsValArgument env (v: Val) = env.argVals.ContainsVal v diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 00fb9a0827..c638d9a864 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -839,16 +839,6 @@ let tryNiceEntityRefOfTyOption ty = | TType_app (tcref, _) -> Some tcref | TType_measure (Measure.Con tcref) -> Some tcref | _ -> None - -let (|NullableTy|_|) g ty = - match tryAppTy g ty with - | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> Some tyarg - | _ -> None - -let (|StripNullableTy|) g ty = - match tryAppTy g ty with - | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> tyarg - | _ -> ty let mkInstForAppTy g ty = match tryAppTy g ty with @@ -3125,6 +3115,31 @@ let destOptionTy g ty = | ValueSome ty -> ty | ValueNone -> failwith "destOptionTy: not an option type" +let isNullableTy (g: TcGlobals) ty = + match tryDestAppTy g ty with + | ValueNone -> false + | ValueSome tcref -> tyconRefEq g g.system_Nullable_tcref tcref + +let tryDestNullableTy g ty = + match argsOfAppTy g ty with + | [ty1] when isNullableTy g ty -> ValueSome ty1 + | _ -> ValueNone + +let destNullableTy g ty = + match tryDestNullableTy g ty with + | ValueSome ty -> ty + | ValueNone -> failwith "destNullableTy: not a Nullable type" + +let (|NullableTy|_|) g ty = + match tryAppTy g ty with + | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> Some tyarg + | _ -> None + +let (|StripNullableTy|) g ty = + match tryDestNullableTy g ty with + | ValueSome tyarg -> tyarg + | _ -> ty + let isLinqExpressionTy g ty = match tryDestAppTy g ty with | ValueNone -> false diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 8c71736a84..b0743de853 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1388,7 +1388,7 @@ val mkVoidPtrTy : TcGlobals -> TType /// Build a single-dimensional array type val mkArrayType : TcGlobals -> TType -> TType -/// Determine is a type is an option type +/// Determine if a type is an option type val isOptionTy : TcGlobals -> TType -> bool /// Take apart an option type @@ -1397,6 +1397,15 @@ val destOptionTy : TcGlobals -> TType -> TType /// Try to take apart an option type val tryDestOptionTy : TcGlobals -> TType -> ValueOption +/// Determine is a type is a System.Nullable type +val isNullableTy : TcGlobals -> TType -> bool + +/// Try to take apart a System.Nullable type +val tryDestNullableTy: TcGlobals -> TType -> ValueOption + +/// Take apart a System.Nullable type +val destNullableTy: TcGlobals -> TType -> TType + /// Determine if a type is a System.Linq.Expression type val isLinqExpressionTy : TcGlobals -> TType -> bool diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ae464f1575..7610c4f209 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -534,7 +534,7 @@ type cenv = conditionalDefines = conditionalDefines isInternalTestSpanStackReferring = isInternalTestSpanStackReferring } - override __.ToString() = "cenv(...)" + override __.ToString() = "" let CopyAndFixupTypars m rigid tpsorig = ConstraintSolver.FreshenAndFixupTypars m rigid [] [] tpsorig @@ -9671,75 +9671,74 @@ and TcMethodApplication // In one case (the second "single named item" rule) we delay the application of a // argument until we've produced a lambda that detuples an input tuple let curriedCallerArgsOpt, unnamedDelayedCallerArgExprOpt, exprTy = - match curriedCallerArgs with - | [] -> - None, None, exprTy - | _ -> - let unnamedCurriedCallerArgs, namedCurriedCallerArgs = curriedCallerArgs |> List.map GetMethodArgs |> List.unzip + match curriedCallerArgs with + | [] -> + None, None, exprTy + | _ -> + let unnamedCurriedCallerArgs, namedCurriedCallerArgs = curriedCallerArgs |> List.map GetMethodArgs |> List.unzip - // There is an mismatch when _uses_ of indexed property setters in the tc.fs code that calls this function. - // The arguments are passed as if they are curried with arity [numberOfIndexParameters;1], however in the TAST, indexed property setters - // are uncurried and have arity [numberOfIndexParameters+1]. - // - // Here we work around this mismatch by crunching all property argument lists to uncirred form. - // Ideally the problem needs to be solved at its root cause at the callsites to this function - let unnamedCurriedCallerArgs, namedCurriedCallerArgs = - if isProp then - [List.concat unnamedCurriedCallerArgs], [List.concat namedCurriedCallerArgs] - else - unnamedCurriedCallerArgs, namedCurriedCallerArgs + // There is an mismatch when _uses_ of indexed property setters in the tc.fs code that calls this function. + // The arguments are passed as if they are curried with arity [numberOfIndexParameters;1], however in the TAST, indexed property setters + // are uncurried and have arity [numberOfIndexParameters+1]. + // + // Here we work around this mismatch by crunching all property argument lists to uncirred form. + // Ideally the problem needs to be solved at its root cause at the callsites to this function + let unnamedCurriedCallerArgs, namedCurriedCallerArgs = + if isProp then + [List.concat unnamedCurriedCallerArgs], [List.concat namedCurriedCallerArgs] + else + unnamedCurriedCallerArgs, namedCurriedCallerArgs - let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv env tpenv x, x.Range) - - // "single named item" rule. This is where we have a single accessible method - // member x.M(arg1) - // being used with - // x.M (x, y) - // Without this rule this requires - // x.M ((x, y)) - match candidates with - | [calledMeth] - when (namedCurriedCallerArgs |> List.forall isNil && - let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) - curriedCalledArgs.Length = 1 && - curriedCalledArgs.Head.Length = 1 && - curriedCalledArgs.Head.Head |> isSimpleFormalArg) -> - let unnamedCurriedCallerArgs = curriedCallerArgs |> List.map (MakeUnnamedCallerArgInfo >> List.singleton) - let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.map (fun _ -> []) - (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) - - // "single named item" rule. This is where we have a single accessible method - // member x.M(arg1, arg2) - // being used with - // x.M p - // We typecheck this as if it has been written "(fun (v1, v2) -> x.M(v1, v2)) p" - // Without this rule this requires - // x.M (fst p, snd p) - | [calledMeth] - when (namedCurriedCallerArgs |> List.forall isNil && - unnamedCurriedCallerArgs.Length = 1 && - unnamedCurriedCallerArgs.Head.Length = 1 && - let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) - curriedCalledArgs.Length = 1 && - curriedCalledArgs.Head.Length > 1 && - curriedCalledArgs.Head |> List.forall isSimpleFormalArg) -> - - // The call lambda has function type - let exprTy = mkFunTy (NewInferenceType ()) exprTy + let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv env tpenv x, x.Range) + + // "single named item" rule. This is where we have a single accessible method + // member x.M(arg1) + // being used with + // x.M (x, y) + // Without this rule this requires + // x.M ((x, y)) + match candidates with + | [calledMeth] + when (namedCurriedCallerArgs |> List.forall isNil && + let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) + curriedCalledArgs.Length = 1 && + curriedCalledArgs.Head.Length = 1 && + curriedCalledArgs.Head.Head |> isSimpleFormalArg) -> + let unnamedCurriedCallerArgs = curriedCallerArgs |> List.map (MakeUnnamedCallerArgInfo >> List.singleton) + let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.map (fun _ -> []) + (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) + + // "single named item" rule. This is where we have a single accessible method + // member x.M(arg1, arg2) + // being used with + // x.M p + // We typecheck this as if it has been written "(fun (v1, v2) -> x.M(v1, v2)) p" + // Without this rule this requires + // x.M (fst p, snd p) + | [calledMeth] + when (namedCurriedCallerArgs |> List.forall isNil && + unnamedCurriedCallerArgs.Length = 1 && + unnamedCurriedCallerArgs.Head.Length = 1 && + let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) + curriedCalledArgs.Length = 1 && + curriedCalledArgs.Head.Length > 1 && + curriedCalledArgs.Head |> List.forall isSimpleFormalArg) -> + + // The call lambda has function type + let exprTy = mkFunTy (NewInferenceType ()) exprTy - (None, Some unnamedCurriedCallerArgs.Head.Head, exprTy) + (None, Some unnamedCurriedCallerArgs.Head.Head, exprTy) - | _ -> - let unnamedCurriedCallerArgs = unnamedCurriedCallerArgs |> List.mapSquared MakeUnnamedCallerArgInfo - let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.mapSquared (fun (isOpt, nm, x) -> - let ty = GetNewInferenceTypeForMethodArg cenv env tpenv x - // #435263: compiler crash with .net optional parameters and F# optional syntax - // named optional arguments should always have option type - let ty = if isOpt then mkOptionTy denv.g ty else ty - nm, isOpt, x, ty, x.Range - ) - - (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) + | _ -> + let unnamedCurriedCallerArgs = unnamedCurriedCallerArgs |> List.mapSquared MakeUnnamedCallerArgInfo + let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.mapSquared (fun (isOpt, nm, x) -> + let ty = GetNewInferenceTypeForMethodArg cenv env tpenv x + // #435263: compiler crash with .net optional parameters and F# optional syntax + // named optional arguments should always have option type + let ty = if isOpt then mkOptionTy denv.g ty else ty + nm, isOpt, x, ty, x.Range) + + (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) let CalledMethHasSingleArgumentGroupOfThisLength n (calledMeth: MethInfo) = @@ -9983,21 +9982,12 @@ and TcMethodApplication let finalCalledMethInfo = finalCalledMeth.Method let finalCalledMethInst = finalCalledMeth.CalledTyArgs - let finalArgSets = finalCalledMeth.ArgSets let finalAssignedItemSetters = finalCalledMeth.AssignedItemSetters - let finalCalledPropInfoOpt = finalCalledMeth.AssociatedPropertyInfo let finalAttributeAssignedNamedItems = finalCalledMeth.AttributeAssignedNamedArgs - let finalUnnamedCalledOptArgs = finalCalledMeth.UnnamedCalledOptArgs - let finalUnnamedCalledOutArgs = finalCalledMeth.UnnamedCalledOutArgs - let finalAssignedNamedArgs = finalArgSets |> List.collect (fun argSet -> argSet.AssignedNamedArgs) - let finalParamArrayCallerArgs = finalArgSets |> List.collect (fun argSet -> argSet.ParamArrayCallerArgs) - let finalUnnamedCalledArgs = finalArgSets |> List.collect (fun argSet -> argSet.UnnamedCalledArgs) - let finalUnnamedCallerArgs = finalArgSets |> List.collect (fun argSet -> argSet.UnnamedCallerArgs) - // STEP 4. Check the attributes on the method and the corresponding event/property, if any - finalCalledPropInfoOpt |> Option.iter (fun pinfo -> CheckPropInfoAttributes pinfo mItem |> CommitOperationResult) + finalCalledMeth.AssociatedPropertyInfo |> Option.iter (fun pinfo -> CheckPropInfoAttributes pinfo mItem |> CommitOperationResult) let isInstance = not (isNil objArgs) MethInfoChecks cenv.g cenv.amap isInstance tyargsOpt objArgs ad mItem finalCalledMethInfo @@ -10026,266 +10016,13 @@ and TcMethodApplication | _ -> () end - if (finalArgSets |> List.existsi (fun i argSet -> argSet.UnnamedCalledArgs |> List.existsi (fun j ca -> ca.Position <> (i, j)))) then + if (finalCalledMeth.ArgSets |> List.existsi (fun i argSet -> argSet.UnnamedCalledArgs |> List.existsi (fun j ca -> ca.Position <> (i, j)))) then errorR(Deprecated(FSComp.SR.tcUnnamedArgumentsDoNotFormPrefix(), mMethExpr)) + /// STEP 5. Build the argument list. Adjust for optional arguments, byref arguments and coercions. - // STEP 5. Build the argument list. Adjust for optional arguments, byref arguments and coercions. - // For example, if you pass an F# reference cell to a byref then we must get the address of the - // contents of the ref. Likewise lots of adjustments are made for optional arguments etc. - - // Some of the code below must allocate temporary variables or bind other variables to particular values. - // As usual we represent variable allocators by expr -> expr functions - // which we then use to wrap the whole expression. These will either do nothing or pre-bind a variable. It doesn't - // matter what order they are applied in as long as they are all composed together. - let emptyPreBinder (e: Expr) = e - - // For unapplied 'e.M' we first evaluate 'e' outside the lambda, i.e. 'let v = e in (fun arg -> v.M(arg))' - let objArgPreBinder, objArgs = - match objArgs, lambdaVars with - | [objArg], Some _ -> - if finalCalledMethInfo.IsExtensionMember && finalCalledMethInfo.ObjArgNeedsAddress(cenv.amap, mMethExpr) then - error(Error(FSComp.SR.tcCannotPartiallyApplyExtensionMethodForByref(finalCalledMethInfo.DisplayName), mMethExpr)) - let objArgTy = tyOfExpr cenv.g objArg - let v, ve = mkCompGenLocal mMethExpr "objectArg" objArgTy - (fun body -> mkCompGenLet mMethExpr v objArg body), [ve] - | _ -> - emptyPreBinder, objArgs - - // Handle adhoc argument conversions - let coerceExpr isOutArg calledArgTy (reflArgInfo: ReflectedArgInfo) callerArgTy m callerArgExpr = - let g = cenv.g - - if isByrefTy g calledArgTy && isRefCellTy g callerArgTy then - None, Expr.Op (TOp.RefAddrGet false, [destRefCellTy g callerArgTy], [callerArgExpr], m) - -#if IMPLICIT_ADDRESS_OF - elif isInByrefTy g calledArgTy && not (isByrefTy cenv.g callerArgTy) then - let wrap, callerArgExprAddress, _readonly, _writeonly = mkExprAddrOfExpr g true false NeverMutates callerArgExpr None m - Some wrap, callerArgExprAddress -#endif - - elif isDelegateTy cenv.g calledArgTy && isFunTy cenv.g callerArgTy then - None, CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr calledArgTy - - elif isLinqExpressionTy cenv.g calledArgTy && isDelegateTy cenv.g (destLinqExpressionTy cenv.g calledArgTy) && isFunTy cenv.g callerArgTy then - let delegateTy = destLinqExpressionTy cenv.g calledArgTy - let expr = CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr delegateTy - None, mkCallQuoteToLinqLambdaExpression cenv.g m delegateTy (Expr.Quote (expr, ref None, false, m, mkQuotedExprTy cenv.g delegateTy)) - - // auto conversions to quotations (to match auto conversions to LINQ expressions) - elif reflArgInfo.AutoQuote && isQuotedExprTy cenv.g calledArgTy && not (isQuotedExprTy cenv.g callerArgTy) then - match reflArgInfo with - | ReflectedArgInfo.Quote true -> - None, mkCallLiftValueWithDefn cenv.g m calledArgTy callerArgExpr - | ReflectedArgInfo.Quote false -> - None, Expr.Quote (callerArgExpr, ref None, false, m, calledArgTy) - | ReflectedArgInfo.None -> failwith "unreachable" // unreachable due to reflArgInfo.AutoQuote condition - - // Note: out args do not need to be coerced - elif isOutArg then - None, callerArgExpr - - // Note: not all these casts are reported in quotations - else - None, mkCoerceIfNeeded cenv.g calledArgTy callerArgTy callerArgExpr - - // Handle param array and optional arguments - let optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds = - - let normalUnnamedArgs = - (finalUnnamedCalledArgs, finalUnnamedCallerArgs) ||> List.map2 (fun called caller -> { NamedArgIdOpt = None; CalledArg=called; CallerArg=caller }) - - let paramArrayPreBinders, paramArrayArgs = - match finalCalledMeth.ParamArrayCalledArgOpt with - | None -> - [], [] - | Some paramArrayCalledArg -> - let paramArrayCalledArgElementType = destArrayTy cenv.g paramArrayCalledArg.CalledArgumentType - - let paramArrayPreBinders, es = - finalParamArrayCallerArgs - |> List.map (fun callerArg -> - let (CallerArg(callerArgTy, m, isOutArg, callerArgExpr)) = callerArg - coerceExpr isOutArg paramArrayCalledArgElementType paramArrayCalledArg.ReflArgInfo callerArgTy m callerArgExpr) - |> List.unzip - - let arg = - [ { NamedArgIdOpt = None - CalledArg=paramArrayCalledArg - CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op (TOp.Array, [paramArrayCalledArgElementType], es, mMethExpr)) } ] - paramArrayPreBinders, arg - - // CLEANUP: Move all this code into some isolated file, e.g. "optional.fs" - // - // Handle CallerSide optional arguments. - // - // CallerSide optional arguments are largely for COM interop, e.g. to PIA assemblies for Word etc. - // As a result we follow the VB and C# behavior here. - // - // "1. If the parameter is statically typed as System.Object and does not have a value, then there are four cases: - // a. The parameter is marked with MarshalAs(IUnknown), MarshalAs(Interface), or MarshalAs(IDispatch). In this case we pass null. - // b. Else if the parameter is marked with IUnknownConstantAttribute. In this case we pass new System.Runtime.InteropServices.UnknownWrapper(null) - // c. Else if the parameter is marked with IDispatchConstantAttribute. In this case we pass new System.Runtime.InteropServices.DispatchWrapper(null) - // d. Else, we will pass Missing.Value. - // 2. Otherwise, if there is a value attribute, then emit the default value. - // 3. Otherwise, we emit default(T). - // 4. Finally, we apply conversions from the value to the parameter type. This is where the nullable conversions take place for VB. - // - VB allows you to mark ref parameters as optional. The semantics of this is that we create a temporary - // with type = type of parameter, load the optional value to it, and call the method. - // - VB also allows you to mark arrays with Nothing as the optional value. - // - VB also allows you to pass intrinsic values as optional values to parameters - // typed as Object. What we do in this case is we box the intrinsic value." - // - let optArgs, optArgPreBinder = - (emptyPreBinder, finalUnnamedCalledOptArgs) ||> List.mapFold (fun wrapper calledArg -> - let calledArgTy = calledArg.CalledArgumentType - let wrapper2, expr = - match calledArg.OptArgInfo with - | NotOptional -> - error(InternalError("Unexpected NotOptional", mItem)) - | CallerSide dfltVal -> - let rec build currCalledArgTy currDfltVal = - match currDfltVal with - | MissingValue -> - // Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr. - emptyPreBinder, mkAsmExpr ([ mkNormalLdsfld (fspec_Missing_Value cenv.g); AI_nop ], [], [], [currCalledArgTy], mMethExpr) - | DefaultValue -> - emptyPreBinder, mkDefault(mMethExpr, currCalledArgTy) - | Constant fieldInit -> - match currCalledArgTy with - | NullableTy cenv.g inst when fieldInit <> ILFieldInit.Null -> - let nullableTy = mkILNonGenericBoxedTy(cenv.g.FindSysILTypeRef "System.Nullable`1") - let ctor = mkILCtorMethSpecForTy(nullableTy, [ILType.TypeVar 0us]).MethodRef - let ctorArgs = [Expr.Const (TcFieldInit mMethExpr fieldInit, mMethExpr, inst)] - emptyPreBinder, Expr.Op (TOp.ILCall (false, false, true, true, NormalValUse, false, false, ctor, [inst], [], [currCalledArgTy]), [], ctorArgs, mMethExpr) - | ByrefTy cenv.g inst -> - build inst (PassByRef(inst, currDfltVal)) - | _ -> - match calledArg.CallerInfo, env.eCallerMemberName with - | CallerLineNumber, _ when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> - emptyPreBinder, Expr.Const (Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) - | CallerFilePath, _ when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> - let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply cenv.g.pathMap - emptyPreBinder, Expr.Const (Const.String fileName, mMethExpr, currCalledArgTy) - | CallerMemberName, Some callerName when (typeEquiv cenv.g currCalledArgTy cenv.g.string_ty) -> - emptyPreBinder, Expr.Const (Const.String callerName, mMethExpr, currCalledArgTy) - | _ -> - emptyPreBinder, Expr.Const (TcFieldInit mMethExpr fieldInit, mMethExpr, currCalledArgTy) - - | WrapperForIDispatch -> - match cenv.g.TryFindSysILTypeRef "System.Runtime.InteropServices.DispatchWrapper" with - | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) - | Some tref -> - let ty = mkILNonGenericBoxedTy tref - let mref = mkILCtorMethSpecForTy(ty, [cenv.g.ilg.typ_Object]).MethodRef - let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [cenv.g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) - emptyPreBinder, expr - | WrapperForIUnknown -> - match cenv.g.TryFindSysILTypeRef "System.Runtime.InteropServices.UnknownWrapper" with - | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) - | Some tref -> - let ty = mkILNonGenericBoxedTy tref - let mref = mkILCtorMethSpecForTy(ty, [cenv.g.ilg.typ_Object]).MethodRef - let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [cenv.g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) - emptyPreBinder, expr - | PassByRef (ty, dfltVal2) -> - let v, _ = mkCompGenLocal mMethExpr "defaultByrefArg" ty - let wrapper2, rhs = build currCalledArgTy dfltVal2 - (wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr false (mkLocalValRef v) - build calledArgTy dfltVal - | CalleeSide -> - let calledNonOptTy = - if isOptionTy cenv.g calledArgTy then - destOptionTy cenv.g calledArgTy - else - calledArgTy // should be unreachable - - match calledArg.CallerInfo, env.eCallerMemberName with - | CallerLineNumber, _ when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> - let lineExpr = Expr.Const(Const.Int32 mMethExpr.StartLine, mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy lineExpr mMethExpr - | CallerFilePath, _ when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply cenv.g.pathMap - let filePathExpr = Expr.Const (Const.String(fileName), mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy filePathExpr mMethExpr - | CallerMemberName, Some(callerName) when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let memberNameExpr = Expr.Const (Const.String callerName, mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy memberNameExpr mMethExpr - | _ -> - emptyPreBinder, mkNone cenv.g calledNonOptTy mMethExpr - - // Combine the variable allocators (if any) - let wrapper = (wrapper >> wrapper2) - let callerArg = CallerArg(calledArgTy, mMethExpr, false, expr) - { NamedArgIdOpt = None; CalledArg = calledArg; CallerArg = callerArg }, wrapper) - - - // Handle optional arguments - let wrapOptionalArg (assignedArg: AssignedCalledArg<_>) = - let (CallerArg(callerArgTy, m, isOptCallerArg, expr)) = assignedArg.CallerArg - match assignedArg.CalledArg.OptArgInfo with - | NotOptional -> - if isOptCallerArg then errorR(Error(FSComp.SR.tcFormalArgumentIsNotOptional(), m)) - assignedArg - | _ -> - let expr = - match assignedArg.CalledArg.OptArgInfo with - | CallerSide _ -> - if isOptCallerArg then - // STRUCT OPTIONS: if we allow struct options as optional arguments then we should take - // the address correctly. - mkUnionCaseFieldGetUnprovenViaExprAddr (expr, mkSomeCase cenv.g, [destOptionTy cenv.g callerArgTy], 0, m) - else - expr - | CalleeSide -> - if isOptCallerArg then - // M(?x=bopt) when M(A) --> M(?x=Some(b.Value)) - expr - else - // M(x=b) when M(A) --> M(?x=Some(b :> A)) - let calledArgTy = assignedArg.CalledArg.CalledArgumentType - if isOptionTy cenv.g calledArgTy then - let calledNonOptTy = destOptionTy cenv.g calledArgTy - mkSome cenv.g calledNonOptTy (mkCoerceIfNeeded cenv.g calledNonOptTy callerArgTy expr) m - else - expr // should be unreachable - - | _ -> failwith "Unreachable" - { assignedArg with CallerArg=CallerArg((tyOfExpr cenv.g expr), m, isOptCallerArg, expr) } - - let outArgsAndExprs, outArgTmpBinds = - finalUnnamedCalledOutArgs |> List.map (fun calledArg -> - let calledArgTy = calledArg.CalledArgumentType - let outArgTy = destByrefTy cenv.g calledArgTy - let outv, outArgExpr = mkMutableCompGenLocal mMethExpr PrettyNaming.outArgCompilerGeneratedName outArgTy // mutable! - let expr = mkDefault(mMethExpr, outArgTy) - let callerArg = CallerArg(calledArgTy, mMethExpr, false, mkValAddr mMethExpr false (mkLocalValRef outv)) - let outArg = { NamedArgIdOpt=None;CalledArg=calledArg;CallerArg=callerArg } - (outArg, outArgExpr), mkCompGenBind outv expr) - |> List.unzip - - let outArgs, outArgExprs = List.unzip outArgsAndExprs - - let allArgs = - List.map wrapOptionalArg normalUnnamedArgs @ - List.map wrapOptionalArg finalAssignedNamedArgs @ - paramArrayArgs @ - optArgs @ - outArgs - - let allArgs = - allArgs |> List.sortBy (fun x -> x.Position) - - optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds - - let coerce (assignedArg: AssignedCalledArg<_>) = - let isOutArg = assignedArg.CalledArg.IsOutArg - let reflArgInfo = assignedArg.CalledArg.ReflArgInfo - let calledArgTy = assignedArg.CalledArg.CalledArgumentType - let (CallerArg(callerArgTy, m, _, e)) = assignedArg.CallerArg - - coerceExpr isOutArg calledArgTy reflArgInfo callerArgTy m e + let objArgPreBinder, objArgs, allArgsPreBinders, allArgs, allArgsCoerced, optArgPreBinder, paramArrayPreBinders, outArgExprs, outArgTmpBinds = + AdjustCallerArgExprs TcFieldInit env.eCallerMemberName cenv.g cenv.amap cenv.infoReader ad finalCalledMeth objArgs lambdaVars mItem mMethExpr // Record the resolution of the named argument for the Language Service allArgs |> List.iter (fun assignedArg -> @@ -10295,84 +10032,61 @@ and TcMethodApplication let item = Item.ArgName (defaultArg assignedArg.CalledArg.NameOpt id, assignedArg.CalledArg.CalledArgumentType, Some(ArgumentContainer.Method finalCalledMethInfo)) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad)) - let allArgsPreBinders, allArgsCoerced = List.map coerce allArgs |> List.unzip - // Make the call expression - let expr, exprty = + /// STEP 6. Build the call expression, then adjust for byref-returns, out-parameters-as-tuples, post-hoc property assignments, methods-as-first-class-value, + /// + + let callExpr0, exprty = BuildPossiblyConditionalMethodCall cenv env mut mMethExpr isProp finalCalledMethInfo isSuperInit finalCalledMethInst objArgs allArgsCoerced // Handle byref returns - let expr = + let callExpr1 = // byref-typed returns get implicitly dereferenced - let vty = tyOfExpr cenv.g expr + let vty = tyOfExpr cenv.g callExpr0 if isByrefTy cenv.g vty then let v, _ = mkCompGenLocal mMethExpr "byrefReturn" vty - mkCompGenLet mMethExpr v expr (mkAddrGet mMethExpr (mkLocalValRef v)) + mkCompGenLet mMethExpr v callExpr0 (mkAddrGet mMethExpr (mkLocalValRef v)) else - expr + callExpr0 // Bind "out" parameters as part of the result tuple - let expr, exprty = + let callExpr2, exprty = + let expr = callExpr1 if isNil outArgTmpBinds then expr, exprty else let outArgTys = outArgExprs |> List.map (tyOfExpr cenv.g) - let expr = if isUnitTy cenv.g exprty then mkCompGenSequential mMethExpr expr (mkRefTupled cenv.g mMethExpr outArgExprs outArgTys) - else mkRefTupled cenv.g mMethExpr (expr :: outArgExprs) (exprty :: outArgTys) + let expr = + if isUnitTy cenv.g exprty then + mkCompGenSequential mMethExpr expr (mkRefTupled cenv.g mMethExpr outArgExprs outArgTys) + else + mkRefTupled cenv.g mMethExpr (expr :: outArgExprs) (exprty :: outArgTys) let expr = mkLetsBind mMethExpr outArgTmpBinds expr expr, tyOfExpr cenv.g expr // Handle post-hoc property assignments - let setterExprPrebinders, expr = - if isCheckingAttributeCall then - [], expr - elif isNil finalAssignedItemSetters then - [], expr - else - // This holds the result of the call - let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct - // This expression mutates the properties on the result of the call - let setterExprPrebinders, propSetExpr = - (mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.mapFold (fun acc (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) -> - if isOptCallerArg then error(Error(FSComp.SR.tcInvalidOptionalAssignmentToPropertyOrField(), m)) - - let argExprPrebinder, action, defnItem = - match setter with - | AssignedPropSetter (pinfo, pminfo, pminst) -> - MethInfoChecks cenv.g cenv.amap true None [objExpr] ad m pminfo - let calledArgTy = List.head (List.head (pminfo.GetParamTypes(cenv.amap, m, pminst))) - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates) - let action = BuildPossiblyConditionalMethodCall cenv env mut m true pminfo NormalValUse pminst [objExpr] [argExpr] |> fst - argExprPrebinder, action, Item.Property (pinfo.PropertyName, [pinfo]) - - | AssignedILFieldSetter finfo -> - // Get or set instance IL field - ILFieldInstanceChecks cenv.g cenv.amap ad m finfo - let calledArgTy = finfo.FieldType (cenv.amap, m) - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let action = BuildILFieldSet cenv.g m objExpr finfo argExpr - argExprPrebinder, action, Item.ILField finfo - - | AssignedRecdFieldSetter rfinfo -> - RecdFieldInstanceChecks cenv.g cenv.amap ad m rfinfo - let calledArgTy = rfinfo.FieldType - CheckRecdFieldMutation m denv rfinfo - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let action = BuildRecdFieldSet cenv.g m objExpr rfinfo argExpr - argExprPrebinder, action, Item.RecdField rfinfo - - // Record the resolution for the Language Service - let item = Item.SetterArg (id, defnItem) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) - - argExprPrebinder, mkCompGenSequential m acc action) - - // now put them together - let expr = mkCompGenLet mMethExpr objv expr (mkCompGenSequential mMethExpr propSetExpr objExpr) - setterExprPrebinders, expr - - // Build the lambda expression if any - let expr = + let setterExprPrebinders, callExpr3 = + let expr = callExpr2 + if isCheckingAttributeCall then + [], expr + elif isNil finalAssignedItemSetters then + [], expr + else + // This holds the result of the call + let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct + + // Build the expression that mutates the properties on the result of the call + let setterExprPrebinders, propSetExpr = + (mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.mapFold (fun acc assignedItemSetter -> + let argExprPrebinder, action, m = TcSetterArgExpr cenv env denv objExpr ad assignedItemSetter + argExprPrebinder, mkCompGenSequential m acc action) + + // now put them together + let expr = mkCompGenLet mMethExpr objv expr (mkCompGenSequential mMethExpr propSetExpr objExpr) + setterExprPrebinders, expr + + // Build the lambda expression if any, if the method is used as a first-class value + let callExpr4 = + let expr = callExpr3 match lambdaVars with | None -> expr | Some curriedLambdaVars -> @@ -10382,7 +10096,8 @@ and TcMethodApplication | _ -> mkMultiLambda mMethExpr vs (expr, tyOfExpr cenv.g expr) List.foldBack mkLambda curriedLambdaVars expr - let expr, tpenv = + let callExpr5, tpenv = + let expr = callExpr4 match unnamedDelayedCallerArgExprOpt with | Some synArgExpr -> match lambdaVars with @@ -10395,15 +10110,53 @@ and TcMethodApplication expr, tpenv // Apply the PreBinders, if any - let expr = (expr, setterExprPrebinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = (expr, paramArrayPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = (expr, allArgsPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let callExpr6 = + let expr = callExpr5 + let expr = (expr, setterExprPrebinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let expr = (expr, paramArrayPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let expr = (expr, allArgsPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = optArgPreBinder expr - let expr = objArgPreBinder expr + let expr = optArgPreBinder expr + let expr = objArgPreBinder expr + expr - (expr, finalAttributeAssignedNamedItems, delayed), tpenv + (callExpr6, finalAttributeAssignedNamedItems, delayed), tpenv +and TcSetterArgExpr cenv env denv objExpr ad (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) = + if isOptCallerArg then error(Error(FSComp.SR.tcInvalidOptionalAssignmentToPropertyOrField(), m)) + + let argExprPrebinder, action, defnItem = + match setter with + | AssignedPropSetter (pinfo, pminfo, pminst) -> + MethInfoChecks cenv.g cenv.amap true None [objExpr] ad m pminfo + let calledArgTy = List.head (List.head (pminfo.GetParamTypes(cenv.amap, m, pminst))) + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates) + let action = BuildPossiblyConditionalMethodCall cenv env mut m true pminfo NormalValUse pminst [objExpr] [argExpr] |> fst + argExprPrebinder, action, Item.Property (pinfo.PropertyName, [pinfo]) + + | AssignedILFieldSetter finfo -> + // Get or set instance IL field + ILFieldInstanceChecks cenv.g cenv.amap ad m finfo + let calledArgTy = finfo.FieldType (cenv.amap, m) + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let action = BuildILFieldSet cenv.g m objExpr finfo argExpr + argExprPrebinder, action, Item.ILField finfo + + | AssignedRecdFieldSetter rfinfo -> + RecdFieldInstanceChecks cenv.g cenv.amap ad m rfinfo + let calledArgTy = rfinfo.FieldType + CheckRecdFieldMutation m denv rfinfo + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let action = BuildRecdFieldSet cenv.g m objExpr rfinfo argExpr + argExprPrebinder, action, Item.RecdField rfinfo + + // Record the resolution for the Language Service + let item = Item.SetterArg (id, defnItem) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) + + argExprPrebinder, action, m + and TcUnnamedMethodArgs cenv env lambdaPropagationInfo tpenv args = List.mapiFoldSquared (TcUnnamedMethodArg cenv env) (lambdaPropagationInfo, tpenv) args diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index 3c341131fb..46bb6b1420 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -1982,7 +1982,7 @@ let ParseAssemblyCodeInstructions s m = try FSharp.Compiler.AbstractIL.Internal.AsciiParser.ilInstrs FSharp.Compiler.AbstractIL.Internal.AsciiLexer.token (UnicodeLexing.StringAsLexbuf s) - with RecoverableParseError -> + with _ -> errorR(Error(FSComp.SR.astParseEmbeddedILError(), m)); [| |] #endif diff --git a/src/fsharp/autobox.fs b/src/fsharp/autobox.fs index da6b5c1d64..8c7036e72c 100644 --- a/src/fsharp/autobox.fs +++ b/src/fsharp/autobox.fs @@ -18,6 +18,8 @@ type cenv = { g: TcGlobals amap: Import.ImportMap } + override x.ToString() = "" + /// Find all the mutable locals that escape a method, function or lambda expression let DecideEscapes syntacticArgs body = let cantBeFree v = diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index de670ab2a7..7799d409e5 100755 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -148,8 +148,8 @@ type InProcErrorLoggerProvider() = CollectDiagnostic (tcConfigBuilder.implicitIncludeDir, tcConfigBuilder.showFullPaths, tcConfigBuilder.flatErrors, tcConfigBuilder.errorStyle, isError, err, true) - let container = if isError then errors else warnings - container.AddRange errs } + let container = if isError then errors else warnings + container.AddRange(errs) } :> ErrorLogger } member __.CapturedErrors = errors.ToArray() @@ -2145,6 +2145,7 @@ let main4 dynamicAssemblyCreator (Args (ctok, tcConfig, tcImports: TcImports, t embedAllSource = tcConfig.embedAllSource embedSourceList = tcConfig.embedSourceList sourceLink = tcConfig.sourceLink + checksumAlgorithm = tcConfig.checksumAlgorithm signer = GetStrongNameSigner signingInfo dumpDebugInfo = tcConfig.dumpDebugInfo pathMap = tcConfig.pathMap }, diff --git a/src/fsharp/fsi/Directory.Build.props b/src/fsharp/fsi/Directory.Build.props deleted file mode 100644 index 7cd41381b5..0000000000 --- a/src/fsharp/fsi/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/src/fsharp/fsi/FSIstrings.txt b/src/fsharp/fsi/FSIstrings.txt old mode 100755 new mode 100644 diff --git a/src/fsharp/fsi/fsi.fsi b/src/fsharp/fsi/fsi.fsi index 845639cfdc..49c307b6cb 100644 --- a/src/fsharp/fsi/fsi.fsi +++ b/src/fsharp/fsi/fsi.fsi @@ -329,5 +329,3 @@ type CompilerOutputStream = new : unit -> CompilerOutputStream member Read : unit -> string - - diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj deleted file mode 100644 index b0a6c6953c..0000000000 --- a/src/fsharp/fsi/fsi.fsproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - Exe - net46;netcoreapp2.1 - net472;netcoreapp2.1 - $(ProtoTargetFramework) - net472;netcoreapp2.1 - netcoreapp2.1 - .exe - $(NoWarn);45;55;62;75;1204 - true - $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 - fsi.res - true - true - - - - true - - - - x86 - $(DefineConstants);FSI_SHADOW_COPY_REFERENCES;FSI_SERVER - - - - - - - {{FSCoreVersion}} - $(FSCoreVersion) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/fsharp/fsi/fsi.ico b/src/fsharp/fsi/fsi.ico deleted file mode 100644 index 236615e876..0000000000 Binary files a/src/fsharp/fsi/fsi.ico and /dev/null differ diff --git a/src/fsharp/fsi/fsi.rc b/src/fsharp/fsi/fsi.rc deleted file mode 100644 index 8bb21ca275..0000000000 --- a/src/fsharp/fsi/fsi.rc +++ /dev/null @@ -1,5 +0,0 @@ -// compile fsi.res by running Windows SDK tool rc.exe like so -// > rc.exe /i "C:\Program Files (x86)\MSBuild\12.0\Bin" /r fsi.rc -// (can replace msbuild path with any path containing default.win32manifest) -1 ICON "fsi.ico" -1 24 "default.win32manifest" \ No newline at end of file diff --git a/src/fsharp/fsi/fsi.res b/src/fsharp/fsi/fsi.res deleted file mode 100644 index e651be6745..0000000000 Binary files a/src/fsharp/fsi/fsi.res and /dev/null differ diff --git a/src/fsharp/fsi/fsimain.fs b/src/fsharp/fsi/fsimain.fs deleted file mode 100644 index c127642db7..0000000000 --- a/src/fsharp/fsi/fsimain.fs +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - - -// This file provides the actual entry point for fsi.exe. -// -// Configure the F# Interactive Session to -// 1. use a WinForms event loop (introduces a System.Windows.Forms.dll dependency) -// 2. provide a remoting connection for the use of editor-hosted sessions (introduces a System.Remoting dependency) -// 3. connect the configuration to the global state programmer-settable settings in FSharp.Compiler.Interactive.Settings.dll -// 4. implement shadow copy of references - -module internal Sample.FSharp.Compiler.Interactive.Main - -open System -open System.Globalization -open System.IO -open System.Reflection -open System.Threading -open System.Runtime.CompilerServices -#if !FX_NO_WINFORMS -open System.Windows.Forms -#endif - -open FSharp.Compiler -open FSharp.Compiler.AbstractIL -open FSharp.Compiler.Interactive.Shell -open FSharp.Compiler.Interactive.Shell.Settings - -#nowarn "55" -#nowarn "40" // let rec on value 'fsiConfig' - - -// Hardbinding dependencies should we NGEN fsi.exe -[] do () -[] do () -// Standard attributes -[] -[] -do() - - -/// Set the current ui culture for the current thread. -#if FX_LCIDFROMCODEPAGE -let internal SetCurrentUICultureForThread (lcid : int option) = - let culture = Thread.CurrentThread.CurrentUICulture - match lcid with - | Some n -> Thread.CurrentThread.CurrentUICulture <- new CultureInfo(n) - | None -> () - { new IDisposable with member x.Dispose() = Thread.CurrentThread.CurrentUICulture <- culture } -#endif - -let callStaticMethod (ty:Type) name args = - ty.InvokeMember(name, (BindingFlags.InvokeMethod ||| BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic), null, null, Array.ofList args,Globalization.CultureInfo.InvariantCulture) - -#if !FX_NO_WINFORMS -///Use a dummy to access protected member -type internal DummyForm() = - inherit Form() - member x.DoCreateHandle() = x.CreateHandle() - /// Creating the dummy form object can crash on Mono Mac, and then prints a nasty background - /// error during finalization of the half-initialized object... - override x.Finalize() = () - -/// This is the event loop implementation for winforms -type WinFormsEventLoop() = - let mainForm = new DummyForm() - do mainForm.DoCreateHandle() - let mutable lcid = None - // Set the default thread exception handler - let restart = ref false - member __.LCID with get () = lcid and set v = lcid <- v - interface IEventLoop with - member x.Run() = - restart := false - Application.Run() - !restart - member x.Invoke (f: unit -> 'T) : 'T = - if not mainForm.InvokeRequired then - f() - else - - // Workaround: Mono's Control.Invoke returns a null result. Hence avoid the problem by - // transferring the resulting state using a mutable location. - let mainFormInvokeResultHolder = ref None - - // Actually, Mono's Control.Invoke isn't even blocking (or wasn't on 1.1.15)! So use a signal to indicate completion. - // Indeed, we should probably do this anyway with a timeout so we can report progress from - // the GUI thread. - use doneSignal = new AutoResetEvent(false) - - - // BLOCKING: This blocks the stdin-reader thread until the - // form invocation has completed. NOTE: does not block on Mono, or did not on 1.1.15 - mainForm.Invoke(new MethodInvoker(fun () -> - try - // When we get called back, someone may jack our culture - // So we must reset our UI culture every time -#if FX_LCIDFROMCODEPAGE - use _scope = SetCurrentUICultureForThread lcid -#else - ignore lcid -#endif - mainFormInvokeResultHolder := Some(f ()) - finally - doneSignal.Set() |> ignore)) |> ignore - - //if !progress then fprintfn outWriter "RunCodeOnWinFormsMainThread: Waiting for completion signal...." - while not (doneSignal.WaitOne(new TimeSpan(0,0,1),true)) do - () // if !progress then fprintf outWriter "." outWriter.Flush() - - //if !progress then fprintfn outWriter "RunCodeOnWinFormsMainThread: Got completion signal, res = %b" (Option.isSome !mainFormInvokeResultHolder) - !mainFormInvokeResultHolder |> Option.get - - member x.ScheduleRestart() = restart := true; Application.Exit() - -/// Try to set the unhandled exception mode of System.Windows.Forms -let internal TrySetUnhandledExceptionMode() = - let i = ref 0 // stop inlining - try - Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) - with _ -> - decr i;() - -#endif - -/// Starts the remoting server to handle interrupt reuests from a host tool. -let StartServer (fsiSession : FsiEvaluationSession) (fsiServerName) = -#if FSI_SERVER - let server = - {new Server.Shared.FSharpInteractiveServer() with - member this.Interrupt() = - //printf "FSI-SERVER: received CTRL-C request...\n" - try - fsiSession.Interrupt() - with e -> - // Final sanity check! - catch all exns - but not expected - assert false - () - } - - Server.Shared.FSharpInteractiveServer.StartServer(fsiServerName,server) -#else - ignore (fsiSession, fsiServerName) -#endif - -//---------------------------------------------------------------------------- -// GUI runCodeOnMainThread -//---------------------------------------------------------------------------- - -let evaluateSession(argv: string[]) = -#if DEBUG - if argv |> Array.exists (fun x -> x = "/pause" || x = "--pause") then - Console.WriteLine("Press any key to continue...") - Console.ReadKey() |> ignore -#endif - - // When VFSI is running, set the input/output encoding to UTF8. - // Otherwise, unicode gets lost during redirection. - // It is required only under Net4.5 or above (with unicode console feature). - if argv |> Array.exists (fun x -> x.Contains "fsi-server") then - Console.InputEncoding <- System.Text.Encoding.UTF8 - Console.OutputEncoding <- System.Text.Encoding.UTF8 - - try - // Create the console reader - let console = new FSharp.Compiler.Interactive.ReadLineConsole() - - // Define the function we pass to the FsiEvaluationSession - let getConsoleReadLine (probeToSeeIfConsoleWorks) = - let consoleIsOperational = - if probeToSeeIfConsoleWorks then - //if progress then fprintfn outWriter "probing to see if console works..." - try - // Probe to see if the console looks functional on this version of .NET - let _ = Console.KeyAvailable - let _ = Console.ForegroundColor - let _ = Console.CursorLeft <- Console.CursorLeft - true - with _ -> - //if progress then fprintfn outWriter "probe failed, we have no console..." - false - else true - if consoleIsOperational then - Some (fun () -> console.ReadLine()) - else - None - -//#if USE_FSharp_Compiler_Interactive_Settings - let fsiObjOpt = - let defaultFSharpBinariesDir = -#if FX_NO_APP_DOMAINS - System.AppContext.BaseDirectory -#else - System.AppDomain.CurrentDomain.BaseDirectory -#endif - // We use LoadFrom to make sure we get the copy of this assembly from the right load context - let fsiAssemblyPath = Path.Combine(defaultFSharpBinariesDir,"FSharp.Compiler.Interactive.Settings.dll") - let fsiAssembly = Assembly.LoadFrom(fsiAssemblyPath) - if isNull fsiAssembly then - None - else - let fsiTy = fsiAssembly.GetType("FSharp.Compiler.Interactive.Settings") - if isNull fsiAssembly then failwith "failed to find type FSharp.Compiler.Interactive.Settings in FSharp.Compiler.Interactive.Settings.dll" - Some (callStaticMethod fsiTy "get_fsi" [ ]) - - let fsiConfig0 = - match fsiObjOpt with - | None -> FsiEvaluationSession.GetDefaultConfiguration() - | Some fsiObj -> FsiEvaluationSession.GetDefaultConfiguration(fsiObj, true) - -//fsiSession.LCID -#if !FX_NO_WINFORMS - // Create the WinForms event loop - let fsiWinFormsLoop = - lazy - try Some (WinFormsEventLoop()) - with e -> - printfn "Your system doesn't seem to support WinForms correctly. You will" - printfn "need to set fsi.EventLoop use GUI windows from F# Interactive." - printfn "You can set different event loops for MonoMac, Gtk#, WinForms and other" - printfn "UI toolkits. Drop the --gui argument if no event loop is required." - None -#endif - - let legacyReferenceResolver = -#if CROSS_PLATFORM_COMPILER - SimulatedMSBuildReferenceResolver.SimulatedMSBuildResolver -#else - LegacyMSBuildReferenceResolver.getResolver() -#endif - // Update the configuration to include 'StartServer', WinFormsEventLoop and 'GetOptionalConsoleReadLine()' - let rec fsiConfig = - { new FsiEvaluationSessionHostConfig () with - member __.FormatProvider = fsiConfig0.FormatProvider - member __.FloatingPointFormat = fsiConfig0.FloatingPointFormat - member __.AddedPrinters = fsiConfig0.AddedPrinters - member __.ShowDeclarationValues = fsiConfig0.ShowDeclarationValues - member __.ShowIEnumerable = fsiConfig0.ShowIEnumerable - member __.ShowProperties = fsiConfig0.ShowProperties - member __.PrintSize = fsiConfig0.PrintSize - member __.PrintDepth = fsiConfig0.PrintDepth - member __.PrintWidth = fsiConfig0.PrintWidth - member __.PrintLength = fsiConfig0.PrintLength - member __.ReportUserCommandLineArgs args = fsiConfig0.ReportUserCommandLineArgs args - member __.EventLoopRun() = -#if !FX_NO_WINFORMS - match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with - | Some l -> (l :> IEventLoop).Run() - | _ -> -#endif - fsiConfig0.EventLoopRun() - member __.EventLoopInvoke(f) = -#if !FX_NO_WINFORMS - match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with - | Some l -> (l :> IEventLoop).Invoke(f) - | _ -> -#endif - fsiConfig0.EventLoopInvoke(f) - member __.EventLoopScheduleRestart() = -#if !FX_NO_WINFORMS - match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with - | Some l -> (l :> IEventLoop).ScheduleRestart() - | _ -> -#endif - fsiConfig0.EventLoopScheduleRestart() - - member __.UseFsiAuxLib = fsiConfig0.UseFsiAuxLib - - member __.StartServer(fsiServerName) = StartServer fsiSession fsiServerName - - // Connect the configuration through to the 'fsi' Event loop - member __.GetOptionalConsoleReadLine(probe) = getConsoleReadLine(probe) } - - // Create the console - and fsiSession : FsiEvaluationSession = FsiEvaluationSession.Create (fsiConfig, argv, Console.In, Console.Out, Console.Error, collectible=false, legacyReferenceResolver=legacyReferenceResolver) - - -#if !FX_NO_WINFORMS - // Configure some remaining parameters of the GUI support - if fsiSession.IsGui then - try - Application.EnableVisualStyles() - with _ -> - () - - // Route GUI application exceptions to the exception handlers - Application.add_ThreadException(new ThreadExceptionEventHandler(fun _ args -> fsiSession.ReportUnhandledException args.Exception)); - - let runningOnMono = try System.Type.GetType("Mono.Runtime") <> null with e-> false - if not runningOnMono then - try - TrySetUnhandledExceptionMode() - with _ -> - () - - fsiWinFormsLoop.Value |> Option.iter (fun l -> l.LCID <- fsiSession.LCID) -#endif - - // Setup the completion function for intellisense in the console - console.SetCompletionFunction(fun (s1,s2) -> fsiSession.GetCompletions (match s1 with | Some s -> s + "." + s2 | None -> s2)) - - // Start the session - fsiSession.Run() - 0 - with - | FSharp.Compiler.ErrorLogger.StopProcessingExn _ -> 1 - | FSharp.Compiler.ErrorLogger.ReportedError _ -> 1 - | e -> eprintf "Exception by fsi.exe:\n%+A\n" e; 1 - -// Mark the main thread as STAThread since it is a GUI thread -[] -[] -[] -let MainMain argv = - ignore argv - let argv = System.Environment.GetCommandLineArgs() - let savedOut = Console.Out - use __ = - { new IDisposable with - member __.Dispose() = - try - Console.SetOut(savedOut) - with _ -> ()} - -#if !FX_NO_APP_DOMAINS - let timesFlag = argv |> Array.exists (fun x -> x = "/times" || x = "--times") - if timesFlag then - AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> - let stats = ILBinaryReader.GetStatistics() - printfn "STATS: #ByteArrayFile = %d, #MemoryMappedFileOpen = %d, #MemoryMappedFileClosed = %d, #RawMemoryFile = %d, #WeakByteArrayFile = %d" stats.byteFileCount stats.memoryMapFileOpenedCount stats.memoryMapFileClosedCount stats.rawMemoryFileCount stats.weakByteFileCount) -#endif - -#if FSI_SHADOW_COPY_REFERENCES - let isShadowCopy x = (x = "/shadowcopyreferences" || x = "--shadowcopyreferences" || x = "/shadowcopyreferences+" || x = "--shadowcopyreferences+") - if AppDomain.CurrentDomain.IsDefaultAppDomain() && argv |> Array.exists isShadowCopy then - let setupInformation = AppDomain.CurrentDomain.SetupInformation - setupInformation.ShadowCopyFiles <- "true" - let helper = AppDomain.CreateDomain("FSI_Domain", null, setupInformation) - helper.ExecuteAssemblyByName(Assembly.GetExecutingAssembly().GetName()) - else - evaluateSession(argv) -#else - evaluateSession(argv) -#endif diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.cs.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.cs.xlf deleted file mode 100644 index 5131c58159..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.cs.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Zastavilo se kvůli chybě.\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Použití: {0} <parametry> [skript.fsx [<argumenty>]] - - - - - INPUT FILES - - - VSTUPNÍ SOUBORY - - - - - - CODE GENERATION - - - GENEROVÁNÍ KÓDU - - - - - - ERRORS AND WARNINGS - - - CHYBY A UPOZORNĚNÍ - - - - - - LANGUAGE - - - JAZYK - - - - - - MISCELLANEOUS - - - RŮZNÉ - - - - - - ADVANCED - - - UPŘESNIT - - - - - Exception raised when starting remoting server.\n{0} - Při spouštění serveru vzdálené komunikace se vyvolala výjimka.\n{0} - - - - Use the given file on startup as initial input - Použít při spuštění zadaný soubor jako počáteční vstup - - - - #load the given file on startup - #load zadaného souboru při spuštění - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Zpracovat zbývající argumenty jako argumenty příkazového řádku, ke kterým se přistupuje pomocí fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Zobrazí tuto zprávu o použití (krátký tvar: -?). - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Ukončit soubor fsi po načtení souborů nebo spuštění skriptu .fsx zadaného na příkazovém řádku - - - - Execute interactions on a Windows Forms event loop (on by default) - Provést interakce u smyčky událostí modelu Windows Forms (ve výchozím nastavení zapnuté) - - - - Suppress fsi writing to stdout - Potlačit zapisování fsi do stdout - - - - Support TAB completion in console (on by default) - Podpora dokončování pomocí tabulátorů v konzole (ve výchozím nastavení zapnuté) - - - - Emit debug information in quotations - Generovat ladicí informace v uvozovkách - - - - For help type #help;; - Nápovědu zobrazíte zadáním #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Při spuštění procesu F# Interactive se vyskytl problém. Ten mohly způsobit známé potíže s podporou konzoly procesu na pozadí pro aplikace umožňující kódování Unicode v některých systémech Windows. V případě sady Visual Studio zkuste vybrat Nástroje->Možnosti->F# Interactive a zadat: --fsi-server-no-unicode. - - - - '{0}' is not a valid assembly name - {0} není platný název sestavení. - - - - Directory '{0}' doesn't exist - Adresář {0} neexistuje. - - - - Invalid directive '#{0} {1}' - Neplatná direktiva #{0} {1} - - - - Warning: line too long, ignoring some characters\n - Upozornění: řádek je příliš dlouhý, některé znaky se ignorují.\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0}, CPU: {1}, GC {2} - - - - gen - obec - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nFunkce přehledného výpisu vyvolala výjimku.\nNahlaste prosím tento problém, abychom ho mohli opravit.\nTrasování: {0}\n - - - - F# Interactive directives: - Direktivy F# Interactive: - - - - Reference (dynamically load) the given DLL - Odkazovat (dynamicky načíst) zadanou knihovnu DLL - - - - Add the given search path for referenced DLLs - Přidat zadanou cestu hledání pro odkazované knihovny DLL - - - - Load the given file(s) as if compiled and referenced - Načíst zadané soubory, jako by byly zkompilované a odkazované - - - - Toggle timing on/off - Přepnout časování do polohy zapnuto nebo vypnuto - - - - Display help - Zobrazí nápovědu. - - - - Exit - Ukončit - - - - F# Interactive command line options: - Možnosti příkazového řádku F# Interactive: - - - - See '{0}' for options - Možnosti viz {0} - - - - Loading - Načítání - - - - \n- Interrupt\n - \n- Přerušit\n - - - - \n- Exit...\n - \n- Ukončit...\n - - - - - Aborting main thread... - – Ukončuje se hlavní vlákno... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Nepovedlo se nainstalovat obslužnou rutinu ctrl-c. Obslužná rutina Ctrl-C nebude dostupná. Vyskytla se tato chyba:\n\t{0} - - - - --> Referenced '{0}' - --> Odkazovaný soubor {0} - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Odkazovaný soubor {0} (Soubor musí být procesem F# Interactive uzamčený.) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Odkazováno {0} (na sestavení s odlišným časovým razítkem se už z tohoto umístění odkazovalo, pro načtení aktualizovaného sestavení obnovte soubor fsi) - - - - --> Added '{0}' to library include path - --> Soubory přidané do knihovny ({0}) zahrnují cestu. - - - - --> Timing now on - --> Časování je teď zapnuté. - - - - --> Timing now off - --> Časování je teď vypnuté. - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Při zpracování události se vyvolala neočekávaná výjimka ThreadAbortException (Ctrl-C): Pokus o restartování... - - - - Failed to resolve assembly '{0}' - Nepovedlo se přeložit sestavení {0}. - - - - Binding session to '{0}'... - Relace se váže na {0}... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive verze {0} - - - - F# Interactive for F# {0} - F# Interactive pro F# {0} - - - - Prevents references from being locked by the F# Interactive process - Znemožňuje zamknutí referencí procesem F# Interactive. - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.de.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.de.xlf deleted file mode 100644 index 3af3100b5f..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.de.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Aufgrund eines Fehlers beendet\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Verwendung: {0} <Optionen> [script.fsx [<Argumente>]] - - - - - INPUT FILES - - - EINGABEDATEIEN - - - - - - CODE GENERATION - - - CODEGENERIERUNG - - - - - - ERRORS AND WARNINGS - - - FEHLER UND WARNUNGEN - - - - - - LANGUAGE - - - SPRACHE - - - - - - MISCELLANEOUS - - - VERSCHIEDENES - - - - - - ADVANCED - - - ERWEITERT - - - - - Exception raised when starting remoting server.\n{0} - Ausnahme beim Starten des Remoteservers.\n{0} - - - - Use the given file on startup as initial input - Die angegebene Datei beim Start als ursprüngliche Eingabe verwenden - - - - #load the given file on startup - #load der angegebenen Datei beim Start - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Verbleibende Argumente als Befehlszeilenargumente (Zugriff mithilfe von fsi.CommandLineArgs) behandeln - - - - Display this usage message (Short form: -?) - Diesen Hilfetext anzeigen (Kurzform: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - FSI nach Laden der Dateien oder Ausführen des in der Befehlszeile angegebenen .fsx-Skripts beenden - - - - Execute interactions on a Windows Forms event loop (on by default) - Interaktionen in einer Windows Forms-Ereignisschleife ausführen (standardmäßig aktiviert) - - - - Suppress fsi writing to stdout - Schreiben von FSI in stdout unterdrücken - - - - Support TAB completion in console (on by default) - Vervollständigung mit der TAB-TASTE in der Konsole unterstützen (standardmäßig aktiviert) - - - - Emit debug information in quotations - Debugginginformationen in Anführungszeichen ausgeben - - - - For help type #help;; - Um Hilfe zu erhalten, geben Sie "#help;;" ein. - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Beim Starten des F# Interactive-Prozesses ist ein Fehler aufgetreten. Ursache hierfür kann ein bekanntes Problem mit der Hintergrundprozess-Konsolenunterstützung für Unicode-aktivierte Anwendungen unter manchen Windows-Systemen sein. Wählen Sie "Tools" -> "Optionen" -> "F# Interactive für Visual Studio" aus, und geben Sie "--fsi-server-no-unicode" ein. - - - - '{0}' is not a valid assembly name - {0} ist kein gültiger Assemblyname. - - - - Directory '{0}' doesn't exist - Das Verzeichnis "{0}" ist nicht vorhanden. - - - - Invalid directive '#{0} {1}' - Ungültige Direktive "#{0} {1}" - - - - Warning: line too long, ignoring some characters\n - Warnung: Die Zeile ist zu lang, einige Zeichen werden ignoriert.\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0}, CPU: {1}, GC {2} - - - - gen - Gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nAusnahme bei der automatischen Strukturierung und Einrückung.\nMelden Sie dies, damit das Problem behoben werden kann.\nAblaufverfolgung: {0}\n - - - - F# Interactive directives: - F# Interactive-Direktiven: - - - - Reference (dynamically load) the given DLL - Auf die angegebene DLL verweisen (dynamisch laden) - - - - Add the given search path for referenced DLLs - Angegebenen Suchpfad für DLLs, auf die verwiesen wird, hinzufügen - - - - Load the given file(s) as if compiled and referenced - Angegebene Datei(en) laden, als wären sie kompiliert und würden Verweise aufweisen - - - - Toggle timing on/off - Zeitliche Steuerung ein/aus - - - - Display help - Hilfe anzeigen - - - - Exit - Beenden - - - - F# Interactive command line options: - F# Interactive-Befehlszeilenoptionen: - - - - See '{0}' for options - Optionen finden Sie unter "{0}". - - - - Loading - Laden - - - - \n- Interrupt\n - \n- Unterbrechen\n - - - - \n- Exit...\n - \n- Beenden...\n - - - - - Aborting main thread... - - Hauptthread wird abgebrochen... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Fehler beim Installieren des STRG-C-Handlers. STRG-C-Behandlung ist nicht verfügbar. Fehler:\n\t{0} - - - - --> Referenced '{0}' - --> Auf "{0}" wurde verwiesen - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Auf "{0}" wurde verwiesen (die Datei wird möglicherweise vom F# Interactive-Prozess gesperrt) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Auf "{0}" wurde verwiesen (eine Assembly mit einem anderen Zeitstempel wurde bereits von diesem Ort verwiesen; stellen Sie fsi wieder her, um die aktualisierte Assembly zu laden) - - - - --> Added '{0}' to library include path - --> "{0}" wurde zum Bibliotheksincludepfad hinzugefügt - - - - --> Timing now on - --> Zeitliche Steuerung jetzt ein - - - - --> Timing now off - --> Zeitliche Steuerung jetzt aus - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Unerwartete ThreadAbortException (Ctrl-C) während der Ereignisbehandlung: Es wird versucht, neu zu starten... - - - - Failed to resolve assembly '{0}' - Fehler beim Auflösen der Assembly "{0}" - - - - Binding session to '{0}'... - Sitzung wird an "{0}" gebunden... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive, Version {0} - - - - F# Interactive for F# {0} - F# Interactive für F# {0} - - - - Prevents references from being locked by the F# Interactive process - Verhindert, dass Verweise vom F# Interactive-Prozess gesperrt werden. - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.es.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.es.xlf deleted file mode 100644 index f2a15eb8d7..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.es.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Detenido debido a un error.\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Uso: {0} <opciones> [script.fsx [<argumentos>]] - - - - - INPUT FILES - - - ARCHIVOS DE ENTRADA - - - - - - CODE GENERATION - - - GENERACIÓN DE CÓDIGO - - - - - - ERRORS AND WARNINGS - - - ERRORES Y ADVERTENCIAS - - - - - - LANGUAGE - - - LENGUAJE - - - - - - MISCELLANEOUS - - - VARIOS - - - - - - ADVANCED - - - AVANZADAS - - - - - Exception raised when starting remoting server.\n{0} - Se generó una excepción al iniciar el servidor remoto.\n{0} - - - - Use the given file on startup as initial input - Usar el archivo proporcionado al inicio como entrada inicial - - - - #load the given file on startup - #load Cargar el archivo proporcionado al inicio - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Tratar los demás argumentos como argumentos de la línea de comandos, a los que se obtiene acceso con fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Muestra este mensaje de uso (forma corta: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Salir de fsi después de cargar los archivos o ejecutar el script .fsx proporcionado en la línea de comandos - - - - Execute interactions on a Windows Forms event loop (on by default) - Ejecutar interacciones en un bucle de evento de Windows Forms (activado de forma predeterminada) - - - - Suppress fsi writing to stdout - Suprimir escritura fsi en stdout - - - - Support TAB completion in console (on by default) - Admitir finalización con TAB en la consola (activada de forma predeterminada) - - - - Emit debug information in quotations - Emitir información de depuración en expresiones de código delimitadas - - - - For help type #help;; - Para obtener ayuda, escriba #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Se produjo un problema al iniciar el proceso de F# interactivo. Esto puede deberse a un problema conocido de compatibilidad de la consola de procesos en segundo plano con aplicaciones habilitadas para Unicode en algunos sistemas Windows. Pruebe lo siguiente: seleccione Herramientas->Opciones->F# interactivo para Visual Studio y escriba '--fsi-server-no-unicode'. - - - - '{0}' is not a valid assembly name - '{0}' no es un nombre de ensamblado válido. - - - - Directory '{0}' doesn't exist - El directorio '{0}' no existe. - - - - Invalid directive '#{0} {1}' - Directiva '#{0} {1}' no válida. - - - - Warning: line too long, ignoring some characters\n - Advertencia: línea demasiado larga, omitiendo algunos caracteres.\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0}, CPU: {1}, GC: {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nSe generó una excepción durante la impresión con sangría.\nComuníquelo para poder corregirlo.\nSeguimiento: {0}\n - - - - F# Interactive directives: - Directivas de F# interactivo: - - - - Reference (dynamically load) the given DLL - Hacer referencia (cargada dinámicamente) al archivo DLL proporcionado - - - - Add the given search path for referenced DLLs - Agregar la ruta de acceso de búsqueda proporcionada para archivos DLL a los que se hace referencia - - - - Load the given file(s) as if compiled and referenced - Cargar los archivos proporcionados como si estuvieran compilados y referenciados - - - - Toggle timing on/off - Activar o desactivar el control de tiempo - - - - Display help - Mostrar ayuda - - - - Exit - Salir - - - - F# Interactive command line options: - Opciones de la línea de comandos de F# interactivo: - - - - See '{0}' for options - Vea '{0}' para conocer las opciones - - - - Loading - Cargando - - - - \n- Interrupt\n - \n- Interrumpir\n - - - - \n- Exit...\n - \n- Salir...\n - - - - - Aborting main thread... - - Anulando el subproceso principal... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - No se pudo instalar el controlador ctrl-c. No estará disponible, por tanto, el control mediante Ctrl-C. El error es:\n\t{0} - - - - --> Referenced '{0}' - --> '{0}' referenciado - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> '{0}' al que se hace referencia (el archivo puede estar bloqueado por un proceso de F# interactivo) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Se hace referencia a '{0}' (ya se ha hecho referencia a un ensamblado con una marca de tiempo distinta desde esta ubicación, restablecer fsi para cargar el ensamblado actualizado) - - - - --> Added '{0}' to library include path - --> Se agregó '{0}' a la ruta de acceso de inclusión de biblioteca - - - - --> Timing now on - --> Control de tiempo activado - - - - --> Timing now off - --> Control de tiempo desactivado - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - ThreadAbortException inesperado (Ctrl-C) durante el control de eventos: intentando reiniciar... - - - - Failed to resolve assembly '{0}' - No se pudo resolver el ensamblado '{0}'. - - - - Binding session to '{0}'... - Enlazando sesión con '{0}'... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# interactivo, versión {0} - - - - F# Interactive for F# {0} - F# interactivo para F# {0} - - - - Prevents references from being locked by the F# Interactive process - Impide que el proceso de F# interactivo bloquee las referencias - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.fr.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.fr.xlf deleted file mode 100644 index 09a95ec2bb..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.fr.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Arrêt en raison d'une erreur\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Utilisation : {0} <options> [script.fsx [<arguments>]] - - - - - INPUT FILES - - - FICHIERS D'ENTRÉE - - - - - - CODE GENERATION - - - GÉNÉRATION DE CODE - - - - - - ERRORS AND WARNINGS - - - ERREURS ET AVERTISSEMENTS - - - - - - LANGUAGE - - - LANGAGE - - - - - - MISCELLANEOUS - - - DIVERS - - - - - - ADVANCED - - - AVANCÉ - - - - - Exception raised when starting remoting server.\n{0} - Exception déclenchée lors du démarrage du serveur de communication à distance.\n{0} - - - - Use the given file on startup as initial input - Utilise le fichier spécifié au démarrage en tant qu'entrée initiale - - - - #load the given file on startup - #load le fichier spécifié au démarrage - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Traite les arguments restants en tant qu'arguments de ligne de commande, accessibles via fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Affiche ce message d'utilisation (forme abrégée : -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Sortie de fsi après le chargement des fichiers ou l'exécution du script .fsx spécifié dans la ligne de commande - - - - Execute interactions on a Windows Forms event loop (on by default) - Exécute des interactions dans une boucle d'événements Windows Forms (activé par default) - - - - Suppress fsi writing to stdout - Supprime l'écriture de fsi dans stdout - - - - Support TAB completion in console (on by default) - Prend en charge la saisie semi-automatique via la touche Tab dans la console (activée par défaut) - - - - Emit debug information in quotations - Émettre les informations de débogage entre quotations - - - - For help type #help;; - Pour obtenir de l'aide, tapez #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Un problème s'est produit lors du démarrage du processus F# Interactive. Cela peut être dû à un problème connu lié à la prise en charge par la console des processus en arrière-plan pour les applications Unicode sur certains systèmes Windows. Essayez de sélectionner Outils->Options->F# Interactive pour Visual Studio, puis entrez '--fsi-server-no-unicode'. - - - - '{0}' is not a valid assembly name - '{0}' n'est pas un nom d'assembly valide - - - - Directory '{0}' doesn't exist - Le répertoire '{0}' n'existe pas - - - - Invalid directive '#{0} {1}' - Directive non valide '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - Avertissement : ligne trop longue, certains caractères sont ignorés\n - - - - Real: {0}, CPU: {1}, GC {2} - Réel : {0}, Processeur : {1}, GC {2} - - - - gen - gén - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nException déclenchée pendant le listing en mode Pretty. \nSignalez ce problème afin qu'il soit corrigé.\nTrace : {0}\n - - - - F# Interactive directives: - Directives F# Interactive : - - - - Reference (dynamically load) the given DLL - Référence (charger dynamiquement) la DLL spécifiée - - - - Add the given search path for referenced DLLs - Ajoute le chemin de recherche spécifié pour les DLL référencées - - - - Load the given file(s) as if compiled and referenced - Charge le ou les fichiers spécifiés comme s'ils étaient compilés et référencés - - - - Toggle timing on/off - Minutage activé/désactivé - - - - Display help - Afficher l'aide - - - - Exit - Quitter - - - - F# Interactive command line options: - Options de ligne de commande F# Interactive : - - - - See '{0}' for options - Consulter '{0}' pour les options - - - - Loading - Chargement - - - - \n- Interrupt\n - \n- Interrompre\n - - - - \n- Exit...\n - \n- Quitter...\n - - - - - Aborting main thread... - - Abandon du thread principal... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Impossible d'installer le gestionnaire ctrl-c - La gestion Ctrl-C n'est pas disponible. L'erreur était :\n\t{0} - - - - --> Referenced '{0}' - --> Référencement de '{0}' - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Référencement de '{0}' (le fichier est peut-être verrouillé par le processus F# Interactive) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Référencement de '{0}' (un assembly avec un horodatage différent a déjà été référencé à partir de cet emplacement, réinitialisez fsi pour charger l'assembly mis à jour) - - - - --> Added '{0}' to library include path - --> Ajout de '{0}' au chemin d'accès Include de la bibliothèque - - - - --> Timing now on - --> Minutage activé - - - - --> Timing now off - --> Minutage désactivé - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - ThreadAbortException inattendu (Ctrl-C) durant la gestion des événements : tentative de redémarrage... - - - - Failed to resolve assembly '{0}' - Échec de la résolution de l'assembly '{0}' - - - - Binding session to '{0}'... - Liaison de la session à '{0}'... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive version {0} - - - - F# Interactive for F# {0} - F# Interactive pour F# {0} - - - - Prevents references from being locked by the F# Interactive process - Empêche le blocage des références par le processus de F# Interactive - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.it.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.it.xlf deleted file mode 100644 index 51a94aabb2..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.it.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Interruzione a causa di un errore\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Sintassi: {0} <opzioni> [script.fsx [<argomenti>]] - - - - - INPUT FILES - - - FILE DI INPUT - - - - - - CODE GENERATION - - - GENERAZIONE CODICE - - - - - - ERRORS AND WARNINGS - - - ERRORI E AVVISI - - - - - - LANGUAGE - - - LINGUAGGIO - - - - - - MISCELLANEOUS - - - VARIE - - - - - - ADVANCED - - - AVANZATE - - - - - Exception raised when starting remoting server.\n{0} - Eccezione all'avvio del server remoto.\n{0} - - - - Use the given file on startup as initial input - Usa il file specificato all'avvio come input iniziale - - - - #load the given file on startup - #load file specificato all'avvio - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Tratta gli argomenti rimanenti come argomenti della riga di comando accessibili mediante fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Visualizza questo messaggio relativo all'uso (forma breve: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Uscita da fsi dopo il caricamento dei file o l'esecuzione dello script .fsx specificato nella riga di comando - - - - Execute interactions on a Windows Forms event loop (on by default) - Esegue interazioni in un ciclo di eventi di Windows Forms (abilitata per impostazione predefinita) - - - - Suppress fsi writing to stdout - Impedisci scrittura fsi su stdout - - - - Support TAB completion in console (on by default) - Supporta completamento con tasto TAB in console (abilitata per impostazione predefinita) - - - - Emit debug information in quotations - Crea informazioni di debug in quotation - - - - For help type #help;; - Per informazioni, digitare #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Si è verificato un problema durante l'avvio del processo F# Interactive. Può trattarsi di un problema noto del supporto della console dei processi in background per le applicazioni abilitate per Unicode in alcuni sistemi Windows. Provare a scegliere Strumenti->Opzioni->F# Interactive per Visual Studio e immettere '--fsi-server-no-unicode'. - - - - '{0}' is not a valid assembly name - '{0}' non è un nome di assembly valido - - - - Directory '{0}' doesn't exist - La directory '{0}' non esiste - - - - Invalid directive '#{0} {1}' - Direttiva '#{0} {1}' non valida - - - - Warning: line too long, ignoring some characters\n - Avviso: riga troppo lunga; alcuni caratteri verranno ignorati\n - - - - Real: {0}, CPU: {1}, GC {2} - Reale: {0}, CPU: {1}, GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nEccezione durante la riformattazione.\nSegnalare il problema affinché possa essere risolto.\nTraccia: {0}\n - - - - F# Interactive directives: - Direttive F# Interactive: - - - - Reference (dynamically load) the given DLL - Aggiunge riferimento alla DLL specificata (caricamento dinamico) - - - - Add the given search path for referenced DLLs - Aggiunge il percorso di ricerca specificato per le DLL a cui viene fatto riferimento - - - - Load the given file(s) as if compiled and referenced - Carica il file (o i file) specificati come se compilati ed aggiunti come riferimento - - - - Toggle timing on/off - Attiva/disattiva la temporizzazione - - - - Display help - Visualizza la guida - - - - Exit - Esci - - - - F# Interactive command line options: - Opzioni della riga di comando F# Interactive: - - - - See '{0}' for options - Vedere '{0}' per le opzioni - - - - Loading - Caricamento - - - - \n- Interrupt\n - \n- Interrupt\n - - - - \n- Exit...\n - \n- Esci...\n - - - - - Aborting main thread... - - Interruzione del thread principale... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Non è stato possibile installare il gestore di CTRL+C. La gestione di CTRL+C non sarà disponibile. Errore:\n\t{0} - - - - --> Referenced '{0}' - --> Riferimento a '{0}' - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Riferimento a '{0}' (il file potrebbe essere bloccato dal processo di F# Interactive) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Riferimento già presente a '{0}' (un assembly con timestamp diverso è già presente come riferimento in questa posizione. Reimpostare fsi per caricare l'assembly aggiornato) - - - - --> Added '{0}' to library include path - --> Aggiunto '{0}' al percorso di inclusione della libreria - - - - --> Timing now on - --> Temporizzazione attivata - - - - --> Timing now off - --> Temporizzazione disattivata - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Eccezione ThreadAbortException (Ctrl-C) imprevista durante la gestione dell'evento. Verrà effettuato un tentativo di riavvio... - - - - Failed to resolve assembly '{0}' - Non è stato possibile risolvere l'assembly '{0}' - - - - Binding session to '{0}'... - Binding della sessione a '{0}'... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive versione {0} - - - - F# Interactive for F# {0} - F# Interactive per F# {0} - - - - Prevents references from being locked by the F# Interactive process - Impedisce che i riferimenti vengano bloccati dal processo F# Interactive - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.ja.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.ja.xlf deleted file mode 100644 index 0751b4601e..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.ja.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - エラーのため停止しました\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - 使い方: {0} <オプション> [script.fsx [<引数>]] - - - - - INPUT FILES - - - 入力ファイル - - - - - - CODE GENERATION - - - コード生成 - - - - - - ERRORS AND WARNINGS - - - エラーと警告 - - - - - - LANGUAGE - - - 言語 - - - - - - MISCELLANEOUS - - - その他 - - - - - - ADVANCED - - - 詳細 - - - - - Exception raised when starting remoting server.\n{0} - サーバーのリモート処理の開始中に例外が発生しました。\n{0} - - - - Use the given file on startup as initial input - 指定されたファイルをスタートアップ時の初期入力として使用します - - - - #load the given file on startup - #load: 指定されたファイルをスタートアップ時に読み込みます - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - 残りの引数は、fsi.CommandLineArgs を使用してアクセスするコマンド ライン引数として扱います - - - - Display this usage message (Short form: -?) - この使用方法に関するメッセージを表示します (短い形式: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - コマンド ライン上で指定されたファイルの読み込みまたは .fsx スクリプトの実行後、fsi を終了します - - - - Execute interactions on a Windows Forms event loop (on by default) - Windows フォーム イベント ループでの対話の実行 (既定でオン) - - - - Suppress fsi writing to stdout - fsi の stdout への書き込みの抑止 - - - - Support TAB completion in console (on by default) - コンソールでの TAB 補完のサポート (既定でオン) - - - - Emit debug information in quotations - デバッグ情報を引用符で囲んで生成します - - - - For help type #help;; - ヘルプを表示するには次を入力してください: #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - F# インタラクティブのプロセスの開始中に問題が発生しました。この原因は、一部の Windows システム上での Unicode 対応アプリケーションのバックグラウンド プロセス コンソールのサポートに関する既知の問題にある可能性があります。[ツール]5D; の [オプション]5D; から [F# Interactive for Visual Studio]5D; を選択し、「--fsi-server-no-unicode」と入力してください。 - - - - '{0}' is not a valid assembly name - '{0}' は有効なアセンブリ名ではありません - - - - Directory '{0}' doesn't exist - ディレクトリ "{0}" は存在しません - - - - Invalid directive '#{0} {1}' - 無効なディレクティブ '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - 警告: 行が長すぎます。一部の文字は無視されます\n - - - - Real: {0}, CPU: {1}, GC {2} - リアル: {0}、CPU: {1}、GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\n再フォーマット中に例外が発生しました。\nこの問題を解決できるように報告してください。\nトレース: {0}\n - - - - F# Interactive directives: - F# インタラクティブ ディレクティブ: - - - - Reference (dynamically load) the given DLL - 指定された DLL を参照します (動的読み込み) - - - - Add the given search path for referenced DLLs - 参照されている DLL に対し、指定された検索パスを追加します - - - - Load the given file(s) as if compiled and referenced - コンパイルおよび参照されているように、指定されたファイルを読み込みます - - - - Toggle timing on/off - タイミングのオンとオフを切り替えます - - - - Display help - ヘルプの表示 - - - - Exit - 終了 - - - - F# Interactive command line options: - F# インタラクティブ コマンド ライン オプション: - - - - See '{0}' for options - オプションについては '{0}' を参照してください - - - - Loading - 読み込み中 - - - - \n- Interrupt\n - \n- 割り込み\n - - - - \n- Exit...\n - \n- 終了...\n - - - - - Aborting main thread... - - メイン スレッドを中止しています... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - ctrl-c ハンドラーをインストールできませんでした - Ctrl-C 処理を使用できるようになりません。エラー:\n\t{0} - - - - --> Referenced '{0}' - --> '{0}' を参照しました - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> '{0}' を参照しました (ファイルが F# インタラクティブのプロセスによってロックされている可能性があります) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> 参照された '{0}' (タイムスタンプが異なるアセンブリが既にこの場所から参照されています。fsi をリセットして更新されたアセンブリを読み込んでください) - - - - --> Added '{0}' to library include path - --> ライブラリのインクルード パスに '{0}' を追加しました - - - - --> Timing now on - --> 現在タイミングはオンです - - - - --> Timing now off - --> 現在タイミングはオフです - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - イベント処理中に予期しない ThreadAbortException (Ctrl-C) が発生しました: 再開を試行しています... - - - - Failed to resolve assembly '{0}' - アセンブリ '{0}' を解決できませんでした - - - - Binding session to '{0}'... - セッションを '{0}' にバインドしています... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# インタラクティブ バージョン {0} - - - - F# Interactive for F# {0} - F# {0} の F# インタラクティブ - - - - Prevents references from being locked by the F# Interactive process - 参照が F# インタラクティブ プロセスによってロックされないようにします。 - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.ko.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.ko.xlf deleted file mode 100644 index 47545ea3e0..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.ko.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - 오류 때문에 중지되었습니다.\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - 사용법: {0} <options> [script.fsx [<arguments>]] - - - - - INPUT FILES - - - 입력 파일 - - - - - - CODE GENERATION - - - 코드 생성 - - - - - - ERRORS AND WARNINGS - - - 오류 및 경고 - - - - - - LANGUAGE - - - 언어 - - - - - - MISCELLANEOUS - - - 기타 - - - - - - ADVANCED - - - 고급 - - - - - Exception raised when starting remoting server.\n{0} - 원격 서버를 시작하는 동안 예외가 발생했습니다.\n{0} - - - - Use the given file on startup as initial input - 시작 시 지정된 파일을 초기 입력으로 사용합니다. - - - - #load the given file on startup - #load: 시작할 때 지정된 파일을 로드합니다. - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - 나머지 인수를 fsi.CommandLineArgs를 사용하여 액세스하는 명령줄 인수로 처리합니다. - - - - Display this usage message (Short form: -?) - 이 사용법 메시지를 표시합니다(약식: -?). - - - - Exit fsi after loading the files or running the .fsx script given on the command line - 파일을 로드한 후 또는 명령줄에 지정된 .fsx 스크립트를 실행한 후 fsi를 종료하세요. - - - - Execute interactions on a Windows Forms event loop (on by default) - Windows Forms 이벤트 루프에서 상호 작용을 실행합니다(기본값: 설정). - - - - Suppress fsi writing to stdout - fsi에서 stdout에 쓰지 않습니다. - - - - Support TAB completion in console (on by default) - 콘솔에서 Tab 키 완성 기능을 지원합니다(기본값: 설정). - - - - Emit debug information in quotations - 인용구의 디버그 정보를 내보냅니다. - - - - For help type #help;; - 도움말을 보려면 #help;;를 입력하세요. - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - F# 대화형 프로세스를 시작하는 동안 오류가 발생했습니다. 일부 Windows 시스템에서 나타나는 유니코드 기반 애플리케이션의 백그라운드 프로세스 콘솔 지원과 관련된 알려진 문제가 원인일 수 있습니다. [도구]->[옵션]->[Visual Studio용 F# 대화형]를 선택하고 '--fsi-server-no-unicode'를 입력해 보세요. - - - - '{0}' is not a valid assembly name - '{0}'은(는) 올바른 어셈블리 이름이 아닙니다. - - - - Directory '{0}' doesn't exist - '{0}' 디렉터리가 없습니다. - - - - Invalid directive '#{0} {1}' - 잘못된 지시문 '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - 경고: 줄이 너무 길어 일부 문자가 무시됩니다.\n - - - - Real: {0}, CPU: {1}, GC {2} - 실제: {0}, CPU: {1}, GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\n자동 서식 지정 중 예외가 발생했습니다.\n문제를 해결할 수 있도록 보고하세요.\n추적: {0}\n - - - - F# Interactive directives: - F# 대화형 지시문: - - - - Reference (dynamically load) the given DLL - 지정된 DLL을 참조(동적 로드)합니다. - - - - Add the given search path for referenced DLLs - 참조된 DLL에 대해 지정된 검색 경로를 추가합니다. - - - - Load the given file(s) as if compiled and referenced - 지정된 파일이 컴파일되고 참조된 것으로 간주하여 해당 파일을 로드합니다. - - - - Toggle timing on/off - 타이밍을 설정/해제합니다. - - - - Display help - 도움말을 표시합니다. - - - - Exit - 끝내기 - - - - F# Interactive command line options: - F# Interactive 명령줄 옵션: - - - - See '{0}' for options - 옵션에 대해서는 '{0}'을(를) 참조하세요. - - - - Loading - 로드 - - - - \n- Interrupt\n - \n- 중단\n - - - - \n- Exit...\n - \n- 끝내기...\n - - - - - Aborting main thread... - - 주 스레드를 중단하는 중... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Ctrl-C 처리기를 설치하지 못했습니다. Ctrl-C 처리를 사용할 수 없습니다. 오류는 다음과 같습니다.\n\t{0} - - - - --> Referenced '{0}' - --> '{0}'이(가) 참조되었습니다. - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> '{0}' 참조됨(파일은 F# 대화형 프로세스에 의해 잠길 수 있음) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> 참조된 '{0}'(다른 타임스탬프가 포함된 어셈블리가 이 위치에서 이미 참조되었습니다. fsi를 다시 설정하여 업데이트된 어셈블리를 로드하세요.) - - - - --> Added '{0}' to library include path - --> 라이브러리 포함 경로에 '{0}'을(를) 추가했습니다. - - - - --> Timing now on - --> 타이밍이 설정되었습니다. - - - - --> Timing now off - --> 타이밍이 해제되었습니다. - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - 이벤트를 처리하는 동안 예기치 않은 ThreadAbortException(Ctrl-C)이 발생했습니다. 다시 시작합니다... - - - - Failed to resolve assembly '{0}' - 어셈블리 '{0}'을(를) 확인하지 못했습니다. - - - - Binding session to '{0}'... - 세션을 '{0}'에 바인딩하는 중... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive 버전 {0} - - - - F# Interactive for F# {0} - F# {0}에 대한 F# 대화형 - - - - Prevents references from being locked by the F# Interactive process - 참조가 F# 대화형 프로세스에 의해 잠기지 않도록 합니다. - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.pl.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.pl.xlf deleted file mode 100644 index f6b3de9b34..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.pl.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Zatrzymano ze względu na błąd\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Składnia: {0} <opcje> [script.fsx [<argumenty>]] - - - - - INPUT FILES - - - PLIKI WEJŚCIOWE - - - - - - CODE GENERATION - - - GENEROWANIE KODU - - - - - - ERRORS AND WARNINGS - - - BŁĘDY I OSTRZEŻENIA - - - - - - LANGUAGE - - - JĘZYK - - - - - - MISCELLANEOUS - - - RÓŻNE - - - - - - ADVANCED - - - ZAAWANSOWANE - - - - - Exception raised when starting remoting server.\n{0} - Wystąpił wyjątek podczas uruchamiania serwera usług zdalnych.\n{0} - - - - Use the given file on startup as initial input - Użyj danego pliku przy uruchamianiu jako początkowych danych wejściowych - - - - #load the given file on startup - #load załaduj dany plik przy uruchamianiu - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Traktuj pozostałe argumenty jak argumenty wiersza polecenia, do których uzyskano dostęp przy użyciu elementu fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Wyświetl ten komunikat dotyczący składni (krótka wersja: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Po załadowaniu plików lub uruchomieniu skryptu .fsx podanego w wierszu polecenia zakończ działanie programu fsi - - - - Execute interactions on a Windows Forms event loop (on by default) - Wykonaj interakcje w pętli zdarzenia Windows Forms (domyślnie włączone) - - - - Suppress fsi writing to stdout - Pomiń zapisywanie przez program fsi w stdout - - - - Support TAB completion in console (on by default) - Obsługa uzupełniania po naciśnięciu klawisza TAB w konsoli (domyślnie włączona) - - - - Emit debug information in quotations - Emituj informacje debugowania w cudzysłowach - - - - For help type #help;; - Aby uzyskać pomoc, wpisz #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Wystąpił problem podczas uruchamiania procesu narzędzia F# Interactive. Taka sytuacja może być spowodowana znanym problemem z obsługą konsoli procesu w tle dla aplikacji obsługujących kodowanie Unicode w niektórych systemach Windows. Spróbuj wybrać kolejno opcje Narzędzia->Opcje->F# Interactive dla Visual Studio i wprowadź „--fsi-server-no-unicode”. - - - - '{0}' is not a valid assembly name - Nazwa „{0}” nie jest prawidłową nazwą zestawu - - - - Directory '{0}' doesn't exist - Katalog „{0}” nie istnieje - - - - Invalid directive '#{0} {1}' - Nieprawidłowa dyrektywa „#{0} {1}” - - - - Warning: line too long, ignoring some characters\n - Ostrzeżenie: wiersz jest zbyt długi, niektóre znaki zostaną zignorowane\n - - - - Real: {0}, CPU: {1}, GC {2} - Czas rzeczywisty: {0}, czas procesora: {1}, operacje odzyskiwania pamięci: {2} - - - - gen - generacja - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nWystąpił wyjątek podczas formatowania kodu.\nZgłoś go, aby można było rozwiązać ten problem.\nŚlad: {0}\n - - - - F# Interactive directives: - Dyrektywy narzędzia F# Interactive: - - - - Reference (dynamically load) the given DLL - Przywołaj (załaduj dynamicznie) daną bibliotekę DLL - - - - Add the given search path for referenced DLLs - Dodaj daną ścieżkę wyszukiwania dla przywoływanych bibliotek DLL - - - - Load the given file(s) as if compiled and referenced - Załaduj dane pliki tak, jakby były skompilowane i przywoływane - - - - Toggle timing on/off - Włącz/wyłącz funkcję chronometrażu - - - - Display help - Wyświetl pomoc - - - - Exit - Zakończ - - - - F# Interactive command line options: - Opcje wiersza polecenia narzędzia F# Interactive: - - - - See '{0}' for options - Aby uzyskać informacje o opcjach, zobacz „{0}” - - - - Loading - Ładowanie - - - - \n- Interrupt\n - \n- Przerwanie\n - - - - \n- Exit...\n - \n- Trwa kończenie działania...\n - - - - - Aborting main thread... - - Trwa przerywanie głównego wątku... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Nie powiodło się zainstalowanie procedury obsługi ctrl-c. Obsługa Ctrl-C będzie niedostępna. Błąd:\n\t{0} - - - - --> Referenced '{0}' - --> Przywołano element „{0}” - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Przywołano element „{0}” (plik może być zablokowany przez proces narzędzia F# Interactive) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Zestaw „{0}” występujący w odwołaniu (zestaw z inną sygnaturą czasową występuje już w odwołaniu z tej lokalizacji; zresetuj narzędzie fsi, aby załadować zaktualizowany zestaw) - - - - --> Added '{0}' to library include path - --> Dodano element „{0}” do ścieżki dołączenia biblioteki - - - - --> Timing now on - --> Funkcja chronometrażu została włączona - - - - --> Timing now off - --> Funkcja chronometrażu została wyłączona - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Nieoczekiwany element ThreadAbortException (Ctrl-C) podczas obsługi zdarzenia: trwa próba ponownego uruchomienia... - - - - Failed to resolve assembly '{0}' - Nie powiodło się rozpoznanie zestawu „{0}” - - - - Binding session to '{0}'... - Trwa tworzenie powiązania sesji z „{0}”... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive, wersja {0} - - - - F# Interactive for F# {0} - F# Interactive dla języka F# {0} - - - - Prevents references from being locked by the F# Interactive process - Uniemożliwia blokowanie odwołań przez proces narzędzia F# Interactive - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.pt-BR.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.pt-BR.xlf deleted file mode 100644 index 0ce87a6b3f..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.pt-BR.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Interrompido devido a erro\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Uso: {0} <opções> [script.fsx [<argumentos>]] - - - - - INPUT FILES - - - ARQUIVOS DE ENTRADA - - - - - - CODE GENERATION - - - GERAÇÃO DE CÓDIGO - - - - - - ERRORS AND WARNINGS - - - ERROS E AVISOS - - - - - - LANGUAGE - - - LINGUAGEM - - - - - - MISCELLANEOUS - - - DIVERSOS - - - - - - ADVANCED - - - AVANÇADO - - - - - Exception raised when starting remoting server.\n{0} - Exceção levantadas ao iniciar o servidor remoto.\n{0} - - - - Use the given file on startup as initial input - Use o arquivo fornecido na inicialização como entrada inicial - - - - #load the given file on startup - #load o arquivo dado na inicialização - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Tratar argumentos restantes como argumentos de linha de comando acessados através de fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Exibir esta mensagem de uso (Forma abreviada: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Feche fsi após o carregamento dos arquivos ou execução do script .fsx fornecido na linha de comando - - - - Execute interactions on a Windows Forms event loop (on by default) - Execute interações em um loop de eventos do Windows Forms (por padrão) - - - - Suppress fsi writing to stdout - Suprimir fsi gravando ao stdout - - - - Support TAB completion in console (on by default) - Suportar a conclusão TAB no console (por padrão) - - - - Emit debug information in quotations - Emitir informações de depuração entre aspas - - - - For help type #help;; - Para ajuda digite #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Um problema ocorreu na inicialização do processo interativo #F. Isto pode ter ocorrido devido a um problema conhecido com processo de fundo do console de apoio pelo aplicativos habilitados Unicode em alguns sistemas do Windows. Tente Ferramentas->Opções->Interativo F# para Visual Studio e insira '--fsi-server-no-unicode'. - - - - '{0}' is not a valid assembly name - '{0}' não é um nome de assembly válido - - - - Directory '{0}' doesn't exist - O diretório '{0}' não existe - - - - Invalid directive '#{0} {1}' - Diretriz inválida '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - Aviso: linha muito longa, ignore alguns caracteres\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0}, CPU: {1}, GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nExceção levantada durante a reformatação automática.\nReporte esta exceção para ela que possa ser corrigida.\nRastrear: {0}\n - - - - F# Interactive directives: - Diretrizes F# Interativo: - - - - Reference (dynamically load) the given DLL - Referenciar (carregar dinamicamente) o DLL dado - - - - Add the given search path for referenced DLLs - Adicionar o caminho pesquisado dado aos DLLs referenciados - - - - Load the given file(s) as if compiled and referenced - Carregar os arquivo(s) como se compilados e referenciados - - - - Toggle timing on/off - Liga/desliga medição de tempo - - - - Display help - Exibir ajuda - - - - Exit - Sair - - - - F# Interactive command line options: - Opções de linha de comando F# Interativo: - - - - See '{0}' for options - Consulte '{0}' para obter opções - - - - Loading - Carregando - - - - \n- Interrupt\n - \n- Interrupção\n - - - - \n- Exit...\n - \n- Sair...\n - - - - - Aborting main thread... - – Anulando o thread principal... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Falha ao instalar o manipulador ctrl-c - As manipulações Ctrl-C não estarão disponíveis. O erro foi:\n\t{0} - - - - --> Referenced '{0}' - --> Referenciado '{0}' - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Referenciado '{0}' (o arquivo pode ter sido bloqueado pelo processo F# Interativo) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> '{0}' referenciado (um assembly com um carimbo de data/hora diferente já foi referenciado deste local, redefina o fsi para carregar o assembly atualizado) - - - - --> Added '{0}' to library include path - --> '{0}' foi adicionado à biblioteca de caminho de inclusão - - - - --> Timing now on - --> Timing ligado agora - - - - --> Timing now off - --> Timing desligado agora - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Inesperada ThreadAbortException (Ctrl-C) durante o manuseio do evento: Tentando reiniciar... - - - - Failed to resolve assembly '{0}' - Falha ao resolver assembly '{0}' - - - - Binding session to '{0}'... - Associando sessão a '{0}'... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interativo versão {0} - - - - F# Interactive for F# {0} - F# Interativo para F# {0} - - - - Prevents references from being locked by the F# Interactive process - Impede que as referências sejam bloqueadas pelo processo de F# interativo - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.ru.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.ru.xlf deleted file mode 100644 index 9fb2d3a00b..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.ru.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Остановлено из-за ошибки\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Использование: {0} <параметры> [script.fsx [<аргументы>]] - - - - - INPUT FILES - - - ВХОДНЫЕ ФАЙЛЫ - - - - - - CODE GENERATION - - - ФОРМИРОВАНИЕ КОДА - - - - - - ERRORS AND WARNINGS - - - ОШИБКИ И ПРЕДУПРЕЖДЕНИЯ - - - - - - LANGUAGE - - - ЯЗЫК - - - - - - MISCELLANEOUS - - - ПРОЧЕЕ - - - - - - ADVANCED - - - ДОПОЛНИТЕЛЬНО - - - - - Exception raised when starting remoting server.\n{0} - При запуске удаленного сервера возникло исключение.\n{0} - - - - Use the given file on startup as initial input - Использование данного файла при запуске в качестве начальных входных данных - - - - #load the given file on startup - #load: загружать данный файл при запуске - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Обрабатывать остальные аргументы как аргументы командной строки с использованием fsi.CommandLineArgs - - - - Display this usage message (Short form: -?) - Вывод данного сообщения об использовании (краткая форма: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Выход из FSI после загрузки файлов или выполнение скрипта .fsx, указанного в командной строке - - - - Execute interactions on a Windows Forms event loop (on by default) - Выполнение взаимодействий при зацикливании события Windows Forms (включено по умолчанию) - - - - Suppress fsi writing to stdout - Запретить fsi запись в stdout - - - - Support TAB completion in console (on by default) - Поддержка заполнения нажатием клавиши TAB в консоли (включено по умолчанию) - - - - Emit debug information in quotations - Вывод отладочной информации в кавычках - - - - For help type #help;; - Для получения справки введите #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - Возникла проблема при запуске процесса F# Interactive. Это может быть вызвано известной проблемой с поддержкой консоли фонового процесса для приложений с поддержкой Юникода в некоторых системах Windows. Попробуйте выбрать "Сервис" -> "Параметры" -> "F# Interactive для Visual Studio" и ввести "--fsi-server-no-unicode". - - - - '{0}' is not a valid assembly name - {0} не является допустимым именем сборки - - - - Directory '{0}' doesn't exist - Каталог "{0}" не существует - - - - Invalid directive '#{0} {1}' - Недопустимая директива "#{0} {1}" - - - - Warning: line too long, ignoring some characters\n - Предупреждение: слишком длинная строка, некоторые знаки игнорируются\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0}, ЦП: {1}, GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nВозникло исключение при автоматическом форматировании.\nОтправьте отчет об этой неполадке для ее устранения.\nТрассировка: {0}\n - - - - F# Interactive directives: - Директивы F# Interactive: - - - - Reference (dynamically load) the given DLL - Ссылка на (динамическая загрузка) данную библиотеку DLL - - - - Add the given search path for referenced DLLs - Добавление данного пути поиска для указанных библиотек DLL - - - - Load the given file(s) as if compiled and referenced - Загрузка данных файлов как скомпилированных и указанных ссылками - - - - Toggle timing on/off - Включение и отключение таймера - - - - Display help - Отображать справку - - - - Exit - Выход - - - - F# Interactive command line options: - Параметры командной строки F# Interactive: - - - - See '{0}' for options - Параметры см. в "{0}" - - - - Loading - Загрузка - - - - \n- Interrupt\n - \n- Прерывать\n - - - - \n- Exit...\n - \n- Выход...\n - - - - - Aborting main thread... - — Отменяется главный поток… - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - Не удалось установить обработчик ctrl-c - обработка Ctrl-C будет недоступна. Ошибка:\n\t{0} - - - - --> Referenced '{0}' - --> Задана ссылка на "{0}" - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> Задана ссылка на "{0}" (возможно, файл заблокирован процессом F# Interactive) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> "{0}" с заданной ссылкой (из этого расположения уже задана ссылка на сборку с другой меткой времени, выполните сброс fsi, чтобы загрузить обновленную сборку) - - - - --> Added '{0}' to library include path - --> Выполнено добавление "{0}" по пути включения в библиотеку - - - - --> Timing now on - --> Таймер включен - - - - --> Timing now off - --> Таймер отключен - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Непредвиденное ThreadAbortException (Ctrl-C) в ходе обработки события: Попытка перезапуска... - - - - Failed to resolve assembly '{0}' - Не удалось выполнить разрешение сборки ''{0}'' - - - - Binding session to '{0}'... - Привязка сеанса к "{0}"... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Interactive, версия {0} - - - - F# Interactive for F# {0} - F# Interactive для F# {0} - - - - Prevents references from being locked by the F# Interactive process - Предотвращает блокировку ссылок интерактивным процессом F#. - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.tr.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.tr.xlf deleted file mode 100644 index 47cfef1be1..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.tr.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - Hata nedeniyle durduruldu\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - Kullanım: {0} <seçenekler> [script.fsx [<bağımsız değişkenler>]] - - - - - INPUT FILES - - - GİRİŞ DOSYALARI - - - - - - CODE GENERATION - - - KOD ÜRETİMİ - - - - - - ERRORS AND WARNINGS - - - HATALAR VE UYARILAR - - - - - - LANGUAGE - - - DİL - - - - - - MISCELLANEOUS - - - ÇEŞİTLİ - - - - - - ADVANCED - - - GELİŞMİŞ - - - - - Exception raised when starting remoting server.\n{0} - Uzaktan iletişim sunucusu başlatılırken özel durum tetiklendi.\n{0} - - - - Use the given file on startup as initial input - Verilen dosyayı başlangıçta ilk giriş olarak kullan - - - - #load the given file on startup - #load verilen dosyayı başlangıçta - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - Kalan bağımsız değişkenlere fsi.CommandLineArgs kullanılarak erişilen komut satırı bağımsız değişkenleri gibi davran - - - - Display this usage message (Short form: -?) - Bu kullanım iletisini görüntüle (Kısa biçimi: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - Dosyaları yükledikten veya komut satırında verilen .fsx betiğini çalıştırdıktan sonra fsi'den çık - - - - Execute interactions on a Windows Forms event loop (on by default) - Etkileşimleri Windows Forms olay döngüsünde yürüt (varsayılan seçenek olarak açık) - - - - Suppress fsi writing to stdout - stdout yazdırırken fsi'yi gizle - - - - Support TAB completion in console (on by default) - Konsolda SEKME ile tamamlamayı destekle (varsayılan seçenek olarak açık) - - - - Emit debug information in quotations - Tırnak içindeki hata ayıklama bilgilerini yay - - - - For help type #help;; - Yardım için #help yazın;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - F# Etkileşimli işlemi başlatılırken bir sorun oluştu. Bu durum, bazı Windows sistemlerindeki Unicode kullanan uygulamalara yönelik arka plan işlemi konsol desteğinde bilinen bir soruna bağlı olabilir. Visual Studio için Araçlar->Seçenekler->F# Etkileşimli'yi seçmeyi deneyin ve '--fsi-server-no-unicode' girin. - - - - '{0}' is not a valid assembly name - '{0}' geçerli bir bütünleştirilmiş kod adı değil - - - - Directory '{0}' doesn't exist - '{0}' dizini yok - - - - Invalid directive '#{0} {1}' - Geçersiz yönerge '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - Uyarı: satır çok uzun, bazı karakterler yok sayılıyor\n - - - - Real: {0}, CPU: {1}, GC {2} - Gerçek: {0}, CPU: {1}, GC {2} - - - - gen - olş - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\nDüzgün yazdırma sırasında özel durum tetiklendi.\nDüzeltilebilmesi için lütfen bunu bildirin.\nİz: {0}\n - - - - F# Interactive directives: - F# Etkileşimli yönergeleri: - - - - Reference (dynamically load) the given DLL - Verilen DLL'ye başvur (dinamik olarak yükle) - - - - Add the given search path for referenced DLLs - Başvurulan DLL'ler için verilen arama yolunu ekle - - - - Load the given file(s) as if compiled and referenced - Verilen dosyaları derlenmiş ve başvurulmuş gibi yükle - - - - Toggle timing on/off - Zamanlamayı aç/kapat - - - - Display help - Yardımı göster - - - - Exit - Çıkış - - - - F# Interactive command line options: - F# Etkileşimli komut satırı seçenekleri: - - - - See '{0}' for options - Seçenekler için bkz. '{0}' - - - - Loading - Yükleniyor - - - - \n- Interrupt\n - \n- Kesme\n - - - - \n- Exit...\n - \n- Çıkış...\n - - - - - Aborting main thread... - - Ana iş parçacığı iptal ediliyor... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - ctrl-c işleyicisi yüklenemedi - Ctrl-C işlemi kullanılamayacak. Hata:\n\t{0} - - - - --> Referenced '{0}' - --> '{0}' öğesine başvuruldu - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> '{0}' öğesine başvuruldu (dosya F# Etkileşimli işlemi tarafından kilitlenmiş olabilir) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> Başvurulan '{0}' (farklı bir zaman damgası olan bir bütünleştirilmiş koda bu konumdan zaten başvuruldu; güncelleştirilen bütünleştirilmiş kodu yüklemek için fsi'yi sıfırlayın) - - - - --> Added '{0}' to library include path - --> Kitaplık ekleme yoluna '{0}' eklendi - - - - --> Timing now on - --> Zamanlama şimdi açık - - - - --> Timing now off - --> Zamanlama şimdi kapalı - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - Olay işlenirken beklenmeyen ThreadAbortException (Ctrl-C): Yeniden başlatma deneniyor... - - - - Failed to resolve assembly '{0}' - '{0}' bütünleştirilmiş kodu çözümlenemedi - - - - Binding session to '{0}'... - Oturum '{0}' öğesine bağlanıyor... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# Etkileşimli sürüm {0} - - - - F# Interactive for F# {0} - F# {0} için F# Etkileşimli - - - - Prevents references from being locked by the F# Interactive process - Başvuruların F# Etkileşimli işlemi tarafından kilitlenmesini engeller - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hans.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hans.xlf deleted file mode 100644 index 4a8085973e..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hans.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - 已因出错而停止\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - 用法: {0} <选项> [script.fsx [<参数>]] - - - - - INPUT FILES - - - 输入文件 - - - - - - CODE GENERATION - - - 代码生成 - - - - - - ERRORS AND WARNINGS - - - 错误和警告 - - - - - - LANGUAGE - - - 语言 - - - - - - MISCELLANEOUS - - - 杂项 - - - - - - ADVANCED - - - 高级 - - - - - Exception raised when starting remoting server.\n{0} - 启动远程处理服务器时发生异常。\n{0} - - - - Use the given file on startup as initial input - 在启动时使用给定文件作为初始输入 - - - - #load the given file on startup - #load 在启动时给定的文件 - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - 将剩余参数视为可使用 fsi.CommandLineArgs 访问的命令行参数 - - - - Display this usage message (Short form: -?) - 显示此用法消息(缩写为: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - 在加载文件或在命令行上运行给定的 .fsx 脚本之后退出 fsi - - - - Execute interactions on a Windows Forms event loop (on by default) - 在 Windows 窗体事件循环中执行交互(默认情况下启用) - - - - Suppress fsi writing to stdout - 禁止 fsi 写入到 stdout - - - - Support TAB completion in console (on by default) - 支持控制台中的 Tab 完成操作(默认情况下启用) - - - - Emit debug information in quotations - 发出用引号引起来的调试信息 - - - - For help type #help;; - 若要获得帮助,请键入 #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - 启动 F# 交互窗口进程时发生问题。此情况可能是由一个已知问题导致的,即某些 Windows 系统上的后台进程控制台不支持启用了 Unicode 的应用程序。请尝试选择“工具”->“选项”->“Visual Studio 的 F# 交互窗口”,然后输入“--fsi-server-no-unicode”。 - - - - '{0}' is not a valid assembly name - “{0}”不是有效的程序集名称 - - - - Directory '{0}' doesn't exist - 目录“{0}”不存在 - - - - Invalid directive '#{0} {1}' - 无效的指令“#{0} {1}” - - - - Warning: line too long, ignoring some characters\n - 警告: 由于行太长,将忽略某些字符\n - - - - Real: {0}, CPU: {1}, GC {2} - Real: {0},CPU: {1},GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\n在整齐打印期间发生异常。\n请报告此异常,以便能够将其修复。\n跟踪: {0}\n - - - - F# Interactive directives: - F# 交互窗口指令: - - - - Reference (dynamically load) the given DLL - 引用(动态加载)给定的 DLL - - - - Add the given search path for referenced DLLs - 为被引用的 DLL 添加给定搜索路径 - - - - Load the given file(s) as if compiled and referenced - 像已编译和被引用的文件一样加载给定的文件 - - - - Toggle timing on/off - 启用/停止计时 - - - - Display help - 显示帮助 - - - - Exit - 退出 - - - - F# Interactive command line options: - F# 交互窗口命令行选项: - - - - See '{0}' for options - 请参阅“{0}”以了解各个选项 - - - - Loading - 正在加载 - - - - \n- Interrupt\n - \n- 中断\n - - - - \n- Exit...\n - \n- 退出...\n - - - - - Aborting main thread... - - 正在中止主线程... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - 未能安装 ctrl-c 处理程序,Ctrl-C 处理将不可用。错误为:\n\t{0} - - - - --> Referenced '{0}' - --> 已引用“{0}” - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> 已引用“{0}”(文件可能由 F# 交互窗口进程锁定) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - ->引用“{0}”(具有不同时间戳的程序集已经从该位置引用并重置 fsi 以加载更新的程序集) - - - - --> Added '{0}' to library include path - --> 已将“{0}”添加到库包含路径 - - - - --> Timing now on - --> 现在已启用计时 - - - - --> Timing now off - --> 现在已关闭计时 - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - 在事件处理过程中出现意外 ThreadAbortException (Ctrl-C): 正在尝试重新启动... - - - - Failed to resolve assembly '{0}' - 未能解析程序集“{0}” - - - - Binding session to '{0}'... - 正在将会话绑定到“{0}”... - - - - Microsoft (R) F# Interactive version {0} - Microsoft(R) F# 交互窗口版本 {0} - - - - F# Interactive for F# {0} - 适用于 F# {0} 的 F# 交互窗口 - - - - Prevents references from being locked by the F# Interactive process - 防止引用被 F# 交互窗口进程锁定 - - - - - \ No newline at end of file diff --git a/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hant.xlf b/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hant.xlf deleted file mode 100644 index 295ea67495..0000000000 --- a/src/fsharp/fsi/xlf/FSIstrings.txt.zh-Hant.xlf +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Stopped due to error\n - 已因錯誤而停止\n - - - - Usage: {0} <options> [script.fsx [<arguments>]] - 使用方式: {0} <選項> [script.fsx [<引數>]] - - - - - INPUT FILES - - - 輸入檔 - - - - - - CODE GENERATION - - - 程式碼產生 - - - - - - ERRORS AND WARNINGS - - - 錯誤和警告 - - - - - - LANGUAGE - - - 語言 - - - - - - MISCELLANEOUS - - - 其他 - - - - - - ADVANCED - - - 進階 - - - - - Exception raised when starting remoting server.\n{0} - 啟動遠端處理伺服器時發生例外狀況。\n{0} - - - - Use the given file on startup as initial input - 啟動時使用所指定的檔案做為初始輸入 - - - - #load the given file on startup - #load 啟動時指定的檔案 - - - - Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs - 將其餘引數視為命令列引數,使用 fsi.CommandLineArgs 存取 - - - - Display this usage message (Short form: -?) - 顯示此訊息 (簡短形式: -?) - - - - Exit fsi after loading the files or running the .fsx script given on the command line - 載入檔案或執行命令列上指定的 .fsx 指令碼後結束 fsi - - - - Execute interactions on a Windows Forms event loop (on by default) - 在 Windows Form 事件迴圈上執行互動 (預設為開啟) - - - - Suppress fsi writing to stdout - 禁止 fsi 寫入 stdout - - - - Support TAB completion in console (on by default) - 支援主控台中的 TAB 鍵自動完成 (預設為開啟) - - - - Emit debug information in quotations - 發出在引號內的偵錯資訊 - - - - For help type #help;; - 如需說明,請輸入 #help;; - - - - A problem occurred starting the F# Interactive process. This may be due to a known problem with background process console support for Unicode-enabled applications on some Windows systems. Try selecting Tools->Options->F# Interactive for Visual Studio and enter '--fsi-server-no-unicode'. - 啟動 F# Interactive 處理序時發生問題。這可能是因為背景處理序主控台對於支援某些 Windows 系統上具備 Unicode 支援功能之應用程式的已知問題所造成。請嘗試選取 [工具]5D; -> [選項]5D; -> [F# Interactive for Visual Studio]5D;,然後輸入 '--fsi-server-no-unicode'。 - - - - '{0}' is not a valid assembly name - '{0}' 不是有效的組件名稱 - - - - Directory '{0}' doesn't exist - 目錄 '{0}' 不存在 - - - - Invalid directive '#{0} {1}' - 無效的指示詞 '#{0} {1}' - - - - Warning: line too long, ignoring some characters\n - 警告: 行太長,將忽略某些字元\n - - - - Real: {0}, CPU: {1}, GC {2} - 實際: {0},CPU: {1},GC {2} - - - - gen - gen - - - - \n\nException raised during pretty printing.\nPlease report this so it can be fixed.\nTrace: {0}\n - \n\n美化顯示期間發生例外狀況。\n請回報此問題以便修正。\n追蹤: {0}\n - - - - F# Interactive directives: - F# Interactive 指示詞: - - - - Reference (dynamically load) the given DLL - 參考 (以動態方式載入) 所指定的 DLL - - - - Add the given search path for referenced DLLs - 加入所參考 DLL 的指定搜尋路徑 - - - - Load the given file(s) as if compiled and referenced - 載入指定的檔案,視為已編譯及已參考 - - - - Toggle timing on/off - 切換計時開/關 - - - - Display help - 顯示說明 - - - - Exit - 結束 - - - - F# Interactive command line options: - F# Interactive 命令列選項: - - - - See '{0}' for options - 相關選項請參閱 '{0}' - - - - Loading - 正在載入 - - - - \n- Interrupt\n - \n- 中斷\n - - - - \n- Exit...\n - \n- 結束...\n - - - - - Aborting main thread... - - 正在中止主要執行緒... - - - - Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was:\n\t{0} - 無法安裝 ctrl-c 處理常式,Ctrl-C 處理將無法使用。錯誤為:\n\t{0} - - - - --> Referenced '{0}' - --> 參考的 '{0}' - - - - --> Referenced '{0}' (file may be locked by F# Interactive process) - --> 參考的 '{0}' (檔案可能已被 F# Interactive 處理序鎖定) - - - - --> Referenced '{0}' (an assembly with a different timestamp has already been referenced from this location, reset fsi to load the updated assembly) - --> 已參考 '{0}' (已經從這個位置參考有不同時間戳記的組件,請重設 fsi 以載入更新的組件) - - - - --> Added '{0}' to library include path - --> 已將 '{0}' 加入程式庫 Include 路徑 - - - - --> Timing now on - --> 計時現已開啟 - - - - --> Timing now off - --> 計時現已關閉 - - - - - Unexpected ThreadAbortException (Ctrl-C) during event handling: Trying to restart... - - 事件處理時發生未預期的 ThreadAbortException (Ctrl-C): 正嘗試重新啟動... - - - - Failed to resolve assembly '{0}' - 無法解析組件 '{0}' - - - - Binding session to '{0}'... - 正在將工作階段繫結到 '{0}'... - - - - Microsoft (R) F# Interactive version {0} - Microsoft (R) F# 互動版本 {0} - - - - F# Interactive for F# {0} - 適用於 F# {0} 的 F# 互動 - - - - Prevents references from being locked by the F# Interactive process - 避免參考遭 F# 互動式處理序封鎖 - - - - - \ No newline at end of file diff --git a/src/fsharp/fsiAnyCpu/Directory.Build.props b/src/fsharp/fsiAnyCpu/Directory.Build.props deleted file mode 100644 index 7cd41381b5..0000000000 --- a/src/fsharp/fsiAnyCpu/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj deleted file mode 100644 index d0b304820a..0000000000 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - Exe - net46 - net472 - AnyCPU - .exe - $(NoWarn);45;55;62;75;1204 - true - $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 - ..\fsi\fsi.res - true - true - true - true - - - - $(DefineConstants);FSI_SHADOW_COPY_REFERENCES;FSI_SERVER - - - - - - - {{FSCoreVersion}} - $(FSCoreVersion) - - - - - - - - - - - - - - - - - - - diff --git a/src/fsharp/fsiattrs.fs b/src/fsharp/fsiattrs.fs deleted file mode 100755 index 8e279c43dd..0000000000 --- a/src/fsharp/fsiattrs.fs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -module FSharp.Compiler.Interactive.Attributes -[] -do() - diff --git a/src/fsharp/fsiaux.fs b/src/fsharp/fsiaux.fs deleted file mode 100755 index f4c5ed9cd5..0000000000 --- a/src/fsharp/fsiaux.fs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.Interactive - -#nowarn "51" -#nowarn "9" - -open System -open System.Diagnostics -open System.Threading - -[] -[] -do() - -type IEventLoop = - abstract Run : unit -> bool - abstract Invoke : (unit -> 'T) -> 'T - abstract ScheduleRestart : unit -> unit - -// An implementation of IEventLoop suitable for the command-line console -[] -type internal SimpleEventLoop() = - let runSignal = new AutoResetEvent(false) - let exitSignal = new AutoResetEvent(false) - let doneSignal = new AutoResetEvent(false) - let mutable queue = ([] : (unit -> obj) list) - let mutable result = (None : obj option) - let setSignal(signal : AutoResetEvent) = while not (signal.Set()) do Thread.Sleep(1); done - let waitSignal signal = WaitHandle.WaitAll([| (signal :> WaitHandle) |]) |> ignore - let waitSignal2 signal1 signal2 = - WaitHandle.WaitAny([| (signal1 :> WaitHandle); (signal2 :> WaitHandle) |]) - let mutable running = false - let mutable restart = false - interface IEventLoop with - member x.Run() = - running <- true - let rec run() = - match waitSignal2 runSignal exitSignal with - | 0 -> - queue |> List.iter (fun f -> result <- try Some(f()) with _ -> None) - setSignal doneSignal - run() - | 1 -> - running <- false - restart - | _ -> run() - run() - member x.Invoke(f : unit -> 'T) : 'T = - queue <- [f >> box] - setSignal runSignal - waitSignal doneSignal - result |> Option.get |> unbox - member x.ScheduleRestart() = - // nb. very minor race condition here on running here, but totally - // unproblematic as ScheduleRestart and Exit are almost never called. - if running then - restart <- true - setSignal exitSignal - interface System.IDisposable with - member x.Dispose() = - runSignal.Dispose() - exitSignal.Dispose() - doneSignal.Dispose() - - - -[] -type InteractiveSession() = - let mutable evLoop = (new SimpleEventLoop() :> IEventLoop) - let mutable showIDictionary = true - let mutable showDeclarationValues = true - let mutable args = System.Environment.GetCommandLineArgs() - let mutable fpfmt = "g10" - let mutable fp = (System.Globalization.CultureInfo.InvariantCulture :> System.IFormatProvider) - let mutable printWidth = 78 - let mutable printDepth = 100 - let mutable printLength = 100 - let mutable printSize = 10000 - let mutable showIEnumerable = true - let mutable showProperties = true - let mutable addedPrinters = [] - - member self.FloatingPointFormat with get() = fpfmt and set v = fpfmt <- v - member self.FormatProvider with get() = fp and set v = fp <- v - member self.PrintWidth with get() = printWidth and set v = printWidth <- v - member self.PrintDepth with get() = printDepth and set v = printDepth <- v - member self.PrintLength with get() = printLength and set v = printLength <- v - member self.PrintSize with get() = printSize and set v = printSize <- v - member self.ShowDeclarationValues with get() = showDeclarationValues and set v = showDeclarationValues <- v - member self.ShowProperties with get() = showProperties and set v = showProperties <- v - member self.ShowIEnumerable with get() = showIEnumerable and set v = showIEnumerable <- v - member self.ShowIDictionary with get() = showIDictionary and set v = showIDictionary <- v - member self.AddedPrinters with get() = addedPrinters and set v = addedPrinters <- v - - [] - member self.CommandLineArgs - with get() = args - and set v = args <- v - - member self.AddPrinter(printer : 'T -> string) = - addedPrinters <- Choice1Of2 (typeof<'T>, (fun (x:obj) -> printer (unbox x))) :: addedPrinters - - member self.EventLoop - with get () = evLoop - and set (x:IEventLoop) = evLoop.ScheduleRestart(); evLoop <- x - - member self.AddPrintTransformer(printer : 'T -> obj) = - addedPrinters <- Choice2Of2 (typeof<'T>, (fun (x:obj) -> printer (unbox x))) :: addedPrinters - - member internal self.SetEventLoop (run: (unit -> bool), invoke: ((unit -> obj) -> obj), restart: (unit -> unit)) = - evLoop.ScheduleRestart() - evLoop <- { new IEventLoop with - member __.Run() = run() - member __.Invoke(f) = invoke((fun () -> f() |> box)) |> unbox - member __.ScheduleRestart() = restart() } - -[] -do() - - -module Settings = - let fsi = new InteractiveSession() - - [] - do() - -// For legacy compatibility with old naming -namespace Microsoft.FSharp.Compiler.Interactive - - type IEventLoop = FSharp.Compiler.Interactive.IEventLoop - - type InteractiveSession = FSharp.Compiler.Interactive.InteractiveSession - - module Settings = - - let fsi = FSharp.Compiler.Interactive.Settings.fsi - - diff --git a/src/fsharp/fsiaux.fsi b/src/fsharp/fsiaux.fsi deleted file mode 100755 index d557c17331..0000000000 --- a/src/fsharp/fsiaux.fsi +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.Interactive - - /// An event loop used by the currently executing F# Interactive session to execute code - /// in the context of a GUI or another event-based system. - type IEventLoop = - - /// Run the event loop. - /// True if the event loop was restarted; false otherwise. - abstract Run : unit -> bool - - /// Request that the given operation be run synchronously on the event loop. - /// The result of the operation. - abstract Invoke : (unit -> 'T) -> 'T - - /// Schedule a restart for the event loop. - abstract ScheduleRestart : unit -> unit - - [] - /// Operations supported by the currently executing F# Interactive session. - type InteractiveSession = - - /// Get or set the floating point format used in the output of the interactive session. - member FloatingPointFormat: string with get,set - - /// Get or set the format provider used in the output of the interactive session. - member FormatProvider: System.IFormatProvider with get,set - - /// Get or set the print width of the interactive session. - member PrintWidth : int with get,set - - /// Get or set the print depth of the interactive session. - member PrintDepth : int with get,set - - /// Get or set the total print length of the interactive session. - member PrintLength : int with get,set - - /// Get or set the total print size of the interactive session. - member PrintSize : int with get,set - - /// When set to 'false', disables the display of properties of evaluated objects in the output of the interactive session. - member ShowProperties : bool with get,set - - /// When set to 'false', disables the display of sequences in the output of the interactive session. - member ShowIEnumerable: bool with get,set - - /// When set to 'false', disables the display of declaration values in the output of the interactive session. - member ShowDeclarationValues: bool with get,set - - /// Register a printer that controls the output of the interactive session. - member AddPrinter: ('T -> string) -> unit - - /// Register a print transformer that controls the output of the interactive session. - member AddPrintTransformer: ('T -> obj) -> unit - - member internal AddedPrinters : Choice<(System.Type * (obj -> string)), - (System.Type * (obj -> obj))> list - - /// The command line arguments after ignoring the arguments relevant to the interactive - /// environment and replacing the first argument with the name of the last script file, - /// if any. Thus 'fsi.exe test1.fs test2.fs -- hello goodbye' will give arguments - /// 'test2.fs', 'hello', 'goodbye'. This value will normally be different to those - /// returned by System.Environment.GetCommandLineArgs. - member CommandLineArgs : string [] with get,set - - /// Gets or sets a the current event loop being used to process interactions. - member EventLoop: IEventLoop with get,set - - /// Sets the current event loop being used to process interactions. - member internal SetEventLoop: (unit -> bool) * ((unit -> obj) -> obj) * (unit -> unit) -> unit - - - module Settings = - - /// The settings associated with the interactive session. - val fsi : InteractiveSession - -// For legacy compatibility with old naming -namespace Microsoft.FSharp.Compiler.Interactive - - type IEventLoop = FSharp.Compiler.Interactive.IEventLoop - - type InteractiveSession = FSharp.Compiler.Interactive.InteractiveSession - - module Settings = - - val fsi : InteractiveSession - - diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index e966678486..6a9a6430cb 100755 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -60,7 +60,8 @@ type lexargs = applyLineDirectives: bool pathMap: PathMap } -/// possible results of lexing a long unicode escape sequence in a string literal, e.g. "\UDEADBEEF" +/// possible results of lexing a long Unicode escape sequence in a string literal, e.g. "\U0001F47D", +/// "\U000000E7", or "\UDEADBEEF" returning SurrogatePair, SingleChar, or Invalid, respectively type LongUnicodeLexResult = | SurrogatePair of uint16 * uint16 | SingleChar of uint16 @@ -169,7 +170,9 @@ let unicodeGraphLong (s:string) = if high = 0 then SingleChar(uint16 low) // invalid encoding elif high > 0x10 then Invalid - // valid surrogate pair - see http://www.unicode.org/unicode/uni2book/ch03.pdf, section 3.7 *) + // valid supplementary character: code points U+10000 to U+10FFFF + // valid surrogate pair: see http://www.unicode.org/versions/latest/ch03.pdf , "Surrogates" section + // high-surrogate code point (U+D800 to U+DBFF) followed by low-surrogate code point (U+DC00 to U+DFFF) else let codepoint = high * 0x10000 + low let hiSurr = uint16 (0xD800 + ((codepoint - 0x10000) / 0x400)) @@ -348,7 +351,7 @@ module Keywords = | _ -> IdentifierToken args lexbuf s - let inline private DoesIdentifierNeedQuotation (s : string) : bool = + let DoesIdentifierNeedQuotation (s : string) : bool = not (String.forall IsIdentifierPartCharacter s) // if it has funky chars || s.Length > 0 && (not(IsIdentifierFirstCharacter s.[0])) // or if it starts with a non-(letter-or-underscore) || keywordTable.ContainsKey s // or if it's a language keyword like "type" diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index 0ccb18d0db..f75ecd392d 100755 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -69,6 +69,7 @@ exception IndentationProblem of string * Range.range module Keywords = val KeywordOrIdentifierToken : lexargs -> UnicodeLexing.Lexbuf -> string -> Parser.token val IdentifierToken : lexargs -> UnicodeLexing.Lexbuf -> string -> Parser.token + val DoesIdentifierNeedQuotation : string -> bool val QuoteIdentifierIfNeeded : string -> string val NormalizeIdentifierBackticks : string -> string val keywordNames : string list diff --git a/src/fsharp/lib.fs b/src/fsharp/lib.fs index e7eaf9543f..dfcbddc2da 100755 --- a/src/fsharp/lib.fs +++ b/src/fsharp/lib.fs @@ -536,3 +536,14 @@ module UnmanagedProcessExecutionOptions = "HeapSetInformation() returned FALSE; LastError = 0x" + GetLastError().ToString("X").PadLeft(8, '0') + ".")) +[] +module StackGuard = + + open System.Runtime.CompilerServices + + [] + let private MaxUncheckedRecursionDepth = 20 + + let EnsureSufficientExecutionStack recursionDepth = + if recursionDepth > MaxUncheckedRecursionDepth then + RuntimeHelpers.EnsureSufficientExecutionStack () \ No newline at end of file diff --git a/src/fsharp/service/Reactor.fs b/src/fsharp/service/Reactor.fs index bae570d0c5..cc2a6af844 100755 --- a/src/fsharp/service/Reactor.fs +++ b/src/fsharp/service/Reactor.fs @@ -35,7 +35,7 @@ type Reactor() = // We need to store the culture for the VS thread that is executing now, // so that when the reactor picks up a thread from the threadpool we can set the culture - let culture = new CultureInfo(CultureInfo.CurrentUICulture.Name) + let mutable culture = CultureInfo(CultureInfo.CurrentUICulture.Name) let mutable bgOpCts = new CancellationTokenSource() /// Mailbox dispatch function. @@ -135,6 +135,17 @@ type Reactor() = Debug.Assert(false, String.Format("unexpected failure in reactor loop {0}, restarting", e)) } + member __.SetPreferredUILang(preferredUiLang: string option) = + match preferredUiLang with + | Some s -> + culture <- CultureInfo s +#if FX_RESHAPED_GLOBALIZATION + CultureInfo.CurrentUICulture <- culture +#else + Thread.CurrentThread.CurrentUICulture <- culture +#endif + | None -> () + // [Foreground Mailbox Accessors] ----------------------------------------------------------- member r.SetBackgroundOp(bgOpOpt) = Trace.TraceInformation("Reactor: {0:n3} enqueue start background, length {1}", DateTime.Now.TimeOfDay.TotalSeconds, builder.CurrentQueueLength) diff --git a/src/fsharp/service/Reactor.fsi b/src/fsharp/service/Reactor.fsi index 5ea9572f48..3040ca65ee 100755 --- a/src/fsharp/service/Reactor.fsi +++ b/src/fsharp/service/Reactor.fsi @@ -23,6 +23,9 @@ type internal IReactorOperations = [] type internal Reactor = + /// Allows to specify the language for error messages + member SetPreferredUILang : string option -> unit + /// Set the background building function, which is called repeatedly /// until it returns 'false'. If None then no background operation is used. member SetBackgroundOp : ( (* userOpName:*) string * (* opName: *) string * (* opArg: *) string * (CompilationThreadToken -> CancellationToken -> bool)) option -> unit diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index 93427382d9..d91cb1f66a 100644 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -783,6 +783,7 @@ type FSharpSourceTokenizer(defineConstants: string list, filename: string option module Keywords = open FSharp.Compiler.Lexhelp.Keywords + let DoesIdentifierNeedQuotation s = DoesIdentifierNeedQuotation s let QuoteIdentifierIfNeeded s = QuoteIdentifierIfNeeded s let NormalizeIdentifierBackticks s = NormalizeIdentifierBackticks s let KeywordsWithDescription = keywordsWithDescription diff --git a/src/fsharp/service/ServiceLexing.fsi b/src/fsharp/service/ServiceLexing.fsi index 84fa2e571a..85e18f171c 100755 --- a/src/fsharp/service/ServiceLexing.fsi +++ b/src/fsharp/service/ServiceLexing.fsi @@ -243,6 +243,9 @@ module internal TestExpose = val TokenInfo : Parser.token -> (FSharpTokenColorKind * FSharpTokenCharKind * FSharpTokenTriggerClass) module Keywords = + /// Checks if adding backticks to identifier is needed. + val DoesIdentifierNeedQuotation : string -> bool + /// Add backticks if the identifier is a keyword. val QuoteIdentifierIfNeeded : string -> string diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index a6590aac2f..9952631bc5 100755 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -423,6 +423,12 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC return res } + member bc.ParseFileNoCache(filename, sourceText, options, userOpName) = + async { + let parseErrors, parseTreeOpt, anyErrors = ParseAndCheckFile.parseFile(sourceText, filename, options, userOpName, false) + return FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, options.SourceFiles) + } + /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API) member __.GetBackgroundParseResultsForFileInProject(filename, options, userOpName) = reactor.EnqueueAndAwaitOpAsync(userOpName, "GetBackgroundParseResultsForFileInProject ", filename, fun ctok -> @@ -518,6 +524,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC keepAssemblyContents, suggestNamesForErrors) let parsingOptions = FSharpParsingOptions.FromTcConfig(tcPrior.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules) + reactor.SetPreferredUILang tcPrior.TcConfig.preferredUiLang bc.RecordTypeCheckFileInProjectResults(fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText.GetHashCode()) return checkAnswer finally @@ -635,6 +642,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC // Do the parsing. let parsingOptions = FSharpParsingOptions.FromTcConfig(builder.TcConfig, Array.ofList (builder.SourceFiles), options.UseScriptResolutionRules) + reactor.SetPreferredUILang tcPrior.TcConfig.preferredUiLang let parseErrors, parseTreeOpt, anyErrors = ParseAndCheckFile.parseFile (sourceText, filename, parsingOptions, userOpName, suggestNamesForErrors) let parseResults = FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, builder.AllDependenciesDeprecated) let! checkResults = bc.CheckOneFileImpl(parseResults, sourceText, filename, options, textSnapshotInfo, fileVersion, builder, tcPrior, creationErrors, userOpName) @@ -889,7 +897,6 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC static member GlobalForegroundTypeCheckCountStatistic = foregroundTypeCheckCount - [] // There is typically only one instance of this type in an IDE process. type FSharpChecker(legacyReferenceResolver, @@ -959,6 +966,11 @@ type FSharpChecker(legacyReferenceResolver, ic.CheckMaxMemoryReached() backgroundCompiler.ParseFile(filename, sourceText, options, userOpName) + member ic.ParseFileNoCache(filename, sourceText, options, ?userOpName) = + let userOpName = defaultArg userOpName "Unknown" + ic.CheckMaxMemoryReached() + backgroundCompiler.ParseFileNoCache(filename, sourceText, options, userOpName) + member ic.ParseFileInProject(filename, source: string, options, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" let parsingOptions, _ = ic.GetParsingOptionsFromProjectOptions(options) @@ -1264,61 +1276,4 @@ module PrettyNaming = let KeywordNames = Lexhelp.Keywords.keywordNames module FSharpFileUtilities = - let isScriptFile (fileName: string) = CompileOps.IsScript fileName - -namespace Microsoft.FSharp.Compiler.SourceCodeServices - - open System - - [] - type FSharpFindDeclFailureReason = A | B - [] - type FSharpFindDeclResult = A | B - [] - type FSharpProjectContext = A | B - [] - type SemanticClassificationType = A | B - [] - type FSharpCheckFileResults = A | B - [] - type FSharpCheckProjectResults = A | B - [] - type UnresolvedReferencesSet = A | B - [] - type FSharpParsingOptions = A | B - [] - type FSharpProjectOptions = A | B - [] - type FSharpCheckFileAnswer = A | B - [] - type FSharpChecker = A | B - [] - type CompilerEnvironment = A | B - [] - module CompilerEnvironment = begin end - [] - module DebuggerEnvironment = begin end - [] - module PrettyNaming = begin end - -namespace Microsoft.FSharp.Compiler.Interactive.Shell - - open System - - [] - type FsiValue = A | B - [] - type EvaluationEventArgs = A | B - [] - type public FsiEvaluationSessionHostConfig = A | B - [] - type FsiEvaluationSession = A | B - [] - module Settings = begin end - - /// Defines a read-only input stream used to feed content to the hosted F# Interactive dynamic compiler. - [] - type CompilerInputStream = A | B - [] - type CompilerOutputStream = A | B - + let isScriptFile (fileName: string) = CompileOps.IsScript fileName \ No newline at end of file diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index 09d8e988a4..63109e4edd 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -103,25 +103,32 @@ type public FSharpChecker = member MatchBraces: filename: string * source: string * options: FSharpProjectOptions * ?userOpName: string -> Async<(range * range)[]> /// - /// Parse a source code file, returning a handle that can be used for obtaining navigation bar information - /// To get the full information, call 'CheckFileInProject' method on the result + /// Parses a source code for a file and caches the results. Returns an AST that can be traversed for various features. /// /// - /// The filename for the file. - /// The full source for the file. + /// The path for the file. The file name is used as a module name for implicit top level modules (e.g. in scripts). + /// The source to be parsed. /// Parsing options for the project or script. /// An optional string used for tracing compiler operations associated with this request. member ParseFile: filename: string * sourceText: ISourceText * options: FSharpParsingOptions * ?userOpName: string -> Async /// - /// Parse a source code file, returning a handle that can be used for obtaining navigation bar information - /// To get the full information, call 'CheckFileInProject' method on the result - /// All files except the one being checked are read from the FileSystem API + /// Parses a source code for a file. Returns an AST that can be traversed for various features. /// /// - /// The filename for the file. - /// The full source for the file. - /// The options for the project or script, used to determine active --define conditionals and other options relevant to parsing. + /// The path for the file. The file name is also as a module name for implicit top level modules (e.g. in scripts). + /// The source to be parsed. + /// Parsing options for the project or script. + /// An optional string used for tracing compiler operations associated with this request. + member ParseFileNoCache: filename: string * sourceText: ISourceText * options: FSharpParsingOptions * ?userOpName: string -> Async + + /// + /// Parses a source code for a file. Returns an AST that can be traversed for various features. + /// + /// + /// The path for the file. The file name is also as a module name for implicit top level modules (e.g. in scripts). + /// The source to be parsed. + /// Parsing options for the project or script. /// An optional string used for tracing compiler operations associated with this request. [] member ParseFileInProject: filename: string * source: string * options: FSharpProjectOptions * ?userOpName: string -> Async @@ -457,59 +464,3 @@ module public PrettyNaming = /// A set of helpers for dealing with F# files. module FSharpFileUtilities = val isScriptFile : string -> bool - -namespace Microsoft.FSharp.Compiler.SourceCodeServices - - open System - - [] - type FSharpFindDeclFailureReason - [] - type FSharpFindDeclResult - [] - type FSharpProjectContext - [] - type SemanticClassificationType - [] - type FSharpCheckFileResults - [] - type FSharpCheckProjectResults - [] - type UnresolvedReferencesSet - [] - type FSharpParsingOptions - [] - type FSharpProjectOptions - [] - type FSharpCheckFileAnswer - [] - type FSharpChecker - [] - type CompilerEnvironment - [] - module CompilerEnvironment = begin end - [] - module DebuggerEnvironment = begin end - [] - module PrettyNaming = begin end - -namespace Microsoft.FSharp.Compiler.Interactive.Shell - - open System - - [] - type FsiValue - [] - type EvaluationEventArgs - [] - type public FsiEvaluationSessionHostConfig - [] - type FsiEvaluationSession - [] - module Settings = begin end - - /// Defines a read-only input stream used to feed content to the hosted F# Interactive dynamic compiler. - [] - type CompilerInputStream - [] - type CompilerOutputStream \ No newline at end of file diff --git a/src/ilx/EraseClosures.fs b/src/ilx/EraseClosures.fs index 3ba574b9ba..ca0dbfcdf8 100755 --- a/src/ilx/EraseClosures.fs +++ b/src/ilx/EraseClosures.fs @@ -116,12 +116,22 @@ let mkFuncTypeRef n = [IlxSettings.ilxNamespace () + ".OptimizedClosures"], "FSharpFunc`"+ string (n + 1)) type cenv = - { ilg:ILGlobals + { + ilg:ILGlobals + tref_Func: ILTypeRef[] + mkILTyFuncTy: ILType + addFieldGeneratedAttrs: ILFieldDef -> ILFieldDef + addFieldNeverAttrs: ILFieldDef -> ILFieldDef - addMethodGeneratedAttrs: ILMethodDef -> ILMethodDef } + + addMethodGeneratedAttrs: ILMethodDef -> ILMethodDef + } + + override __.ToString() = "" + let addMethodGeneratedAttrsToTypeDef cenv (tdef: ILTypeDef) = tdef.With(methods = (tdef.Methods.AsList |> List.map (fun md -> md |> cenv.addMethodGeneratedAttrs) |> mkILMethods)) diff --git a/src/utils/prim-lexing.fs b/src/utils/prim-lexing.fs index 6658a35354..c397257b46 100755 --- a/src/utils/prim-lexing.fs +++ b/src/utils/prim-lexing.fs @@ -105,7 +105,6 @@ namespace Internal.Utilities.Text.Lexing open FSharp.Compiler.Text open Microsoft.FSharp.Core - open FSharp.Compiler.Text open Microsoft.FSharp.Collections open System.Collections.Generic diff --git a/src/utils/sformat.fs b/src/utils/sformat.fs index b490283f67..228f4aba39 100755 --- a/src/utils/sformat.fs +++ b/src/utils/sformat.fs @@ -759,18 +759,14 @@ namespace Microsoft.FSharp.Text.StructuredPrintfImpl // pprinter: attributes // -------------------------------------------------------------------- - let makeRecordVerticalL nameXs = - let itemL (name,xL) = let labelL = wordL name in ((labelL ^^ wordL Literals.equals)) -- (xL ^^ (rightL Literals.semicolon)) - let braceL xs = (leftL Literals.leftBrace) ^^ xs ^^ (rightL Literals.rightBrace) - braceL (aboveListL (List.map itemL nameXs)) - - // This is a more compact rendering of records - and is more like tuples - let makeRecordHorizontalL nameXs = - let itemL (name,xL) = let labelL = wordL name in ((labelL ^^ wordL Literals.equals)) -- xL - let braceL xs = (leftL Literals.leftBrace) ^^ xs ^^ (rightL Literals.rightBrace) - braceL (sepListL (rightL Literals.semicolon) (List.map itemL nameXs)) - - let makeRecordL nameXs = makeRecordVerticalL nameXs + let makeRecordL nameXs = + let itemL (name,xL) = wordL name ^^ wordL Literals.equals -- xL + let braceL xs = (wordL Literals.leftBrace) ^^ xs ^^ (wordL Literals.rightBrace) + + nameXs + |> List.map itemL + |> aboveListL + |> braceL let makePropertiesL nameXs = let itemL (name,v) = diff --git a/tests/fsharp/core/members/ops/THIRD-PARTY-NOTICES.TXT b/tests/fsharp/core/members/ops/THIRD-PARTY-NOTICES.TXT deleted file mode 100644 index 75a2788250..0000000000 --- a/tests/fsharp/core/members/ops/THIRD-PARTY-NOTICES.TXT +++ /dev/null @@ -1,24 +0,0 @@ -F# uses third-party libraries or other resources that may be -distributed under licenses different than the .NET Core software. - -Attributions and license notices for test cases originally authored by -third parties can be found in the respective test directories. - -In the event that we accidentally failed to list a required notice, please -bring it to our attention. Post an issue or email us: - - dotnet@microsoft.com - -The attached notices are provided for information only. - -License notice for Stack Overflow -------------------------------------- - -Policy: https://stackoverflow.com/help/licensing -License: https://creativecommons.org/licenses/by-sa/3.0/ - -Content: How to write a variadic function in F# emulating a similar Haskell solution? -URL: https://stackoverflow.com/questions/28243963/how-to-write-a-variadic-function-in-f-emulating-a-similar-haskell-solution/28244413#28244413 - -Question author: robkuz -- https://stackoverflow.com/users/621427/robkuz -Answer author: Gustavo -- https://stackoverflow.com/users/446822/gustavo