From ad81c6d53c3f198e0f522cedd444ebcf20c58f5a Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 22 Oct 2019 16:28:09 -0700 Subject: [PATCH 001/101] update version numbers for vs 16.5 (#7763) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 3c78780d9f..6329f6dfcd 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,14 +23,14 @@ $(FSCorePackageVersion)-$(PreReleaseVersionLabel).* - 10.7 + 10.8 $(FSPackageMajorVersion).0 $(FSPackageVersion) $(FSPackageVersion).0 16 - 4 + 5 $(VSMajorVersion).0 $(VSMajorVersion).$(VSMinorVersion).0 $(VSAssemblyVersionPrefix).0 From 70e6f65d48ee6ecb02dcea9362d030872c2ba05c Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 28 Oct 2019 11:00:55 -0700 Subject: [PATCH 002/101] insert dev16.5 builds into vs master --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7895b291d1..e8b0e6bac4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -339,7 +339,7 @@ stages: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - template: eng/release/insert-into-vs.yml parameters: - componentBranchName: refs/heads/release/dev16.4 + componentBranchName: refs/heads/release/dev16.5 insertTargetBranch: master insertTeamEmail: fsharpteam@microsoft.com insertTeamName: 'F#' From 8cb7d1531a54c731f4937c85db0dd76c997ba99c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2019 16:26:37 -0800 Subject: [PATCH 003/101] Update dependencies from https://github.com/dotnet/arcade build 20191203.16 (#7936) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19603.16 --- eng/Version.Details.xml | 4 +- eng/common/CheckSymbols.ps1 | 53 ++-- eng/common/PublishToSymbolServers.proj | 6 +- eng/common/SetupNugetSources.ps1 | 65 +++-- eng/common/SetupNugetSources.sh | 80 ++++-- eng/common/SourceLinkValidation.ps1 | 269 +++++++++--------- eng/common/build.ps1 | 102 +++---- eng/common/build.sh | 24 +- eng/common/cross/build-rootfs.sh | 2 +- eng/common/cross/toolchain.cmake | 49 +++- eng/common/darc-init.ps1 | 26 +- eng/common/darc-init.sh | 30 +- eng/common/dotnet-install.ps1 | 23 +- eng/common/dotnet-install.sh | 50 +--- eng/common/enable-cross-org-publishing.ps1 | 6 +- eng/common/generate-graph-files.ps1 | 49 ++-- eng/common/init-tools-native.ps1 | 35 ++- eng/common/init-tools-native.sh | 5 +- eng/common/internal-feed-operations.ps1 | 28 +- eng/common/internal-feed-operations.sh | 4 +- eng/common/msbuild.ps1 | 5 +- eng/common/native/common-library.sh | 10 +- eng/common/native/install-cmake-test.sh | 4 +- eng/common/native/install-cmake.sh | 4 +- eng/common/native/install-tool.ps1 | 10 +- eng/common/pipeline-logging-functions.ps1 | 70 +++-- eng/common/pipeline-logging-functions.sh | 11 +- eng/common/post-build/darc-gather-drop.ps1 | 15 +- eng/common/post-build/nuget-validation.ps1 | 11 +- eng/common/post-build/post-build-utils.ps1 | 27 +- eng/common/post-build/promote-build.ps1 | 18 +- eng/common/post-build/setup-maestro-vars.ps1 | 26 ++ .../post-build/sourcelink-validation.ps1 | 42 +-- eng/common/post-build/symbols-validation.ps1 | 71 ++--- .../post-build/trigger-subscriptions.ps1 | 87 +++--- eng/common/sdk-task.ps1 | 19 +- eng/common/sdl/execute-all-sdl-tools.ps1 | 176 ++++++------ eng/common/sdl/extract-artifact-packages.ps1 | 89 +++--- eng/common/sdl/init-sdl.ps1 | 38 +-- eng/common/sdl/push-gdn.ps1 | 92 +++--- eng/common/sdl/run-sdl.ps1 | 86 +++--- eng/common/templates/job/execute-sdl.yml | 8 +- eng/common/templates/job/job.yml | 142 +++++---- eng/common/templates/jobs/jobs.yml | 74 +++-- .../channels/generic-internal-channel.yml | 36 +-- .../channels/generic-public-channel.yml | 17 +- .../templates/post-build/common-variables.yml | 6 +- .../templates/post-build/post-build.yml | 205 ++++++++++--- .../post-build/setup-maestro-vars.yml | 26 +- eng/common/templates/steps/publish-logs.yml | 23 -- eng/common/templates/steps/send-to-helix.yml | 3 - eng/common/tools.ps1 | 195 +++++-------- eng/common/tools.sh | 68 ++--- global.json | 4 +- 54 files changed, 1261 insertions(+), 1367 deletions(-) create mode 100644 eng/common/post-build/setup-maestro-vars.ps1 delete mode 100644 eng/common/templates/steps/publish-logs.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0288911f9e..d50d7faa10 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 9d34fd008e754e1ada35c8b6bc3694e7a90b4ed7 + 8e47254f93b276c974968aff83222f89ec3931ed diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 index 5442eff386..b8d84607b8 100644 --- a/eng/common/CheckSymbols.ps1 +++ b/eng/common/CheckSymbols.ps1 @@ -5,12 +5,11 @@ param( ) Add-Type -AssemblyName System.IO.Compression.FileSystem -. $PSScriptRoot\pipeline-logging-functions.ps1 function FirstMatchingSymbolDescriptionOrDefault { param( [string] $FullPath, # Full path to the module that has to be checked - [string] $TargetServerParameter, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + [string] $TargetServerParam, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols [string] $SymbolsPath ) @@ -22,36 +21,36 @@ function FirstMatchingSymbolDescriptionOrDefault { # checking and which type of file was uploaded. # The file itself is returned - $SymbolPath = $SymbolsPath + '\' + $FileName + $SymbolPath = $SymbolsPath + "\" + $FileName # PDB file for the module - $PdbPath = $SymbolPath.Replace($Extension, '.pdb') + $PdbPath = $SymbolPath.Replace($Extension, ".pdb") # PDB file for R2R module (created by crossgen) - $NGenPdb = $SymbolPath.Replace($Extension, '.ni.pdb') + $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") # DBG file for a .so library - $SODbg = $SymbolPath.Replace($Extension, '.so.dbg') + $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") # DWARF file for a .dylib - $DylibDwarf = $SymbolPath.Replace($Extension, '.dylib.dwarf') + $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") - .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParameter $FullPath -o $SymbolsPath | Out-Null + .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null if (Test-Path $PdbPath) { - return 'PDB' + return "PDB" } elseif (Test-Path $NGenPdb) { - return 'NGen PDB' + return "NGen PDB" } elseif (Test-Path $SODbg) { - return 'DBG for SO' + return "DBG for SO" } elseif (Test-Path $DylibDwarf) { - return 'Dwarf for Dylib' + return "Dwarf for Dylib" } elseif (Test-Path $SymbolPath) { - return 'Module' + return "Module" } else { return $null @@ -69,7 +68,7 @@ function CountMissingSymbols { } # Extensions for which we'll look for symbols - $RelevantExtensions = @('.dll', '.exe', '.so', '.dylib') + $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") # How many files are missing symbol information $MissingSymbols = 0 @@ -77,7 +76,7 @@ function CountMissingSymbols { $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) $PackageGuid = New-Guid $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid - $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath 'Symbols' + $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols" [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) @@ -87,31 +86,31 @@ function CountMissingSymbols { Get-ChildItem -Recurse $ExtractPath | Where-Object {$RelevantExtensions -contains $_.Extension} | ForEach-Object { - if ($_.FullName -Match '\\ref\\') { + if ($_.FullName -Match "\\ref\\") { Write-Host "`t Ignoring reference assembly file" $_.FullName return } - $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--microsoft-symbol-server' -SymbolsPath $SymbolsPath - $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--internal-server' -SymbolsPath $SymbolsPath + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath Write-Host -NoNewLine "`t Checking file" $_.FullName "... " if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { - Write-Host "Symbols found on MSDL (${$SymbolsOnMSDL}) and SymWeb (${$SymbolsOnSymWeb})" + Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" } else { $MissingSymbols++ if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { - Write-Host 'No symbols found on MSDL or SymWeb!' + Write-Host "No symbols found on MSDL or SymWeb!" } else { if ($SymbolsOnMSDL -eq $null) { - Write-Host 'No symbols found on MSDL!' + Write-Host "No symbols found on MSDL!" } else { - Write-Host 'No symbols found on SymWeb!' + Write-Host "No symbols found on SymWeb!" } } } @@ -130,26 +129,26 @@ function CheckSymbolsAvailable { Get-ChildItem "$InputPath\*.nupkg" | ForEach-Object { $FileName = $_.Name - + # These packages from Arcade-Services include some native libraries that # our current symbol uploader can't handle. Below is a workaround until # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted. - if ($FileName -Match 'Microsoft\.DotNet\.Darc\.') { + if ($FileName -Match "Microsoft\.DotNet\.Darc\.") { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - elseif ($FileName -Match 'Microsoft\.DotNet\.Maestro\.Tasks\.') { + elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - + Write-Host "Validating $FileName " $Status = CountMissingSymbols "$InputPath\$FileName" if ($Status -ne 0) { - Write-PipelineTelemetryError -Category 'CheckSymbols' -Message "Missing symbols for $Status modules in the package $FileName" + Write-Error "Missing symbols for $Status modules in the package $FileName" } Write-Host diff --git a/eng/common/PublishToSymbolServers.proj b/eng/common/PublishToSymbolServers.proj index 311e2bbe0f..5d55e312b0 100644 --- a/eng/common/PublishToSymbolServers.proj +++ b/eng/common/PublishToSymbolServers.proj @@ -37,8 +37,6 @@ 3650 true - true - true false @@ -58,7 +56,7 @@ DryRun="false" ConvertPortablePdbsToWindowsPdbs="false" PdbConversionTreatAsWarning="" - Condition="$(PublishToSymbolServer) and $(PublishToMSDL)"/> + Condition="$(PublishToSymbolServer)"/> git commit --> git push - Write-Host 'git add .' - git add . - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git add failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" - git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git commit failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - Write-Host 'git push' - git push - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git push failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } +# We create the temp directory where we'll store the sdl-config repository +$sdlDir = Join-Path $env:TEMP "sdl" +if (Test-Path $sdlDir) { + Remove-Item -Force -Recurse $sdlDir +} - # Return to the original directory - Pop-Location +Write-Host "git clone https://dnceng:`$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir" +git clone https://dnceng:$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir +if ($LASTEXITCODE -ne 0) { + Write-Error "Git clone failed with exit code $LASTEXITCODE." +} +# We copy the .gdn folder from our local run into the git repository so it can be committed +$sdlRepositoryFolder = Join-Path (Join-Path (Join-Path $sdlDir $Repository) $BranchName) ".gdn" +if (Get-Command Robocopy) { + Robocopy /S $GdnFolder $sdlRepositoryFolder +} else { + rsync -r $GdnFolder $sdlRepositoryFolder } -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} \ No newline at end of file +# cd to the sdl-config directory so we can run git there +Push-Location $sdlDir +# git add . --> git commit --> git push +Write-Host "git add ." +git add . +if ($LASTEXITCODE -ne 0) { + Write-Error "Git add failed with exit code $LASTEXITCODE." +} +Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" +git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" +if ($LASTEXITCODE -ne 0) { + Write-Error "Git commit failed with exit code $LASTEXITCODE." +} +Write-Host "git push" +git push +if ($LASTEXITCODE -ne 0) { + Write-Error "Git push failed with exit code $LASTEXITCODE." +} + +# Return to the original directory +Pop-Location \ No newline at end of file diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 index 40a084f796..9bc25314ae 100644 --- a/eng/common/sdl/run-sdl.ps1 +++ b/eng/common/sdl/run-sdl.ps1 @@ -5,65 +5,55 @@ Param( [string] $GdnFolder, [string[]] $ToolsList, [string] $UpdateBaseline, - [string] $GuardianLoggerLevel='Standard', + [string] $GuardianLoggerLevel="Standard", [string[]] $CrScanAdditionalRunConfigParams, [string[]] $PoliCheckAdditionalRunConfigParams ) -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = "Stop" Set-StrictMode -Version 2.0 -$disableConfigureToolsetImport = $true $LASTEXITCODE = 0 -try { - . $PSScriptRoot\..\tools.ps1 +# We store config files in the r directory of .gdn +Write-Host $ToolsList +$gdnConfigPath = Join-Path $GdnFolder "r" +$ValidPath = Test-Path $GuardianCliLocation - # We store config files in the r directory of .gdn - Write-Host $ToolsList - $gdnConfigPath = Join-Path $GdnFolder 'r' - $ValidPath = Test-Path $GuardianCliLocation - - if ($ValidPath -eq $False) - { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." - ExitWithExitCode 1 - } - - $configParam = @('--config') +if ($ValidPath -eq $False) +{ + Write-Host "Invalid Guardian CLI Location." + exit 1 +} - foreach ($tool in $ToolsList) { - $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" - 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" - & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } +$configParam = @("--config") + +foreach ($tool in $ToolsList) { + $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" + 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" + & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) + if ($LASTEXITCODE -ne 0) { + Write-Host "Guardian configure for $tool failed with exit code $LASTEXITCODE." + exit $LASTEXITCODE } - if ($tool -eq 'policheck') { - 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-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } + } + if ($tool -eq "policheck") { + 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 } - - $configParam+=$gdnConfigFile } - Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" - & $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } + $configParam+=$gdnConfigFile +} + +Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" +& $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam +if ($LASTEXITCODE -ne 0) { + Write-Host "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." + exit $LASTEXITCODE } -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} \ No newline at end of file diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 2973bcaf3a..52e2ff021d 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -40,13 +40,13 @@ jobs: itemPattern: "**" downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts + -InputPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts displayName: Extract Blob Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts + -InputPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts displayName: Extract Package Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - task: NuGetToolInstaller@1 diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index ecebd0f03e..ffda80a197 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,33 +1,67 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - parameters: # Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job cancelTimeoutInMinutes: '' + condition: '' - container: '' + continueOnError: false + + container: '' + dependsOn: '' + displayName: '' - pool: '' + steps: [] + + pool: '' + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' + # Job base template specific parameters + # Optional: Enable installing Microbuild plugin + # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix + # _TeamName - the name of your team + # _SignType - 'test' or 'real' enableMicrobuild: false + + # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false + + # Optional: Enable publishing to the build asset registry enablePublishBuildAssets: false - enablePublishTestResults: false + + # Optional: Prevent gather/push manifest from executing when using publishing pipelines enablePublishUsingPipelines: false + + # Optional: Include PublishTestResults task + enablePublishTestResults: false + + # Optional: enable sending telemetry + enableTelemetry: false + + # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') + helixRepo: '' + + # Optional: define the helix type for telemetry (example: 'build/product/') + helixType: '' + + # Required: name of the job name: '' - preSteps: [] + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. runAsPublic: false +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + jobs: - job: ${{ parameters.name }} @@ -59,7 +93,7 @@ jobs: timeoutInMinutes: ${{ parameters.timeoutInMinutes }} variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - ${{ if eq(parameters.enableTelemetry, 'true') }}: - name: DOTNET_CLI_TELEMETRY_PROFILE value: '$(Build.Repository.Uri)' - ${{ each variable in parameters.variables }}: @@ -91,12 +125,21 @@ jobs: workspace: ${{ parameters.workspace }} steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} + - ${{ if eq(parameters.enableTelemetry, 'true') }}: + # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions + - task: sendStartTelemetry@0 + displayName: 'Send Helix Start Telemetry' + inputs: + helixRepo: ${{ parameters.helixRepo }} + ${{ if ne(parameters.helixType, '') }}: + helixType: ${{ parameters.helixType }} + buildConfig: $(_BuildConfig) + runAsPublic: ${{ parameters.runAsPublic }} + continueOnError: ${{ parameters.continueOnError }} + condition: always() - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: MicroBuildSigningPlugin@2 displayName: Install MicroBuild plugin inputs: @@ -108,16 +151,9 @@ jobs: continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: NuGetAuthenticate@0 - - ${{ if or(eq(parameters.artifacts.download, 'true'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - ${{ each step in parameters.steps }}: - ${{ step }} @@ -130,60 +166,20 @@ jobs: env: TeamName: $(_TeamName) - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if or(eq(parameters.artifacts.publish.artifacts, 'true'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if or(eq(parameters.artifacts.publish.logs, 'true'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - ${{ if or(eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - ${{ if and(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: - SourceFolder: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/AssetManifest' - TargetFolder: '$(Build.ArtifactStagingDirectory)/AssetManifests' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) - - - task: PublishBuildArtifacts@1 - displayName: Push Asset Manifests - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/AssetManifests' - PublishLocation: Container - ArtifactName: AssetManifests - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - ${{ if eq(parameters.enableTelemetry, 'true') }}: + # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions + - task: sendEndTelemetry@0 + displayName: 'Send Helix End Telemetry' + continueOnError: ${{ parameters.continueOnError }} + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - task: PublishBuildArtifacts@1 displayName: Publish Logs inputs: PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + ArtifactName: $(Agent.Os)_$(Agent.JobName) continueOnError: true condition: always() diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index c08225a9a9..6a2f98c036 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,10 +1,19 @@ parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + # Optional: 'true' if failures in job.yml job should not fail the job continueOnError: false + # Optional: Enable installing Microbuild plugin + # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix + # _TeamName - the name of your team + # _SignType - 'test' or 'real' + enableMicrobuild: false + # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false + # Optional: Enable publishing to the build asset registry + enablePublishBuildAssets: false + # Optional: Enable publishing using release pipelines enablePublishUsingPipelines: false @@ -14,9 +23,19 @@ parameters: # Optional: Include toolset dependencies in the generated graph files includeToolset: false + # Optional: Include PublishTestResults task + enablePublishTestResults: false + + # Optional: enable sending telemetry + # if enabled then the 'helixRepo' parameter should also be specified + enableTelemetry: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job jobs: [] + # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') + helixRepo: '' + # Optional: Override automatically derived dependsOn value for "publish build assets" job publishBuildAssetsDependsOn: '' @@ -43,30 +62,29 @@ jobs: name: ${{ job.job }} -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - pool: - vmImage: vs2017-win2016 - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - - - ${{ if eq(parameters.graphFileGeneration.enabled, true) }}: - - template: ../job/generate-graph-files.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} - dependsOn: - - Asset_Registry_Publish - pool: - vmImage: vs2017-win2016 +- ${{ if and(eq(parameters.enablePublishBuildAssets, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: ../job/publish-build-assets.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + pool: + vmImage: vs2017-win2016 + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + +- ${{ if and(eq(parameters.graphFileGeneration.enabled, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: ../job/generate-graph-files.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} + dependsOn: + - Asset_Registry_Publish + pool: + vmImage: vs2017-win2016 diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml index 3a8755fbbb..68fdec0290 100644 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml @@ -1,7 +1,4 @@ parameters: - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -13,14 +10,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} + dependsOn: validate variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: publish_symbols + - job: displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -41,18 +38,6 @@ stages: artifactName: 'PDBArtifacts' continueOnError: true - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - task: PowerShell@2 displayName: Publish inputs: @@ -64,18 +49,14 @@ stages: /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' /p:Configuration=Release - /p:PublishToMSDL=false ${{ parameters.symbolPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - 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 @@ -89,14 +70,13 @@ stages: inputs: buildType: current artifactName: PackageArtifacts - continueOnError: true - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: buildType: current artifactName: BlobArtifacts - continueOnError: true + - task: DownloadBuildArtifacts@0 displayName: Download Asset Manifests inputs: @@ -140,6 +120,7 @@ stages: /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey) /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) + /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -149,11 +130,6 @@ stages: /p:PublishToMSDL=false ${{ parameters.artifactsPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml index 3f572f8b12..c4bc1897d8 100644 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ b/eng/common/templates/post-build/channels/generic-public-channel.yml @@ -1,7 +1,5 @@ parameters: artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -13,14 +11,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} + dependsOn: validate variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: publish_symbols + - job: displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -66,11 +64,6 @@ stages: /p:Configuration=Release ${{ parameters.symbolPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - job: publish_assets displayName: Publish Assets dependsOn: setupMaestroVars @@ -141,6 +134,7 @@ stages: /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) + /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -149,11 +143,6 @@ stages: /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' ${{ parameters.artifactsPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 9505cf170f..216d043e4e 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,7 +4,7 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - + # .NET Core 3.1 Dev - name: PublicDevRelease_31_Channel_Id value: 128 @@ -49,10 +49,6 @@ variables: - name: NetCore_31_Blazor_Features_Channel_Id value: 531 - # .NET Core Experimental - - name: NetCore_Experimental_Channel_Id - value: 562 - # Whether the build is internal or not - name: IsInternalBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 8a8d84f202..9921743bcd 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -17,14 +17,11 @@ parameters: signingValidationAdditionalParameters: '' # Which stages should finish execution before post-build stages start - validateDependsOn: - - build - publishDependsOn: - - Validate + dependsOn: [build] stages: -- stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} +- stage: validate + dependsOn: ${{ parameters.dependsOn }} displayName: Validate jobs: - ${{ if eq(parameters.enableNugetValidation, 'true') }}: @@ -49,8 +46,6 @@ stages: - ${{ if eq(parameters.enableSigningValidation, 'true') }}: - job: displayName: Signing Validation - variables: - - template: common-variables.yml pool: vmImage: 'windows-2019' steps: @@ -60,18 +55,6 @@ stages: buildType: current artifactName: PackageArtifacts - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - task: PowerShell@2 displayName: Validate inputs: @@ -79,13 +62,9 @@ stages: arguments: -task SigningValidation -restore -msbuildEngine dotnet /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + /p:Configuration=Release ${{ parameters.signingValidationAdditionalParameters }} - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - - ${{ if eq(parameters.enableSourceLinkValidation, 'true') }}: - job: displayName: SourceLink Validation @@ -121,7 +100,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NetCore_Dev5_Publish' @@ -134,7 +112,18 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Dev31_Publish' + channelName: '.NET Core 3.1 Dev' + channelId: 128 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Latest_Publish' @@ -147,7 +136,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Validation_Publish' @@ -160,7 +148,90 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Validation_Publish' + channelName: '.NET 3 Tools - Validation' + channelId: 390 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Publish' + channelName: '.NET 3 Tools' + channelId: 344 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release30_Publish' + channelName: '.NET Core 3.0 Release' + channelId: 19 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release31_Publish' + channelName: '.NET Core 3.1 Release' + channelId: 129 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Blazor31_Features_Publish' + channelName: '.NET Core 3.1 Blazor Features' + channelId: 531 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_30_Internal_Servicing_Publishing' + channelName: '.NET Core 3.0 Internal Servicing' + channelId: 184 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_31_Internal_Servicing_Publishing' + channelName: '.NET Core 3.1 Internal Servicing' + channelId: 550 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'General_Testing_Publish' @@ -173,7 +244,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Dev_Publishing' @@ -186,7 +256,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Release_Publishing' @@ -196,28 +265,74 @@ stages: shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_301xx_Publishing' + channelName: '.NET Core SDK 3.0.1xx' + channelId: 556 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NET_Internal_Tooling_Publishing' - channelName: '.NET Internal Tooling' - channelId: 551 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json' + stageName: 'NETCore_SDK_301xx_Internal_Publishing' + channelName: '.NET Core SDK 3.0.1xx Internal' + channelId: 555 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Experimental_Publishing' - channelName: '.NET Core Experimental' - channelId: 562 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json' + stageName: 'NETCore_SDK_311xx_Publishing' + channelName: '.NET Core SDK 3.1.1xx' + channelId: 560 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_311xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.1xx Internal' + channelId: 559 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Publishing' + channelName: '.NET Core SDK 3.1.2xx' + channelId: 558 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.2xx Internal' + channelId: 557 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 716b53f740..56242b068e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -4,8 +4,6 @@ jobs: pool: vmImage: 'windows-2019' steps: - - checkout: none - - task: DownloadBuildArtifacts@0 displayName: Download Release Configs inputs: @@ -16,25 +14,5 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - targetType: inline - script: | - try { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - - $Channels = "" - $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - - $IsStableBuild = $Content | Select -Index 2 - - Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" - Write-Host "##vso[task.setvariable variable=InitialChannels;isOutput=true]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } + filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 + arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml deleted file mode 100644 index 8903ba57c0..0000000000 --- a/eng/common/templates/steps/publish-logs.yml +++ /dev/null @@ -1,23 +0,0 @@ -parameters: - StageLabel: '' - JobLabel: '' - -steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuilLogs - continueOnError: true - condition: always() diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 30becf01ea..05df886f55 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -23,7 +23,6 @@ parameters: 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." IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting int) Creator: '' # optional -- if the build is external, use this to specify who is sending the job DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() @@ -56,7 +55,6 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) @@ -87,7 +85,6 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index d762c9f044..91efea9405 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -5,7 +5,7 @@ [bool]$ci = if (Test-Path variable:ci) { $ci } else { $false } # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names. -[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { 'Debug' } +[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { "Debug" } # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build. # Binary log must be enabled on CI. @@ -24,7 +24,7 @@ [bool]$restore = if (Test-Path variable:restore) { $restore } else { $true } # Adjusts msbuild verbosity level. -[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { 'minimal' } +[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { "minimal" } # Set to true to reuse msbuild nodes. Recommended to not reuse on CI. [bool]$nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { !$ci } @@ -41,23 +41,21 @@ # 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' } +[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 } # An array of names of processes to stop on script exit if prepareMachine is true. -$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @('msbuild', 'dotnet', 'vbcscompiler') } - -$disableConfigureToolsetImport = if (Test-Path variable:disableConfigureToolsetImport) { $disableConfigureToolsetImport } else { $null } +$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @("msbuild", "dotnet", "vbcscompiler") } set-strictmode -version 2.0 -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = "Stop" [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Create-Directory([string[]] $path) { if (!(Test-Path $path)) { - New-Item -path $path -force -itemType 'Directory' | Out-Null + New-Item -path $path -force -itemType "Directory" | Out-Null } } @@ -121,7 +119,7 @@ function InitializeDotNetCli([bool]$install) { # Find the first path on %PATH% that contains the dotnet.exe if ($useInstalledDotNetCli -and (-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -eq $null)) { - $dotnetCmd = Get-Command 'dotnet.exe' -ErrorAction SilentlyContinue + $dotnetCmd = Get-Command "dotnet.exe" -ErrorAction SilentlyContinue if ($dotnetCmd -ne $null) { $env:DOTNET_INSTALL_DIR = Split-Path $dotnetCmd.Path -Parent } @@ -134,13 +132,13 @@ function InitializeDotNetCli([bool]$install) { if ((-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -ne $null) -and (Test-Path(Join-Path $env:DOTNET_INSTALL_DIR "sdk\$dotnetSdkVersion"))) { $dotnetRoot = $env:DOTNET_INSTALL_DIR } else { - $dotnetRoot = Join-Path $RepoRoot '.dotnet' + $dotnetRoot = Join-Path $RepoRoot ".dotnet" if (-not (Test-Path(Join-Path $dotnetRoot "sdk\$dotnetSdkVersion"))) { if ($install) { InstallDotNetSdk $dotnetRoot $dotnetSdkVersion } else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" ExitWithExitCode 1 } } @@ -156,6 +154,15 @@ function InitializeDotNetCli([bool]$install) { # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot + # Work around issues with Azure Artifacts credential provider + # https://github.com/dotnet/arcade/issues/3932 + if ($ci) { + $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 + $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' + } + Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' @@ -163,7 +170,7 @@ function InitializeDotNetCli([bool]$install) { } function GetDotNetInstallScript([string] $dotnetRoot) { - $installScript = Join-Path $dotnetRoot 'dotnet-install.ps1' + $installScript = Join-Path $dotnetRoot "dotnet-install.ps1" if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit @@ -173,18 +180,11 @@ function GetDotNetInstallScript([string] $dotnetRoot) { return $installScript } -function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = '') { +function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = "") { InstallDotNet $dotnetRoot $version $architecture } -function InstallDotNet([string] $dotnetRoot, - [string] $version, - [string] $architecture = '', - [string] $runtime = '', - [bool] $skipNonVersionedFiles = $false, - [string] $runtimeSourceFeed = '', - [string] $runtimeSourceFeedKey = '') { - +function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ Version = $version @@ -195,29 +195,10 @@ function InstallDotNet([string] $dotnetRoot, if ($runtime) { $installParameters.Runtime = $runtime } if ($skipNonVersionedFiles) { $installParameters.SkipNonVersionedFiles = $skipNonVersionedFiles } - try { - & $installScript @installParameters - } - catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet runtime '$runtime' from public location." - - # Only the runtime can be installed from a custom [private] location. - if ($runtime -and ($runtimeSourceFeed -or $runtimeSourceFeedKey)) { - if ($runtimeSourceFeed) { $installParameters.AzureFeed = $runtimeSourceFeed } - - if ($runtimeSourceFeedKey) { - $decodedBytes = [System.Convert]::FromBase64String($runtimeSourceFeedKey) - $decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes) - $installParameters.FeedCredential = $decodedString - } - - try { - & $installScript @installParameters - } - catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet runtime '$runtime' from custom location '$runtimeSourceFeed'." - } - } + & $installScript @installParameters + if ($lastExitCode -ne 0) { + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Failed to install dotnet cli (exit code '$lastExitCode')." + ExitWithExitCode $lastExitCode } } @@ -238,16 +219,16 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { '15.9' } + $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { "15.9" } $vsMinVersion = [Version]::new($vsMinVersionStr) # Try msbuild command available in the environment. if ($env:VSINSTALLDIR -ne $null) { - $msbuildCmd = Get-Command 'msbuild.exe' -ErrorAction SilentlyContinue + $msbuildCmd = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue if ($msbuildCmd -ne $null) { # Workaround for https://github.com/dotnet/roslyn/issues/35793 # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+ - $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split([char[]]@('-', '+'))[0]) + $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0]) if ($msbuildVersion -ge $vsMinVersion) { return $global:_MSBuildExe = $msbuildCmd.Path @@ -267,7 +248,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = InitializeVisualStudioEnvironmentVariables $vsInstallDir $vsMajorVersion } else { - if (Get-Member -InputObject $GlobalJson.tools -Name 'xcopy-msbuild') { + if (Get-Member -InputObject $GlobalJson.tools -Name "xcopy-msbuild") { $xcopyMSBuildVersion = $GlobalJson.tools.'xcopy-msbuild' $vsMajorVersion = $xcopyMSBuildVersion.Split('.')[0] } else { @@ -277,7 +258,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install if ($vsInstallDir -eq $null) { - throw 'Unable to find Visual Studio that has required version and components installed' + throw "Unable to find Visual Studio that has required version and components installed" } } @@ -301,7 +282,7 @@ function InstallXCopyMSBuild([string]$packageVersion) { } function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { - $packageName = 'RoslynTools.MSBuild' + $packageName = "RoslynTools.MSBuild" $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion" $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" @@ -317,7 +298,7 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { Unzip $packagePath $packageDir } - return Join-Path $packageDir 'tools' + return Join-Path $packageDir "tools" } # @@ -334,32 +315,32 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { # or $null if no instance meeting the requirements is found on the machine. # function LocateVisualStudio([object]$vsRequirements = $null){ - if (Get-Member -InputObject $GlobalJson.tools -Name 'vswhere') { + if (Get-Member -InputObject $GlobalJson.tools -Name "vswhere") { $vswhereVersion = $GlobalJson.tools.vswhere } else { - $vswhereVersion = '2.5.2' + $vswhereVersion = "2.5.2" } $vsWhereDir = Join-Path $ToolsDir "vswhere\$vswhereVersion" - $vsWhereExe = Join-Path $vsWhereDir 'vswhere.exe' + $vsWhereExe = Join-Path $vsWhereDir "vswhere.exe" if (!(Test-Path $vsWhereExe)) { Create-Directory $vsWhereDir - Write-Host 'Downloading vswhere' + Write-Host "Downloading vswhere" Invoke-WebRequest "https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $args = @('-latest', '-prerelease', '-format', 'json', '-requires', 'Microsoft.Component.MSBuild', '-products', '*') + $args = @("-latest", "-prerelease", "-format", "json", "-requires", "Microsoft.Component.MSBuild", "-products", "*") - if (Get-Member -InputObject $vsRequirements -Name 'version') { - $args += '-version' + if (Get-Member -InputObject $vsRequirements -Name "version") { + $args += "-version" $args += $vsRequirements.version } - if (Get-Member -InputObject $vsRequirements -Name 'components') { + if (Get-Member -InputObject $vsRequirements -Name "components") { foreach ($component in $vsRequirements.components) { - $args += '-requires' + $args += "-requires" $args += $component } } @@ -385,27 +366,27 @@ function InitializeBuildTool() { # Initialize dotnet cli if listed in 'tools' $dotnetRoot = $null - if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { + if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { $dotnetRoot = InitializeDotNetCli -install:$restore } - if ($msbuildEngine -eq 'dotnet') { + if ($msbuildEngine -eq "dotnet") { if (!$dotnetRoot) { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "/global.json must specify 'tools.dotnet'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "/global.json must specify 'tools.dotnet'." ExitWithExitCode 1 } - $buildTool = @{ Path = Join-Path $dotnetRoot 'dotnet.exe'; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'netcoreapp2.1' } + $buildTool = @{ Path = Join-Path $dotnetRoot "dotnet.exe"; Command = "msbuild"; Tool = "dotnet"; Framework = "netcoreapp2.1" } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore } catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ + Write-PipelineTelemetryError -Category "InitializeToolset" -Message $_ ExitWithExitCode 1 } $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "net472" } } else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." ExitWithExitCode 1 } @@ -414,15 +395,15 @@ function InitializeBuildTool() { function GetDefaultMSBuildEngine() { # Presence of tools.vs indicates the repo needs to build using VS msbuild on Windows. - if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { - return 'vs' + if (Get-Member -InputObject $GlobalJson.tools -Name "vs") { + return "vs" } - if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { - return 'dotnet' + if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { + return "dotnet" } - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." ExitWithExitCode 1 } @@ -431,9 +412,9 @@ function GetNuGetPackageCachePath() { # Use local cache on CI to ensure deterministic build, # use global cache in dev builds to avoid cost of downloading packages. if ($useGlobalNuGetCache) { - $env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages' + $env:NUGET_PACKAGES = Join-Path $env:UserProfile ".nuget\packages" } else { - $env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages' + $env:NUGET_PACKAGES = Join-Path $RepoRoot ".packages" } } @@ -446,7 +427,7 @@ function GetSdkTaskProject([string]$taskName) { } function InitializeNativeTools() { - if (-Not (Test-Path variable:DisableNativeToolsetInstalls) -And (Get-Member -InputObject $GlobalJson -Name "native-tools")) { + if (Get-Member -InputObject $GlobalJson -Name "native-tools") { $nativeArgs= @{} if ($ci) { $nativeArgs = @{ @@ -475,14 +456,14 @@ function InitializeToolset() { } if (-not $restore) { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Toolset version $toolsetVersion has not been restored." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Toolset version $toolsetVersion has not been restored." ExitWithExitCode 1 } $buildTool = InitializeBuildTool - $proj = Join-Path $ToolsetDir 'restore.proj' - $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'ToolsetRestore.binlog') } else { '' } + $proj = Join-Path $ToolsetDir "restore.proj" + $bl = if ($binaryLog) { "/bl:" + (Join-Path $LogDir "ToolsetRestore.binlog") } else { "" } '' | Set-Content $proj @@ -504,7 +485,7 @@ function ExitWithExitCode([int] $exitCode) { } function Stop-Processes() { - Write-Host 'Killing running build processes...' + Write-Host "Killing running build processes..." foreach ($processName in $processesToStopOnExit) { Get-Process -Name $processName -ErrorAction SilentlyContinue | Stop-Process } @@ -521,18 +502,13 @@ function MSBuild() { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 - if ($ci -and $buildTool.Tool -eq 'dotnet') { + if ($ci -and $buildTool.Tool -eq "dotnet") { dotnet nuget locals http-cache -c - - $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 - $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } $toolsetBuildProject = InitializeToolset $path = Split-Path -parent $toolsetBuildProject - $path = Join-Path $path (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll') + $path = Join-Path $path (Join-Path $buildTool.Framework "Microsoft.DotNet.Arcade.Sdk.dll") $args += "/logger:$path" } @@ -547,12 +523,12 @@ function MSBuild() { function MSBuild-Core() { if ($ci) { if (!$binaryLog) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build.' + Write-PipelineTaskError -Message "Binary log must be enabled in CI build." ExitWithExitCode 1 } if ($nodeReuse) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Node reuse must be disabled in CI build.' + Write-PipelineTaskError -Message "Node reuse must be disabled in CI build." ExitWithExitCode 1 } } @@ -562,10 +538,10 @@ function MSBuild-Core() { $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci" if ($warnAsError) { - $cmdArgs += ' /warnaserror /p:TreatWarningsAsErrors=true' + $cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true" } else { - $cmdArgs += ' /p:TreatWarningsAsErrors=false' + $cmdArgs += " /p:TreatWarningsAsErrors=false" } foreach ($arg in $args) { @@ -577,7 +553,7 @@ function MSBuild-Core() { $exitCode = Exec-Process $buildTool.Path $cmdArgs if ($exitCode -ne 0) { - Write-PipelineTelemetryError Category 'Build' -Message 'Build failed.' + Write-PipelineTaskError -Message "Build failed." $buildLog = GetMSBuildBinaryLogCommandLineArgument $args if ($buildLog -ne $null) { @@ -592,12 +568,12 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { foreach ($argument in $arguments) { if ($argument -ne $null) { $arg = $argument.Trim() - if ($arg.StartsWith('/bl:', "OrdinalIgnoreCase")) { - return $arg.Substring('/bl:'.Length) + if ($arg.StartsWith("/bl:", "OrdinalIgnoreCase")) { + return $arg.Substring("/bl:".Length) } - if ($arg.StartsWith('/binaryLogger:', 'OrdinalIgnoreCase')) { - return $arg.Substring('/binaryLogger:'.Length) + if ($arg.StartsWith("/binaryLogger:", "OrdinalIgnoreCase")) { + return $arg.Substring("/binaryLogger:".Length) } } } @@ -607,14 +583,14 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { . $PSScriptRoot\pipeline-logging-functions.ps1 -$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..') -$EngRoot = Resolve-Path (Join-Path $PSScriptRoot '..') -$ArtifactsDir = Join-Path $RepoRoot 'artifacts' -$ToolsetDir = Join-Path $ArtifactsDir 'toolset' -$ToolsDir = Join-Path $RepoRoot '.tools' -$LogDir = Join-Path (Join-Path $ArtifactsDir 'log') $configuration -$TempDir = Join-Path (Join-Path $ArtifactsDir 'tmp') $configuration -$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot 'global.json') | ConvertFrom-Json +$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") +$EngRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +$ArtifactsDir = Join-Path $RepoRoot "artifacts" +$ToolsetDir = Join-Path $ArtifactsDir "toolset" +$ToolsDir = Join-Path $RepoRoot ".tools" +$LogDir = Join-Path (Join-Path $ArtifactsDir "log") $configuration +$TempDir = Join-Path (Join-Path $ArtifactsDir "tmp") $configuration +$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot "global.json") | ConvertFrom-Json # true if global.json contains a "runtimes" section $globalJsonHasRuntimes = if ($GlobalJson.tools.PSObject.Properties.Name -Match 'runtimes') { $true } else { $false } @@ -627,18 +603,3 @@ Write-PipelineSetVariable -Name 'Artifacts.Toolset' -Value $ToolsetDir Write-PipelineSetVariable -Name 'Artifacts.Log' -Value $LogDir Write-PipelineSetVariable -Name 'TEMP' -Value $TempDir Write-PipelineSetVariable -Name 'TMP' -Value $TempDir - -# Import custom tools configuration, if present in the repo. -# Note: Import in global scope so that the script set top-level variables without qualification. -if (!$disableConfigureToolsetImport) { - $configureToolsetScript = Join-Path $EngRoot 'configure-toolset.ps1' - if (Test-Path $configureToolsetScript) { - . $configureToolsetScript - if ((Test-Path variable:failOnConfigureToolsetError) -And $failOnConfigureToolsetError) { - if ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) { - Write-PipelineTelemetryError -Category 'Build' -Message 'configure-toolset.ps1 returned a non-zero exit code' - ExitWithExitCode $LastExitCode - } - } - } -} diff --git a/eng/common/tools.sh b/eng/common/tools.sh index f58db5e25d..757d5b9ea4 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -81,7 +81,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'Build' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -152,6 +152,15 @@ function InitializeDotNetCli { # build steps from using anything other than what we've downloaded. Write-PipelinePrependPath -path "$dotnet_root" + # Work around issues with Azure Artifacts credential provider + # https://github.com/dotnet/arcade/issues/3932 + if [[ "$ci" == true ]]; then + export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 + export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 + Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" + Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + fi + Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" @@ -191,28 +200,8 @@ function InstallDotNet { fi bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg || { local exit_code=$? - Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from public location (exit code '$exit_code')." - - if [[ -n "$runtimeArg" ]]; then - local runtimeSourceFeed='' - if [[ -n "${6:-}" ]]; then - runtimeSourceFeed="--azure-feed $6" - fi - - local runtimeSourceFeedKey='' - if [[ -n "${7:-}" ]]; then - decodedFeedKey=`echo $7 | base64 --decode` - runtimeSourceFeedKey="--feed-credential $decodedFeedKey" - fi - - if [[ -n "$runtimeSourceFeed" || -n "$runtimeSourceFeedKey" ]]; then - bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg $runtimeSourceFeed $runtimeSourceFeedKey || { - local exit_code=$? - Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from custom location '$runtimeSourceFeed' (exit code '$exit_code')." - ExitWithExitCode $exit_code - } - fi - fi + Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK (exit code '$exit_code')." + ExitWithExitCode $exit_code } } @@ -272,9 +261,6 @@ function GetNuGetPackageCachePath { } function InitializeNativeTools() { - if [[ -n "${DisableNativeToolsetInstalls:-}" ]]; then - return - fi if grep -Fq "native-tools" $global_json_file then local nativeArgs="" @@ -324,7 +310,7 @@ function InitializeToolset { local toolset_build_proj=`cat "$toolset_location_file"` if [[ ! -a "$toolset_build_proj" ]]; then - Write-PipelineTelemetryError -category 'Build' "Invalid toolset path: $toolset_build_proj" + Write-PipelineTelemetryError -category 'InitializeToolset' "Invalid toolset path: $toolset_build_proj" ExitWithExitCode 3 fi @@ -355,12 +341,7 @@ function MSBuild { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 if [[ "$ci" == true ]]; then - "$_InitializeBuildTool" nuget locals http-cache -c - - export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 - export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 - Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" - Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + dotnet nuget locals http-cache -c fi local toolset_dir="${_InitializeToolset%/*}" @@ -374,12 +355,12 @@ function MSBuild { function MSBuild-Core { if [[ "$ci" == true ]]; then if [[ "$binary_log" != true ]]; then - Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build." + Write-PipelineTaskError "Binary log must be enabled in CI build." ExitWithExitCode 1 fi if [[ "$node_reuse" == true ]]; then - Write-PipelineTelemetryError -category 'Build' "Node reuse must be disabled in CI build." + Write-PipelineTaskError "Node reuse must be disabled in CI build." ExitWithExitCode 1 fi fi @@ -393,7 +374,7 @@ function MSBuild-Core { "$_InitializeBuildTool" "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" || { local exit_code=$? - Write-PipelineTelemetryError -category 'Build' "Build failed (exit code '$exit_code')." + Write-PipelineTaskError "Build failed (exit code '$exit_code')." ExitWithExitCode $exit_code } } @@ -434,18 +415,3 @@ 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" - -# Import custom tools configuration, if present in the repo. -if [ -z "${disable_configure_toolset_import:-}" ]; then - configure_toolset_script="$eng_root/configure-toolset.sh" - if [[ -a "$configure_toolset_script" ]]; then - . "$configure_toolset_script" - fi -fi - -# TODO: https://github.com/dotnet/arcade/issues/1468 -# Temporary workaround to avoid breaking change. -# Remove once repos are updated. -if [[ -n "${useInstalledDotNetCli:-}" ]]; then - use_installed_dotnet_cli="$useInstalledDotNetCli" -fi diff --git a/global.json b/global.json index 707f7b7357..951a2ccba1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "3.0.100", + "dotnet": "3.0.101", "vs": { "version": "16.3", "components": [ @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19602.4", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19603.16", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 32b12496654edb07d95efd52e5e09a34b341f23c Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Mon, 9 Dec 2019 10:33:43 -0800 Subject: [PATCH 004/101] Update to 3.1.100 rtm sdk (#7942) --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 951a2ccba1..7788552df2 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "3.0.101", + "dotnet": "3.1.100", "vs": { "version": "16.3", "components": [ From 94da88c64e7b10e23d265b225f8c04a6ea428071 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 10 Dec 2019 13:39:02 -0800 Subject: [PATCH 005/101] add internal package feed (#7949) --- NuGet.config | 1 + 1 file changed, 1 insertion(+) diff --git a/NuGet.config b/NuGet.config index ef069a5bdf..26edd0d796 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,6 +7,7 @@ + From ccf22bf73e927e35683d02fc0b8fec07d1d7e4b2 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Sun, 15 Dec 2019 12:05:34 -0800 Subject: [PATCH 006/101] Improve package reference diags (#7909) --- .../FSharp.DependencyManager.Utilities.fs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index 945ca021d0..493a6ba789 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -158,14 +158,26 @@ module Utilities = None #endif + let drainStreamToFile (stream: StreamReader) filename = + use file = File.OpenWrite(filename) + use writer = new StreamWriter(file) + let rec copyLines () = + match stream.ReadLine() with + | null -> () + | line -> + writer.WriteLine(line) + copyLines () + copyLines () + let executeBuild pathToExe arguments workingDir = match pathToExe with | Some path -> + let psi = ProcessStartInfo() psi.FileName <- path psi.WorkingDirectory <- workingDir - psi.RedirectStandardOutput <- false - psi.RedirectStandardError <- false + psi.RedirectStandardOutput <- true + psi.RedirectStandardError <- true psi.Arguments <- arguments psi.CreateNoWindow <- true psi.UseShellExecute <- false @@ -173,8 +185,13 @@ module Utilities = use p = new Process() p.StartInfo <- psi p.Start() |> ignore + + drainStreamToFile p.StandardOutput (Path.Combine(workingDir, "StandardOutput.txt")) + drainStreamToFile p.StandardError (Path.Combine(workingDir, "StandardError.txt")) + p.WaitForExit() p.ExitCode = 0 + | None -> false let buildProject projectPath binLogPath = From a2eea3045448b4f807723170628661371aed0c30 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Tue, 31 Dec 2019 22:55:24 -0800 Subject: [PATCH 007/101] remove dupe --- src/fsharp/DotNetFrameworkDependencies.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fsharp/DotNetFrameworkDependencies.fs b/src/fsharp/DotNetFrameworkDependencies.fs index e1be666fb2..a454ec8059 100644 --- a/src/fsharp/DotNetFrameworkDependencies.fs +++ b/src/fsharp/DotNetFrameworkDependencies.fs @@ -13,7 +13,6 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies type private TypeInThisAssembly = class end - let implementationAssemblyDir = Path.GetDirectoryName(typeof.Assembly.Location) let fSharpCompilerLocation = let location = Path.GetDirectoryName(typeof.Assembly.Location) match FSharpEnvironment.BinFolderOfDefaultFSharpCompiler (Some location) with From e7eb1434d774b51ebd77af5e409de4288b085f9f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 2 Jan 2020 22:24:36 +0000 Subject: [PATCH 008/101] Update dependencies from https://github.com/dotnet/arcade build 20200102.1 - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20052.1 --- eng/Version.Details.xml | 4 +- eng/common/CheckSymbols.ps1 | 53 ++-- eng/common/PublishToSymbolServers.proj | 6 +- eng/common/SetupNugetSources.sh | 2 +- eng/common/SourceLinkValidation.ps1 | 269 +++++++++--------- eng/common/build.ps1 | 95 ++++--- eng/common/build.sh | 24 +- eng/common/cross/build-rootfs.sh | 2 +- eng/common/cross/toolchain.cmake | 49 +--- eng/common/darc-init.ps1 | 26 +- eng/common/darc-init.sh | 30 +- eng/common/dotnet-install.ps1 | 23 +- eng/common/dotnet-install.sh | 50 +++- eng/common/enable-cross-org-publishing.ps1 | 6 +- eng/common/generate-graph-files.ps1 | 49 ++-- eng/common/init-tools-native.ps1 | 37 +-- eng/common/init-tools-native.sh | 5 +- eng/common/internal-feed-operations.ps1 | 28 +- eng/common/internal-feed-operations.sh | 4 +- eng/common/msbuild.ps1 | 5 +- eng/common/native/common-library.sh | 10 +- eng/common/native/install-cmake-test.sh | 4 +- eng/common/native/install-cmake.sh | 4 +- eng/common/native/install-tool.ps1 | 10 +- eng/common/pipeline-logging-functions.ps1 | 70 ++--- eng/common/pipeline-logging-functions.sh | 11 +- eng/common/post-build/darc-gather-drop.ps1 | 15 +- eng/common/post-build/nuget-validation.ps1 | 11 +- eng/common/post-build/post-build-utils.ps1 | 27 +- eng/common/post-build/promote-build.ps1 | 18 +- eng/common/post-build/setup-maestro-vars.ps1 | 26 -- .../post-build/sourcelink-validation.ps1 | 42 +-- eng/common/post-build/symbols-validation.ps1 | 71 +++-- .../post-build/trigger-subscriptions.ps1 | 87 +++--- eng/common/sdk-task.ps1 | 19 +- eng/common/sdl/execute-all-sdl-tools.ps1 | 176 ++++++------ eng/common/sdl/extract-artifact-packages.ps1 | 89 +++--- eng/common/sdl/init-sdl.ps1 | 38 ++- eng/common/sdl/push-gdn.ps1 | 92 +++--- eng/common/sdl/run-sdl.ps1 | 86 +++--- eng/common/templates/job/execute-sdl.yml | 8 +- eng/common/templates/job/job.yml | 142 ++++----- eng/common/templates/jobs/jobs.yml | 74 ++--- .../channels/generic-internal-channel.yml | 36 ++- .../channels/generic-public-channel.yml | 17 +- .../templates/post-build/common-variables.yml | 6 +- .../templates/post-build/post-build.yml | 205 +++---------- .../post-build/setup-maestro-vars.yml | 26 +- eng/common/templates/steps/publish-logs.yml | 23 ++ eng/common/templates/steps/send-to-helix.yml | 3 + eng/common/tools.ps1 | 168 ++++++----- eng/common/tools.sh | 44 ++- global.json | 2 +- 53 files changed, 1264 insertions(+), 1163 deletions(-) delete mode 100644 eng/common/post-build/setup-maestro-vars.ps1 create mode 100644 eng/common/templates/steps/publish-logs.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b38d39faa6..d87b36dd3a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - cc596c55ac68c952d0e052e6ed50334ed170b53a + 98cc270f5e08096729fc7d54ffafa9e3c6576316 diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 index b8d84607b8..5442eff386 100644 --- a/eng/common/CheckSymbols.ps1 +++ b/eng/common/CheckSymbols.ps1 @@ -5,11 +5,12 @@ param( ) Add-Type -AssemblyName System.IO.Compression.FileSystem +. $PSScriptRoot\pipeline-logging-functions.ps1 function FirstMatchingSymbolDescriptionOrDefault { param( [string] $FullPath, # Full path to the module that has to be checked - [string] $TargetServerParam, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + [string] $TargetServerParameter, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols [string] $SymbolsPath ) @@ -21,36 +22,36 @@ function FirstMatchingSymbolDescriptionOrDefault { # checking and which type of file was uploaded. # The file itself is returned - $SymbolPath = $SymbolsPath + "\" + $FileName + $SymbolPath = $SymbolsPath + '\' + $FileName # PDB file for the module - $PdbPath = $SymbolPath.Replace($Extension, ".pdb") + $PdbPath = $SymbolPath.Replace($Extension, '.pdb') # PDB file for R2R module (created by crossgen) - $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") + $NGenPdb = $SymbolPath.Replace($Extension, '.ni.pdb') # DBG file for a .so library - $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") + $SODbg = $SymbolPath.Replace($Extension, '.so.dbg') # DWARF file for a .dylib - $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") + $DylibDwarf = $SymbolPath.Replace($Extension, '.dylib.dwarf') - .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null + .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParameter $FullPath -o $SymbolsPath | Out-Null if (Test-Path $PdbPath) { - return "PDB" + return 'PDB' } elseif (Test-Path $NGenPdb) { - return "NGen PDB" + return 'NGen PDB' } elseif (Test-Path $SODbg) { - return "DBG for SO" + return 'DBG for SO' } elseif (Test-Path $DylibDwarf) { - return "Dwarf for Dylib" + return 'Dwarf for Dylib' } elseif (Test-Path $SymbolPath) { - return "Module" + return 'Module' } else { return $null @@ -68,7 +69,7 @@ function CountMissingSymbols { } # Extensions for which we'll look for symbols - $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") + $RelevantExtensions = @('.dll', '.exe', '.so', '.dylib') # How many files are missing symbol information $MissingSymbols = 0 @@ -76,7 +77,7 @@ function CountMissingSymbols { $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) $PackageGuid = New-Guid $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid - $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols" + $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath 'Symbols' [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) @@ -86,31 +87,31 @@ function CountMissingSymbols { Get-ChildItem -Recurse $ExtractPath | Where-Object {$RelevantExtensions -contains $_.Extension} | ForEach-Object { - if ($_.FullName -Match "\\ref\\") { + if ($_.FullName -Match '\\ref\\') { Write-Host "`t Ignoring reference assembly file" $_.FullName return } - $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath - $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--microsoft-symbol-server' -SymbolsPath $SymbolsPath + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--internal-server' -SymbolsPath $SymbolsPath Write-Host -NoNewLine "`t Checking file" $_.FullName "... " if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { - Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" + Write-Host "Symbols found on MSDL (${$SymbolsOnMSDL}) and SymWeb (${$SymbolsOnSymWeb})" } else { $MissingSymbols++ if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { - Write-Host "No symbols found on MSDL or SymWeb!" + Write-Host 'No symbols found on MSDL or SymWeb!' } else { if ($SymbolsOnMSDL -eq $null) { - Write-Host "No symbols found on MSDL!" + Write-Host 'No symbols found on MSDL!' } else { - Write-Host "No symbols found on SymWeb!" + Write-Host 'No symbols found on SymWeb!' } } } @@ -129,26 +130,26 @@ function CheckSymbolsAvailable { Get-ChildItem "$InputPath\*.nupkg" | ForEach-Object { $FileName = $_.Name - + # These packages from Arcade-Services include some native libraries that # our current symbol uploader can't handle. Below is a workaround until # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted. - if ($FileName -Match "Microsoft\.DotNet\.Darc\.") { + if ($FileName -Match 'Microsoft\.DotNet\.Darc\.') { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") { + elseif ($FileName -Match 'Microsoft\.DotNet\.Maestro\.Tasks\.') { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - + Write-Host "Validating $FileName " $Status = CountMissingSymbols "$InputPath\$FileName" if ($Status -ne 0) { - Write-Error "Missing symbols for $Status modules in the package $FileName" + Write-PipelineTelemetryError -Category 'CheckSymbols' -Message "Missing symbols for $Status modules in the package $FileName" } Write-Host diff --git a/eng/common/PublishToSymbolServers.proj b/eng/common/PublishToSymbolServers.proj index 5d55e312b0..311e2bbe0f 100644 --- a/eng/common/PublishToSymbolServers.proj +++ b/eng/common/PublishToSymbolServers.proj @@ -37,6 +37,8 @@ 3650 true + true + true false @@ -56,7 +58,7 @@ DryRun="false" ConvertPortablePdbsToWindowsPdbs="false" PdbConversionTreatAsWarning="" - Condition="$(PublishToSymbolServer)"/> + Condition="$(PublishToSymbolServer) and $(PublishToMSDL)"/> git commit --> git push -Write-Host "git add ." -git add . -if ($LASTEXITCODE -ne 0) { - Write-Error "Git add failed with exit code $LASTEXITCODE." -} -Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" -git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" -if ($LASTEXITCODE -ne 0) { - Write-Error "Git commit failed with exit code $LASTEXITCODE." -} -Write-Host "git push" -git push -if ($LASTEXITCODE -ne 0) { - Write-Error "Git push failed with exit code $LASTEXITCODE." -} + # We create the temp directory where we'll store the sdl-config repository + $sdlDir = Join-Path $env:TEMP 'sdl' + if (Test-Path $sdlDir) { + Remove-Item -Force -Recurse $sdlDir + } -# Return to the original directory -Pop-Location \ No newline at end of file + Write-Host "git clone https://dnceng:`$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir" + git clone https://dnceng:$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git clone failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } + # We copy the .gdn folder from our local run into the git repository so it can be committed + $sdlRepositoryFolder = Join-Path (Join-Path (Join-Path $sdlDir $Repository) $BranchName) '.gdn' + if (Get-Command Robocopy) { + Robocopy /S $GdnFolder $sdlRepositoryFolder + } else { + rsync -r $GdnFolder $sdlRepositoryFolder + } + # cd to the sdl-config directory so we can run git there + Push-Location $sdlDir + # git add . --> git commit --> git push + Write-Host 'git add .' + git add . + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git add failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } + Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" + git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git commit failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } + Write-Host 'git push' + git push + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git push failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } + + # Return to the original directory + Pop-Location +} +catch { + Write-Host $_.ScriptStackTrace + Write-PipelineTelemetryError -Category 'Sdl' -Message $_ + ExitWithExitCode 1 +} \ No newline at end of file diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 index 9bc25314ae..40a084f796 100644 --- a/eng/common/sdl/run-sdl.ps1 +++ b/eng/common/sdl/run-sdl.ps1 @@ -5,55 +5,65 @@ Param( [string] $GdnFolder, [string[]] $ToolsList, [string] $UpdateBaseline, - [string] $GuardianLoggerLevel="Standard", + [string] $GuardianLoggerLevel='Standard', [string[]] $CrScanAdditionalRunConfigParams, [string[]] $PoliCheckAdditionalRunConfigParams ) -$ErrorActionPreference = "Stop" +$ErrorActionPreference = 'Stop' Set-StrictMode -Version 2.0 +$disableConfigureToolsetImport = $true $LASTEXITCODE = 0 -# We store config files in the r directory of .gdn -Write-Host $ToolsList -$gdnConfigPath = Join-Path $GdnFolder "r" -$ValidPath = Test-Path $GuardianCliLocation +try { + . $PSScriptRoot\..\tools.ps1 -if ($ValidPath -eq $False) -{ - Write-Host "Invalid Guardian CLI Location." - exit 1 -} + # We store config files in the r directory of .gdn + Write-Host $ToolsList + $gdnConfigPath = Join-Path $GdnFolder 'r' + $ValidPath = Test-Path $GuardianCliLocation -$configParam = @("--config") - -foreach ($tool in $ToolsList) { - $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" - 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" - & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) - if ($LASTEXITCODE -ne 0) { - Write-Host "Guardian configure for $tool failed with exit code $LASTEXITCODE." - exit $LASTEXITCODE - } + if ($ValidPath -eq $False) + { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." + ExitWithExitCode 1 } - if ($tool -eq "policheck") { - 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 + + $configParam = @('--config') + + foreach ($tool in $ToolsList) { + $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" + 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" + & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } + } + if ($tool -eq 'policheck') { + 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-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } } - } - $configParam+=$gdnConfigFile -} + $configParam+=$gdnConfigFile + } -Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" -& $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam -if ($LASTEXITCODE -ne 0) { - Write-Host "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." - exit $LASTEXITCODE + Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" + & $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam + if ($LASTEXITCODE -ne 0) { + Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." + ExitWithExitCode $LASTEXITCODE + } } +catch { + Write-Host $_.ScriptStackTrace + Write-PipelineTelemetryError -Category 'Sdl' -Message $_ + ExitWithExitCode 1 +} \ No newline at end of file diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 52e2ff021d..2973bcaf3a 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -40,13 +40,13 @@ jobs: itemPattern: "**" downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts + -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts + -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts displayName: Extract Blob Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts + -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts + -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts displayName: Extract Package Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - task: NuGetToolInstaller@1 diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index ffda80a197..ecebd0f03e 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,67 +1,33 @@ +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + parameters: # Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job cancelTimeoutInMinutes: '' - condition: '' - - continueOnError: false - container: '' - + continueOnError: false dependsOn: '' - displayName: '' - - steps: [] - pool: '' - + steps: [] strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - # Job base template specific parameters - # Optional: Enable installing Microbuild plugin - # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix - # _TeamName - the name of your team - # _SignType - 'test' or 'real' +# Job base template specific parameters + # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md + artifacts: '' enableMicrobuild: false - - # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false - - # 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 - - # Optional: enable sending telemetry - enableTelemetry: false - - # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') - helixRepo: '' - - # Optional: define the helix type for telemetry (example: 'build/product/') - helixType: '' - - # Required: name of the job + enablePublishUsingPipelines: false name: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + preSteps: [] runAsPublic: false -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: - job: ${{ parameters.name }} @@ -93,7 +59,7 @@ jobs: timeoutInMinutes: ${{ parameters.timeoutInMinutes }} variables: - - ${{ if eq(parameters.enableTelemetry, 'true') }}: + - ${{ if ne(parameters.enableTelemetry, 'false') }}: - name: DOTNET_CLI_TELEMETRY_PROFILE value: '$(Build.Repository.Uri)' - ${{ each variable in parameters.variables }}: @@ -125,21 +91,12 @@ jobs: workspace: ${{ parameters.workspace }} steps: - - ${{ if eq(parameters.enableTelemetry, 'true') }}: - # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions - - task: sendStartTelemetry@0 - displayName: 'Send Helix Start Telemetry' - inputs: - helixRepo: ${{ parameters.helixRepo }} - ${{ if ne(parameters.helixType, '') }}: - helixType: ${{ parameters.helixType }} - buildConfig: $(_BuildConfig) - runAsPublic: ${{ parameters.runAsPublic }} - continueOnError: ${{ parameters.continueOnError }} - condition: always() + - ${{ if ne(parameters.preSteps, '') }}: + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - task: MicroBuildSigningPlugin@2 displayName: Install MicroBuild plugin inputs: @@ -151,9 +108,16 @@ jobs: continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: NuGetAuthenticate@0 + - ${{ if or(eq(parameters.artifacts.download, 'true'), ne(parameters.artifacts.download, '')) }}: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: current + artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} + targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} + itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} + - ${{ each step in parameters.steps }}: - ${{ step }} @@ -166,20 +130,60 @@ jobs: env: TeamName: $(_TeamName) - - ${{ if eq(parameters.enableTelemetry, 'true') }}: - # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions - - task: sendEndTelemetry@0 - displayName: 'Send Helix End Telemetry' - continueOnError: ${{ parameters.continueOnError }} - condition: always() - - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if or(eq(parameters.artifacts.publish.artifacts, 'true'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - task: CopyFiles@2 + displayName: Gather binaries for publish to artifacts + inputs: + SourceFolder: 'artifacts/bin' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' + - task: CopyFiles@2 + displayName: Gather packages for publish to artifacts + inputs: + SourceFolder: 'artifacts/packages' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' + - task: PublishBuildArtifacts@1 + displayName: Publish pipeline artifacts + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + PublishLocation: Container + ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + continueOnError: true + condition: always() + - ${{ if or(eq(parameters.artifacts.publish.logs, 'true'), ne(parameters.artifacts.publish.logs, '')) }}: + - publish: artifacts/log + artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} + displayName: Publish logs + continueOnError: true + condition: always() + - ${{ if or(eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - ${{ if and(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: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/AssetManifest' + TargetFolder: '$(Build.ArtifactStagingDirectory)/AssetManifests' + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) + + - task: PublishBuildArtifacts@1 + displayName: Push Asset Manifests + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/AssetManifests' + PublishLocation: Container + ArtifactName: AssetManifests + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) + + - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - task: PublishBuildArtifacts@1 displayName: Publish Logs inputs: PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' PublishLocation: Container - ArtifactName: $(Agent.Os)_$(Agent.JobName) + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} continueOnError: true condition: always() diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 6a2f98c036..c08225a9a9 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,19 +1,10 @@ parameters: - # Optional: 'true' if failures in job.yml job should not fail the job + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md continueOnError: false - # Optional: Enable installing Microbuild plugin - # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix - # _TeamName - the name of your team - # _SignType - 'test' or 'real' - enableMicrobuild: false - # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false - # Optional: Enable publishing to the build asset registry - enablePublishBuildAssets: false - # Optional: Enable publishing using release pipelines enablePublishUsingPipelines: false @@ -23,19 +14,9 @@ parameters: # Optional: Include toolset dependencies in the generated graph files includeToolset: false - # Optional: Include PublishTestResults task - enablePublishTestResults: false - - # Optional: enable sending telemetry - # if enabled then the 'helixRepo' parameter should also be specified - enableTelemetry: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job jobs: [] - # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') - helixRepo: '' - # Optional: Override automatically derived dependsOn value for "publish build assets" job publishBuildAssetsDependsOn: '' @@ -62,29 +43,30 @@ jobs: name: ${{ job.job }} -- ${{ if and(eq(parameters.enablePublishBuildAssets, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - pool: - vmImage: vs2017-win2016 - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - -- ${{ if and(eq(parameters.graphFileGeneration.enabled, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - template: ../job/generate-graph-files.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} - dependsOn: - - Asset_Registry_Publish - pool: - vmImage: vs2017-win2016 +- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - template: ../job/publish-build-assets.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + pool: + vmImage: vs2017-win2016 + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + + - ${{ if eq(parameters.graphFileGeneration.enabled, true) }}: + - template: ../job/generate-graph-files.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} + dependsOn: + - Asset_Registry_Publish + pool: + vmImage: vs2017-win2016 diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml index 68fdec0290..3a8755fbbb 100644 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml @@ -1,4 +1,7 @@ parameters: + artifactsPublishingAdditionalParameters: '' + dependsOn: + - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -10,14 +13,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: validate + dependsOn: ${{ parameters.dependsOn }} variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: + - job: publish_symbols displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -38,6 +41,18 @@ stages: artifactName: 'PDBArtifacts' continueOnError: true + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@0 + displayName: 'Authenticate to AzDO Feeds' + + - task: PowerShell@2 + displayName: Enable cross-org publishing + inputs: + filePath: eng\common\enable-cross-org-publishing.ps1 + arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) + - task: PowerShell@2 displayName: Publish inputs: @@ -49,14 +64,18 @@ stages: /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' /p:Configuration=Release + /p:PublishToMSDL=false ${{ parameters.symbolPublishingAdditionalParameters }} + - template: ../../steps/publish-logs.yml + parameters: + StageLabel: '${{ parameters.stageName }}' + JobLabel: 'SymbolPublishing' + - 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 @@ -70,13 +89,14 @@ stages: inputs: buildType: current artifactName: PackageArtifacts + continueOnError: true - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: buildType: current artifactName: BlobArtifacts - + continueOnError: true - task: DownloadBuildArtifacts@0 displayName: Download Asset Manifests inputs: @@ -120,7 +140,6 @@ stages: /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey) /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) - /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -130,6 +149,11 @@ stages: /p:PublishToMSDL=false ${{ parameters.artifactsPublishingAdditionalParameters }} + - template: ../../steps/publish-logs.yml + parameters: + StageLabel: '${{ parameters.stageName }}' + JobLabel: 'AssetsPublishing' + - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml index c4bc1897d8..3f572f8b12 100644 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ b/eng/common/templates/post-build/channels/generic-public-channel.yml @@ -1,5 +1,7 @@ parameters: artifactsPublishingAdditionalParameters: '' + dependsOn: + - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -11,14 +13,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: validate + dependsOn: ${{ parameters.dependsOn }} variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: + - job: publish_symbols displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -64,6 +66,11 @@ stages: /p:Configuration=Release ${{ parameters.symbolPublishingAdditionalParameters }} + - template: ../../steps/publish-logs.yml + parameters: + StageLabel: '${{ parameters.stageName }}' + JobLabel: 'SymbolPublishing' + - job: publish_assets displayName: Publish Assets dependsOn: setupMaestroVars @@ -134,7 +141,6 @@ stages: /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -143,6 +149,11 @@ stages: /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' ${{ parameters.artifactsPublishingAdditionalParameters }} + - template: ../../steps/publish-logs.yml + parameters: + StageLabel: '${{ parameters.stageName }}' + JobLabel: 'AssetsPublishing' + - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 216d043e4e..9505cf170f 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,7 +4,7 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - + # .NET Core 3.1 Dev - name: PublicDevRelease_31_Channel_Id value: 128 @@ -49,6 +49,10 @@ variables: - name: NetCore_31_Blazor_Features_Channel_Id value: 531 + # .NET Core Experimental + - name: NetCore_Experimental_Channel_Id + value: 562 + # Whether the build is internal or not - name: IsInternalBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 9921743bcd..8a8d84f202 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -17,11 +17,14 @@ parameters: signingValidationAdditionalParameters: '' # Which stages should finish execution before post-build stages start - dependsOn: [build] + validateDependsOn: + - build + publishDependsOn: + - Validate stages: -- stage: validate - dependsOn: ${{ parameters.dependsOn }} +- stage: Validate + dependsOn: ${{ parameters.validateDependsOn }} displayName: Validate jobs: - ${{ if eq(parameters.enableNugetValidation, 'true') }}: @@ -46,6 +49,8 @@ stages: - ${{ if eq(parameters.enableSigningValidation, 'true') }}: - job: displayName: Signing Validation + variables: + - template: common-variables.yml pool: vmImage: 'windows-2019' steps: @@ -55,6 +60,18 @@ stages: buildType: current artifactName: PackageArtifacts + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@0 + displayName: 'Authenticate to AzDO Feeds' + + - task: PowerShell@2 + displayName: Enable cross-org publishing + inputs: + filePath: eng\common\enable-cross-org-publishing.ps1 + arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) + - task: PowerShell@2 displayName: Validate inputs: @@ -62,9 +79,13 @@ stages: arguments: -task SigningValidation -restore -msbuildEngine dotnet /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - /p:Configuration=Release ${{ parameters.signingValidationAdditionalParameters }} + - template: ../steps/publish-logs.yml + parameters: + StageLabel: 'Validation' + JobLabel: 'Signing' + - ${{ if eq(parameters.enableSourceLinkValidation, 'true') }}: - job: displayName: SourceLink Validation @@ -100,6 +121,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NetCore_Dev5_Publish' @@ -112,18 +134,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Dev31_Publish' - channelName: '.NET Core 3.1 Dev' - channelId: 128 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Latest_Publish' @@ -136,6 +147,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Validation_Publish' @@ -148,90 +160,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_3_Tools_Validation_Publish' - channelName: '.NET 3 Tools - Validation' - channelId: 390 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_3_Tools_Publish' - channelName: '.NET 3 Tools' - channelId: 344 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Release30_Publish' - channelName: '.NET Core 3.0 Release' - channelId: 19 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Release31_Publish' - channelName: '.NET Core 3.1 Release' - channelId: 129 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Blazor31_Features_Publish' - channelName: '.NET Core 3.1 Blazor Features' - channelId: 531 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_30_Internal_Servicing_Publishing' - channelName: '.NET Core 3.0 Internal Servicing' - channelId: 184 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_31_Internal_Servicing_Publishing' - channelName: '.NET Core 3.1 Internal Servicing' - channelId: 550 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'General_Testing_Publish' @@ -244,6 +173,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Dev_Publishing' @@ -256,6 +186,7 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Release_Publishing' @@ -265,74 +196,28 @@ stages: shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_301xx_Publishing' - channelName: '.NET Core SDK 3.0.1xx' - channelId: 556 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_301xx_Internal_Publishing' - channelName: '.NET Core SDK 3.0.1xx Internal' - channelId: 555 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' + stageName: 'NET_Internal_Tooling_Publishing' + channelName: '.NET Internal Tooling' + channelId: 551 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json' - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_311xx_Publishing' - channelName: '.NET Core SDK 3.1.1xx' - channelId: 560 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_311xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.1xx Internal' - channelId: 559 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_312xx_Publishing' - channelName: '.NET Core SDK 3.1.2xx' - channelId: 558 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - -- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_312xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.2xx Internal' - channelId: 557 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' \ No newline at end of file + stageName: 'NETCore_Experimental_Publishing' + channelName: '.NET Core Experimental' + channelId: 562 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json' diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 56242b068e..716b53f740 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -4,6 +4,8 @@ jobs: pool: vmImage: 'windows-2019' steps: + - checkout: none + - task: DownloadBuildArtifacts@0 displayName: Download Release Configs inputs: @@ -14,5 +16,25 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 - arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' + targetType: inline + script: | + try { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + + $BarId = $Content | Select -Index 0 + + $Channels = "" + $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } + + $IsStableBuild = $Content | Select -Index 2 + + Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" + Write-Host "##vso[task.setvariable variable=InitialChannels;isOutput=true]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml new file mode 100644 index 0000000000..f91751fe78 --- /dev/null +++ b/eng/common/templates/steps/publish-logs.yml @@ -0,0 +1,23 @@ +parameters: + StageLabel: '' + JobLabel: '' + +steps: +- task: Powershell@2 + displayName: Prepare Binlogs to Upload + inputs: + targetType: inline + script: | + New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + continueOnError: true + condition: always() + +- task: PublishBuildArtifacts@1 + displayName: Publish Logs + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' + PublishLocation: Container + ArtifactName: PostBuildLogs + continueOnError: true + condition: always() diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 05df886f55..30becf01ea 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -23,6 +23,7 @@ parameters: 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." IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set + HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting int) Creator: '' # optional -- if the build is external, use this to specify who is sending the job DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() @@ -55,6 +56,7 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) @@ -85,6 +87,7 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 895ab93e4b..d3a432878e 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -5,7 +5,7 @@ [bool]$ci = if (Test-Path variable:ci) { $ci } else { $false } # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names. -[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { "Debug" } +[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { 'Debug' } # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build. # Binary log must be enabled on CI. @@ -24,7 +24,7 @@ [bool]$restore = if (Test-Path variable:restore) { $restore } else { $true } # Adjusts msbuild verbosity level. -[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { "minimal" } +[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { 'minimal' } # Set to true to reuse msbuild nodes. Recommended to not reuse on CI. [bool]$nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { !$ci } @@ -41,21 +41,23 @@ # 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" } +[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 } # An array of names of processes to stop on script exit if prepareMachine is true. -$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @("msbuild", "dotnet", "vbcscompiler") } +$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @('msbuild', 'dotnet', 'vbcscompiler') } + +$disableConfigureToolsetImport = if (Test-Path variable:disableConfigureToolsetImport) { $disableConfigureToolsetImport } else { $null } set-strictmode -version 2.0 -$ErrorActionPreference = "Stop" +$ErrorActionPreference = 'Stop' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Create-Directory([string[]] $path) { if (!(Test-Path $path)) { - New-Item -path $path -force -itemType "Directory" | Out-Null + New-Item -path $path -force -itemType 'Directory' | Out-Null } } @@ -122,7 +124,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Find the first path on %PATH% that contains the dotnet.exe if ($useInstalledDotNetCli -and (-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -eq $null)) { - $dotnetCmd = Get-Command "dotnet.exe" -ErrorAction SilentlyContinue + $dotnetCmd = Get-Command 'dotnet.exe' -ErrorAction SilentlyContinue if ($dotnetCmd -ne $null) { $env:DOTNET_INSTALL_DIR = Split-Path $dotnetCmd.Path -Parent } @@ -135,13 +137,13 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { if ((-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -ne $null) -and (Test-Path(Join-Path $env:DOTNET_INSTALL_DIR "sdk\$dotnetSdkVersion"))) { $dotnetRoot = $env:DOTNET_INSTALL_DIR } else { - $dotnetRoot = Join-Path $RepoRoot ".dotnet" + $dotnetRoot = Join-Path $RepoRoot '.dotnet' if (-not (Test-Path(Join-Path $dotnetRoot "sdk\$dotnetSdkVersion"))) { if ($install) { InstallDotNetSdk $dotnetRoot $dotnetSdkVersion } else { - Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" ExitWithExitCode 1 } } @@ -175,15 +177,6 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot - # Work around issues with Azure Artifacts credential provider - # https://github.com/dotnet/arcade/issues/3932 - if ($ci) { - $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 - $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' - } - Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' @@ -191,7 +184,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { } function GetDotNetInstallScript([string] $dotnetRoot) { - $installScript = Join-Path $dotnetRoot "dotnet-install.ps1" + $installScript = Join-Path $dotnetRoot 'dotnet-install.ps1' if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit @@ -201,11 +194,18 @@ function GetDotNetInstallScript([string] $dotnetRoot) { return $installScript } -function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = "") { +function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = '') { InstallDotNet $dotnetRoot $version $architecture } -function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { +function InstallDotNet([string] $dotnetRoot, + [string] $version, + [string] $architecture = '', + [string] $runtime = '', + [bool] $skipNonVersionedFiles = $false, + [string] $runtimeSourceFeed = '', + [string] $runtimeSourceFeedKey = '') { + $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ Version = $version @@ -262,16 +262,16 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { "15.9" } + $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { '15.9' } $vsMinVersion = [Version]::new($vsMinVersionStr) # Try msbuild command available in the environment. if ($env:VSINSTALLDIR -ne $null) { - $msbuildCmd = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue + $msbuildCmd = Get-Command 'msbuild.exe' -ErrorAction SilentlyContinue if ($msbuildCmd -ne $null) { # Workaround for https://github.com/dotnet/roslyn/issues/35793 # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+ - $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0]) + $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split([char[]]@('-', '+'))[0]) if ($msbuildVersion -ge $vsMinVersion) { return $global:_MSBuildExe = $msbuildCmd.Path @@ -291,7 +291,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = InitializeVisualStudioEnvironmentVariables $vsInstallDir $vsMajorVersion } else { - if (Get-Member -InputObject $GlobalJson.tools -Name "xcopy-msbuild") { + if (Get-Member -InputObject $GlobalJson.tools -Name 'xcopy-msbuild') { $xcopyMSBuildVersion = $GlobalJson.tools.'xcopy-msbuild' $vsMajorVersion = $xcopyMSBuildVersion.Split('.')[0] } else { @@ -304,7 +304,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install } if ($vsInstallDir -eq $null) { - throw "Unable to find Visual Studio that has required version and components installed" + throw 'Unable to find Visual Studio that has required version and components installed' } } @@ -328,7 +328,7 @@ function InstallXCopyMSBuild([string]$packageVersion) { } function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { - $packageName = "RoslynTools.MSBuild" + $packageName = 'RoslynTools.MSBuild' $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion" $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" @@ -344,7 +344,7 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { Unzip $packagePath $packageDir } - return Join-Path $packageDir "tools" + return Join-Path $packageDir 'tools' } # @@ -361,32 +361,32 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { # or $null if no instance meeting the requirements is found on the machine. # function LocateVisualStudio([object]$vsRequirements = $null){ - if (Get-Member -InputObject $GlobalJson.tools -Name "vswhere") { + if (Get-Member -InputObject $GlobalJson.tools -Name 'vswhere') { $vswhereVersion = $GlobalJson.tools.vswhere } else { - $vswhereVersion = "2.5.2" + $vswhereVersion = '2.5.2' } $vsWhereDir = Join-Path $ToolsDir "vswhere\$vswhereVersion" - $vsWhereExe = Join-Path $vsWhereDir "vswhere.exe" + $vsWhereExe = Join-Path $vsWhereDir 'vswhere.exe' if (!(Test-Path $vsWhereExe)) { Create-Directory $vsWhereDir - Write-Host "Downloading vswhere" + Write-Host 'Downloading vswhere' Invoke-WebRequest "https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $args = @("-latest", "-prerelease", "-format", "json", "-requires", "Microsoft.Component.MSBuild", "-products", "*") + $args = @('-latest', '-prerelease', '-format', 'json', '-requires', 'Microsoft.Component.MSBuild', '-products', '*') - if (Get-Member -InputObject $vsRequirements -Name "version") { - $args += "-version" + if (Get-Member -InputObject $vsRequirements -Name 'version') { + $args += '-version' $args += $vsRequirements.version } - if (Get-Member -InputObject $vsRequirements -Name "components") { + if (Get-Member -InputObject $vsRequirements -Name 'components') { foreach ($component in $vsRequirements.components) { - $args += "-requires" + $args += '-requires' $args += $component } } @@ -412,27 +412,27 @@ function InitializeBuildTool() { # Initialize dotnet cli if listed in 'tools' $dotnetRoot = $null - if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { + if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { $dotnetRoot = InitializeDotNetCli -install:$restore } - if ($msbuildEngine -eq "dotnet") { + if ($msbuildEngine -eq 'dotnet') { if (!$dotnetRoot) { - Write-PipelineTelemetryError -Category "InitializeToolset" -Message "/global.json must specify 'tools.dotnet'." + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "/global.json must specify 'tools.dotnet'." ExitWithExitCode 1 } - $buildTool = @{ Path = Join-Path $dotnetRoot "dotnet.exe"; Command = "msbuild"; Tool = "dotnet"; Framework = "netcoreapp2.1" } + $buildTool = @{ Path = Join-Path $dotnetRoot 'dotnet.exe'; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'netcoreapp2.1' } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore } catch { - Write-PipelineTelemetryError -Category "InitializeToolset" -Message $_ + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ ExitWithExitCode 1 } $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "net472" } } else { - Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." ExitWithExitCode 1 } @@ -441,15 +441,15 @@ function InitializeBuildTool() { function GetDefaultMSBuildEngine() { # Presence of tools.vs indicates the repo needs to build using VS msbuild on Windows. - if (Get-Member -InputObject $GlobalJson.tools -Name "vs") { - return "vs" + if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { + return 'vs' } - if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { - return "dotnet" + if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { + return 'dotnet' } - Write-PipelineTelemetryError -Category "InitializeToolset" -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." ExitWithExitCode 1 } @@ -458,9 +458,9 @@ function GetNuGetPackageCachePath() { # Use local cache on CI to ensure deterministic build, # use global cache in dev builds to avoid cost of downloading packages. if ($useGlobalNuGetCache) { - $env:NUGET_PACKAGES = Join-Path $env:UserProfile ".nuget\packages" + $env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages' } else { - $env:NUGET_PACKAGES = Join-Path $RepoRoot ".packages" + $env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages' } } @@ -473,7 +473,7 @@ function GetSdkTaskProject([string]$taskName) { } function InitializeNativeTools() { - if (Get-Member -InputObject $GlobalJson -Name "native-tools") { + if (-Not (Test-Path variable:DisableNativeToolsetInstalls) -And (Get-Member -InputObject $GlobalJson -Name "native-tools")) { $nativeArgs= @{} if ($ci) { $nativeArgs = @{ @@ -502,14 +502,14 @@ function InitializeToolset() { } if (-not $restore) { - Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Toolset version $toolsetVersion has not been restored." + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Toolset version $toolsetVersion has not been restored." ExitWithExitCode 1 } $buildTool = InitializeBuildTool - $proj = Join-Path $ToolsetDir "restore.proj" - $bl = if ($binaryLog) { "/bl:" + (Join-Path $LogDir "ToolsetRestore.binlog") } else { "" } + $proj = Join-Path $ToolsetDir 'restore.proj' + $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'ToolsetRestore.binlog') } else { '' } '' | Set-Content $proj @@ -531,7 +531,7 @@ function ExitWithExitCode([int] $exitCode) { } function Stop-Processes() { - Write-Host "Killing running build processes..." + Write-Host 'Killing running build processes...' foreach ($processName in $processesToStopOnExit) { Get-Process -Name $processName -ErrorAction SilentlyContinue | Stop-Process } @@ -548,13 +548,18 @@ function MSBuild() { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 - if ($ci -and $buildTool.Tool -eq "dotnet") { + if ($ci -and $buildTool.Tool -eq 'dotnet') { dotnet nuget locals http-cache -c + + $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 + $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } $toolsetBuildProject = InitializeToolset $path = Split-Path -parent $toolsetBuildProject - $path = Join-Path $path (Join-Path $buildTool.Framework "Microsoft.DotNet.Arcade.Sdk.dll") + $path = Join-Path $path (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll') $args += "/logger:$path" } @@ -569,12 +574,12 @@ function MSBuild() { function MSBuild-Core() { if ($ci) { if (!$binaryLog) { - Write-PipelineTaskError -Message "Binary log must be enabled in CI build." + Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build.' ExitWithExitCode 1 } if ($nodeReuse) { - Write-PipelineTaskError -Message "Node reuse must be disabled in CI build." + Write-PipelineTelemetryError -Category 'Build' -Message 'Node reuse must be disabled in CI build.' ExitWithExitCode 1 } } @@ -584,10 +589,10 @@ function MSBuild-Core() { $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci" if ($warnAsError) { - $cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true" + $cmdArgs += ' /warnaserror /p:TreatWarningsAsErrors=true' } else { - $cmdArgs += " /p:TreatWarningsAsErrors=false" + $cmdArgs += ' /p:TreatWarningsAsErrors=false' } foreach ($arg in $args) { @@ -599,7 +604,7 @@ function MSBuild-Core() { $exitCode = Exec-Process $buildTool.Path $cmdArgs if ($exitCode -ne 0) { - Write-PipelineTaskError -Message "Build failed." + Write-PipelineTelemetryError Category 'Build' -Message 'Build failed.' $buildLog = GetMSBuildBinaryLogCommandLineArgument $args if ($buildLog -ne $null) { @@ -614,12 +619,12 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { foreach ($argument in $arguments) { if ($argument -ne $null) { $arg = $argument.Trim() - if ($arg.StartsWith("/bl:", "OrdinalIgnoreCase")) { - return $arg.Substring("/bl:".Length) + if ($arg.StartsWith('/bl:', "OrdinalIgnoreCase")) { + return $arg.Substring('/bl:'.Length) } - if ($arg.StartsWith("/binaryLogger:", "OrdinalIgnoreCase")) { - return $arg.Substring("/binaryLogger:".Length) + if ($arg.StartsWith('/binaryLogger:', 'OrdinalIgnoreCase')) { + return $arg.Substring('/binaryLogger:'.Length) } } } @@ -629,14 +634,14 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { . $PSScriptRoot\pipeline-logging-functions.ps1 -$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") -$EngRoot = Resolve-Path (Join-Path $PSScriptRoot "..") -$ArtifactsDir = Join-Path $RepoRoot "artifacts" -$ToolsetDir = Join-Path $ArtifactsDir "toolset" -$ToolsDir = Join-Path $RepoRoot ".tools" -$LogDir = Join-Path (Join-Path $ArtifactsDir "log") $configuration -$TempDir = Join-Path (Join-Path $ArtifactsDir "tmp") $configuration -$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot "global.json") | ConvertFrom-Json +$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..') +$EngRoot = Resolve-Path (Join-Path $PSScriptRoot '..') +$ArtifactsDir = Join-Path $RepoRoot 'artifacts' +$ToolsetDir = Join-Path $ArtifactsDir 'toolset' +$ToolsDir = Join-Path $RepoRoot '.tools' +$LogDir = Join-Path (Join-Path $ArtifactsDir 'log') $configuration +$TempDir = Join-Path (Join-Path $ArtifactsDir 'tmp') $configuration +$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot 'global.json') | ConvertFrom-Json # true if global.json contains a "runtimes" section $globalJsonHasRuntimes = if ($GlobalJson.tools.PSObject.Properties.Name -Match 'runtimes') { $true } else { $false } @@ -649,3 +654,18 @@ Write-PipelineSetVariable -Name 'Artifacts.Toolset' -Value $ToolsetDir Write-PipelineSetVariable -Name 'Artifacts.Log' -Value $LogDir Write-PipelineSetVariable -Name 'TEMP' -Value $TempDir Write-PipelineSetVariable -Name 'TMP' -Value $TempDir + +# Import custom tools configuration, if present in the repo. +# Note: Import in global scope so that the script set top-level variables without qualification. +if (!$disableConfigureToolsetImport) { + $configureToolsetScript = Join-Path $EngRoot 'configure-toolset.ps1' + if (Test-Path $configureToolsetScript) { + . $configureToolsetScript + if ((Test-Path variable:failOnConfigureToolsetError) -And $failOnConfigureToolsetError) { + if ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) { + Write-PipelineTelemetryError -Category 'Build' -Message 'configure-toolset.ps1 returned a non-zero exit code' + ExitWithExitCode $LastExitCode + } + } + } +} diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 94965a8fd2..e071af4ee4 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -81,7 +81,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'Build' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -152,15 +152,6 @@ function InitializeDotNetCli { # build steps from using anything other than what we've downloaded. Write-PipelinePrependPath -path "$dotnet_root" - # Work around issues with Azure Artifacts credential provider - # https://github.com/dotnet/arcade/issues/3932 - if [[ "$ci" == true ]]; then - export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 - export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 - Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" - Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" - fi - Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" @@ -283,6 +274,9 @@ function GetNuGetPackageCachePath { } function InitializeNativeTools() { + if [[ -n "${DisableNativeToolsetInstalls:-}" ]]; then + return + fi if grep -Fq "native-tools" $global_json_file then local nativeArgs="" @@ -332,7 +326,7 @@ function InitializeToolset { local toolset_build_proj=`cat "$toolset_location_file"` if [[ ! -a "$toolset_build_proj" ]]; then - Write-PipelineTelemetryError -category 'InitializeToolset' "Invalid toolset path: $toolset_build_proj" + Write-PipelineTelemetryError -category 'Build' "Invalid toolset path: $toolset_build_proj" ExitWithExitCode 3 fi @@ -363,7 +357,12 @@ function MSBuild { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 if [[ "$ci" == true ]]; then - dotnet nuget locals http-cache -c + "$_InitializeBuildTool" nuget locals http-cache -c + + export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 + export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 + Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" + Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" fi local toolset_dir="${_InitializeToolset%/*}" @@ -377,12 +376,12 @@ function MSBuild { function MSBuild-Core { if [[ "$ci" == true ]]; then if [[ "$binary_log" != true ]]; then - Write-PipelineTaskError "Binary log must be enabled in CI build." + Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build." ExitWithExitCode 1 fi if [[ "$node_reuse" == true ]]; then - Write-PipelineTaskError "Node reuse must be disabled in CI build." + Write-PipelineTelemetryError -category 'Build' "Node reuse must be disabled in CI build." ExitWithExitCode 1 fi fi @@ -396,7 +395,7 @@ function MSBuild-Core { "$_InitializeBuildTool" "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" || { local exit_code=$? - Write-PipelineTaskError "Build failed (exit code '$exit_code')." + Write-PipelineTelemetryError -category 'Build' "Build failed (exit code '$exit_code')." ExitWithExitCode $exit_code } } @@ -437,3 +436,18 @@ 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" + +# Import custom tools configuration, if present in the repo. +if [ -z "${disable_configure_toolset_import:-}" ]; then + configure_toolset_script="$eng_root/configure-toolset.sh" + if [[ -a "$configure_toolset_script" ]]; then + . "$configure_toolset_script" + fi +fi + +# TODO: https://github.com/dotnet/arcade/issues/1468 +# Temporary workaround to avoid breaking change. +# Remove once repos are updated. +if [[ -n "${useInstalledDotNetCli:-}" ]]; then + use_installed_dotnet_cli="$useInstalledDotNetCli" +fi diff --git a/global.json b/global.json index 186855dd2a..2f1050a189 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19631.1", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20052.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 032b1090540d1c9de0f4cbf89a3195f935e1b1e3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sat, 4 Jan 2020 13:24:44 +0000 Subject: [PATCH 009/101] Update dependencies from https://github.com/dotnet/arcade build 20200103.2 - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20053.2 --- eng/Version.Details.xml | 4 +-- eng/common/post-build/setup-maestro-vars.ps1 | 26 -------------------- global.json | 2 +- 3 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 eng/common/post-build/setup-maestro-vars.ps1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d87b36dd3a..b8e9e82820 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 98cc270f5e08096729fc7d54ffafa9e3c6576316 + b49ab5e13eb7c5678d6720ef041dc675cf8e9307 diff --git a/eng/common/post-build/setup-maestro-vars.ps1 b/eng/common/post-build/setup-maestro-vars.ps1 deleted file mode 100644 index d7f64dc63c..0000000000 --- a/eng/common/post-build/setup-maestro-vars.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -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/global.json b/global.json index 2f1050a189..ffdfe37838 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20052.1", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20053.2", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From eafb6a177f25a5806c7632d2c6ff9e9ed7d1d5bf Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sun, 5 Jan 2020 13:27:06 +0000 Subject: [PATCH 010/101] Update dependencies from https://github.com/dotnet/arcade build 20200104.1 - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20054.1 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b8e9e82820..56e60061a1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - b49ab5e13eb7c5678d6720ef041dc675cf8e9307 + 96ab522b32ff4d0f7bfc18074fd5ae3673c59d0a diff --git a/global.json b/global.json index ffdfe37838..01306251ae 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20053.2", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20054.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 111fae7f0eeeff8d56dec4264b2de6d1be3e0699 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2020 20:37:16 +0000 Subject: [PATCH 011/101] Update dependencies from https://github.com/dotnet/arcade build 20200105.1 (#8102) - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20055.1 --- eng/Version.Details.xml | 4 ++-- eng/common/dotnet-install.sh | 10 ++++++++++ global.json | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 56e60061a1..9fd9fffc66 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 96ab522b32ff4d0f7bfc18074fd5ae3673c59d0a + 111d78c79ac38f596688af152779d7a39e4bf973 diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 801297b599..50bc5e475c 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -16,6 +16,8 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" version='Latest' architecture='' runtime='dotnet' +runtimeSourceFeed='' +runtimeSourceFeedKey='' while [[ $# > 0 ]]; do opt="$(echo "$1" | awk '{print tolower($0)}')" case "$opt" in @@ -31,6 +33,14 @@ while [[ $# > 0 ]]; do shift runtime="$1" ;; + -runtimesourcefeed) + shift + runtimeSourceFeed="$1" + ;; + -runtimesourcefeedkey) + shift + runtimeSourceFeedKey="$1" + ;; *) Write-PipelineTelemetryError -Category 'Build' -Message "Invalid argument: $1" exit 1 diff --git a/global.json b/global.json index 01306251ae..875313b65d 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20054.1", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20055.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From a78da067384798b1bc1ae6fa0a5987d519cb1bca Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 7 Jan 2020 13:27:25 +0000 Subject: [PATCH 012/101] Update dependencies from https://github.com/dotnet/arcade build 20200106.6 - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20056.6 --- eng/Version.Details.xml | 4 +- .../channels/generic-internal-channel.yml | 38 +++++++----------- .../channels/generic-public-channel.yml | 39 +++++++------------ global.json | 2 +- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9fd9fffc66..cfdceb169f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 111d78c79ac38f596688af152779d7a39e4bf973 + 5cbca575e9002cc2d9814c3471d38882df2fcc8e diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml index 3a8755fbbb..700211049b 100644 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml @@ -30,16 +30,15 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' + displayName: Download Build Assets continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts inputs: - artifactName: 'PDBArtifacts' - continueOnError: true + buildType: 'current' + downloadType: 'specific' + itemPattern: | + PDBArtifacts/** + BlobArtifacts/** + downloadPath: '$(Build.ArtifactStagingDirectory)' # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here @@ -85,23 +84,16 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts + displayName: Download Build Assets continueOnError: true - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests inputs: - buildType: current - artifactName: AssetManifests + buildType: 'current' + downloadType: 'specific' + itemPattern: | + PackageArtifacts/** + BlobArtifacts/** + AssetManifests/** + downloadPath: '$(Build.ArtifactStagingDirectory)' - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml index 3f572f8b12..fbb5a19b67 100644 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ b/eng/common/templates/post-build/channels/generic-public-channel.yml @@ -30,16 +30,15 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' + displayName: Download Build Assets continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts inputs: - artifactName: 'PDBArtifacts' - continueOnError: true + buildType: 'current' + downloadType: 'specific' + itemPattern: | + PDBArtifacts/** + BlobArtifacts/** + downloadPath: '$(Build.ArtifactStagingDirectory)' # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here @@ -84,24 +83,16 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts + displayName: Download Build Assets continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests inputs: - buildType: current - artifactName: AssetManifests + buildType: 'current' + downloadType: 'specific' + itemPattern: | + PackageArtifacts/** + BlobArtifacts/** + AssetManifests/** + downloadPath: '$(Build.ArtifactStagingDirectory)' - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' diff --git a/global.json b/global.json index 875313b65d..6fe6bcd1ce 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20055.1", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20056.6", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 19c57738183eb8e0e4bf5ad8282b17856e992d60 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 7 Jan 2020 23:16:01 -0800 Subject: [PATCH 013/101] Allow --langversion:preview to disable ExperimentalAttribut warning. (#8042) * Merge issues * More attributes * Experimental Attribute * literally the message * .fsi and [] don't mix with lkg compiler. --- src/fsharp/AttributeChecking.fs | 35 ++++--- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 2 +- src/fsharp/FSharp.Core/prim-types.fs | 92 ++++++++++++++----- src/fsharp/FSharp.Core/prim-types.fsi | 37 ++++++-- src/fsharp/LanguageFeatures.fs | 10 +- src/fsharp/LanguageFeatures.fsi | 5 +- .../SurfaceArea.coreclr.fs | 8 +- .../SurfaceArea.net40.fs | 10 +- tests/fsharp/Compiler/CompilerAssert.fs | 14 +++ .../Warnings/ExperimentalAttributeTests.fs | 32 +++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + tests/fsharp/tests.fs | 2 +- 12 files changed, 197 insertions(+), 51 deletions(-) create mode 100644 tests/fsharp/Compiler/Warnings/ExperimentalAttributeTests.fs diff --git a/src/fsharp/AttributeChecking.fs b/src/fsharp/AttributeChecking.fs index 07ac05faa8..fb19937c53 100644 --- a/src/fsharp/AttributeChecking.fs +++ b/src/fsharp/AttributeChecking.fs @@ -4,6 +4,7 @@ /// on items from name resolution module internal FSharp.Compiler.AttributeChecking +open System open System.Collections.Generic open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Library @@ -246,7 +247,6 @@ let MethInfoHasAttribute g m attribSpec minfo = |> Option.isSome - /// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = let (AttribInfo(tref,_)) = g.attrib_SystemObsolete @@ -267,9 +267,16 @@ let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = /// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute', /// returning errors and warnings as data -let CheckFSharpAttributes g attribs m = - if isNil attribs then CompleteD - else +let langVersionPrefix = "--langversion:preview" +let CheckFSharpAttributes (g:TcGlobals) attribs m = + let isExperimentalAttributeDisabled (s:string) = + if g.compilingFslib then + true + else + g.langVersion.IsPreviewEnabled && (s.IndexOf(langVersionPrefix, StringComparison.OrdinalIgnoreCase) >= 0) + + if isNil attribs then CompleteD + else (match TryFindFSharpAttribute g g.attrib_SystemObsolete attribs with | Some(Attrib(_, _, [ AttribStringArg s ], _, _, _, _)) -> WarnD(ObsoleteWarning(s, m)) @@ -283,28 +290,30 @@ let CheckFSharpAttributes g attribs m = | None -> CompleteD ) ++ (fun () -> - + match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with - | Some(Attrib(_, _, [ AttribStringArg s ; AttribInt32Arg n ], namedArgs, _, _, _)) -> + | Some(Attrib(_, _, [ AttribStringArg s ; AttribInt32Arg n ], namedArgs, _, _, _)) -> let msg = UserCompilerMessage(s, n, m) let isError = match namedArgs with | ExtractAttribNamedArg "IsError" (AttribBoolArg v) -> v | _ -> false if isError && (not g.compilingFslib || n <> 1204) then ErrorD msg else WarnD msg - | _ -> CompleteD ) ++ (fun () -> - + match TryFindFSharpAttribute g g.attrib_ExperimentalAttribute attribs with - | Some(Attrib(_, _, [ AttribStringArg(s) ], _, _, _, _)) -> - WarnD(Experimental(s, m)) - | Some _ -> + | Some(Attrib(_, _, [ AttribStringArg(s) ], _, _, _, _)) -> + if isExperimentalAttributeDisabled s then + CompleteD + else + WarnD(Experimental(s, m)) + | Some _ -> WarnD(Experimental(FSComp.SR.experimentalConstruct (), m)) - | _ -> + | _ -> CompleteD - ) ++ (fun () -> + ) ++ (fun () -> match TryFindFSharpAttribute g g.attrib_UnverifiableAttribute attribs with | Some _ -> diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index ef68a28e6d..360dc74e37 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -10,7 +10,7 @@ true $(DefineConstants);FSHARP_CORE BUILDING_WITH_LKG;$(DefineConstants) - $(OtherFlags) --warnon:1182 --compiling-fslib --compiling-fslib-40 --maxerrors:20 --extraoptimizationloops:1 + $(OtherFlags) --warnon:1182 --compiling-fslib --compiling-fslib-40 --maxerrors:20 --extraoptimizationloops:1 --nowarn:57 true true diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 60d52b3a78..8f219ab78f 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -237,11 +237,17 @@ namespace Microsoft.FSharp.Core inherit System.Attribute() member x.Flags = flags + + module internal ExperimentalAttributeMessages = + [] + let RequiresPreview : string = "Experimental library feature, requires '--langversion:preview'" + [] [] type ExperimentalAttribute(message:string) = inherit System.Attribute() - member x.Message = message + + member x.Message = message [] [] @@ -379,7 +385,7 @@ namespace Microsoft.FSharp.Core let inline box (x:'T) = (# "box !0" type ('T) x : obj #) let inline not (b:bool) = (# "ceq" b false : bool #) let inline (=) (x:int) (y:int) = (# "ceq" x y : bool #) - let inline (<>) (x:int) (y:int) = not(# "ceq" x y : bool #) + let inline (<>) (x:int) (y:int) = not(# "ceq" x y : bool #) let inline (<=) (x:int) (y:int) = not(# "cgt" x y : bool #) let inline (>=) (x:int) (y:int) = not(# "clt" x y : bool #) let inline (>=.) (x:int64) (y:int64) = not(# "clt" x y : bool #) @@ -3189,6 +3195,7 @@ namespace Microsoft.FSharp.Collections let start = if i < 0 then 0 else i PrivateListHelpers.sliceTake (j - start) (PrivateListHelpers.sliceSkip start l) + [] member l.GetReverseIndex(_: int, offset: int) = l.Length - offset - 1 interface IEnumerable<'T> with @@ -3224,8 +3231,6 @@ namespace Microsoft.FSharp.Core open Microsoft.FSharp.Core.BasicInlinedOperations open Microsoft.FSharp.Collections - - [] module Operators = @@ -5007,10 +5012,13 @@ namespace Microsoft.FSharp.Core dst + [] let inline GetArraySlice3DFixedSingle1 (source: _[,,]) index1 start2 finish2 start3 finish3 = GetArraySlice3DFixedSingle source start2 finish2 start3 finish3 index1 1 2 + [] let inline GetArraySlice3DFixedSingle2 (source: _[,,]) start1 finish1 index2 start3 finish3 = GetArraySlice3DFixedSingle source start1 finish1 start3 finish3 index2 0 2 + [] let inline GetArraySlice3DFixedSingle3 (source: _[,,]) start1 finish1 start2 finish2 index3 = GetArraySlice3DFixedSingle source start1 finish1 start2 finish2 index3 0 1 let inline GetArraySlice3DFixedDouble (source: _[,,]) start finish index1 index2 nonFixedDim = @@ -5028,15 +5036,18 @@ namespace Microsoft.FSharp.Core SetArray dst j (getArrayElem j) dst + [] let inline GetArraySlice3DFixedDouble1 (source: _[,,]) index1 index2 start3 finish3 = GetArraySlice3DFixedDouble source start3 finish3 index1 index2 2 + [] let inline GetArraySlice3DFixedDouble2 (source: _[,,]) index1 start2 finish2 index3 = GetArraySlice3DFixedDouble source start2 finish2 index1 index3 1 + [] let inline GetArraySlice3DFixedDouble3 (source: _[,,]) start1 finish1 index2 index3 = GetArraySlice3DFixedDouble source start1 finish1 index2 index3 0 - + let inline SetArraySlice3D (target: _[,,]) start1 finish1 start2 finish2 start3 finish3 (source:_[,,]) = let bound1 = target.GetLowerBound(0) let bound2 = target.GetLowerBound(1) @@ -5067,12 +5078,15 @@ namespace Microsoft.FSharp.Core for j = 0 to len2 - 1 do setArrayElem i j + [] let inline SetArraySlice3DFixedSingle1 (target: _[,,]) index start2 finish2 start3 finish3 (source: _[,]) = SetArraySlice3DFixedSingle target source index start2 finish2 start3 finish3 1 2 + [] let inline SetArraySlice3DFixedSingle2 (target: _[,,]) start1 finish1 index start3 finish3 (source: _[,]) = SetArraySlice3DFixedSingle target source index start1 finish1 start3 finish3 0 2 + [] let inline SetArraySlice3DFixedSingle3 (target: _[,,]) start1 finish1 start2 finish2 index (source: _[,]) = SetArraySlice3DFixedSingle target source index start1 finish1 start2 finish2 0 1 @@ -5089,30 +5103,33 @@ namespace Microsoft.FSharp.Core for j = 0 to len - 1 do setArrayElem j + [] let inline SetArraySlice3DFixedDouble1 (target: _[,,]) index1 index2 start3 finish3 (source: _[]) = SetArraySlice3DFixedDouble target source index1 index2 start3 finish3 2 + [] let inline SetArraySlice3DFixedDouble2 (target: _[,,]) index1 start2 finish2 index3 (source: _[]) = SetArraySlice3DFixedDouble target source index1 index3 start2 finish2 1 + [] let inline SetArraySlice3DFixedDouble3 (target: _[,,]) start1 finish1 index2 index3 (source: _[]) = SetArraySlice3DFixedDouble target source index2 index3 start1 finish1 0 - let inline GetArraySlice4D (source: _[,,,]) start1 finish1 start2 finish2 start3 finish3 start4 finish4 = + let inline GetArraySlice4D (source: _[,,,]) start1 finish1 start2 finish2 start3 finish3 start4 finish4 = let bound1 = source.GetLowerBound(0) let bound2 = source.GetLowerBound(1) let bound3 = source.GetLowerBound(2) let bound4 = source.GetLowerBound(3) - let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray4DLength1 source) - let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray4DLength2 source) - let start3, finish3 = ComputeSlice bound3 start3 finish3 (GetArray4DLength3 source) - let start4, finish4 = ComputeSlice bound4 start4 finish4 (GetArray4DLength4 source) + let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray4DLength1 source) + let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray4DLength2 source) + let start3, finish3 = ComputeSlice bound3 start3 finish3 (GetArray4DLength3 source) + let start4, finish4 = ComputeSlice bound4 start4 finish4 (GetArray4DLength4 source) let len1 = (finish1 - start1 + 1) let len2 = (finish2 - start2 + 1) let len3 = (finish3 - start3 + 1) let len4 = (finish4 - start4 + 1) GetArray4DSub source start1 start2 start3 start4 len1 len2 len3 len4 - + let inline GetArraySlice4DFixedSingle (source: _[,,,]) start1 finish1 start2 finish2 start3 finish3 index nonFixedDim1 nonFixedDim2 nonFixedDim3 = let bound1 = source.GetLowerBound(nonFixedDim1) let bound2 = source.GetLowerBound(nonFixedDim2) @@ -5139,15 +5156,19 @@ namespace Microsoft.FSharp.Core dst + [] let inline GetArraySlice4DFixedSingle1 (source: _[,,,]) index1 start2 finish2 start3 finish3 start4 finish4 = GetArraySlice4DFixedSingle source start2 finish2 start3 finish3 start4 finish4 index1 1 2 3 + [] let inline GetArraySlice4DFixedSingle2 (source: _[,,,]) start1 finish1 index2 start3 finish3 start4 finish4 = GetArraySlice4DFixedSingle source start1 finish1 start3 finish3 start4 finish4 index2 0 2 3 + [] let inline GetArraySlice4DFixedSingle3 (source: _[,,,]) start1 finish1 start2 finish2 index3 start4 finish4 = GetArraySlice4DFixedSingle source start1 finish1 start2 finish2 start4 finish4 index3 0 1 3 + [] let inline GetArraySlice4DFixedSingle4 (source: _[,,,]) start1 finish1 start2 finish2 start3 finish3 index4 = GetArraySlice4DFixedSingle source start1 finish1 start2 finish2 start3 finish3 index4 0 1 2 @@ -5158,7 +5179,7 @@ namespace Microsoft.FSharp.Core let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray4DLength source nonFixedDim2) let len1 = (finish1 - start1 + 1) let len2 = (finish2 - start2 + 1) - + let dst = Array2DZeroCreate (max len1 0) (max len2 0) let getArrayElem = match nonFixedDim1, nonFixedDim2 with @@ -5175,21 +5196,27 @@ namespace Microsoft.FSharp.Core dst - let inline GetArraySlice4DFixedDouble1 (source: _[,,,]) index1 index2 start3 finish3 start4 finish4 = + [] + let inline GetArraySlice4DFixedDouble1 (source: _[,,,]) index1 index2 start3 finish3 start4 finish4 = GetArraySlice4DFixedDouble source start3 finish3 start4 finish4 index1 index2 2 3 - let inline GetArraySlice4DFixedDouble2 (source: _[,,,]) index1 start2 finish2 index3 start4 finish4 = + [] + let inline GetArraySlice4DFixedDouble2 (source: _[,,,]) index1 start2 finish2 index3 start4 finish4 = GetArraySlice4DFixedDouble source start2 finish2 start4 finish4 index1 index3 1 3 - let inline GetArraySlice4DFixedDouble3 (source: _[,,,]) index1 start2 finish2 start3 finish3 index4 = + [] + let inline GetArraySlice4DFixedDouble3 (source: _[,,,]) index1 start2 finish2 start3 finish3 index4 = GetArraySlice4DFixedDouble source start2 finish2 start3 finish3 index1 index4 1 2 - let inline GetArraySlice4DFixedDouble4 (source: _[,,,]) start1 finish1 index2 index3 start4 finish4 = + [] + let inline GetArraySlice4DFixedDouble4 (source: _[,,,]) start1 finish1 index2 index3 start4 finish4 = GetArraySlice4DFixedDouble source start1 finish1 start4 finish4 index2 index3 0 3 + [] let inline GetArraySlice4DFixedDouble5 (source: _[,,,]) start1 finish1 index2 start3 finish3 index4 = GetArraySlice4DFixedDouble source start1 finish1 start3 finish3 index2 index4 0 2 + [] let inline GetArraySlice4DFixedDouble6 (source: _[,,,]) start1 finish1 start2 finish2 index3 index4 = GetArraySlice4DFixedDouble source start1 finish1 start2 finish2 index3 index4 0 1 @@ -5210,15 +5237,19 @@ namespace Microsoft.FSharp.Core dst + [] let inline GetArraySlice4DFixedTriple1 (source: _[,,,]) start1 finish1 index2 index3 index4 = GetArraySlice4DFixedTriple source start1 finish1 index2 index3 index4 0 + [] let inline GetArraySlice4DFixedTriple2 (source: _[,,,]) index1 start2 finish2 index3 index4 = GetArraySlice4DFixedTriple source start2 finish2 index1 index3 index4 1 + [] let inline GetArraySlice4DFixedTriple3 (source: _[,,,]) index1 index2 start3 finish3 index4 = GetArraySlice4DFixedTriple source start3 finish3 index1 index2 index4 2 + [] let inline GetArraySlice4DFixedTriple4 (source: _[,,,]) index1 index2 index3 start4 finish4 = GetArraySlice4DFixedTriple source start4 finish4 index1 index2 index3 3 @@ -5236,7 +5267,7 @@ namespace Microsoft.FSharp.Core let finish3 = (match finish3 with None -> bound3 + GetArray4DLength3 target - 1 | Some n -> n) let finish4 = (match finish4 with None -> bound4 + GetArray4DLength4 target - 1 | Some n -> n) SetArray4DSub target start1 start2 start3 start4 (finish1 - start1 + 1) (finish2 - start2 + 1) (finish3 - start3 + 1) (finish4 - start4 + 1) source - + let inline SetArraySlice4DFixedSingle (target: _[,,,]) (source: _[,,]) index start1 finish1 start2 finish2 start3 finish3 nonFixedDim1 nonFixedDim2 nonFixedDim3 = let bound1 = target.GetLowerBound(nonFixedDim1) let bound2 = target.GetLowerBound(nonFixedDim2) @@ -5260,16 +5291,20 @@ namespace Microsoft.FSharp.Core for j = 0 to len2 - 1 do for k = 0 to len3 - 1 do setArrayElem i j k - + + [] let inline SetArraySlice4DFixedSingle1 (target: _[,,,]) index1 start2 finish2 start3 finish3 start4 finish4 (source: _[,,]) = SetArraySlice4DFixedSingle target source index1 start2 finish2 start3 finish3 start4 finish4 1 2 3 + [] let inline SetArraySlice4DFixedSingle2 (target: _[,,,]) start1 finish1 index2 start3 finish3 start4 finish4 (source: _[,,]) = SetArraySlice4DFixedSingle target source index2 start1 finish1 start3 finish3 start4 finish4 0 2 3 + [] let inline SetArraySlice4DFixedSingle3 (target: _[,,,]) start1 finish1 start2 finish2 index3 start4 finish4 (source: _[,,]) = SetArraySlice4DFixedSingle target source index3 start1 finish1 start2 finish2 start4 finish4 0 1 3 + [] let inline SetArraySlice4DFixedSingle4 (target: _[,,,]) start1 finish1 start2 finish2 start3 finish3 index4 (source: _[,,]) = SetArraySlice4DFixedSingle target source index4 start1 finish1 start2 finish2 start3 finish3 0 1 2 @@ -5295,21 +5330,27 @@ namespace Microsoft.FSharp.Core for j = 0 to len2 - 1 do setArrayElem i j + [] let inline SetArraySlice4DFixedDouble1 (target: _[,,,]) index1 index2 start3 finish3 start4 finish4 (source: _[,]) = SetArraySlice4DFixedDouble target source index1 index2 start3 finish3 start4 finish4 2 3 + [] let inline SetArraySlice4DFixedDouble2 (target: _[,,,]) index1 start2 finish2 index3 start4 finish4 (source: _[,]) = SetArraySlice4DFixedDouble target source index1 index3 start2 finish2 start4 finish4 1 3 + [] let inline SetArraySlice4DFixedDouble3 (target: _[,,,]) index1 start2 finish2 start3 finish3 index4 (source: _[,]) = SetArraySlice4DFixedDouble target source index1 index4 start2 finish2 start3 finish3 1 2 + [] let inline SetArraySlice4DFixedDouble4 (target: _[,,,]) start1 finish1 index2 index3 start4 finish4 (source: _[,]) = SetArraySlice4DFixedDouble target source index2 index3 start1 finish1 start4 finish4 0 3 + [] let inline SetArraySlice4DFixedDouble5 (target: _[,,,]) start1 finish1 index2 start3 finish3 index4 (source: _[,]) = SetArraySlice4DFixedDouble target source index2 index4 start1 finish1 start3 finish3 0 2 + [] let inline SetArraySlice4DFixedDouble6 (target: _[,,,]) start1 finish1 start2 finish2 index3 index4 (source: _[,]) = SetArraySlice4DFixedDouble target source index3 index4 start1 finish1 start2 finish2 0 1 @@ -5327,15 +5368,19 @@ namespace Microsoft.FSharp.Core for i = 0 to len1 - 1 do setArrayElem i + [] let inline SetArraySlice4DFixedTriple1 (target: _[,,,]) start1 finish1 index2 index3 index4 (source: _[]) = SetArraySlice4DFixedTriple target source index2 index3 index4 start1 finish1 0 + [] let inline SetArraySlice4DFixedTriple2 (target: _[,,,]) index1 start2 finish2 index3 index4 (source: _[]) = SetArraySlice4DFixedTriple target source index1 index3 index4 start2 finish2 1 + [] let inline SetArraySlice4DFixedTriple3 (target: _[,,,]) index1 index2 start3 finish3 index4 (source: _[]) = SetArraySlice4DFixedTriple target source index1 index2 index4 start3 finish3 2 + [] let inline SetArraySlice4DFixedTriple4 (target: _[,,,]) index1 index2 index3 start4 finish4 (source: _[]) = SetArraySlice4DFixedTriple target source index1 index2 index3 start4 finish4 3 @@ -5361,7 +5406,7 @@ namespace Microsoft.FSharp.Core when ^T : int16 = let x : int16 = retype x in System.Math.Abs(x) when ^T : sbyte = let x : sbyte = retype x in System.Math.Abs(x) when ^T : decimal = System.Math.Abs(retype x : decimal) - + [] let inline acosImpl(x: ^T) : ^T = (^T: (static member Acos : ^T -> ^T) (x)) @@ -5931,8 +5976,10 @@ namespace Microsoft.FSharp.Core if n >= 0 then PowDecimal x n else 1.0M / PowDecimal x n) [] + [] module ArrayExtensions = type ``[,,,]``<'T> with + [] member arr.GetReverseIndex(dim: int, offset: int) = let len = match dim with @@ -5945,6 +5992,7 @@ namespace Microsoft.FSharp.Core len - offset - 1 type ``[,,]``<'T> with + [] member arr.GetReverseIndex(dim: int, offset: int) = let len = match dim with @@ -5956,6 +6004,7 @@ namespace Microsoft.FSharp.Core len - offset - 1 type ``[,]``<'T> with + [] member arr.GetReverseIndex(dim: int, offset: int) = let len = match dim with @@ -5966,12 +6015,13 @@ namespace Microsoft.FSharp.Core len - offset - 1 type ``[]``<'T> with + [] member arr.GetReverseIndex (_: int, offset: int) = arr.Length - offset - 1 - + type System.String with + [] member str.GetReverseIndex (_: int, offset: int) = str.Length - offset - 1 - namespace Microsoft.FSharp.Control open System diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 0f1ba6901f..fd6c7557ef 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -618,7 +618,7 @@ namespace Microsoft.FSharp.Core /// This attribute is used to tag values that are part of an experimental library /// feature. - [] + [] [] type ExperimentalAttribute = inherit Attribute @@ -1935,8 +1935,9 @@ namespace Microsoft.FSharp.Collections /// The rank of the index. /// The offset from the end. /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int - + /// Returns a list with head as its first element and tail as its subsequent elements /// A new head value for the list. /// The existing list. @@ -2747,12 +2748,14 @@ namespace Microsoft.FSharp.Core val ( |KeyValue| ): keyValuePair:KeyValuePair<'Key,'Value> -> 'Key * 'Value [] + [] module ArrayExtensions = type ``[,,,]``<'T> with /// Get the index for the element offset elements away from the end of the collection. /// The rank of the index. This refers to the dimension in the 4d array. /// The offset from the end. /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int type ``[,,]``<'T> with @@ -2760,6 +2763,7 @@ namespace Microsoft.FSharp.Core /// The rank of the index. This refers to the dimension in the 3d array. /// The offset from the end. /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int type ``[,]``<'T> with @@ -2767,13 +2771,15 @@ namespace Microsoft.FSharp.Core /// The rank of the index. This refers to the dimension in the 2d array. /// The offset from the end. /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int type ``[]``<'T> with /// Get the index for the element offset elements away from the end of the collection. /// The rank of the index. /// The offset from the end. - /// The corresponding index from the start. + /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int type System.String with @@ -2781,6 +2787,7 @@ namespace Microsoft.FSharp.Core /// The rank of the index. /// The offset from the end. /// The corresponding index from the start. + [] member GetReverseIndex: rank: int * offset: int -> int @@ -2867,20 +2874,22 @@ namespace Microsoft.FSharp.Core /// The source array. /// The fixed index of the first dimension. /// The start index of the second dimension. - /// The end index of the second dimension. + /// The end index of the second dimension. /// The start index of the third dimension. /// The end index of the third dimension. /// The two dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedSingle1 : source:'T[,,] -> index1:int -> start2:int option -> finish2:int option -> start3:int option -> finish3:int option -> 'T[,] /// Gets a 2D slice of a 3D array. /// The source array. /// The start index of the first dimension. - /// The end index of the first dimension. + /// The end index of the first dimension. /// The fixed index of the second dimension. /// The start index of the third dimension. /// The end index of the third dimension. /// The two dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedSingle2 : source:'T[,,] -> start1:int option -> finish1:int option -> index2: int -> start3:int option -> finish3:int option -> 'T[,] /// Gets a 2D slice of a 3D array. @@ -2888,9 +2897,10 @@ namespace Microsoft.FSharp.Core /// The start index of the first dimension. /// The end index of the first dimension. /// The start index of the second dimension. - /// The end index of the second dimension. + /// The end index of the second dimension. /// The fixed index of the third dimension. /// The two dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedSingle3 : source:'T[,,] -> start1:int option -> finish1:int option -> start2:int option -> finish2:int option -> index3: int -> 'T[,] /// Gets a 1D slice of a 3D array. @@ -2899,16 +2909,18 @@ namespace Microsoft.FSharp.Core /// The fixed index of the second dimension. /// The start index of the third dimension. /// The end index of the third dimension. - /// The one dimensional sub array from the given indices. + /// The one dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedDouble1 : source:'T[,,] -> index1:int -> index2:int -> start3:int option -> finish3:int option -> 'T[] /// Gets a 1D slice of a 3D array. /// The source array. /// The fixed index of the first dimension. /// The start index of the second dimension. - /// The end index of the second dimension. + /// The end index of the second dimension. /// The fixed index of the third dimension. /// The one dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedDouble2 : source:'T[,,] -> index1:int -> start2:int option -> finish2:int option -> index3:int -> 'T[] /// Gets a 1D slice of a 3D array. @@ -2918,6 +2930,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the second dimension. /// The fixed index of the third dimension. /// The one dimensional sub array from the given indices. + [] val inline GetArraySlice3DFixedDouble3 : source:'T[,,] -> start1:int option -> finish1:int option -> index2:int -> index3:int -> 'T[] /// Sets a slice of an array @@ -2940,6 +2953,7 @@ namespace Microsoft.FSharp.Core /// The end index of the third dimension. /// The source array. /// The two dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedSingle1 : target: 'T[,,] -> index1: int -> start2: int option -> finish2: int option -> start3: int option -> finish3: int option -> source: 'T[,] -> unit /// Sets a 2D slice of a 3D array @@ -2951,6 +2965,7 @@ namespace Microsoft.FSharp.Core /// The end index of the third dimension. /// The source array. /// The two dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedSingle2 : target: 'T[,,] -> start1: int option -> finish1: int option -> index2: int -> start3: int option -> finish3: int option -> source: 'T[,] -> unit /// Sets a 2D slice of a 3D array @@ -2962,6 +2977,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// The source array. /// The two dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedSingle3 : target: 'T[,,] -> start1: int option -> finish1: int option -> start2: int option -> finish2: int option -> index3: int -> source: 'T[,] -> unit /// Sets a 1D slice of a 3D array. @@ -2972,16 +2988,18 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// The source array. /// The one dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedDouble1 : target: 'T[,,] -> index1: int -> index2: int -> start3: int option -> finish3: int option -> source: 'T[] -> unit /// Sets a 1D slice of a 3D array. /// The source array. /// The fixed index of the first dimension. /// The start index of the second dimension. - /// The end index of the second dimension. + /// The end index of the second dimension. /// The fixed index of the third dimension. /// The source array. /// The one dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedDouble2 : target: 'T[,,] -> index1: int -> start2: int option -> finish2: int option -> index3: int -> source: 'T[] -> unit /// Sets a 1D slice of a 3D array. @@ -2992,6 +3010,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// The source array. /// The one dimensional sub array from the given indices. + [] val inline SetArraySlice3DFixedDouble3 : target: 'T[,,] -> start1: int option -> finish1: int option -> index2: int -> index3: int -> source: 'T[] -> unit /// Gets a slice of an array diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 0c1f6a0d79..6909cfcf5c 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -52,13 +52,15 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.RelaxWhitespace, languageVersion47 LanguageFeature.ImplicitYield, languageVersion47 + // F# 5.0 + LanguageFeature.FixedIndexSlice3d4d, languageVersion50 + LanguageFeature.FromEndSlicing, languageVersion50 + // F# preview LanguageFeature.NameOf, previewVersion LanguageFeature.OpenStaticClasses, previewVersion LanguageFeature.DotlessFloat32Literal, languageVersion50 LanguageFeature.PackageManagement, previewVersion - LanguageFeature.FixedIndexSlice3d4d, previewVersion - LanguageFeature.FromEndSlicing, previewVersion ] let specified = @@ -79,6 +81,10 @@ type LanguageVersion (specifiedVersionAsString) = | true, v -> v <= specified | false, _ -> false + /// Has preview been explicitly specified + member __.IsPreviewEnabled = + specified = previewVersion + /// Does the languageVersion support this version string member __.ContainsVersion version = match version with diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index 2a58ab164d..37a58a50b4 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -27,7 +27,10 @@ type LanguageVersion = /// Get the list of valid versions member ContainsVersion: string -> bool - /// Does the specified LanguageVersion support the specified feature + /// Has preview been explicitly specified + member IsPreviewEnabled: bool + + /// Does the selected LanguageVersion support the specified feature member SupportsFeature: LanguageFeature -> bool /// Get the list of valid versions diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs index 0e4685a346..75461964f2 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs @@ -2746,5 +2746,11 @@ Microsoft.FSharp.Reflection.UnionCaseInfo: System.String Name Microsoft.FSharp.Reflection.UnionCaseInfo: System.String ToString() Microsoft.FSharp.Reflection.UnionCaseInfo: System.String get_Name() Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type DeclaringType -Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType()" +Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType() +" +#if DEBUG + let expected = + expected + + @"Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +#endif SurfaceArea.verify expected "coreclr" (System.IO.Path.Combine(__SOURCE_DIRECTORY__,__SOURCE_FILE__)) diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs index 4857dba6c1..5b9b5f4388 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs @@ -183,9 +183,9 @@ Microsoft.FSharp.Collections.FSharpList`1[T]: Boolean get_IsEmpty() Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 CompareTo(Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 CompareTo(System.Object) Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 GetReverseIndex(Int32, Int32) Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 GetHashCode() Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 GetHashCode(System.Collections.IEqualityComparer) +Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 GetReverseIndex(Int32, Int32) Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 Length Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 Tag Microsoft.FSharp.Collections.FSharpList`1[T]: Int32 get_Length() @@ -2746,7 +2746,13 @@ Microsoft.FSharp.Reflection.UnionCaseInfo: System.String Name Microsoft.FSharp.Reflection.UnionCaseInfo: System.String ToString() Microsoft.FSharp.Reflection.UnionCaseInfo: System.String get_Name() Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type DeclaringType -Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType()" +Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType() +" +#if DEBUG + let expected = + expected + + @"Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +#endif #if CROSS_PLATFORM_COMPILER () // disabled because of slight order and GetMember discrepencies diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 8ff0c7f5f5..8c3fb277d7 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -192,6 +192,20 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) + let PassWithOptions options (source: string) = + lock gate <| fun () -> + let options = { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions} + + let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, options) |> Async.RunSynchronously + + Assert.IsEmpty(parseResults.Errors, sprintf "Parse errors: %A" parseResults.Errors) + + match fileAnswer with + | FSharpCheckFileAnswer.Aborted _ -> Assert.Fail("Type Checker Aborted") + | FSharpCheckFileAnswer.Succeeded(typeCheckResults) -> + + Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) + let TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = lock gate <| fun () -> let parseResults, fileAnswer = diff --git a/tests/fsharp/Compiler/Warnings/ExperimentalAttributeTests.fs b/tests/fsharp/Compiler/Warnings/ExperimentalAttributeTests.fs new file mode 100644 index 0000000000..dc93060024 --- /dev/null +++ b/tests/fsharp/Compiler/Warnings/ExperimentalAttributeTests.fs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Validate ExperimentalAttribute and LanguageVersion`` = + + let experimentalSource = """ +module TestModule = + + [] + let getString = "A string" + + if getString = "A string" then () +""" + + [] + let ``ExperimentalAttribute nowarn when preview specified``() = + CompilerAssert.PassWithOptions + [| "--langversion:preview" |] + experimentalSource + + [] + let ``ExperimentalAttribute warn when preview not specified``() = + CompilerAssert.TypeCheckSingleError + experimentalSource + FSharpErrorSeverity.Warning + 57 + (7, 8, 7, 17) + "Preview library feature, requires '--langversion:preview'. This warning can be disabled using '--nowarn:57' or '#nowarn \"57\"'." diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 41ef988bc7..81cf83c77d 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -55,6 +55,7 @@ + diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 89e103775f..2247c318f6 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -1,4 +1,4 @@ -// To run these tests in F# Interactive , 'build net40', then send this chunk, then evaluate body of a test vvvvvvvvvvvvvvvv +// To run these tests in F# Interactive , 'build net40', then send this chunk, then evaluate body of a test #if INTERACTIVE #r @"../../packages/NUnit.3.5.0/lib/net45/nunit.framework.dll" #load "../../src/scripts/scriptlib.fsx" From 74f453bed39f1fec8ed1570703d19a7bfe86a8a1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Wed, 8 Jan 2020 13:31:38 +0000 Subject: [PATCH 014/101] Update dependencies from https://github.com/dotnet/arcade build 20200107.5 - Microsoft.DotNet.Arcade.Sdk - 5.0.0-beta.20057.5 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index cfdceb169f..c98fbfbee4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 5cbca575e9002cc2d9814c3471d38882df2fcc8e + d0833c8e5e58cfc507ce3c8da364e55931190263 diff --git a/global.json b/global.json index 6fe6bcd1ce..51d8c790fc 100644 --- a/global.json +++ b/global.json @@ -9,7 +9,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20056.6", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20057.5", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 9fd8fc72385a7f7b16664d5a2f6a08f31f4f07e8 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Wed, 8 Jan 2020 14:21:37 -0800 Subject: [PATCH 015/101] Fix merge errors --- src/fsharp/CompileOps.fs | 16 ++++++++-------- tests/fsharp/Compiler/CompilerAssert.fs | 11 ++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 93dab5a629..676ea72f16 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5115,7 +5115,7 @@ module ScriptPreprocessClosure = TcConfig.Create(tcConfigB, validate=false), nowarns let FindClosureFiles(mainFile, _m, closureSources, origTcConfig:TcConfig, codeContext, lexResourceManager: Lexhelp.LexResourceManager) = - let tcConfig = origTcConfig + let mutable tcConfig = origTcConfig let observedSources = Observed() let loadScripts = HashSet<_>() @@ -5123,7 +5123,7 @@ module ScriptPreprocessClosure = // Resolve the packages let rec resolveDependencyManagerSources scriptName = if not (loadScripts.Contains scriptName) then - [ for kv in tcConfig.Value.packageManagerLines do + [ for kv in tcConfig.packageManagerLines do let packageManagerKey, packageManagerLines = kv.Key, kv.Value match packageManagerLines with | [] -> () @@ -5131,14 +5131,14 @@ module ScriptPreprocessClosure = match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with | Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> () | _ -> - match DependencyManagerIntegration.tryFindDependencyManagerByKey tcConfig.Value.compilerToolPaths tcConfig.Value.outputDir m packageManagerKey with + match DependencyManagerIntegration.tryFindDependencyManagerByKey tcConfig.compilerToolPaths tcConfig.outputDir m packageManagerKey with | None -> - errorR(DependencyManagerIntegration.createPackageManagerUnknownError tcConfig.Value.compilerToolPaths tcConfig.Value.outputDir packageManagerKey m) + errorR(DependencyManagerIntegration.createPackageManagerUnknownError tcConfig.compilerToolPaths tcConfig.outputDir packageManagerKey m) | Some packageManager -> let inline snd3 (_, b, _) = b let packageManagerTextLines = packageManagerLines |> List.map snd3 - match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir mainFile scriptName m packageManagerTextLines with + match DependencyManagerIntegration.resolve packageManager tcConfig.implicitIncludeDir mainFile scriptName m packageManagerTextLines with | None -> () // error already reported | Some (succeeded, generatedScripts, additionalIncludeFolders) -> //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // This may incrementally update tcConfig too with new #r references @@ -5147,11 +5147,11 @@ module ScriptPreprocessClosure = | true -> // Resolution produced no errors if not (isNil additionalIncludeFolders) then - let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder + let tcConfigB = tcConfig.CloneOfOriginalBuilder for folder in additionalIncludeFolders do tcConfigB.AddIncludePath(m, folder, "") tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) - tcConfig := TcConfig.Create(tcConfigB, validate=false) + tcConfig <- TcConfig.Create(tcConfigB, validate=false) for script in generatedScripts do let scriptText = File.ReadAllText script loadScripts.Add script |> ignore @@ -5160,7 +5160,7 @@ module ScriptPreprocessClosure = | false -> // Resolution produced errors update packagerManagerLines entries to note these failure // failed resolutions will no longer be considered - let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder + let tcConfigB = tcConfig.CloneOfOriginalBuilder tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.filter(fun (tried, _, _) -> tried)) tcConfig <- TcConfig.Create(tcConfigB, validate=false)] else [] diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 270f79d82c..9f0bc09553 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -384,7 +384,7 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - let PassWithOptions options (source: string) = + static member PassWithOptions options (source: string) = lock gate <| fun () -> let options = { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions} @@ -398,7 +398,7 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - let TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = + static member TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = lock gate <| fun () -> let parseResults, fileAnswer = checker.ParseAndCheckFileInProject( @@ -444,7 +444,7 @@ let main argv = 0""" Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)) static member CompileExe (source: string) = - CompileExeWithOptions [||] source + CompilerAssert.CompileExeWithOptions [||] source static member CompileExeAndRunWithOptions options (source: string) = compile true options source (fun (errors, outputExe) -> @@ -456,7 +456,7 @@ let main argv = 0""" ) static member CompileExeAndRun (source: string) = - CompileExeAndRunWithOptions [||] source + CompilerAssert.CompileExeAndRunWithOptions [||] source static member CompileLibraryAndVerifyILWithOptions options (source: string) (f: ILVerifier -> unit) = compile false options source (fun (errors, outputFilePath) -> @@ -508,7 +508,8 @@ let main argv = 0""" Assert.AreEqual(expectedErrorMessage, errorMessage) ) - static member RunScript source expectedErrorMessages = RunScriptWithOptions [||] source expectedErrorMessages + static member RunScript source expectedErrorMessages = + CompilerAssert.RunScriptWithOptions [||] source expectedErrorMessages static member ParseWithErrors (source: string) expectedParseErrors = let sourceFileName = "test.fs" From fadf667f65645c88f7ce8649d2c8876cefa87fe7 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Wed, 8 Jan 2020 17:15:04 -0800 Subject: [PATCH 016/101] Back to master --- eng/Versions.props | 8 +- eng/common/CheckSymbols.ps1 | 53 ++-- eng/common/PublishToSymbolServers.proj | 6 +- eng/common/SetupNugetSources.ps1 | 16 +- eng/common/SetupNugetSources.sh | 2 +- eng/common/SourceLinkValidation.ps1 | 269 +++++++++--------- eng/common/build.ps1 | 97 +++---- eng/common/build.sh | 24 +- eng/common/cross/build-rootfs.sh | 2 +- eng/common/cross/toolchain.cmake | 49 +++- eng/common/darc-init.ps1 | 26 +- eng/common/darc-init.sh | 30 +- eng/common/dotnet-install.ps1 | 25 +- eng/common/dotnet-install.sh | 37 +-- eng/common/enable-cross-org-publishing.ps1 | 6 +- eng/common/generate-graph-files.ps1 | 49 ++-- eng/common/init-tools-native.ps1 | 37 ++- eng/common/init-tools-native.sh | 5 +- eng/common/internal-feed-operations.ps1 | 28 +- eng/common/internal-feed-operations.sh | 4 +- eng/common/msbuild.ps1 | 5 +- eng/common/native/common-library.sh | 10 +- eng/common/native/install-cmake-test.sh | 4 +- eng/common/native/install-cmake.sh | 4 +- eng/common/native/install-tool.ps1 | 12 +- eng/common/pipeline-logging-functions.ps1 | 72 +++-- eng/common/pipeline-logging-functions.sh | 11 +- eng/common/post-build/darc-gather-drop.ps1 | 15 +- eng/common/post-build/nuget-validation.ps1 | 11 +- eng/common/post-build/post-build-utils.ps1 | 27 +- eng/common/post-build/promote-build.ps1 | 18 +- eng/common/post-build/setup-maestro-vars.ps1 | 26 ++ .../post-build/sourcelink-validation.ps1 | 42 +-- eng/common/post-build/symbols-validation.ps1 | 71 ++--- .../post-build/trigger-subscriptions.ps1 | 87 +++--- eng/common/sdk-task.ps1 | 19 +- eng/common/sdl/execute-all-sdl-tools.ps1 | 176 ++++++------ eng/common/sdl/extract-artifact-packages.ps1 | 89 +++--- eng/common/sdl/init-sdl.ps1 | 38 +-- eng/common/sdl/push-gdn.ps1 | 92 +++--- eng/common/sdl/run-sdl.ps1 | 86 +++--- eng/common/templates/job/execute-sdl.yml | 8 +- eng/common/templates/job/job.yml | 142 +++++---- eng/common/templates/jobs/jobs.yml | 74 +++-- .../channels/generic-internal-channel.yml | 72 ++--- .../channels/generic-public-channel.yml | 56 ++-- .../templates/post-build/common-variables.yml | 6 +- .../templates/post-build/post-build.yml | 207 +++++++++++--- .../post-build/setup-maestro-vars.yml | 26 +- eng/common/templates/steps/publish-logs.yml | 23 -- eng/common/templates/steps/send-to-helix.yml | 3 - eng/common/tools.ps1 | 201 ++++++------- eng/common/tools.sh | 44 +-- global.json | 3 +- 54 files changed, 1237 insertions(+), 1316 deletions(-) create mode 100644 eng/common/post-build/setup-maestro-vars.ps1 delete mode 100644 eng/common/templates/steps/publish-logs.yml diff --git a/eng/Versions.props b/eng/Versions.props index 6761b89a3f..acb04ff55b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -12,9 +12,9 @@ beta - 5.0 + 4.7 $(FSLanguageVersion) - $(FSCoreMajorVersion).0 + $(FSCoreMajorVersion).1 $(FSCoreMajorVersion).0 $(FSCoreVersionPrefix).0 @@ -23,14 +23,14 @@ $(FSCorePackageVersion)-$(PreReleaseVersionLabel).* - 11.0 + 10.7 $(FSPackageMajorVersion).0 $(FSPackageVersion) $(FSPackageVersion).0 16 - 5 + 4 $(VSMajorVersion).0 $(VSMajorVersion).$(VSMinorVersion).0 $(VSAssemblyVersionPrefix).0 diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 index 5442eff386..b8d84607b8 100644 --- a/eng/common/CheckSymbols.ps1 +++ b/eng/common/CheckSymbols.ps1 @@ -5,12 +5,11 @@ param( ) Add-Type -AssemblyName System.IO.Compression.FileSystem -. $PSScriptRoot\pipeline-logging-functions.ps1 function FirstMatchingSymbolDescriptionOrDefault { param( [string] $FullPath, # Full path to the module that has to be checked - [string] $TargetServerParameter, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + [string] $TargetServerParam, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols [string] $SymbolsPath ) @@ -22,36 +21,36 @@ function FirstMatchingSymbolDescriptionOrDefault { # checking and which type of file was uploaded. # The file itself is returned - $SymbolPath = $SymbolsPath + '\' + $FileName + $SymbolPath = $SymbolsPath + "\" + $FileName # PDB file for the module - $PdbPath = $SymbolPath.Replace($Extension, '.pdb') + $PdbPath = $SymbolPath.Replace($Extension, ".pdb") # PDB file for R2R module (created by crossgen) - $NGenPdb = $SymbolPath.Replace($Extension, '.ni.pdb') + $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") # DBG file for a .so library - $SODbg = $SymbolPath.Replace($Extension, '.so.dbg') + $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") # DWARF file for a .dylib - $DylibDwarf = $SymbolPath.Replace($Extension, '.dylib.dwarf') + $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") - .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParameter $FullPath -o $SymbolsPath | Out-Null + .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null if (Test-Path $PdbPath) { - return 'PDB' + return "PDB" } elseif (Test-Path $NGenPdb) { - return 'NGen PDB' + return "NGen PDB" } elseif (Test-Path $SODbg) { - return 'DBG for SO' + return "DBG for SO" } elseif (Test-Path $DylibDwarf) { - return 'Dwarf for Dylib' + return "Dwarf for Dylib" } elseif (Test-Path $SymbolPath) { - return 'Module' + return "Module" } else { return $null @@ -69,7 +68,7 @@ function CountMissingSymbols { } # Extensions for which we'll look for symbols - $RelevantExtensions = @('.dll', '.exe', '.so', '.dylib') + $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") # How many files are missing symbol information $MissingSymbols = 0 @@ -77,7 +76,7 @@ function CountMissingSymbols { $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) $PackageGuid = New-Guid $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid - $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath 'Symbols' + $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols" [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) @@ -87,31 +86,31 @@ function CountMissingSymbols { Get-ChildItem -Recurse $ExtractPath | Where-Object {$RelevantExtensions -contains $_.Extension} | ForEach-Object { - if ($_.FullName -Match '\\ref\\') { + if ($_.FullName -Match "\\ref\\") { Write-Host "`t Ignoring reference assembly file" $_.FullName return } - $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--microsoft-symbol-server' -SymbolsPath $SymbolsPath - $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--internal-server' -SymbolsPath $SymbolsPath + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath Write-Host -NoNewLine "`t Checking file" $_.FullName "... " if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { - Write-Host "Symbols found on MSDL (${$SymbolsOnMSDL}) and SymWeb (${$SymbolsOnSymWeb})" + Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" } else { $MissingSymbols++ if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { - Write-Host 'No symbols found on MSDL or SymWeb!' + Write-Host "No symbols found on MSDL or SymWeb!" } else { if ($SymbolsOnMSDL -eq $null) { - Write-Host 'No symbols found on MSDL!' + Write-Host "No symbols found on MSDL!" } else { - Write-Host 'No symbols found on SymWeb!' + Write-Host "No symbols found on SymWeb!" } } } @@ -130,26 +129,26 @@ function CheckSymbolsAvailable { Get-ChildItem "$InputPath\*.nupkg" | ForEach-Object { $FileName = $_.Name - + # These packages from Arcade-Services include some native libraries that # our current symbol uploader can't handle. Below is a workaround until # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted. - if ($FileName -Match 'Microsoft\.DotNet\.Darc\.') { + if ($FileName -Match "Microsoft\.DotNet\.Darc\.") { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - elseif ($FileName -Match 'Microsoft\.DotNet\.Maestro\.Tasks\.') { + elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") { Write-Host "Ignoring Arcade-services file: $FileName" Write-Host return } - + Write-Host "Validating $FileName " $Status = CountMissingSymbols "$InputPath\$FileName" if ($Status -ne 0) { - Write-PipelineTelemetryError -Category 'CheckSymbols' -Message "Missing symbols for $Status modules in the package $FileName" + Write-Error "Missing symbols for $Status modules in the package $FileName" } Write-Host diff --git a/eng/common/PublishToSymbolServers.proj b/eng/common/PublishToSymbolServers.proj index 311e2bbe0f..5d55e312b0 100644 --- a/eng/common/PublishToSymbolServers.proj +++ b/eng/common/PublishToSymbolServers.proj @@ -37,8 +37,6 @@ 3650 true - true - true false @@ -58,7 +56,7 @@ DryRun="false" ConvertPortablePdbsToWindowsPdbs="false" PdbConversionTreatAsWarning="" - Condition="$(PublishToSymbolServer) and $(PublishToMSDL)"/> + Condition="$(PublishToSymbolServer)"/> git commit --> git push - Write-Host 'git add .' - git add . - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git add failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" - git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git commit failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - Write-Host 'git push' - git push - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Git push failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } +# We create the temp directory where we'll store the sdl-config repository +$sdlDir = Join-Path $env:TEMP "sdl" +if (Test-Path $sdlDir) { + Remove-Item -Force -Recurse $sdlDir +} - # Return to the original directory - Pop-Location +Write-Host "git clone https://dnceng:`$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir" +git clone https://dnceng:$AzureDevOpsAccessToken@dev.azure.com/dnceng/internal/_git/sdl-tool-cfg $sdlDir +if ($LASTEXITCODE -ne 0) { + Write-Error "Git clone failed with exit code $LASTEXITCODE." +} +# We copy the .gdn folder from our local run into the git repository so it can be committed +$sdlRepositoryFolder = Join-Path (Join-Path (Join-Path $sdlDir $Repository) $BranchName) ".gdn" +if (Get-Command Robocopy) { + Robocopy /S $GdnFolder $sdlRepositoryFolder +} else { + rsync -r $GdnFolder $sdlRepositoryFolder } -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} \ No newline at end of file +# cd to the sdl-config directory so we can run git there +Push-Location $sdlDir +# git add . --> git commit --> git push +Write-Host "git add ." +git add . +if ($LASTEXITCODE -ne 0) { + Write-Error "Git add failed with exit code $LASTEXITCODE." +} +Write-Host "git -c user.email=`"dn-bot@microsoft.com`" -c user.name=`"Dotnet Bot`" commit -m `"$PushReason for $Repository/$BranchName`"" +git -c user.email="dn-bot@microsoft.com" -c user.name="Dotnet Bot" commit -m "$PushReason for $Repository/$BranchName" +if ($LASTEXITCODE -ne 0) { + Write-Error "Git commit failed with exit code $LASTEXITCODE." +} +Write-Host "git push" +git push +if ($LASTEXITCODE -ne 0) { + Write-Error "Git push failed with exit code $LASTEXITCODE." +} + +# Return to the original directory +Pop-Location \ No newline at end of file diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 index 40a084f796..9bc25314ae 100644 --- a/eng/common/sdl/run-sdl.ps1 +++ b/eng/common/sdl/run-sdl.ps1 @@ -5,65 +5,55 @@ Param( [string] $GdnFolder, [string[]] $ToolsList, [string] $UpdateBaseline, - [string] $GuardianLoggerLevel='Standard', + [string] $GuardianLoggerLevel="Standard", [string[]] $CrScanAdditionalRunConfigParams, [string[]] $PoliCheckAdditionalRunConfigParams ) -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = "Stop" Set-StrictMode -Version 2.0 -$disableConfigureToolsetImport = $true $LASTEXITCODE = 0 -try { - . $PSScriptRoot\..\tools.ps1 +# We store config files in the r directory of .gdn +Write-Host $ToolsList +$gdnConfigPath = Join-Path $GdnFolder "r" +$ValidPath = Test-Path $GuardianCliLocation - # We store config files in the r directory of .gdn - Write-Host $ToolsList - $gdnConfigPath = Join-Path $GdnFolder 'r' - $ValidPath = Test-Path $GuardianCliLocation - - if ($ValidPath -eq $False) - { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." - ExitWithExitCode 1 - } - - $configParam = @('--config') +if ($ValidPath -eq $False) +{ + Write-Host "Invalid Guardian CLI Location." + exit 1 +} - foreach ($tool in $ToolsList) { - $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" - 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" - & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } +$configParam = @("--config") + +foreach ($tool in $ToolsList) { + $gdnConfigFile = Join-Path $gdnConfigPath "$tool-configure.gdnconfig" + 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 `" `" OutputType < pre `" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams})" + & $GuardianCliLocation configure --working-directory $WorkingDirectory --tool $tool --output-path $gdnConfigFile --logger-level $GuardianLoggerLevel --noninteractive --force --args " TargetDirectory < $TargetDirectory " "OutputType < pre" $(If ($CrScanAdditionalRunConfigParams) {$CrScanAdditionalRunConfigParams}) + if ($LASTEXITCODE -ne 0) { + Write-Host "Guardian configure for $tool failed with exit code $LASTEXITCODE." + exit $LASTEXITCODE } - if ($tool -eq 'policheck') { - 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-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian configure for $tool failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } + } + if ($tool -eq "policheck") { + 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 } - - $configParam+=$gdnConfigFile } - Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" - & $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } + $configParam+=$gdnConfigFile +} + +Write-Host "$GuardianCliLocation run --working-directory $WorkingDirectory --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam" +& $GuardianCliLocation run --working-directory $WorkingDirectory --tool $tool --baseline mainbaseline --update-baseline $UpdateBaseline --logger-level $GuardianLoggerLevel $configParam +if ($LASTEXITCODE -ne 0) { + Write-Host "Guardian run for $ToolsList using $configParam failed with exit code $LASTEXITCODE." + exit $LASTEXITCODE } -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} \ No newline at end of file diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 2973bcaf3a..52e2ff021d 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -40,13 +40,13 @@ jobs: itemPattern: "**" downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts + -InputPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts displayName: Extract Blob Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts + -InputPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts + -ExtractPath $(Build.SourcesDirectory)\artifacts\PackageArtifacts displayName: Extract Package Artifacts continueOnError: ${{ parameters.sdlContinueOnError }} - task: NuGetToolInstaller@1 diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index ecebd0f03e..ffda80a197 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,33 +1,67 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - parameters: # Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job cancelTimeoutInMinutes: '' + condition: '' - container: '' + continueOnError: false + + container: '' + dependsOn: '' + displayName: '' - pool: '' + steps: [] + + pool: '' + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' + # Job base template specific parameters + # Optional: Enable installing Microbuild plugin + # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix + # _TeamName - the name of your team + # _SignType - 'test' or 'real' enableMicrobuild: false + + # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false + + # Optional: Enable publishing to the build asset registry enablePublishBuildAssets: false - enablePublishTestResults: false + + # Optional: Prevent gather/push manifest from executing when using publishing pipelines enablePublishUsingPipelines: false + + # Optional: Include PublishTestResults task + enablePublishTestResults: false + + # Optional: enable sending telemetry + enableTelemetry: false + + # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') + helixRepo: '' + + # Optional: define the helix type for telemetry (example: 'build/product/') + helixType: '' + + # Required: name of the job name: '' - preSteps: [] + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. runAsPublic: false +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + jobs: - job: ${{ parameters.name }} @@ -59,7 +93,7 @@ jobs: timeoutInMinutes: ${{ parameters.timeoutInMinutes }} variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - ${{ if eq(parameters.enableTelemetry, 'true') }}: - name: DOTNET_CLI_TELEMETRY_PROFILE value: '$(Build.Repository.Uri)' - ${{ each variable in parameters.variables }}: @@ -91,12 +125,21 @@ jobs: workspace: ${{ parameters.workspace }} steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} + - ${{ if eq(parameters.enableTelemetry, 'true') }}: + # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions + - task: sendStartTelemetry@0 + displayName: 'Send Helix Start Telemetry' + inputs: + helixRepo: ${{ parameters.helixRepo }} + ${{ if ne(parameters.helixType, '') }}: + helixType: ${{ parameters.helixType }} + buildConfig: $(_BuildConfig) + runAsPublic: ${{ parameters.runAsPublic }} + continueOnError: ${{ parameters.continueOnError }} + condition: always() - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: MicroBuildSigningPlugin@2 displayName: Install MicroBuild plugin inputs: @@ -108,16 +151,9 @@ jobs: continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: NuGetAuthenticate@0 - - ${{ if or(eq(parameters.artifacts.download, 'true'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - ${{ each step in parameters.steps }}: - ${{ step }} @@ -130,60 +166,20 @@ jobs: env: TeamName: $(_TeamName) - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if or(eq(parameters.artifacts.publish.artifacts, 'true'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if or(eq(parameters.artifacts.publish.logs, 'true'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - ${{ if or(eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - ${{ if and(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: - SourceFolder: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/AssetManifest' - TargetFolder: '$(Build.ArtifactStagingDirectory)/AssetManifests' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) - - - task: PublishBuildArtifacts@1 - displayName: Push Asset Manifests - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/AssetManifests' - PublishLocation: Container - ArtifactName: AssetManifests - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - ${{ if eq(parameters.enableTelemetry, 'true') }}: + # Telemetry tasks are built from https://github.com/dotnet/arcade-extensions + - task: sendEndTelemetry@0 + displayName: 'Send Helix End Telemetry' + continueOnError: ${{ parameters.continueOnError }} + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - task: PublishBuildArtifacts@1 displayName: Publish Logs inputs: PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + ArtifactName: $(Agent.Os)_$(Agent.JobName) continueOnError: true condition: always() diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index c08225a9a9..6a2f98c036 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,10 +1,19 @@ parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + # Optional: 'true' if failures in job.yml job should not fail the job continueOnError: false + # Optional: Enable installing Microbuild plugin + # if 'true', these "variables" must be specified in the variables object or as part of the queue matrix + # _TeamName - the name of your team + # _SignType - 'test' or 'real' + enableMicrobuild: false + # Optional: Include PublishBuildArtifacts task enablePublishBuildArtifacts: false + # Optional: Enable publishing to the build asset registry + enablePublishBuildAssets: false + # Optional: Enable publishing using release pipelines enablePublishUsingPipelines: false @@ -14,9 +23,19 @@ parameters: # Optional: Include toolset dependencies in the generated graph files includeToolset: false + # Optional: Include PublishTestResults task + enablePublishTestResults: false + + # Optional: enable sending telemetry + # if enabled then the 'helixRepo' parameter should also be specified + enableTelemetry: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job jobs: [] + # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') + helixRepo: '' + # Optional: Override automatically derived dependsOn value for "publish build assets" job publishBuildAssetsDependsOn: '' @@ -43,30 +62,29 @@ jobs: name: ${{ job.job }} -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - pool: - vmImage: vs2017-win2016 - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - - - ${{ if eq(parameters.graphFileGeneration.enabled, true) }}: - - template: ../job/generate-graph-files.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} - dependsOn: - - Asset_Registry_Publish - pool: - vmImage: vs2017-win2016 +- ${{ if and(eq(parameters.enablePublishBuildAssets, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: ../job/publish-build-assets.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + pool: + vmImage: vs2017-win2016 + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + +- ${{ if and(eq(parameters.graphFileGeneration.enabled, true), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: ../job/generate-graph-files.yml + parameters: + continueOnError: ${{ parameters.continueOnError }} + includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} + dependsOn: + - Asset_Registry_Publish + pool: + vmImage: vs2017-win2016 diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml index 700211049b..ad9375f5e5 100644 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml @@ -1,7 +1,4 @@ parameters: - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -13,14 +10,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} + dependsOn: validate variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: publish_symbols + - job: displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -29,28 +26,21 @@ stages: pool: vmImage: 'windows-2019' steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: 'current' - downloadType: 'specific' - itemPattern: | - PDBArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - task: NuGetAuthenticate@0 displayName: 'Authenticate to AzDO Feeds' - - task: PowerShell@2 - displayName: Enable cross-org publishing + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) + artifactName: 'BlobArtifacts' + continueOnError: true + + - task: DownloadBuildArtifacts@0 + displayName: Download PDB Artifacts + inputs: + artifactName: 'PDBArtifacts' + continueOnError: true - task: PowerShell@2 displayName: Publish @@ -63,18 +53,14 @@ stages: /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' /p:Configuration=Release - /p:PublishToMSDL=false ${{ parameters.symbolPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - 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 @@ -84,16 +70,22 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true + displayName: Download Package Artifacts inputs: - buildType: 'current' - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' + 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: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' @@ -132,6 +124,7 @@ stages: /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey) /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) + /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -141,11 +134,6 @@ stages: /p:PublishToMSDL=false ${{ parameters.artifactsPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml index fbb5a19b67..c4bc1897d8 100644 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ b/eng/common/templates/post-build/channels/generic-public-channel.yml @@ -1,7 +1,5 @@ parameters: artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' stageName: '' @@ -13,14 +11,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} + dependsOn: validate variables: - template: ../common-variables.yml displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - - job: publish_symbols + - job: displayName: Symbol Publishing dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) @@ -30,15 +28,16 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets + displayName: Download Blob Artifacts + inputs: + artifactName: 'BlobArtifacts' continueOnError: true + + - task: DownloadBuildArtifacts@0 + displayName: Download PDB Artifacts inputs: - buildType: 'current' - downloadType: 'specific' - itemPattern: | - PDBArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' + artifactName: 'PDBArtifacts' + continueOnError: true # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here @@ -65,11 +64,6 @@ stages: /p:Configuration=Release ${{ parameters.symbolPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - job: publish_assets displayName: Publish Assets dependsOn: setupMaestroVars @@ -83,16 +77,24 @@ stages: vmImage: 'windows-2019' steps: - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts continueOnError: true + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts inputs: - buildType: 'current' - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' + buildType: current + artifactName: BlobArtifacts + continueOnError: true + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' @@ -132,6 +134,7 @@ stages: /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) + /p:PublishToAzureDevOpsNuGetFeeds=true /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' @@ -140,11 +143,6 @@ stages: /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' ${{ parameters.artifactsPublishingAdditionalParameters }} - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - template: ../../steps/promote-build.yml parameters: ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 9505cf170f..216d043e4e 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,7 +4,7 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - + # .NET Core 3.1 Dev - name: PublicDevRelease_31_Channel_Id value: 128 @@ -49,10 +49,6 @@ variables: - name: NetCore_31_Blazor_Features_Channel_Id value: 531 - # .NET Core Experimental - - name: NetCore_Experimental_Channel_Id - value: 562 - # Whether the build is internal or not - name: IsInternalBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 8a8d84f202..b121d77e07 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -17,14 +17,11 @@ parameters: signingValidationAdditionalParameters: '' # Which stages should finish execution before post-build stages start - validateDependsOn: - - build - publishDependsOn: - - Validate + dependsOn: [build] stages: -- stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} +- stage: validate + dependsOn: ${{ parameters.dependsOn }} displayName: Validate jobs: - ${{ if eq(parameters.enableNugetValidation, 'true') }}: @@ -49,28 +46,20 @@ stages: - ${{ if eq(parameters.enableSigningValidation, 'true') }}: - job: displayName: Signing Validation - variables: - - template: common-variables.yml pool: vmImage: 'windows-2019' steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here # otherwise it'll complain about accessing a private feed. - task: NuGetAuthenticate@0 displayName: 'Authenticate to AzDO Feeds' - - task: PowerShell@2 - displayName: Enable cross-org publishing + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) + buildType: current + artifactName: PackageArtifacts - task: PowerShell@2 displayName: Validate @@ -79,13 +68,9 @@ stages: arguments: -task SigningValidation -restore -msbuildEngine dotnet /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + /p:Configuration=Release ${{ parameters.signingValidationAdditionalParameters }} - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - - ${{ if eq(parameters.enableSourceLinkValidation, 'true') }}: - job: displayName: SourceLink Validation @@ -121,7 +106,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NetCore_Dev5_Publish' @@ -134,7 +118,18 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Dev31_Publish' + channelName: '.NET Core 3.1 Dev' + channelId: 128 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Latest_Publish' @@ -147,7 +142,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'Net_Eng_Validation_Publish' @@ -160,7 +154,90 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Validation_Publish' + channelName: '.NET 3 Tools - Validation' + channelId: 390 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Publish' + channelName: '.NET 3 Tools' + channelId: 344 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release30_Publish' + channelName: '.NET Core 3.0 Release' + channelId: 19 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release31_Publish' + channelName: '.NET Core 3.1 Release' + channelId: 129 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Blazor31_Features_Publish' + channelName: '.NET Core 3.1 Blazor Features' + channelId: 531 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_30_Internal_Servicing_Publishing' + channelName: '.NET Core 3.0 Internal Servicing' + channelId: 184 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_31_Internal_Servicing_Publishing' + channelName: '.NET Core 3.1 Internal Servicing' + channelId: 550 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'General_Testing_Publish' @@ -173,7 +250,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Dev_Publishing' @@ -186,7 +262,6 @@ stages: - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} stageName: 'NETCore_Tooling_Release_Publishing' @@ -196,28 +271,74 @@ stages: shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_301xx_Publishing' + channelName: '.NET Core SDK 3.0.1xx' + channelId: 556 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NET_Internal_Tooling_Publishing' - channelName: '.NET Internal Tooling' - channelId: 551 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json' + stageName: 'NETCore_SDK_301xx_Internal_Publishing' + channelName: '.NET Core SDK 3.0.1xx Internal' + channelId: 555 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' - template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Experimental_Publishing' - channelName: '.NET Core Experimental' - channelId: 562 - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json' + stageName: 'NETCore_SDK_311xx_Publishing' + channelName: '.NET Core SDK 3.1.1xx' + channelId: 560 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_311xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.1xx Internal' + channelId: 559 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Publishing' + channelName: '.NET Core SDK 3.1.2xx' + channelId: 558 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.2xx Internal' + channelId: 557 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 716b53f740..56242b068e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -4,8 +4,6 @@ jobs: pool: vmImage: 'windows-2019' steps: - - checkout: none - - task: DownloadBuildArtifacts@0 displayName: Download Release Configs inputs: @@ -16,25 +14,5 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - targetType: inline - script: | - try { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - - $Channels = "" - $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - - $IsStableBuild = $Content | Select -Index 2 - - Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" - Write-Host "##vso[task.setvariable variable=InitialChannels;isOutput=true]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } + filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 + arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml deleted file mode 100644 index f91751fe78..0000000000 --- a/eng/common/templates/steps/publish-logs.yml +++ /dev/null @@ -1,23 +0,0 @@ -parameters: - StageLabel: '' - JobLabel: '' - -steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 30becf01ea..05df886f55 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -23,7 +23,6 @@ parameters: 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." IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting int) Creator: '' # optional -- if the build is external, use this to specify who is sending the job DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() @@ -56,7 +55,6 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) @@ -87,7 +85,6 @@ steps: DotNetCliVersion: ${{ parameters.DotNetCliVersion }} EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index d3a432878e..92a053bd16 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -5,7 +5,7 @@ [bool]$ci = if (Test-Path variable:ci) { $ci } else { $false } # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names. -[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { 'Debug' } +[string]$configuration = if (Test-Path variable:configuration) { $configuration } else { "Debug" } # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build. # Binary log must be enabled on CI. @@ -24,7 +24,7 @@ [bool]$restore = if (Test-Path variable:restore) { $restore } else { $true } # Adjusts msbuild verbosity level. -[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { 'minimal' } +[string]$verbosity = if (Test-Path variable:verbosity) { $verbosity } else { "minimal" } # Set to true to reuse msbuild nodes. Recommended to not reuse on CI. [bool]$nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { !$ci } @@ -41,23 +41,21 @@ # 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' } +[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 } # An array of names of processes to stop on script exit if prepareMachine is true. -$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @('msbuild', 'dotnet', 'vbcscompiler') } - -$disableConfigureToolsetImport = if (Test-Path variable:disableConfigureToolsetImport) { $disableConfigureToolsetImport } else { $null } +$processesToStopOnExit = if (Test-Path variable:processesToStopOnExit) { $processesToStopOnExit } else { @("msbuild", "dotnet", "vbcscompiler") } set-strictmode -version 2.0 -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = "Stop" [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Create-Directory([string[]] $path) { if (!(Test-Path $path)) { - New-Item -path $path -force -itemType 'Directory' | Out-Null + New-Item -path $path -force -itemType "Directory" | Out-Null } } @@ -98,10 +96,7 @@ function Exec-Process([string]$command, [string]$commandArgs) { } } -# createSdkLocationFile parameter enables a file being generated under the toolset directory -# which writes the sdk's location into. This is only necessary for cmd --> powershell invocations -# as dot sourcing isn't possible. -function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { +function InitializeDotNetCli([bool]$install) { if (Test-Path variable:global:_DotNetInstallDir) { return $global:_DotNetInstallDir } @@ -124,7 +119,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Find the first path on %PATH% that contains the dotnet.exe if ($useInstalledDotNetCli -and (-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -eq $null)) { - $dotnetCmd = Get-Command 'dotnet.exe' -ErrorAction SilentlyContinue + $dotnetCmd = Get-Command "dotnet.exe" -ErrorAction SilentlyContinue if ($dotnetCmd -ne $null) { $env:DOTNET_INSTALL_DIR = Split-Path $dotnetCmd.Path -Parent } @@ -137,13 +132,13 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { if ((-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -ne $null) -and (Test-Path(Join-Path $env:DOTNET_INSTALL_DIR "sdk\$dotnetSdkVersion"))) { $dotnetRoot = $env:DOTNET_INSTALL_DIR } else { - $dotnetRoot = Join-Path $RepoRoot '.dotnet' + $dotnetRoot = Join-Path $RepoRoot ".dotnet" if (-not (Test-Path(Join-Path $dotnetRoot "sdk\$dotnetSdkVersion"))) { if ($install) { InstallDotNetSdk $dotnetRoot $dotnetSdkVersion } else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unable to find dotnet with SDK version '$dotnetSdkVersion'" ExitWithExitCode 1 } } @@ -151,24 +146,6 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { $env:DOTNET_INSTALL_DIR = $dotnetRoot } - # Creates a temporary file under the toolset dir. - # The following code block is protecting against concurrent access so that this function can - # be called in parallel. - if ($createSdkLocationFile) { - do { - $sdkCacheFileTemp = Join-Path $ToolsetDir $([System.IO.Path]::GetRandomFileName()) - } - until (!(Test-Path $sdkCacheFileTemp)) - Set-Content -Path $sdkCacheFileTemp -Value $dotnetRoot - - try { - Rename-Item -Force -Path $sdkCacheFileTemp 'sdk.txt' - } catch { - # Somebody beat us - Remove-Item -Path $sdkCacheFileTemp - } - } - # Add dotnet to PATH. This prevents any bare invocation of dotnet in custom # build steps from using anything other than what we've downloaded. # It also ensures that VS msbuild will use the downloaded sdk targets. @@ -177,6 +154,15 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot + # Work around issues with Azure Artifacts credential provider + # https://github.com/dotnet/arcade/issues/3932 + if ($ci) { + $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 + $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' + Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' + } + Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' @@ -184,7 +170,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { } function GetDotNetInstallScript([string] $dotnetRoot) { - $installScript = Join-Path $dotnetRoot 'dotnet-install.ps1' + $installScript = Join-Path $dotnetRoot "dotnet-install.ps1" if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit @@ -194,17 +180,17 @@ function GetDotNetInstallScript([string] $dotnetRoot) { return $installScript } -function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = '') { +function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $architecture = "") { InstallDotNet $dotnetRoot $version $architecture } function InstallDotNet([string] $dotnetRoot, [string] $version, - [string] $architecture = '', - [string] $runtime = '', + [string] $architecture = "", + [string] $runtime = "", [bool] $skipNonVersionedFiles = $false, - [string] $runtimeSourceFeed = '', - [string] $runtimeSourceFeedKey = '') { + [string] $runtimeSourceFeed = "", + [string] $runtimeSourceFeedKey = "") { $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ @@ -220,7 +206,7 @@ function InstallDotNet([string] $dotnetRoot, & $installScript @installParameters } catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet runtime '$runtime' from public location." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Failed to install dotnet runtime '$runtime' from public location." # Only the runtime can be installed from a custom [private] location. if ($runtime -and ($runtimeSourceFeed -or $runtimeSourceFeedKey)) { @@ -236,7 +222,7 @@ function InstallDotNet([string] $dotnetRoot, & $installScript @installParameters } catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet runtime '$runtime' from custom location '$runtimeSourceFeed'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Failed to install dotnet runtime '$runtime' from custom location '$runtimeSourceFeed'." ExitWithExitCode 1 } } else { @@ -262,16 +248,16 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { '15.9' } + $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { "15.9" } $vsMinVersion = [Version]::new($vsMinVersionStr) # Try msbuild command available in the environment. if ($env:VSINSTALLDIR -ne $null) { - $msbuildCmd = Get-Command 'msbuild.exe' -ErrorAction SilentlyContinue + $msbuildCmd = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue if ($msbuildCmd -ne $null) { # Workaround for https://github.com/dotnet/roslyn/issues/35793 # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+ - $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split([char[]]@('-', '+'))[0]) + $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0]) if ($msbuildVersion -ge $vsMinVersion) { return $global:_MSBuildExe = $msbuildCmd.Path @@ -291,20 +277,17 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = InitializeVisualStudioEnvironmentVariables $vsInstallDir $vsMajorVersion } else { - if (Get-Member -InputObject $GlobalJson.tools -Name 'xcopy-msbuild') { + if (Get-Member -InputObject $GlobalJson.tools -Name "xcopy-msbuild") { $xcopyMSBuildVersion = $GlobalJson.tools.'xcopy-msbuild' $vsMajorVersion = $xcopyMSBuildVersion.Split('.')[0] } else { $vsMajorVersion = $vsMinVersion.Major $xcopyMSBuildVersion = "$vsMajorVersion.$($vsMinVersion.Minor).0-alpha" } - - $vsInstallDir = $null - if ($xcopyMSBuildVersion.Trim() -ine "none") { - $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install - } + + $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install if ($vsInstallDir -eq $null) { - throw 'Unable to find Visual Studio that has required version and components installed' + throw "Unable to find Visual Studio that has required version and components installed" } } @@ -328,7 +311,7 @@ function InstallXCopyMSBuild([string]$packageVersion) { } function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { - $packageName = 'RoslynTools.MSBuild' + $packageName = "RoslynTools.MSBuild" $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion" $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" @@ -344,7 +327,7 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { Unzip $packagePath $packageDir } - return Join-Path $packageDir 'tools' + return Join-Path $packageDir "tools" } # @@ -361,32 +344,32 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { # or $null if no instance meeting the requirements is found on the machine. # function LocateVisualStudio([object]$vsRequirements = $null){ - if (Get-Member -InputObject $GlobalJson.tools -Name 'vswhere') { + if (Get-Member -InputObject $GlobalJson.tools -Name "vswhere") { $vswhereVersion = $GlobalJson.tools.vswhere } else { - $vswhereVersion = '2.5.2' + $vswhereVersion = "2.5.2" } $vsWhereDir = Join-Path $ToolsDir "vswhere\$vswhereVersion" - $vsWhereExe = Join-Path $vsWhereDir 'vswhere.exe' + $vsWhereExe = Join-Path $vsWhereDir "vswhere.exe" if (!(Test-Path $vsWhereExe)) { Create-Directory $vsWhereDir - Write-Host 'Downloading vswhere' + Write-Host "Downloading vswhere" Invoke-WebRequest "https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } - $args = @('-latest', '-prerelease', '-format', 'json', '-requires', 'Microsoft.Component.MSBuild', '-products', '*') + $args = @("-latest", "-prerelease", "-format", "json", "-requires", "Microsoft.Component.MSBuild", "-products", "*") - if (Get-Member -InputObject $vsRequirements -Name 'version') { - $args += '-version' + if (Get-Member -InputObject $vsRequirements -Name "version") { + $args += "-version" $args += $vsRequirements.version } - if (Get-Member -InputObject $vsRequirements -Name 'components') { + if (Get-Member -InputObject $vsRequirements -Name "components") { foreach ($component in $vsRequirements.components) { - $args += '-requires' + $args += "-requires" $args += $component } } @@ -412,27 +395,27 @@ function InitializeBuildTool() { # Initialize dotnet cli if listed in 'tools' $dotnetRoot = $null - if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { + if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { $dotnetRoot = InitializeDotNetCli -install:$restore } - if ($msbuildEngine -eq 'dotnet') { + if ($msbuildEngine -eq "dotnet") { if (!$dotnetRoot) { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "/global.json must specify 'tools.dotnet'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "/global.json must specify 'tools.dotnet'." ExitWithExitCode 1 } - $buildTool = @{ Path = Join-Path $dotnetRoot 'dotnet.exe'; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'netcoreapp2.1' } + $buildTool = @{ Path = Join-Path $dotnetRoot "dotnet.exe"; Command = "msbuild"; Tool = "dotnet"; Framework = "netcoreapp2.1" } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore } catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ + Write-PipelineTelemetryError -Category "InitializeToolset" -Message $_ ExitWithExitCode 1 } $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "net472" } } else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." ExitWithExitCode 1 } @@ -441,15 +424,15 @@ function InitializeBuildTool() { function GetDefaultMSBuildEngine() { # Presence of tools.vs indicates the repo needs to build using VS msbuild on Windows. - if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { - return 'vs' + if (Get-Member -InputObject $GlobalJson.tools -Name "vs") { + return "vs" } - if (Get-Member -InputObject $GlobalJson.tools -Name 'dotnet') { - return 'dotnet' + if (Get-Member -InputObject $GlobalJson.tools -Name "dotnet") { + return "dotnet" } - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'." ExitWithExitCode 1 } @@ -458,9 +441,9 @@ function GetNuGetPackageCachePath() { # Use local cache on CI to ensure deterministic build, # use global cache in dev builds to avoid cost of downloading packages. if ($useGlobalNuGetCache) { - $env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages' + $env:NUGET_PACKAGES = Join-Path $env:UserProfile ".nuget\packages" } else { - $env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages' + $env:NUGET_PACKAGES = Join-Path $RepoRoot ".packages" } } @@ -473,7 +456,7 @@ function GetSdkTaskProject([string]$taskName) { } function InitializeNativeTools() { - if (-Not (Test-Path variable:DisableNativeToolsetInstalls) -And (Get-Member -InputObject $GlobalJson -Name "native-tools")) { + if (Get-Member -InputObject $GlobalJson -Name "native-tools") { $nativeArgs= @{} if ($ci) { $nativeArgs = @{ @@ -502,14 +485,14 @@ function InitializeToolset() { } if (-not $restore) { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Toolset version $toolsetVersion has not been restored." + Write-PipelineTelemetryError -Category "InitializeToolset" -Message "Toolset version $toolsetVersion has not been restored." ExitWithExitCode 1 } $buildTool = InitializeBuildTool - $proj = Join-Path $ToolsetDir 'restore.proj' - $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'ToolsetRestore.binlog') } else { '' } + $proj = Join-Path $ToolsetDir "restore.proj" + $bl = if ($binaryLog) { "/bl:" + (Join-Path $LogDir "ToolsetRestore.binlog") } else { "" } '' | Set-Content $proj @@ -531,7 +514,7 @@ function ExitWithExitCode([int] $exitCode) { } function Stop-Processes() { - Write-Host 'Killing running build processes...' + Write-Host "Killing running build processes..." foreach ($processName in $processesToStopOnExit) { Get-Process -Name $processName -ErrorAction SilentlyContinue | Stop-Process } @@ -548,18 +531,13 @@ function MSBuild() { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 - if ($ci -and $buildTool.Tool -eq 'dotnet') { + if ($ci -and $buildTool.Tool -eq "dotnet") { dotnet nuget locals http-cache -c - - $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 - $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } $toolsetBuildProject = InitializeToolset $path = Split-Path -parent $toolsetBuildProject - $path = Join-Path $path (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll') + $path = Join-Path $path (Join-Path $buildTool.Framework "Microsoft.DotNet.Arcade.Sdk.dll") $args += "/logger:$path" } @@ -574,12 +552,12 @@ function MSBuild() { function MSBuild-Core() { if ($ci) { if (!$binaryLog) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build.' + Write-PipelineTaskError -Message "Binary log must be enabled in CI build." ExitWithExitCode 1 } if ($nodeReuse) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Node reuse must be disabled in CI build.' + Write-PipelineTaskError -Message "Node reuse must be disabled in CI build." ExitWithExitCode 1 } } @@ -589,10 +567,10 @@ function MSBuild-Core() { $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci" if ($warnAsError) { - $cmdArgs += ' /warnaserror /p:TreatWarningsAsErrors=true' + $cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true" } else { - $cmdArgs += ' /p:TreatWarningsAsErrors=false' + $cmdArgs += " /p:TreatWarningsAsErrors=false" } foreach ($arg in $args) { @@ -604,7 +582,7 @@ function MSBuild-Core() { $exitCode = Exec-Process $buildTool.Path $cmdArgs if ($exitCode -ne 0) { - Write-PipelineTelemetryError Category 'Build' -Message 'Build failed.' + Write-PipelineTaskError -Message "Build failed." $buildLog = GetMSBuildBinaryLogCommandLineArgument $args if ($buildLog -ne $null) { @@ -619,12 +597,12 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { foreach ($argument in $arguments) { if ($argument -ne $null) { $arg = $argument.Trim() - if ($arg.StartsWith('/bl:', "OrdinalIgnoreCase")) { - return $arg.Substring('/bl:'.Length) + if ($arg.StartsWith("/bl:", "OrdinalIgnoreCase")) { + return $arg.Substring("/bl:".Length) } - if ($arg.StartsWith('/binaryLogger:', 'OrdinalIgnoreCase')) { - return $arg.Substring('/binaryLogger:'.Length) + if ($arg.StartsWith("/binaryLogger:", "OrdinalIgnoreCase")) { + return $arg.Substring("/binaryLogger:".Length) } } } @@ -634,14 +612,14 @@ function GetMSBuildBinaryLogCommandLineArgument($arguments) { . $PSScriptRoot\pipeline-logging-functions.ps1 -$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..') -$EngRoot = Resolve-Path (Join-Path $PSScriptRoot '..') -$ArtifactsDir = Join-Path $RepoRoot 'artifacts' -$ToolsetDir = Join-Path $ArtifactsDir 'toolset' -$ToolsDir = Join-Path $RepoRoot '.tools' -$LogDir = Join-Path (Join-Path $ArtifactsDir 'log') $configuration -$TempDir = Join-Path (Join-Path $ArtifactsDir 'tmp') $configuration -$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot 'global.json') | ConvertFrom-Json +$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") +$EngRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +$ArtifactsDir = Join-Path $RepoRoot "artifacts" +$ToolsetDir = Join-Path $ArtifactsDir "toolset" +$ToolsDir = Join-Path $RepoRoot ".tools" +$LogDir = Join-Path (Join-Path $ArtifactsDir "log") $configuration +$TempDir = Join-Path (Join-Path $ArtifactsDir "tmp") $configuration +$GlobalJson = Get-Content -Raw -Path (Join-Path $RepoRoot "global.json") | ConvertFrom-Json # true if global.json contains a "runtimes" section $globalJsonHasRuntimes = if ($GlobalJson.tools.PSObject.Properties.Name -Match 'runtimes') { $true } else { $false } @@ -654,18 +632,3 @@ Write-PipelineSetVariable -Name 'Artifacts.Toolset' -Value $ToolsetDir Write-PipelineSetVariable -Name 'Artifacts.Log' -Value $LogDir Write-PipelineSetVariable -Name 'TEMP' -Value $TempDir Write-PipelineSetVariable -Name 'TMP' -Value $TempDir - -# Import custom tools configuration, if present in the repo. -# Note: Import in global scope so that the script set top-level variables without qualification. -if (!$disableConfigureToolsetImport) { - $configureToolsetScript = Join-Path $EngRoot 'configure-toolset.ps1' - if (Test-Path $configureToolsetScript) { - . $configureToolsetScript - if ((Test-Path variable:failOnConfigureToolsetError) -And $failOnConfigureToolsetError) { - if ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) { - Write-PipelineTelemetryError -Category 'Build' -Message 'configure-toolset.ps1 returned a non-zero exit code' - ExitWithExitCode $LastExitCode - } - } - } -} diff --git a/eng/common/tools.sh b/eng/common/tools.sh index e071af4ee4..94965a8fd2 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -81,7 +81,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'Build' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -152,6 +152,15 @@ function InitializeDotNetCli { # build steps from using anything other than what we've downloaded. Write-PipelinePrependPath -path "$dotnet_root" + # Work around issues with Azure Artifacts credential provider + # https://github.com/dotnet/arcade/issues/3932 + if [[ "$ci" == true ]]; then + export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 + export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 + Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" + Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + fi + Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" @@ -274,9 +283,6 @@ function GetNuGetPackageCachePath { } function InitializeNativeTools() { - if [[ -n "${DisableNativeToolsetInstalls:-}" ]]; then - return - fi if grep -Fq "native-tools" $global_json_file then local nativeArgs="" @@ -326,7 +332,7 @@ function InitializeToolset { local toolset_build_proj=`cat "$toolset_location_file"` if [[ ! -a "$toolset_build_proj" ]]; then - Write-PipelineTelemetryError -category 'Build' "Invalid toolset path: $toolset_build_proj" + Write-PipelineTelemetryError -category 'InitializeToolset' "Invalid toolset path: $toolset_build_proj" ExitWithExitCode 3 fi @@ -357,12 +363,7 @@ function MSBuild { # Work around issues with Azure Artifacts credential provider # https://github.com/dotnet/arcade/issues/3932 if [[ "$ci" == true ]]; then - "$_InitializeBuildTool" nuget locals http-cache -c - - export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 - export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 - Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" - Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + dotnet nuget locals http-cache -c fi local toolset_dir="${_InitializeToolset%/*}" @@ -376,12 +377,12 @@ function MSBuild { function MSBuild-Core { if [[ "$ci" == true ]]; then if [[ "$binary_log" != true ]]; then - Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build." + Write-PipelineTaskError "Binary log must be enabled in CI build." ExitWithExitCode 1 fi if [[ "$node_reuse" == true ]]; then - Write-PipelineTelemetryError -category 'Build' "Node reuse must be disabled in CI build." + Write-PipelineTaskError "Node reuse must be disabled in CI build." ExitWithExitCode 1 fi fi @@ -395,7 +396,7 @@ function MSBuild-Core { "$_InitializeBuildTool" "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" || { local exit_code=$? - Write-PipelineTelemetryError -category 'Build' "Build failed (exit code '$exit_code')." + Write-PipelineTaskError "Build failed (exit code '$exit_code')." ExitWithExitCode $exit_code } } @@ -436,18 +437,3 @@ 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" - -# Import custom tools configuration, if present in the repo. -if [ -z "${disable_configure_toolset_import:-}" ]; then - configure_toolset_script="$eng_root/configure-toolset.sh" - if [[ -a "$configure_toolset_script" ]]; then - . "$configure_toolset_script" - fi -fi - -# TODO: https://github.com/dotnet/arcade/issues/1468 -# Temporary workaround to avoid breaking change. -# Remove once repos are updated. -if [[ -n "${useInstalledDotNetCli:-}" ]]; then - use_installed_dotnet_cli="$useInstalledDotNetCli" -fi diff --git a/global.json b/global.json index 51d8c790fc..f12de76387 100644 --- a/global.json +++ b/global.json @@ -4,12 +4,13 @@ "vs": { "version": "16.3", "components": [ + "Microsoft.Net.Core.Component.SDK.2.1", "Microsoft.VisualStudio.Component.FSharp" ] } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20057.5", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19616.5", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From f98a8abaabf26edba58ad3d87b087deb71d6b7e3 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Wed, 8 Jan 2020 19:39:01 -0800 Subject: [PATCH 017/101] Command line help + tests --- src/fsharp/LanguageFeatures.fs | 4 ++-- .../fsc/langversion/langversionhelp.437.1033.bsl | 3 +-- .../fsi/langversion/langversionhelp.437.1033.bsl | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 6909cfcf5c..016ccd535a 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -42,7 +42,7 @@ type LanguageVersion (specifiedVersionAsString) = static let latestMajorVersion = languageVersion47 // Language version when latestmajor specified static let validOptions = [| "preview"; "default"; "latest"; "latestmajor" |] - static let languageVersions = set [| languageVersion46; languageVersion47; languageVersion50 |] + static let languageVersions = set [| languageVersion46; languageVersion47 (*; languageVersion50 *) |] static let features = dict [ @@ -72,7 +72,7 @@ type LanguageVersion (specifiedVersionAsString) = | "latestmajor" -> latestMajorVersion | "4.6" -> languageVersion46 | "4.7" -> languageVersion47 - | "5.0" -> languageVersion50 +(* | "5.0" -> languageVersion50 *) | _ -> 0m /// Check if this feature is supported by the selected langversion diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/langversion/langversionhelp.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsc/langversion/langversionhelp.437.1033.bsl index b7f6805220..83fd0bfa99 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/langversion/langversionhelp.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/langversion/langversionhelp.437.1033.bsl @@ -4,5 +4,4 @@ default latest latestmajor 4.6 -4.7 -5.0 (Default) \ No newline at end of file +4.7 (Default) \ No newline at end of file diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/langversion/langversionhelp.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/langversion/langversionhelp.437.1033.bsl index b7f6805220..83fd0bfa99 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/langversion/langversionhelp.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/langversion/langversionhelp.437.1033.bsl @@ -4,5 +4,4 @@ default latest latestmajor 4.6 -4.7 -5.0 (Default) \ No newline at end of file +4.7 (Default) \ No newline at end of file From d1467431e9db01a47cba93f3f1123d37a2364ea6 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Wed, 8 Jan 2020 22:35:07 -0800 Subject: [PATCH 018/101] Version it --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index acb04ff55b..f7611980e0 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,7 +24,7 @@ 10.7 - $(FSPackageMajorVersion).0 + $(FSPackageMajorVersion).1 $(FSPackageVersion) $(FSPackageVersion).0 From 75375024d835666ba8c40c586a622fabc2ab879b Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Thu, 9 Jan 2020 00:00:15 -0800 Subject: [PATCH 019/101] Correctly identify default --- src/fsharp/LanguageFeatures.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 016ccd535a..eeac561751 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -37,7 +37,7 @@ type LanguageVersion (specifiedVersionAsString) = static let languageVersion47 = 4.7m static let languageVersion50 = 5.0m static let previewVersion = 9999m // Language version when preview specified - static let defaultVersion = languageVersion50 // Language version when default specified + static let defaultVersion = languageVersion47 // Language version when default specified static let latestVersion = defaultVersion // Language version when latest specified static let latestMajorVersion = languageVersion47 // Language version when latestmajor specified From f7ef22af5b68de7fcac20e2ebf074afedd7326e8 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Thu, 9 Jan 2020 20:40:17 -0800 Subject: [PATCH 020/101] Fix merge issue with dotnet files (#8163) --- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index f8750b1387..cc91a60360 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -32,10 +32,10 @@ Microsoft.FSharp.NetSdk.props - {{FSharpCoreShippedVersion}} - $(FSharpCoreShippedVersion) - {{FSharpCorePreviewVersion}} - $(FSharpCorePreviewVersion) + {{FSharpCoreShippedPackageVersion}} + $(FSharpCoreShippedPackageVersion) + {{FSharpCorePreviewPackageVersion}} + $(FSharpCorePreviewPackageVersion) From 613d69c58d35099c9d3a4437e4568982ac766f5d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 13 Jan 2020 05:44:08 +0000 Subject: [PATCH 021/101] Document baseline update and allow tests to run in debug mode without assert (#8149) * document baseline update and allow tests to run in debug mode without assert * Update DEVGUIDE.md * Update DEVGUIDE.md * Update readme.md --- src/fsharp/IlxGen.fs | 1 - tests/fsharpqa/readme.md | 14 ++++++++++++++ tests/fsharpqa/testenv/bin/runall.pl | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 18be85e72a..9534358624 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5089,7 +5089,6 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau | _ -> error(InternalError("these matches should never be needed", switchm)) and GenDecisionTreeCases cenv cgbuf stackAtTargets eenv defaultTargetOpt targets repeatSP targetInfos sequel caseLabels cases (contf: Zmap<_,_> -> FakeUnit) = - assert(cgbuf.GetCurrentStack() = stackAtTargets) // cgbuf stack should be unchanged over tests. [bug://1750]. match defaultTargetOpt with | Some defaultTarget -> diff --git a/tests/fsharpqa/readme.md b/tests/fsharpqa/readme.md index 88bda09b36..ecdcd63bde 100644 --- a/tests/fsharpqa/readme.md +++ b/tests/fsharpqa/readme.md @@ -32,3 +32,17 @@ A convenience "fsharpqafiles.csproj" project is located in the fsharp.sln soluti (TODO, provide some guidance about how to define env.lst files) +## Updating baselines in tests + +Some tests use "baseline" files. There is sometimes a way to update these baselines en-masse in your local build, +useful when some change affects many baselines. For example, in the 'fsharpqa' tests the baselines +are updated using scripts or utilities that allow the following environment variable to be set: + +``` +set TEST_UPDATE_BSL=1 +``` + +Updating baselines en-masse should be done very carefully and subject to careful code review. Where possible the +compiler change causing the en-masse update should be isolated and minimized so it is obvious at review time that no other +code generation chagnes will be caused. + diff --git a/tests/fsharpqa/testenv/bin/runall.pl b/tests/fsharpqa/testenv/bin/runall.pl index 045a0076de..53be793355 100644 --- a/tests/fsharpqa/testenv/bin/runall.pl +++ b/tests/fsharpqa/testenv/bin/runall.pl @@ -147,7 +147,7 @@ my $FILE_ERROR_EXITVAL = 5; my $OTHER_ERROR_EXITVAL = 9; -my $perl = $Config{perlpath}; +my $perl = $^X; BEGIN { @required_mods = ("Win32\\Process.pm"); From e99777ccc3bfc15e964f25cd0d640eb7eae2a593 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 13 Jan 2020 07:47:54 -0800 Subject: [PATCH 022/101] Use for..in..do instead of List.iter to prevent function allocations (#8175) --- src/fsharp/PostInferenceChecks.fs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 1730f88bd2..2420e636d2 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -322,14 +322,14 @@ let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, v // In an ideal world we would, instead, record the solutions to these constraints as "witness variables" in expressions, // rather than solely in types. match ty with - | TType_var tp when tp.Solution.IsSome -> - tp.Constraints |> List.iter (fun cx -> + | TType_var tp when tp.Solution.IsSome -> + for cx in tp.Constraints do match cx with | TyparConstraint.MayResolveMember((TTrait(_, _, _, _, _, soln)), _) -> match visitTraitSolutionOpt, !soln with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () - | _ -> ()) + | _ -> () | _ -> () let ty = @@ -379,10 +379,12 @@ let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, v visitTyar (env, tp) and CheckTypesDeep cenv f g env tys = - tys |> List.iter (CheckTypeDeep cenv f g env true) + for ty in tys do + CheckTypeDeep cenv f g env true ty and CheckTypesDeepNoInner cenv f g env tys = - tys |> List.iter (CheckTypeDeep cenv f g env false) + for ty in tys do + CheckTypeDeep cenv f g env false ty and CheckTypeConstraintDeep cenv f g env x = match x with From 4b15d8dd416499cbc833ec321d0b54b654e2a436 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 13 Jan 2020 10:59:07 -0800 Subject: [PATCH 023/101] Scripting package (#8173) --- .../FSharp.Compiler.Private.Scripting.fsproj | 1 + .../FSharp.Compiler.Private.Scripting.nuspec | 5 +++- src/utils/CompilerLocationUtils.fs | 25 ++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.fsproj b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.fsproj index ac31809c48..8a49e311df 100644 --- a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.fsproj +++ b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.fsproj @@ -21,6 +21,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.nuspec b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.nuspec index ef9ff88ca4..42a7c538eb 100644 --- a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.nuspec +++ b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharp.Compiler.Private.Scripting.nuspec @@ -5,17 +5,20 @@ en-US - $CommonFileElements$ + + + + diff --git a/src/utils/CompilerLocationUtils.fs b/src/utils/CompilerLocationUtils.fs index 204af8f412..923ab41843 100644 --- a/src/utils/CompilerLocationUtils.fs +++ b/src/utils/CompilerLocationUtils.fs @@ -182,10 +182,6 @@ module internal FSharpEnvironment = // - default location of fsi.exe in FSharp.VS.FSI.dll (REVIEW: check this) // - default F# binaries directory in (project system) Project.fs let BinFolderOfDefaultFSharpCompiler(probePoint:string option) = -#if FX_NO_WIN_REGISTRY - ignore probePoint - Some AppDomain.CurrentDomain.BaseDirectory -#else // Check for an app.config setting to redirect the default compiler location // Like fsharp-compiler-location try @@ -200,18 +196,17 @@ module internal FSharpEnvironment = // Look in the probePoint if given, e.g. look for a compiler alongside of FSharp.Build.dll match probePoint with | Some p when safeExists (Path.Combine(p,"FSharp.Core.dll")) -> Some p - | _ -> - - // We let you set FSHARP_COMPILER_BIN. I've rarely seen this used and its not documented in the install instructions. - let result = Environment.GetEnvironmentVariable("FSHARP_COMPILER_BIN") - if not (String.IsNullOrEmpty(result)) then - Some result - else - // For the prototype compiler, we can just use the current domain - tryCurrentDomain() + | _ -> + // We let you set FSHARP_COMPILER_BIN. I've rarely seen this used and its not documented in the install instructions. + let result = Environment.GetEnvironmentVariable("FSHARP_COMPILER_BIN") + if not (String.IsNullOrEmpty(result)) then + Some result + else + // For the prototype compiler, we can just use the current domain + tryCurrentDomain() with e -> None - +#if !FX_NO_WIN_REGISTRY // Apply the given function to the registry entry corresponding to the subKey. // The reg key is disposed at the end of the scope. let useKey subKey f = @@ -236,7 +231,7 @@ module internal FSharpEnvironment = IsNetFx45OrAboveInstalledAt @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client" || IsNetFx45OrAboveInstalledAt @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" || runningOnMono - + // Check if the running framework version is 4.5 or above. // Use the presence of v4.5.x in the registry to distinguish between 4.0 and 4.5 let IsRunningOnNetFx45OrAbove = From e1559cfa75e24b90aa1a8ec4788bb7464d3ca971 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Tue, 14 Jan 2020 12:03:07 -0800 Subject: [PATCH 024/101] Path to dotnet tools that supports 4.8 --- eng/Build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index d68a683f29..b1bac65054 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -221,7 +221,7 @@ function UpdatePath() { TestAndAddToPath $subdir # add windows SDK dir for ildasm.exe - foreach ($child in Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.?.? Tools") { + foreach ($child in Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.* Tools") { $subdir = $child } TestAndAddToPath $subdir From f9e70262e83c032fbe6340dec6064350ad1edb64 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 14 Jan 2020 18:31:46 -0800 Subject: [PATCH 025/101] restore templates removed in #7379 (#8205) --- VisualFSharp.sln | 63 + vsintegration/ProjectTemplates/.gitignore | 2 + .../ConsoleProject/ConsoleProject.csproj | 18 + .../ConsoleProject/Template/App.config | 6 + .../ConsoleProject/Template/AssemblyInfo.fs | 41 + .../Template/ConsoleApplication.fsproj | 65 + .../Template/ConsoleApplication.vstemplate | 33 + .../ConsoleProject/Template/Program.fs | 7 + .../Template/xlf/AssemblyInfo.fs.cs.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.de.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.es.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.fr.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.it.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ja.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ko.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.pl.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.pt-BR.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ru.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.tr.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.zh-Hans.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.zh-Hant.xlf | 77 + .../Template/xlf/Program.fs.cs.xlf | 22 + .../Template/xlf/Program.fs.de.xlf | 22 + .../Template/xlf/Program.fs.es.xlf | 22 + .../Template/xlf/Program.fs.fr.xlf | 22 + .../Template/xlf/Program.fs.it.xlf | 22 + .../Template/xlf/Program.fs.ja.xlf | 22 + .../Template/xlf/Program.fs.ko.xlf | 22 + .../Template/xlf/Program.fs.pl.xlf | 22 + .../Template/xlf/Program.fs.pt-BR.xlf | 22 + .../Template/xlf/Program.fs.ru.xlf | 22 + .../Template/xlf/Program.fs.tr.xlf | 22 + .../Template/xlf/Program.fs.zh-Hans.xlf | 22 + .../Template/xlf/Program.fs.zh-Hant.xlf | 22 + .../source.extension.vsixmanifest | 24 + .../ProjectTemplates/Directory.Build.props | 10 + .../ProjectTemplates/Directory.Build.targets | 3 + .../LibraryProject/LibraryProject.csproj | 18 + .../LibraryProject/Template/AssemblyInfo.fs | 41 + .../LibraryProject/Template/Library.fsproj | 61 + .../Template/Library.vstemplate | 33 + .../LibraryProject/Template/Library1.fs | 4 + .../LibraryProject/Template/Script.fsx | 8 + .../Template/xlf/AssemblyInfo.fs.cs.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.de.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.es.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.fr.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.it.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ja.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ko.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.pl.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.pt-BR.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.ru.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.tr.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.zh-Hans.xlf | 77 + .../Template/xlf/AssemblyInfo.fs.zh-Hant.xlf | 77 + .../Template/xlf/Script.fsx.cs.xlf | 22 + .../Template/xlf/Script.fsx.de.xlf | 22 + .../Template/xlf/Script.fsx.es.xlf | 22 + .../Template/xlf/Script.fsx.fr.xlf | 22 + .../Template/xlf/Script.fsx.it.xlf | 22 + .../Template/xlf/Script.fsx.ja.xlf | 22 + .../Template/xlf/Script.fsx.ko.xlf | 22 + .../Template/xlf/Script.fsx.pl.xlf | 22 + .../Template/xlf/Script.fsx.pt-BR.xlf | 22 + .../Template/xlf/Script.fsx.ru.xlf | 22 + .../Template/xlf/Script.fsx.tr.xlf | 22 + .../Template/xlf/Script.fsx.zh-Hans.xlf | 22 + .../Template/xlf/Script.fsx.zh-Hant.xlf | 22 + .../source.extension.vsixmanifest | 25 + .../TutorialProject/Template/Tutorial.fsproj | 66 + .../TutorialProject/Template/Tutorial.fsx | 997 ++++++++++ .../Template/Tutorial.vstemplate | 31 + .../Template/xlf/Tutorial.fsx.cs.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.de.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.es.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.fr.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.it.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.ja.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.ko.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.pl.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.pt-BR.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.ru.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.tr.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.zh-Hans.xlf | 1637 +++++++++++++++++ .../Template/xlf/Tutorial.fsx.zh-Hant.xlf | 1637 +++++++++++++++++ .../TutorialProject/TutorialProject.csproj | 17 + .../source.extension.vsixmanifest | 25 + .../Source.extension.vsixmanifest | 28 + .../VisualFSharpTemplates.csproj | 60 + vsintegration/readme.md | 4 + 91 files changed, 25545 insertions(+) create mode 100644 vsintegration/ProjectTemplates/.gitignore create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/App.config create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/AssemblyInfo.fs create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.fsproj create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.vstemplate create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/Program.fs create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.cs.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.de.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.es.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.fr.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.it.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ja.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ko.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pl.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ru.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.tr.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.cs.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.de.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.es.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.fr.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.it.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ja.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ko.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pl.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pt-BR.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ru.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.tr.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hans.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hant.xlf create mode 100644 vsintegration/ProjectTemplates/ConsoleProject/source.extension.vsixmanifest create mode 100644 vsintegration/ProjectTemplates/Directory.Build.props create mode 100644 vsintegration/ProjectTemplates/Directory.Build.targets create mode 100644 vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/AssemblyInfo.fs create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/Library.fsproj create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/Library.vstemplate create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/Library1.fs create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/Script.fsx create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.cs.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.de.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.es.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.fr.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.it.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ja.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ko.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pl.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ru.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.tr.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.cs.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.de.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.es.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.fr.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.it.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ja.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ko.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pl.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pt-BR.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ru.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.tr.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hans.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hant.xlf create mode 100644 vsintegration/ProjectTemplates/LibraryProject/source.extension.vsixmanifest create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsproj create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsx create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.vstemplate create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.cs.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.de.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.es.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.fr.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.it.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ja.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ko.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pl.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pt-BR.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ru.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.tr.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hans.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hant.xlf create mode 100644 vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj create mode 100644 vsintegration/ProjectTemplates/TutorialProject/source.extension.vsixmanifest create mode 100644 vsintegration/Vsix/VisualFSharpTemplates/Source.extension.vsixmanifest create mode 100644 vsintegration/Vsix/VisualFSharpTemplates/VisualFSharpTemplates.csproj diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 37ea6f1aef..76bcf8369e 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -158,6 +158,16 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.UnitTests", "tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj", "{AF7AE565-E1C4-4A24-BD4B-D7983FC84768}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualFSharpTemplates", "vsintegration\Vsix\VisualFSharpTemplates\VisualFSharpTemplates.csproj", "{AA259A37-418F-4E18-87B2-C7D5F8C26CC4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProjectTemplates", "ProjectTemplates", "{12EF27FD-A34B-4373-860A-F9FCE9651859}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleProject", "vsintegration\ProjectTemplates\ConsoleProject\ConsoleProject.csproj", "{44155269-9B30-43DA-B97F-4F36F887B211}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryProject", "vsintegration\ProjectTemplates\LibraryProject\LibraryProject.csproj", "{B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TutorialProject", "vsintegration\ProjectTemplates\TutorialProject\TutorialProject.csproj", "{2937CBEC-262D-4C94-BE1D-291FAB72E3E8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -924,6 +934,54 @@ Global {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|Any CPU.Build.0 = Release|Any CPU {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.ActiveCfg = Release|Any CPU {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.Build.0 = Release|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|x86.Build.0 = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Proto|Any CPU.Build.0 = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Proto|x86.ActiveCfg = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Proto|x86.Build.0 = Debug|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Release|Any CPU.Build.0 = Release|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Release|x86.ActiveCfg = Release|Any CPU + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Release|x86.Build.0 = Release|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Debug|x86.ActiveCfg = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Debug|x86.Build.0 = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Proto|Any CPU.Build.0 = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Proto|x86.ActiveCfg = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Proto|x86.Build.0 = Debug|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Release|Any CPU.Build.0 = Release|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Release|x86.ActiveCfg = Release|Any CPU + {44155269-9B30-43DA-B97F-4F36F887B211}.Release|x86.Build.0 = Release|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Debug|x86.ActiveCfg = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Debug|x86.Build.0 = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Proto|Any CPU.Build.0 = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Proto|x86.ActiveCfg = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Proto|x86.Build.0 = Debug|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Release|Any CPU.Build.0 = Release|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Release|x86.ActiveCfg = Release|Any CPU + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8}.Release|x86.Build.0 = Release|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Debug|x86.ActiveCfg = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Debug|x86.Build.0 = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Proto|Any CPU.Build.0 = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Proto|x86.ActiveCfg = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Proto|x86.Build.0 = Debug|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|Any CPU.Build.0 = Release|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|x86.ActiveCfg = Release|Any CPU + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -998,6 +1056,11 @@ Global {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {DFA30881-C0B1-4813-B087-C21B5AF9B77F} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {AF7AE565-E1C4-4A24-BD4B-D7983FC84768} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} + {AA259A37-418F-4E18-87B2-C7D5F8C26CC4} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} + {12EF27FD-A34B-4373-860A-F9FCE9651859} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} + {44155269-9B30-43DA-B97F-4F36F887B211} = {12EF27FD-A34B-4373-860A-F9FCE9651859} + {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8} = {12EF27FD-A34B-4373-860A-F9FCE9651859} + {2937CBEC-262D-4C94-BE1D-291FAB72E3E8} = {12EF27FD-A34B-4373-860A-F9FCE9651859} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37} diff --git a/vsintegration/ProjectTemplates/.gitignore b/vsintegration/ProjectTemplates/.gitignore new file mode 100644 index 0000000000..cd42ee34e8 --- /dev/null +++ b/vsintegration/ProjectTemplates/.gitignore @@ -0,0 +1,2 @@ +bin/ +obj/ diff --git a/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj b/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj new file mode 100644 index 0000000000..82e55b95ec --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj @@ -0,0 +1,18 @@ + + + + + + ConsoleProject + + + + + + Template\AssemblyInfo.fs; + Template\Program.fs; + + + + + diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/App.config b/vsintegration/ProjectTemplates/ConsoleProject/Template/App.config new file mode 100644 index 0000000000..7301b90379 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/App.config @@ -0,0 +1,6 @@ + + + + $if$ ($targetframeworkversion$ >= 4.0)$endif$$if$ ($targetframeworkversion$ < 4.0)$endif$ + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/AssemblyInfo.fs b/vsintegration/ProjectTemplates/ConsoleProject/Template/AssemblyInfo.fs new file mode 100644 index 0000000000..ae735840e6 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/AssemblyInfo.fs @@ -0,0 +1,41 @@ +namespace $safeprojectname$.AssemblyInfo + +open System.Reflection +open System.Runtime.CompilerServices +open System.Runtime.InteropServices + +// @@@GeneralInfo-Line1|General Information about an assembly is controlled through the following@@@ +// @@@GeneralInfo-Line2|set of attributes. Change these attribute values to modify the information@@@ +// @@@GeneralInfo-Line3|associated with an assembly.@@@ +[] +[] +[] +[] +[] +[] +[] +[] + +// @@@ComVisible-Line1|Setting ComVisible to false makes the types in this assembly not visible@@@ +// @@@ComVisible-Line2|to COM components. If you need to access a type in this assembly from@@@ +// @@@ComVisible-Line3|COM, set the ComVisible attribute to true on that type.@@@ +[] + +// @@@Guid-Line1|The following GUID is for the ID of the typelib if this project is exposed to COM@@@ +[] + +// @@@VersionInfo-Line1|Version information for an assembly consists of the following four values:@@@ +// +// @@@MajorVersion|Major Version@@@ +// @@@MinorVersion|Minor Version@@@ +// @@@BuildNumber|Build Number@@@ +// @@@Revision|Revision@@@ +// +// @@@VersionInfo-Line2|You can specify all the values or you can default the Build and Revision Numbers@@@ +// @@@VersionInfo-Line3|by using the '*' as shown below:@@@ +// [] +[] +[] + +do + () \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.fsproj b/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.fsproj new file mode 100644 index 0000000000..19c297de5e --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.fsproj @@ -0,0 +1,65 @@ + + + + + Debug + AnyCPU + 2.0 + $guid1$ + Exe + $safeprojectname$ + $safeprojectname$ + v$targetframeworkversion$ + true + true + 3239;$(WarningsAsErrors) + + + true + full + false + false + bin\$(Configuration)\ + DEBUG;TRACE + 3 + AnyCPU + bin\$(Configuration)\$(AssemblyName).XML + true + + + pdbonly + true + true + bin\$(Configuration)\ + TRACE + 3 + AnyCPU + bin\$(Configuration)\$(AssemblyName).XML + true + + + + + + + + + + + + + + 11 + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.vstemplate b/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.vstemplate new file mode 100644 index 0000000000..fea0279b94 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/ConsoleApplication.vstemplate @@ -0,0 +1,33 @@ + + + + + + + Microsoft.FSharp.Application + FSharp + 4.5 + 1 + true + ConsoleApplication + true + true + + + + AssemblyInfo.fs + Program.fs + App.config + + + + NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + NuGet.VisualStudio.TemplateWizard + + + + + + + + diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/Program.fs b/vsintegration/ProjectTemplates/ConsoleProject/Template/Program.fs new file mode 100644 index 0000000000..93b7275510 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/Program.fs @@ -0,0 +1,7 @@ +// @@@LearnMore|Learn more about F# at https://fsharp.org@@@ +// @@@SeeTutorial|See the 'F# Tutorial' project for more help.@@@ + +[] +let main argv = + printfn "%A" argv + 0 // @@@Return|return an integer exit code@@@ diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.cs.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.cs.xlf new file mode 100644 index 0000000000..a580d9e396 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.cs.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Obecné informace o sestavení se řídí přes následující + + + + set of attributes. Change these attribute values to modify the information + sadu atributů. Změnou hodnot těchto atributů se upraví informace + + + + associated with an assembly. + přidružené k sestavení. + + + + Setting ComVisible to false makes the types in this assembly not visible + Nastavením atributu ComVisible na hodnotu False budou typy v tomto sestavení neviditelné + + + + to COM components. If you need to access a type in this assembly from + pro komponenty modelu COM. Pokud potřebujete přistoupit k typu v tomto sestavení z + + + + COM, set the ComVisible attribute to true on that type. + modelu COM, nastavte atribut ComVisible daného typu na hodnotu True. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Následující GUID se používá pro ID knihovny typů, pokud je tento projekt vystavený pro COM. + + + + Version information for an assembly consists of the following four values: + Informace o verzi sestavení se skládá z těchto čtyř hodnot: + + + + Major Version + Hlavní verze + + + + Minor Version + Podverze + + + + Build Number + Číslo sestavení + + + + Revision + Revize + + + + You can specify all the values or you can default the Build and Revision Numbers + Můžete zadat všechny hodnoty nebo nechat nastavená výchozí čísla sestavení a revize + + + + by using the '*' as shown below: + pomocí zástupného znaku * takto: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.de.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.de.xlf new file mode 100644 index 0000000000..8df6ae7fc3 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.de.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Allgemeine Informationen über eine Assembly werden über die folgende + + + + set of attributes. Change these attribute values to modify the information + Attributgruppe gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, + + + + associated with an assembly. + die einer Assembly zugeordnet sind. + + + + Setting ComVisible to false makes the types in this assembly not visible + Durch Festlegen von ComVisible auf FALSE sind die Typen in dieser Assembly nicht + + + + to COM components. If you need to access a type in this assembly from + für COM-Komponenten sichtbar. Wenn Sie auf einen Typ in dieser Assembly von + + + + COM, set the ComVisible attribute to true on that type. + COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf TRUE festlegen. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird + + + + Version information for an assembly consists of the following four values: + Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: + + + + Major Version + Hauptversion + + + + Minor Version + Nebenversion + + + + Build Number + Buildnummer + + + + Revision + Revision + + + + You can specify all the values or you can default the Build and Revision Numbers + Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern + + + + by using the '*' as shown below: + übernehmen, indem Sie "*" eingeben: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.es.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.es.xlf new file mode 100644 index 0000000000..9beb403796 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.es.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + La información general de un ensamblado se controla mediante el siguiente + + + + set of attributes. Change these attribute values to modify the information + conjunto de atributos. Cambie estos valores de atributo para modificar la información + + + + associated with an assembly. + asociada con un ensamblado. + + + + Setting ComVisible to false makes the types in this assembly not visible + Si establece ComVisible en false, los tipos de este ensamblado no estarán visibles + + + + to COM components. If you need to access a type in this assembly from + para los componentes COM. Si necesita obtener acceso a un tipo de este ensamblado desde + + + + COM, set the ComVisible attribute to true on that type. + COM, establezca el atributo ComVisible en true en este tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + El siguiente GUID sirve como id. de typelib si este proyecto se expone a COM. + + + + Version information for an assembly consists of the following four values: + La información de versión de un ensamblado consta de los cuatro valores siguientes: + + + + Major Version + Versión principal + + + + Minor Version + Versión secundaria + + + + Build Number + Número de compilación + + + + Revision + Revisión + + + + You can specify all the values or you can default the Build and Revision Numbers + Puede especificar todos los valores o usar los valores predeterminados de número de compilación y de revisión + + + + by using the '*' as shown below: + mediante el carácter '*', como se muestra a continuación: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.fr.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.fr.xlf new file mode 100644 index 0000000000..a259bd3051 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.fr.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Les informations générales relatives à un assembly dépendent de + + + + set of attributes. Change these attribute values to modify the information + l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations + + + + associated with an assembly. + associées à un assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly + + + + to COM components. If you need to access a type in this assembly from + aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de + + + + COM, set the ComVisible attribute to true on that type. + COM, affectez la valeur true à l'attribut ComVisible sur ce type. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM + + + + Version information for an assembly consists of the following four values: + Les informations de version pour un assembly se composent des quatre valeurs suivantes : + + + + Major Version + Version principale + + + + Minor Version + Version secondaire + + + + Build Number + Numéro de build + + + + Revision + Révision + + + + You can specify all the values or you can default the Build and Revision Numbers + Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut + + + + by using the '*' as shown below: + en utilisant '*', comme indiqué ci-dessous : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.it.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.it.xlf new file mode 100644 index 0000000000..d5fc6c7558 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.it.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Le informazioni generali relative a un assembly sono controllate dal seguente + + + + set of attributes. Change these attribute values to modify the information + set di attributi. Modificare i valori di questi attributi per modificare le informazioni + + + + associated with an assembly. + associate a un assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili + + + + to COM components. If you need to access a type in this assembly from + ai componenti COM. Se è necessario accedere a un tipo in questo assembly da + + + + COM, set the ComVisible attribute to true on that type. + COM, impostare su true l'attributo ComVisible per tale tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Se il progetto viene esposto a COM, il seguente GUID verrà utilizzato come ID della libreria dei tipi + + + + Version information for an assembly consists of the following four values: + Le informazioni sulla versione di un assembly sono costituite dai quattro valori seguenti: + + + + Major Version + Versione principale + + + + Minor Version + Versione secondaria + + + + Build Number + Numero di build + + + + Revision + Revisione + + + + You can specify all the values or you can default the Build and Revision Numbers + È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build + + + + by using the '*' as shown below: + utilizzando l'asterisco (*) come illustrato di seguito: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ja.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ja.xlf new file mode 100644 index 0000000000..1f413753d1 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ja.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + アセンブリに関する一般情報は、以下の属性セットによって + + + + set of attributes. Change these attribute values to modify the information + 制御されます。アセンブリに関連付けられている情報を変更するには、 + + + + associated with an assembly. + これらの属性値を変更します。 + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 + + + + to COM components. If you need to access a type in this assembly from + できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 + + + + COM, set the ComVisible attribute to true on that type. + その型の ComVisible 属性を true に設定します。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります + + + + Version information for an assembly consists of the following four values: + アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: + + + + Major Version + メジャー バージョン + + + + Minor Version + マイナー バージョン + + + + Build Number + ビルド番号 + + + + Revision + リビジョン + + + + You can specify all the values or you can default the Build and Revision Numbers + すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を + + + + by using the '*' as shown below: + 既定値にすることができます。: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ko.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ko.xlf new file mode 100644 index 0000000000..258b4ebab2 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ko.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 어셈블리의 일반 정보는 다음 특성 집합을 통해 + + + + set of attributes. Change these attribute values to modify the information + 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 + + + + associated with an assembly. + 이러한 특성 값을 변경하세요. + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 + + + + to COM components. If you need to access a type in this assembly from + 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 + + + + COM, set the ComVisible attribute to true on that type. + 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. + + + + Version information for an assembly consists of the following four values: + 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.: + + + + Major Version + 주 버전 + + + + Minor Version + 부 버전 + + + + Build Number + 빌드 번호 + + + + Revision + 수정 버전 + + + + You can specify all the values or you can default the Build and Revision Numbers + 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로 + + + + by using the '*' as shown below: + 지정되도록 할 수 있습니다.: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pl.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pl.xlf new file mode 100644 index 0000000000..ee3471fb55 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pl.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Ogólne informacje o zestawie są kontrolowane poprzez następujący + + + + set of attributes. Change these attribute values to modify the information + zbiór atrybutów. Zmień wartości tych atrybutów by zmodyfikować informacje + + + + associated with an assembly. + powiązane z zestawem. + + + + Setting ComVisible to false makes the types in this assembly not visible + Ustawienie wartości ComVisible na false sprawia, że typy w tym zestawie nie będą widoczne + + + + to COM components. If you need to access a type in this assembly from + dla składników COM. Jeśli potrzebny jest dostęp do typu w tym zestawie z + + + + COM, set the ComVisible attribute to true on that type. + COM, ustaw atrybut ComVisible na true dla danego typu. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Następujący GUID jest dla ID typelib jeśli ten projekt jest dostępny dla COM + + + + Version information for an assembly consists of the following four values: + Informacje o wersji zestawu zawierają następujące cztery wartości: + + + + Major Version + Wersja główna + + + + Minor Version + Wersja pomocnicza + + + + Build Number + Numer kompilacji + + + + Revision + Poprawka + + + + You can specify all the values or you can default the Build and Revision Numbers + Można określać wszystkie wartości lub używać domyślnych numerów kompilacji i poprawki + + + + by using the '*' as shown below: + przy użyciu symbolu „*”, tak jak pokazano poniżej: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf new file mode 100644 index 0000000000..48d258faa2 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + As informações gerais sobre um assembly são controladas por meio do seguinte + + + + set of attributes. Change these attribute values to modify the information + conjunto de atributos. Altere estes valores de atributo para modificar as informações + + + + associated with an assembly. + associados a um assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + Definir ComVisible como false oculta os tipos neste assembly + + + + to COM components. If you need to access a type in this assembly from + para componentes COM. Caso precise acessar um tipo neste assembly a partir de + + + + COM, set the ComVisible attribute to true on that type. + COM, defina o atributo ComVisible como true nesse tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + O GUID a seguir é para a ID de typelib quando este projeto é exposto a COM + + + + Version information for an assembly consists of the following four values: + As informações da versão de um assembly consistem nos quatro valores a seguir: + + + + Major Version + Versão Principal + + + + Minor Version + Versão Secundária + + + + Build Number + Número da Versão + + + + Revision + Revisão + + + + You can specify all the values or you can default the Build and Revision Numbers + É possível especificar todos os valores ou usar como padrão os Números da Versão e da Revisão + + + + by using the '*' as shown below: + utilizando o '*' como mostrado abaixo: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ru.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ru.xlf new file mode 100644 index 0000000000..c0f2735eae --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.ru.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Общие сведения о сборке можно задать с помощью следующего + + + + set of attributes. Change these attribute values to modify the information + набора атрибутов. Отредактируйте эти значения атрибутов, чтобы изменить сведения, + + + + associated with an assembly. + связанные с этой сборкой. + + + + Setting ComVisible to false makes the types in this assembly not visible + При установке значения False в атрибуте ComVisible типы в этой сборке становятся невидимыми + + + + to COM components. If you need to access a type in this assembly from + для COM-компонентов. Если требуется обратиться к типу в этой сборке через + + + + COM, set the ComVisible attribute to true on that type. + COM, задайте для атрибута ComVisible значение True для этого типа. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Следующий GUID служит для идентификации библиотеки типов, если этот проект видим для COM + + + + Version information for an assembly consists of the following four values: + Сведения о версии сборки состоят из следующих четырех значений: + + + + Major Version + Основной номер версии + + + + Minor Version + Вспомогательная версия + + + + Build Number + Номер сборки + + + + Revision + Редакция + + + + You can specify all the values or you can default the Build and Revision Numbers + Можно задать все значения или принять номера сборки и редакции по умолчанию + + + + by using the '*' as shown below: + используя "*", как показано ниже: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.tr.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.tr.xlf new file mode 100644 index 0000000000..906ec8f3ef --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.tr.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Bir bütünleştirilmiş koda ilişkin Genel Bilgiler aşağıdaki + + + + set of attributes. Change these attribute values to modify the information + öznitelikler kümesi. Bilgileri değiştirmek için bu öznitelik değerlerini değiştirin + + + + associated with an assembly. + Bir bütünleştirilmiş kod ile ilişkilendirildi. + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible ayarının false olarak belirlenmesi bu derlemedeki türleri + + + + to COM components. If you need to access a type in this assembly from + COM bileşenlerine görünmez yapar. Bu derlemedeki bir türe COM'dan + + + + COM, set the ComVisible attribute to true on that type. + erişmeniz gerekirse ComVisible özniteliğini o türde true olarak ayarlayın. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Eğer bu proje COM'a maruz kaldıysa aşağıdaki GUID typelib'in IDsi içindir + + + + Version information for an assembly consists of the following four values: + Bir derlemenin sürüm bilgileri aşağıdaki dört değerden oluşur: + + + + Major Version + Birincil Sürüm + + + + Minor Version + İkincil Sürüm + + + + Build Number + Yapı Numarası + + + + Revision + Düzeltme + + + + You can specify all the values or you can default the Build and Revision Numbers + Tüm değerleri belirtebilir veya varsayılan Oluşturma ve Düzeltme Numaralarını kullanabilirsiniz + + + + by using the '*' as shown below: + '*' karakterini aşağıda gösterildiği gibi kullanarak: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf new file mode 100644 index 0000000000..d76c9dbd18 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 有关程序集的一般信息由以下 + + + + set of attributes. Change these attribute values to modify the information + 控制。更改这些特性值可修改 + + + + associated with an assembly. + 与程序集关联的信息。 + + + + Setting ComVisible to false makes the types in this assembly not visible + 将 ComVisible 设置为 false 将使此程序集中的类型 + + + + to COM components. If you need to access a type in this assembly from + 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, + + + + COM, set the ComVisible attribute to true on that type. + 请将此类型的 ComVisible 特性设置为 true。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID + + + + Version information for an assembly consists of the following four values: + 程序集的版本信息由下列四个值组成: + + + + Major Version + 主版本 + + + + Minor Version + 次版本 + + + + Build Number + 生成号 + + + + Revision + 修订 + + + + You can specify all the values or you can default the Build and Revision Numbers + 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, + + + + by using the '*' as shown below: + 方法是按如下所示使用“*”: : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf new file mode 100644 index 0000000000..477f8719df --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 組件的一般資訊是由下列的屬性集控制 + + + + set of attributes. Change these attribute values to modify the information + 變更這些屬性的值即可修改組件的相關 + + + + associated with an assembly. + 資訊。 + + + + Setting ComVisible to false makes the types in this assembly not visible + 將 ComVisible 設定為 false 會使得這個組件中的類型 + + + + to COM components. If you need to access a type in this assembly from + 對 COM 元件而言為不可見。如果您需要從 COM 存取這個組件中 + + + + COM, set the ComVisible attribute to true on that type. + 的類型,請在該類型上將 ComVisible 屬性設定為 true。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID + + + + Version information for an assembly consists of the following four values: + 組件的版本資訊由下列四個值所組成: : + + + + Major Version + 主要版本 + + + + Minor Version + 次要版本 + + + + Build Number + 組建編號 + + + + Revision + 修訂 + + + + You can specify all the values or you can default the Build and Revision Numbers + 您可以指定所有的值,也可以依照以下的方式,使用 '*' 將組建和修訂編號 + + + + by using the '*' as shown below: + 指定為預設值: : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.cs.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.cs.xlf new file mode 100644 index 0000000000..0a1913fea3 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.cs.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Další informace o F# najdete na https://fsharp.org. + + + + See the 'F# Tutorial' project for more help. + Pokud potřebujete další nápovědu, viz projekt Výukový kurz F#. + + + + return an integer exit code + vrátit celočíselný ukončovací kód + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.de.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.de.xlf new file mode 100644 index 0000000000..8c434e9d7d --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.de.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Weitere Informationen zu F# unter https://fsharp.org. + + + + See the 'F# Tutorial' project for more help. + Weitere Hilfe finden Sie im Projekt "F#-Tutorial". + + + + return an integer exit code + Integer-Exitcode zurückgeben + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.es.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.es.xlf new file mode 100644 index 0000000000..1472966885 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.es.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Más información sobre F# en https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Vea el proyecto "Tutorial de F#" para obtener más ayuda. + + + + return an integer exit code + devolver un código de salida entero + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.fr.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.fr.xlf new file mode 100644 index 0000000000..8052d98708 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.fr.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + En savoir plus sur F# : https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Voir le projet 'Didacticiel F#' pour obtenir de l'aide. + + + + return an integer exit code + retourne du code de sortie entier + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.it.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.it.xlf new file mode 100644 index 0000000000..c9027ad5b6 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.it.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Altre informazioni su F# disponibili all'indirizzo https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Per altre informazioni, vedere il progetto 'Esercitazione su F#'. + + + + return an integer exit code + restituisce un intero come codice di uscita + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ja.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ja.xlf new file mode 100644 index 0000000000..c24608aec3 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ja.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + F# の詳細については、https://fsharp.org をご覧ください + + + + See the 'F# Tutorial' project for more help. + 詳細については、'F# チュートリアル' プロジェクトを参照してください。 + + + + return an integer exit code + 整数の終了コードを返します + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ko.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ko.xlf new file mode 100644 index 0000000000..7d9f7dc54e --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ko.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + https://fsharp.org에서 F#에 대해 자세히 알아보기 + + + + See the 'F# Tutorial' project for more help. + 자세한 도움말은 'F# 자습서' 프로젝트를 참조하세요. + + + + return an integer exit code + 정수 종료 코드 반환 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pl.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pl.xlf new file mode 100644 index 0000000000..763d2db3df --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pl.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Dowiedz się więcej o języku F# na stronie https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Aby uzyskać dodatkową pomoc, zobacz projekt „Samouczek języka F#”. + + + + return an integer exit code + zwracanie kodu zakończenia w postaci liczby całkowitej + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pt-BR.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pt-BR.xlf new file mode 100644 index 0000000000..7af54cd8fd --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.pt-BR.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Saiba mais sobre o F# em https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Veja o projeto 'F# Tutorial' para obter mais ajuda. + + + + return an integer exit code + retornar um código de saída inteiro + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ru.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ru.xlf new file mode 100644 index 0000000000..54eb018503 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.ru.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Дополнительные сведения об F# см. на странице https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Дополнительную справку см. в проекте "Учебник по F#". + + + + return an integer exit code + возвращение целочисленного кода выхода + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.tr.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.tr.xlf new file mode 100644 index 0000000000..c584140b66 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.tr.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + F# hakkında daha fazla bilgi edinmek için bkz. https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Daha fazla yardım almak için 'F# Öğreticisi' projesine göz atın. + + + + return an integer exit code + bir tamsayı çıkış kodu döndürür + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hans.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hans.xlf new file mode 100644 index 0000000000..27df727dbd --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hans.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + 了解更多关于 F# 的信息,请访问 https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + 请参阅“F# 教程”项目以获取更多帮助。 + + + + return an integer exit code + 返回整数退出代码 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hant.xlf b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hant.xlf new file mode 100644 index 0000000000..5f67238de8 --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/Template/xlf/Program.fs.zh-Hant.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + 前往 https://fsharp.org 深入了解 F# + + + + See the 'F# Tutorial' project for more help. + 請參閱「F# 教學課程」專案,取得更多說明。 + + + + return an integer exit code + 傳回整數的結束代碼 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/ConsoleProject/source.extension.vsixmanifest b/vsintegration/ProjectTemplates/ConsoleProject/source.extension.vsixmanifest new file mode 100644 index 0000000000..5f28d2c06e --- /dev/null +++ b/vsintegration/ProjectTemplates/ConsoleProject/source.extension.vsixmanifest @@ -0,0 +1,24 @@ + + + + + F# .NETCore Project Templates + F# project templates for .NETCore. + + + + + + + + + + + + + + + + + + diff --git a/vsintegration/ProjectTemplates/Directory.Build.props b/vsintegration/ProjectTemplates/Directory.Build.props new file mode 100644 index 0000000000..49fb4e2d1f --- /dev/null +++ b/vsintegration/ProjectTemplates/Directory.Build.props @@ -0,0 +1,10 @@ + + + + ProjectTemplates + Microsoft.FSharp + + + + + diff --git a/vsintegration/ProjectTemplates/Directory.Build.targets b/vsintegration/ProjectTemplates/Directory.Build.targets new file mode 100644 index 0000000000..6dd437b28f --- /dev/null +++ b/vsintegration/ProjectTemplates/Directory.Build.targets @@ -0,0 +1,3 @@ + + + diff --git a/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj b/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj new file mode 100644 index 0000000000..23239f0047 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj @@ -0,0 +1,18 @@ + + + + + + LibraryProject + + + + + + Template\AssemblyInfo.fs; + Template\Script.fsx; + + + + + diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/AssemblyInfo.fs b/vsintegration/ProjectTemplates/LibraryProject/Template/AssemblyInfo.fs new file mode 100644 index 0000000000..ae735840e6 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/AssemblyInfo.fs @@ -0,0 +1,41 @@ +namespace $safeprojectname$.AssemblyInfo + +open System.Reflection +open System.Runtime.CompilerServices +open System.Runtime.InteropServices + +// @@@GeneralInfo-Line1|General Information about an assembly is controlled through the following@@@ +// @@@GeneralInfo-Line2|set of attributes. Change these attribute values to modify the information@@@ +// @@@GeneralInfo-Line3|associated with an assembly.@@@ +[] +[] +[] +[] +[] +[] +[] +[] + +// @@@ComVisible-Line1|Setting ComVisible to false makes the types in this assembly not visible@@@ +// @@@ComVisible-Line2|to COM components. If you need to access a type in this assembly from@@@ +// @@@ComVisible-Line3|COM, set the ComVisible attribute to true on that type.@@@ +[] + +// @@@Guid-Line1|The following GUID is for the ID of the typelib if this project is exposed to COM@@@ +[] + +// @@@VersionInfo-Line1|Version information for an assembly consists of the following four values:@@@ +// +// @@@MajorVersion|Major Version@@@ +// @@@MinorVersion|Minor Version@@@ +// @@@BuildNumber|Build Number@@@ +// @@@Revision|Revision@@@ +// +// @@@VersionInfo-Line2|You can specify all the values or you can default the Build and Revision Numbers@@@ +// @@@VersionInfo-Line3|by using the '*' as shown below:@@@ +// [] +[] +[] + +do + () \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/Library.fsproj b/vsintegration/ProjectTemplates/LibraryProject/Template/Library.fsproj new file mode 100644 index 0000000000..5878583967 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/Library.fsproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + 2.0 + $guid1$ + Library + $safeprojectname$ + $safeprojectname$ + true + v$targetframeworkversion$ + true + 3239;$(WarningsAsErrors) + + + true + full + false + false + bin\$(Configuration)\ + DEBUG;TRACE + 3 + bin\$(Configuration)\$(AssemblyName).XML + + + pdbonly + true + true + bin\$(Configuration)\ + TRACE + 3 + bin\$(Configuration)\$(AssemblyName).XML + + + + + + + + + + + + + + 11 + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/Library.vstemplate b/vsintegration/ProjectTemplates/LibraryProject/Template/Library.vstemplate new file mode 100644 index 0000000000..d7f9a14d8d --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/Library.vstemplate @@ -0,0 +1,33 @@ + + + + + + + Microsoft.FSharp.Library + FSharp + 4.5 + 1 + true + Library + true + true + + + + AssemblyInfo.fs + Library1.fs + Script.fsx + + + + NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + NuGet.VisualStudio.TemplateWizard + + + + + + + + diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/Library1.fs b/vsintegration/ProjectTemplates/LibraryProject/Template/Library1.fs new file mode 100644 index 0000000000..c8a8cd1b46 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/Library1.fs @@ -0,0 +1,4 @@ +namespace $safeprojectname$ + +type Class1() = + member this.X = "F#" diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/Script.fsx b/vsintegration/ProjectTemplates/LibraryProject/Template/Script.fsx new file mode 100644 index 0000000000..0caeb86ca6 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/Script.fsx @@ -0,0 +1,8 @@ +// @@@LearnMore|Learn more about F# at https://fsharp.org@@@ +// @@@SeeTutorial|See the 'F# Tutorial' project for more help.@@@ + +#load "Library1.fs" +open $safeprojectname$ + +// @@@Define|Define your library scripting code here@@@ + diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.cs.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.cs.xlf new file mode 100644 index 0000000000..a580d9e396 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.cs.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Obecné informace o sestavení se řídí přes následující + + + + set of attributes. Change these attribute values to modify the information + sadu atributů. Změnou hodnot těchto atributů se upraví informace + + + + associated with an assembly. + přidružené k sestavení. + + + + Setting ComVisible to false makes the types in this assembly not visible + Nastavením atributu ComVisible na hodnotu False budou typy v tomto sestavení neviditelné + + + + to COM components. If you need to access a type in this assembly from + pro komponenty modelu COM. Pokud potřebujete přistoupit k typu v tomto sestavení z + + + + COM, set the ComVisible attribute to true on that type. + modelu COM, nastavte atribut ComVisible daného typu na hodnotu True. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Následující GUID se používá pro ID knihovny typů, pokud je tento projekt vystavený pro COM. + + + + Version information for an assembly consists of the following four values: + Informace o verzi sestavení se skládá z těchto čtyř hodnot: + + + + Major Version + Hlavní verze + + + + Minor Version + Podverze + + + + Build Number + Číslo sestavení + + + + Revision + Revize + + + + You can specify all the values or you can default the Build and Revision Numbers + Můžete zadat všechny hodnoty nebo nechat nastavená výchozí čísla sestavení a revize + + + + by using the '*' as shown below: + pomocí zástupného znaku * takto: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.de.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.de.xlf new file mode 100644 index 0000000000..8df6ae7fc3 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.de.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Allgemeine Informationen über eine Assembly werden über die folgende + + + + set of attributes. Change these attribute values to modify the information + Attributgruppe gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, + + + + associated with an assembly. + die einer Assembly zugeordnet sind. + + + + Setting ComVisible to false makes the types in this assembly not visible + Durch Festlegen von ComVisible auf FALSE sind die Typen in dieser Assembly nicht + + + + to COM components. If you need to access a type in this assembly from + für COM-Komponenten sichtbar. Wenn Sie auf einen Typ in dieser Assembly von + + + + COM, set the ComVisible attribute to true on that type. + COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf TRUE festlegen. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird + + + + Version information for an assembly consists of the following four values: + Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: + + + + Major Version + Hauptversion + + + + Minor Version + Nebenversion + + + + Build Number + Buildnummer + + + + Revision + Revision + + + + You can specify all the values or you can default the Build and Revision Numbers + Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern + + + + by using the '*' as shown below: + übernehmen, indem Sie "*" eingeben: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.es.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.es.xlf new file mode 100644 index 0000000000..9beb403796 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.es.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + La información general de un ensamblado se controla mediante el siguiente + + + + set of attributes. Change these attribute values to modify the information + conjunto de atributos. Cambie estos valores de atributo para modificar la información + + + + associated with an assembly. + asociada con un ensamblado. + + + + Setting ComVisible to false makes the types in this assembly not visible + Si establece ComVisible en false, los tipos de este ensamblado no estarán visibles + + + + to COM components. If you need to access a type in this assembly from + para los componentes COM. Si necesita obtener acceso a un tipo de este ensamblado desde + + + + COM, set the ComVisible attribute to true on that type. + COM, establezca el atributo ComVisible en true en este tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + El siguiente GUID sirve como id. de typelib si este proyecto se expone a COM. + + + + Version information for an assembly consists of the following four values: + La información de versión de un ensamblado consta de los cuatro valores siguientes: + + + + Major Version + Versión principal + + + + Minor Version + Versión secundaria + + + + Build Number + Número de compilación + + + + Revision + Revisión + + + + You can specify all the values or you can default the Build and Revision Numbers + Puede especificar todos los valores o usar los valores predeterminados de número de compilación y de revisión + + + + by using the '*' as shown below: + mediante el carácter '*', como se muestra a continuación: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.fr.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.fr.xlf new file mode 100644 index 0000000000..a259bd3051 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.fr.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Les informations générales relatives à un assembly dépendent de + + + + set of attributes. Change these attribute values to modify the information + l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations + + + + associated with an assembly. + associées à un assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly + + + + to COM components. If you need to access a type in this assembly from + aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de + + + + COM, set the ComVisible attribute to true on that type. + COM, affectez la valeur true à l'attribut ComVisible sur ce type. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM + + + + Version information for an assembly consists of the following four values: + Les informations de version pour un assembly se composent des quatre valeurs suivantes : + + + + Major Version + Version principale + + + + Minor Version + Version secondaire + + + + Build Number + Numéro de build + + + + Revision + Révision + + + + You can specify all the values or you can default the Build and Revision Numbers + Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut + + + + by using the '*' as shown below: + en utilisant '*', comme indiqué ci-dessous : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.it.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.it.xlf new file mode 100644 index 0000000000..d5fc6c7558 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.it.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Le informazioni generali relative a un assembly sono controllate dal seguente + + + + set of attributes. Change these attribute values to modify the information + set di attributi. Modificare i valori di questi attributi per modificare le informazioni + + + + associated with an assembly. + associate a un assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili + + + + to COM components. If you need to access a type in this assembly from + ai componenti COM. Se è necessario accedere a un tipo in questo assembly da + + + + COM, set the ComVisible attribute to true on that type. + COM, impostare su true l'attributo ComVisible per tale tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Se il progetto viene esposto a COM, il seguente GUID verrà utilizzato come ID della libreria dei tipi + + + + Version information for an assembly consists of the following four values: + Le informazioni sulla versione di un assembly sono costituite dai quattro valori seguenti: + + + + Major Version + Versione principale + + + + Minor Version + Versione secondaria + + + + Build Number + Numero di build + + + + Revision + Revisione + + + + You can specify all the values or you can default the Build and Revision Numbers + È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build + + + + by using the '*' as shown below: + utilizzando l'asterisco (*) come illustrato di seguito: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ja.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ja.xlf new file mode 100644 index 0000000000..1f413753d1 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ja.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + アセンブリに関する一般情報は、以下の属性セットによって + + + + set of attributes. Change these attribute values to modify the information + 制御されます。アセンブリに関連付けられている情報を変更するには、 + + + + associated with an assembly. + これらの属性値を変更します。 + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 + + + + to COM components. If you need to access a type in this assembly from + できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 + + + + COM, set the ComVisible attribute to true on that type. + その型の ComVisible 属性を true に設定します。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります + + + + Version information for an assembly consists of the following four values: + アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: + + + + Major Version + メジャー バージョン + + + + Minor Version + マイナー バージョン + + + + Build Number + ビルド番号 + + + + Revision + リビジョン + + + + You can specify all the values or you can default the Build and Revision Numbers + すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を + + + + by using the '*' as shown below: + 既定値にすることができます。: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ko.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ko.xlf new file mode 100644 index 0000000000..258b4ebab2 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ko.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 어셈블리의 일반 정보는 다음 특성 집합을 통해 + + + + set of attributes. Change these attribute values to modify the information + 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 + + + + associated with an assembly. + 이러한 특성 값을 변경하세요. + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 + + + + to COM components. If you need to access a type in this assembly from + 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 + + + + COM, set the ComVisible attribute to true on that type. + 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. + + + + Version information for an assembly consists of the following four values: + 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.: + + + + Major Version + 주 버전 + + + + Minor Version + 부 버전 + + + + Build Number + 빌드 번호 + + + + Revision + 수정 버전 + + + + You can specify all the values or you can default the Build and Revision Numbers + 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로 + + + + by using the '*' as shown below: + 지정되도록 할 수 있습니다.: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pl.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pl.xlf new file mode 100644 index 0000000000..ee3471fb55 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pl.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Ogólne informacje o zestawie są kontrolowane poprzez następujący + + + + set of attributes. Change these attribute values to modify the information + zbiór atrybutów. Zmień wartości tych atrybutów by zmodyfikować informacje + + + + associated with an assembly. + powiązane z zestawem. + + + + Setting ComVisible to false makes the types in this assembly not visible + Ustawienie wartości ComVisible na false sprawia, że typy w tym zestawie nie będą widoczne + + + + to COM components. If you need to access a type in this assembly from + dla składników COM. Jeśli potrzebny jest dostęp do typu w tym zestawie z + + + + COM, set the ComVisible attribute to true on that type. + COM, ustaw atrybut ComVisible na true dla danego typu. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Następujący GUID jest dla ID typelib jeśli ten projekt jest dostępny dla COM + + + + Version information for an assembly consists of the following four values: + Informacje o wersji zestawu zawierają następujące cztery wartości: + + + + Major Version + Wersja główna + + + + Minor Version + Wersja pomocnicza + + + + Build Number + Numer kompilacji + + + + Revision + Poprawka + + + + You can specify all the values or you can default the Build and Revision Numbers + Można określać wszystkie wartości lub używać domyślnych numerów kompilacji i poprawki + + + + by using the '*' as shown below: + przy użyciu symbolu „*”, tak jak pokazano poniżej: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf new file mode 100644 index 0000000000..48d258faa2 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.pt-BR.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + As informações gerais sobre um assembly são controladas por meio do seguinte + + + + set of attributes. Change these attribute values to modify the information + conjunto de atributos. Altere estes valores de atributo para modificar as informações + + + + associated with an assembly. + associados a um assembly. + + + + Setting ComVisible to false makes the types in this assembly not visible + Definir ComVisible como false oculta os tipos neste assembly + + + + to COM components. If you need to access a type in this assembly from + para componentes COM. Caso precise acessar um tipo neste assembly a partir de + + + + COM, set the ComVisible attribute to true on that type. + COM, defina o atributo ComVisible como true nesse tipo. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + O GUID a seguir é para a ID de typelib quando este projeto é exposto a COM + + + + Version information for an assembly consists of the following four values: + As informações da versão de um assembly consistem nos quatro valores a seguir: + + + + Major Version + Versão Principal + + + + Minor Version + Versão Secundária + + + + Build Number + Número da Versão + + + + Revision + Revisão + + + + You can specify all the values or you can default the Build and Revision Numbers + É possível especificar todos os valores ou usar como padrão os Números da Versão e da Revisão + + + + by using the '*' as shown below: + utilizando o '*' como mostrado abaixo: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ru.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ru.xlf new file mode 100644 index 0000000000..c0f2735eae --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.ru.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Общие сведения о сборке можно задать с помощью следующего + + + + set of attributes. Change these attribute values to modify the information + набора атрибутов. Отредактируйте эти значения атрибутов, чтобы изменить сведения, + + + + associated with an assembly. + связанные с этой сборкой. + + + + Setting ComVisible to false makes the types in this assembly not visible + При установке значения False в атрибуте ComVisible типы в этой сборке становятся невидимыми + + + + to COM components. If you need to access a type in this assembly from + для COM-компонентов. Если требуется обратиться к типу в этой сборке через + + + + COM, set the ComVisible attribute to true on that type. + COM, задайте для атрибута ComVisible значение True для этого типа. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Следующий GUID служит для идентификации библиотеки типов, если этот проект видим для COM + + + + Version information for an assembly consists of the following four values: + Сведения о версии сборки состоят из следующих четырех значений: + + + + Major Version + Основной номер версии + + + + Minor Version + Вспомогательная версия + + + + Build Number + Номер сборки + + + + Revision + Редакция + + + + You can specify all the values or you can default the Build and Revision Numbers + Можно задать все значения или принять номера сборки и редакции по умолчанию + + + + by using the '*' as shown below: + используя "*", как показано ниже: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.tr.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.tr.xlf new file mode 100644 index 0000000000..906ec8f3ef --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.tr.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + Bir bütünleştirilmiş koda ilişkin Genel Bilgiler aşağıdaki + + + + set of attributes. Change these attribute values to modify the information + öznitelikler kümesi. Bilgileri değiştirmek için bu öznitelik değerlerini değiştirin + + + + associated with an assembly. + Bir bütünleştirilmiş kod ile ilişkilendirildi. + + + + Setting ComVisible to false makes the types in this assembly not visible + ComVisible ayarının false olarak belirlenmesi bu derlemedeki türleri + + + + to COM components. If you need to access a type in this assembly from + COM bileşenlerine görünmez yapar. Bu derlemedeki bir türe COM'dan + + + + COM, set the ComVisible attribute to true on that type. + erişmeniz gerekirse ComVisible özniteliğini o türde true olarak ayarlayın. + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + Eğer bu proje COM'a maruz kaldıysa aşağıdaki GUID typelib'in IDsi içindir + + + + Version information for an assembly consists of the following four values: + Bir derlemenin sürüm bilgileri aşağıdaki dört değerden oluşur: + + + + Major Version + Birincil Sürüm + + + + Minor Version + İkincil Sürüm + + + + Build Number + Yapı Numarası + + + + Revision + Düzeltme + + + + You can specify all the values or you can default the Build and Revision Numbers + Tüm değerleri belirtebilir veya varsayılan Oluşturma ve Düzeltme Numaralarını kullanabilirsiniz + + + + by using the '*' as shown below: + '*' karakterini aşağıda gösterildiği gibi kullanarak: + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf new file mode 100644 index 0000000000..d76c9dbd18 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hans.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 有关程序集的一般信息由以下 + + + + set of attributes. Change these attribute values to modify the information + 控制。更改这些特性值可修改 + + + + associated with an assembly. + 与程序集关联的信息。 + + + + Setting ComVisible to false makes the types in this assembly not visible + 将 ComVisible 设置为 false 将使此程序集中的类型 + + + + to COM components. If you need to access a type in this assembly from + 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, + + + + COM, set the ComVisible attribute to true on that type. + 请将此类型的 ComVisible 特性设置为 true。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID + + + + Version information for an assembly consists of the following four values: + 程序集的版本信息由下列四个值组成: + + + + Major Version + 主版本 + + + + Minor Version + 次版本 + + + + Build Number + 生成号 + + + + Revision + 修订 + + + + You can specify all the values or you can default the Build and Revision Numbers + 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, + + + + by using the '*' as shown below: + 方法是按如下所示使用“*”: : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf new file mode 100644 index 0000000000..477f8719df --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/AssemblyInfo.fs.zh-Hant.xlf @@ -0,0 +1,77 @@ + + + + + + General Information about an assembly is controlled through the following + 組件的一般資訊是由下列的屬性集控制 + + + + set of attributes. Change these attribute values to modify the information + 變更這些屬性的值即可修改組件的相關 + + + + associated with an assembly. + 資訊。 + + + + Setting ComVisible to false makes the types in this assembly not visible + 將 ComVisible 設定為 false 會使得這個組件中的類型 + + + + to COM components. If you need to access a type in this assembly from + 對 COM 元件而言為不可見。如果您需要從 COM 存取這個組件中 + + + + COM, set the ComVisible attribute to true on that type. + 的類型,請在該類型上將 ComVisible 屬性設定為 true。 + + + + The following GUID is for the ID of the typelib if this project is exposed to COM + 下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID + + + + Version information for an assembly consists of the following four values: + 組件的版本資訊由下列四個值所組成: : + + + + Major Version + 主要版本 + + + + Minor Version + 次要版本 + + + + Build Number + 組建編號 + + + + Revision + 修訂 + + + + You can specify all the values or you can default the Build and Revision Numbers + 您可以指定所有的值,也可以依照以下的方式,使用 '*' 將組建和修訂編號 + + + + by using the '*' as shown below: + 指定為預設值: : + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.cs.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.cs.xlf new file mode 100644 index 0000000000..e9771690a9 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.cs.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Další informace o F# najdete na https://fsharp.org. + + + + See the 'F# Tutorial' project for more help. + Pokud potřebujete další nápovědu, viz projekt Výukový kurz F#. + + + + Define your library scripting code here + Tady definujte skriptovací kód knihovny. + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.de.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.de.xlf new file mode 100644 index 0000000000..61df76a280 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.de.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Weitere Informationen zu F# unter https://fsharp.org. + + + + See the 'F# Tutorial' project for more help. + Weitere Hilfe finden Sie im Projekt "F#-Tutorial". + + + + Define your library scripting code here + Skriptcode für die Bibliothek hier definieren + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.es.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.es.xlf new file mode 100644 index 0000000000..96fb3d3647 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.es.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Más información sobre F# en https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Vea el proyecto "Tutorial de F#" para obtener más ayuda. + + + + Define your library scripting code here + Definir aquí el código de scripting de bibliotecas + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.fr.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.fr.xlf new file mode 100644 index 0000000000..cb48575303 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.fr.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Pour en savoir plus sur le F# : https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Voir le projet 'Didacticiel F#' pour obtenir de l'aide. + + + + Define your library scripting code here + Définir votre code de script de bibliothèque ici + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.it.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.it.xlf new file mode 100644 index 0000000000..42558ead9d --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.it.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Altre informazioni su F# disponibili all'indirizzo https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Per altre informazioni, vedere il progetto 'Esercitazione su F#'. + + + + Define your library scripting code here + Viene definito qui il codice di script della libreria + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ja.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ja.xlf new file mode 100644 index 0000000000..45967e26bf --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ja.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + F# の詳細については、https://fsharp.org をご覧ください + + + + See the 'F# Tutorial' project for more help. + 詳細については、'F# チュートリアル' プロジェクトを参照してください。 + + + + Define your library scripting code here + ここでライブラリ スクリプト コードを定義します + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ko.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ko.xlf new file mode 100644 index 0000000000..661f9e6344 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ko.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + https://fsharp.org에서 F#에 대해 자세히 알아보기 + + + + See the 'F# Tutorial' project for more help. + 자세한 도움말은 'F# 자습서' 프로젝트를 참조하세요. + + + + Define your library scripting code here + 라이브러리 스크립팅 코드를 정의합니다. + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pl.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pl.xlf new file mode 100644 index 0000000000..e32717ff70 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pl.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Dowiedz się więcej o języku F# na stronie https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Aby uzyskać dodatkową pomoc, zobacz projekt „Samouczek języka F#”. + + + + Define your library scripting code here + Tutaj zdefiniuj kod skryptu biblioteki + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pt-BR.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pt-BR.xlf new file mode 100644 index 0000000000..1bd32f9343 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.pt-BR.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Saiba mais sobre o F# em https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Veja o projeto 'F# Tutorial' para obter mais ajuda. + + + + Define your library scripting code here + Defina seu código de script de biblioteca aqui + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ru.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ru.xlf new file mode 100644 index 0000000000..b8a6d8cced --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.ru.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + Дополнительные сведения об F# см. на странице https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Дополнительную справку см. в проекте "Учебник по F#". + + + + Define your library scripting code here + Определите здесь код скрипта библиотеки + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.tr.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.tr.xlf new file mode 100644 index 0000000000..1b3c2476e6 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.tr.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + F# hakkında daha fazla bilgi edinmek için bkz. https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + Daha fazla yardım almak için 'F# Öğreticisi' projesine göz atın. + + + + Define your library scripting code here + Kitaplık betik oluşturma kodunuzu buradan tanımlayın + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hans.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hans.xlf new file mode 100644 index 0000000000..4d849f68e3 --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hans.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + 了解更多关于 F# 的信息,请访问 https://fsharp.org + + + + See the 'F# Tutorial' project for more help. + 请参阅“F# 教程”项目以获取更多帮助。 + + + + Define your library scripting code here + 在此处定义库脚本代码 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hant.xlf b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hant.xlf new file mode 100644 index 0000000000..14ed4156de --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/Template/xlf/Script.fsx.zh-Hant.xlf @@ -0,0 +1,22 @@ + + + + + + Learn more about F# at https://fsharp.org + 前往 https://fsharp.org 深入了解 F# + + + + See the 'F# Tutorial' project for more help. + 請參閱「F# 教學課程」專案,取得更多說明。 + + + + Define your library scripting code here + 在這裡定義程式庫指令碼程式碼 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/LibraryProject/source.extension.vsixmanifest b/vsintegration/ProjectTemplates/LibraryProject/source.extension.vsixmanifest new file mode 100644 index 0000000000..f5157eaa6b --- /dev/null +++ b/vsintegration/ProjectTemplates/LibraryProject/source.extension.vsixmanifest @@ -0,0 +1,25 @@ + + + + + F# .NETCore Project Templates + F# project templates for .NETCore. + + + + + + + + + + + + + + + + + + + diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsproj b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsproj new file mode 100644 index 0000000000..dd2eed1525 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + 2.0 + $guid1$ + Exe + $safeprojectname$ + $safeprojectname$ + v$targetframeworkversion$ + true + true + true + 3239;$(WarningsAsErrors) + + + true + full + false + false + bin\$(Configuration)\ + DEBUG;TRACE + 3 + AnyCPU + bin\$(Configuration)\$(AssemblyName).XML + true + + + pdbonly + true + true + bin\$(Configuration)\ + TRACE + 3 + AnyCPU + bin\$(Configuration)\$(AssemblyName).XML + true + + + + + + + + + + + + + + 11 + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsx b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsx new file mode 100644 index 0000000000..52b6649ca3 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsx @@ -0,0 +1,997 @@ +// @@@SampleHeader|This sample will guide you through elements of the F# language.@@@ +// +// ******************************************************************************************************* +// @@@Instructions-Line1|To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click@@@ +// @@@Instructions-Line2|and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu.@@@ +// ******************************************************************************************************* +// +// @@@MoreAbout|For more about F#, see:@@@ +// https://fsharp.org +// https://docs.microsoft.com/en-us/dotnet/articles/fsharp/ +// +// @@@SeeDocumentaton|To see this tutorial in documentation form, see:@@@ +// https://docs.microsoft.com/en-us/dotnet/articles/fsharp/tour +// +// @@@LearnMoreAbout|To learn more about applied F# programming, use@@@ +// https://fsharp.org/guides/enterprise/ +// https://fsharp.org/guides/cloud/ +// https://fsharp.org/guides/web/ +// https://fsharp.org/guides/data-science/ +// +// @@@ToInstall-Line1|To install the Visual F# Power Tools, use@@@ +// @@@ToInstall-Line2|'Tools' --> 'Extensions and Updates' --> `Online` and search@@@ +// +// @@@AdditionalTemplates-Line1|For additional templates to use with F#, see the 'Online Templates' in Visual Studio,@@@ +// @@@AdditionalTemplates-Line2|'New Project' --> 'Online Templates'@@@ + +// @@@SupportsComments|F# supports three kinds of comments:@@@ + +// @@@DoubleSlash|1. Double-slash comments. These are used in most situations.@@@ +(* @@@MLStyle|2. ML-style Block comments. These aren't used that often.@@@ *) +/// @@@TripleSlash-Line1|3. Triple-slash comments. These are used for documenting functions, types, and so on.@@@ +/// @@@TripleSlash-Line2|They will appear as text when you hover over something which is decorated with these comments.@@@ +/// +/// @@@XmlComments-Line1|They also support .NET-style XML comments, which allow you to generate reference documentation,@@@ +/// @@@XmlComments-Line2|and they also allow editors (such as Visual Studio) to extract information from them.@@@ +/// @@@XmlComments-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation@@@ + + +// @@@OpenNamespaces|Open namespaces using the 'open' keyword.@@@ +// +// @@@LearnMore|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword@@@ +open System + + +/// @@@Module-Line1|A module is a grouping of F# code, such as values, types, and function values.@@@ +/// @@@Module-Line2|Grouping code in modules helps keep related code together and helps avoid name conflicts in your program.@@@ +/// +/// @@@Module-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules@@@ +module IntegersAndNumbers = + + /// @@@SampleInt|This is a sample integer.@@@ + let sampleInteger = 176 + + /// @@@SampleFloat|This is a sample floating point number.@@@ + let sampleDouble = 4.1 + + /// @@@Computed-Line1|This computed a new number by some arithmetic. Numeric types are converted using@@@ + /// @@@Computed-Line2|functions 'int', 'double' and so on.@@@ + let sampleInteger2 = (sampleInteger/4 + 5 - 7) * 4 + int sampleDouble + + /// @@@ListNumbers|This is a list of the numbers from 0 to 99.@@@ + let sampleNumbers = [ 0 .. 99 ] + + /// @@@ListSquares|This is a list of all tuples containing all the numbers from 0 to 99 and their squares.@@@ + let sampleTableOfSquares = [ for i in 0 .. 99 -> (i, i*i) ] + + // @@@PrintList1|The next line prints a list that includes tuples, using '%A' for generic printing.@@@ + printfn "The table of squares from 0 to 99 is:\n%A" sampleTableOfSquares + + // @@@SampleIntType|This is a sample integer with a type annotation@@@ + let sampleInteger3: int = 1 + + +/// @@@ValuesImmutable-Line1|Values in F# are immutable by default. They cannot be changed@@@ +/// @@@ValuesImmutable-Line2|in the course of a program's execution unless explicitly marked as mutable.@@@ +/// +/// @@@ValuesImmutable-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable@@@ +module Immutability = + + /// @@@LetKeyword-Line1|Binding a value to a name via 'let' makes it immutable.@@@ + /// + /// @@@LetKeyword-Line2|The second line of code fails to compile because 'number' is immutable and bound.@@@ + /// @@@LetKeyword-Line3|Re-defining 'number' to be a different value is not allowed in F#.@@@ + let number = 2 + // let number = 3 + + /// @@@MutableKeyword|A mutable binding. This is required to be able to mutate the value of 'otherNumber'.@@@ + let mutable otherNumber = 2 + + printfn "'otherNumber' is %d" otherNumber + + // @@@MutableAssignment-Line1|When mutating a value, use '<-' to assign a new value.@@@ + // + // @@@MutableAssignment-Line2|You could not use '=' here for this purpose since it is used for equality@@@ + // @@@MutableAssignment-Line3|or other contexts such as 'let' or 'module'@@@ + otherNumber <- otherNumber + 1 + + printfn "'otherNumber' changed to be %d" otherNumber + + +/// @@@FunctionsModule-Line1|Much of F# programming consists of defining functions that transform input data to produce@@@ +/// @@@FunctionsModule-Line2|useful results.@@@ +/// +/// @@@FunctionsModule-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/@@@ +module BasicFunctions = + + /// @@@LetFunction-Line1|You use 'let' to define a function. This one accepts an integer argument and returns an integer.@@@ + /// @@@LetFunction-Line2|Parentheses are optional for function arguments, except for when you use an explicit type annotation.@@@ + let sampleFunction1 x = x*x + 3 + + /// @@@ApplyFunction-Line1|Apply the function, naming the function return result using 'let'.@@@ + /// @@@ApplyFunction-Line2|The variable type is inferred from the function return type.@@@ + let result1 = sampleFunction1 4573 + + // @@@printf-Line1|This line uses '%d' to print the result as an integer. This is type-safe.@@@ + // @@@printf-Line2|If 'result1' were not of type 'int', then the line would fail to compile.@@@ + printfn "The result of squaring the integer 4573 and adding 3 is %d" result1 + + /// @@@TypeAnnotation|When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required.@@@ + let sampleFunction2 (x:int) = 2*x*x - x/5 + 3 + + let result2 = sampleFunction2 (7 + 4) + printfn "The result of applying the 2nd sample function to (7 + 4) is %d" result2 + + /// @@@Conditionals-Line1|Conditionals use if/then/elid/elif/else.@@@ + /// + /// @@@Conditionals-Line2|Note that F# uses whitespace indentation-aware syntax, similar to languages like Python.@@@ + let sampleFunction3 x = + if x < 100.0 then + 2.0*x*x - x/5.0 + 3.0 + else + 2.0*x*x + x/5.0 - 37.0 + + let result3 = sampleFunction3 (6.5 + 4.5) + + // @@@printf-Line3|This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe.@@@ + printfn "The result of applying the 3rd sample function to (6.5 + 4.5) is %f" result3 + + +/// @@@Booleans-Line1|Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic.@@@ +/// +/// @@@Booleans-Line2|To learn more, see:@@@ +/// https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/primitive-types +/// @@@Booleans-Line3|and@@@ +/// https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/symbol-and-operator-reference/boolean-operators +module Booleans = + + /// @@@BooleanValues|Booleans values are 'true' and 'false'.@@@ + let boolean1 = true + let boolean2 = false + + /// @@@BooleanOperators|Operators on booleans are 'not', '&&' and '||'.@@@ + let boolean3 = not boolean1 && (boolean2 || false) + + // @@@BooleanPrintf|This line uses '%b'to print a boolean value. This is type-safe.@@@ + printfn "The expression 'not boolean1 && (boolean2 || false)' is %b" boolean3 + + +/// @@@Strings-Line1|Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation.@@@ +/// +/// @@@Strings-Line2|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings@@@ +module StringManipulation = + + /// @@@StringQuotes|Strings use double quotes.@@@ + let string1 = "Hello" + let string2 = "world" + + /// @@@StringLiterals-Line1|Strings can also use @ to create a verbatim string literal.@@@ + /// @@@StringLiterals-Line2|This will ignore escape characters such as '\', '\n', '\t', etc.@@@ + let string3 = @"C:\Program Files\" + + /// @@@StringTripleQuotes|String literals can also use triple-quotes.@@@ + let string4 = """The computer said "hello world" when I told it to!""" + + /// @@@StringConcatenation|String concatenation is normally done with the '+' operator.@@@ + let helloWorld = string1 + " " + string2 + + // @@@StringPrinting|This line uses '%s' to print a string value. This is type-safe.@@@ + printfn "%s" helloWorld + + /// @@@Substrings-Line1|Substrings use the indexer notation. This line extracts the first 7 characters as a substring.@@@ + /// @@@Substrings-Line2|Note that like many languages, Strings are zero-indexed in F#.@@@ + let substring = helloWorld.[0..6] + printfn "%s" substring + + +/// @@@Tuples-Line1|Tuples are simple combinations of data values into a combined value.@@@ +/// +/// @@@Tuples-Line2|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples@@@ +module Tuples = + + /// @@@TupleInteger|A simple tuple of integers.@@@ + let tuple1 = (1, 2, 3) + + /// @@@TupleFunction-Line1|A function that swaps the order of two values in a tuple.@@@ + /// + /// @@@TupleFunction-Line2|F# Type Inference will automatically generalize the function to have a generic type,@@@ + /// @@@TupleFunction-Line3|meaning that it will work with any type.@@@ + let swapElems (a, b) = (b, a) + + printfn "The result of swapping (1, 2) is %A" (swapElems (1,2)) + + /// @@@TupleMultiType-Line1|A tuple consisting of an integer, a string,@@@ + /// @@@TupleMultiType-Line2|and a double-precision floating point number.@@@ + let tuple2 = (1, "fred", 3.1415) + + printfn "tuple1: %A\ttuple2: %A" tuple1 tuple2 + + /// @@@TupleTypeAnnotation-Line1|A simple tuple of integers with a type annotation.@@@ + /// @@@TupleTypeAnnotation-Line2|Type annotations for tuples use the * symbol to separate elements@@@ + let tuple3: int * int = (5, 9) + + /// @@@StructTuple-Line1|Tuples are normally objects, but they can also be represented as structs.@@@ + /// + /// @@@StructTuple-Line2|These interoperate completely with structs in C# and Visual Basic.NET; however,@@@ + /// @@@StructTuple-Line3|struct tuples are not implicitly convertable with object tuples (often called reference tuples).@@@ + /// + /// @@@StructTuple-Line4|The second line below will fail to compile because of this. Uncomment it to see what happens.@@@ + let sampleStructTuple = struct (1, 2) + //let thisWillNotCompile: (int*int) = struct (1, 2) + + // @@@TupleConvert-Line1|Although you cannot implicitly convert between struct tuples and reference tuples,@@@ + // @@@TupleConvert-Line2|you can explicitly convert via pattern matching, as demonstrated below.@@@ + let convertFromStructTuple (struct(a, b)) = (a, b) + let convertToStructTuple (a, b) = struct(a, b) + + printfn "Struct Tuple: %A\nReference tuple made from the Struct Tuple: %A" sampleStructTuple (sampleStructTuple |> convertFromStructTuple) + + +/// @@@Pipes-Line1|The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<')@@@ +/// @@@Pipes-Line2|are used extensively when processing data. These operators are themselves functions@@@ +/// @@@Pipes-Line3|which make use of Partial Application.@@@ +/// +/// @@@Pipes-Line4|To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining@@@ +/// @@@Pipes-Line5|To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments@@@ +module PipelinesAndComposition = + + /// @@@Squares|Squares a value.@@@ + let square x = x * x + + /// @@@AddOne|Adds 1 to a value.@@@ + let addOne x = x + 1 + + /// @@@TestOdd|Tests if an integer value is odd via modulo.@@@ + let isOdd x = x % 2 <> 0 + + /// @@@NumberList1|A list of 5 numbers. More on lists later.@@@ + let numbers = [ 1; 2; 3; 4; 5 ] + + /// @@@FilterWithoutPipes-Line1|Given a list of integers, it filters out the even numbers,@@@ + /// @@@FilterWithoutPipes-Line2|squares the resulting odds, and adds 1 to the squared odds.@@@ + let squareOddValuesAndAddOne values = + let odds = List.filter isOdd values + let squares = List.map square odds + let result = List.map addOne squares + result + + printfn "processing %A through 'squareOddValuesAndAddOne' produces: %A" numbers (squareOddValuesAndAddOne numbers) + + /// @@@FilterShorter-Line1|A shorter way to write 'squareOddValuesAndAddOne' is to nest each@@@ + /// @@@FilterShorter-Line2|sub-result into the function calls themselves.@@@ + /// + /// @@@FilterShorter-Line3|This makes the function much shorter, but it's difficult to see the@@@ + /// @@@FilterShorter-Line4|order in which the data is processed.@@@ + let squareOddValuesAndAddOneNested values = + List.map addOne (List.map square (List.filter isOdd values)) + + printfn "processing %A through 'squareOddValuesAndAddOneNested' produces: %A" numbers (squareOddValuesAndAddOneNested numbers) + + /// @@@FilterWithPipes-Line1|A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators.@@@ + /// @@@FilterWithPipes-Line2|This allows you to avoid creating intermediate results, but is much more readable@@@ + /// @@@FilterWithPipes-Line3|than nesting function calls like 'squareOddValuesAndAddOneNested'@@@ + let squareOddValuesAndAddOnePipeline values = + values + |> List.filter isOdd + |> List.map square + |> List.map addOne + + printfn "processing %A through 'squareOddValuesAndAddOnePipeline' produces: %A" numbers (squareOddValuesAndAddOnePipeline numbers) + + /// @@@PipeInLambda-Line1|You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call@@@ + /// @@@PipeInLambda-Line2|into the first, using a Lambda Function.@@@ + /// + /// @@@PipeInLambda-Line3|Note that pipelines are also being used inside the lambda function. F# pipe operators@@@ + /// @@@PipeInLambda-Line4|can be used for single values as well. This makes them very powerful for processing data.@@@ + let squareOddValuesAndAddOneShorterPipeline values = + values + |> List.filter isOdd + |> List.map(fun x -> x |> square |> addOne) + + printfn "processing %A through 'squareOddValuesAndAddOneShorterPipeline' produces: %A" numbers (squareOddValuesAndAddOneShorterPipeline numbers) + + /// @@@PipesComposition-Line1|Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>'@@@ + /// @@@PipesComposition-Line2|to compose the two core operations: filtering out even numbers, then squaring and adding one.@@@ + /// @@@PipesComposition-Line3|Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply@@@ + /// @@@PipesComposition-Line4|being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used@@@ + /// @@@PipesComposition-Line5|there as well.@@@ + /// + /// @@@PipesComposition-Line6|The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a@@@ + /// @@@PipesComposition-Line7|list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list@@@ + /// @@@PipesComposition-Line8|of integers, you'll notice that it produces the same results as previous functions.@@@ + /// + /// @@@PipesComposition-Line9|This is using what is known as function composition. This is possible because functions in F#@@@ + /// @@@PipesComposition-Line10|use Partial Application and the input and output types of each data processing operation match@@@ + /// @@@PipesComposition-Line11|the signatures of the functions we're using.@@@ + let squareOddValuesAndAddOneComposition = + List.filter isOdd >> List.map (square >> addOne) + + printfn "processing %A through 'squareOddValuesAndAddOneComposition' produces: %A" numbers (squareOddValuesAndAddOneComposition numbers) + + +/// @@@Lists-Line1|Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation.@@@ +/// +/// @@@Lists-Line2|This module shows various ways to generate lists and process lists with some functions@@@ +/// @@@Lists-Line3|in the 'List' module in the F# Core Library.@@@ +/// +/// @@@Lists-Line4|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists@@@ +module Lists = + + /// @@@ListEmptyDefinition|Lists are defined using [ ... ]. This is an empty list.@@@ + let list1 = [ ] + + /// @@@ListElementDefinition|This is a list with 3 elements. ';' is used to separate elements on the same line.@@@ + let list2 = [ 1; 2; 3 ] + + /// @@@ListNewlineElements|You can also separate elements by placing them on their own lines.@@@ + let list3 = [ + 1 + 2 + 3 + ] + + /// @@@NumberList2|This is a list of integers from 1 to 1000@@@ + let numberList = [ 1 .. 1000 ] + + /// @@@ListComputation-Line1|Lists can also be generated by computations. This is a list containing@@@ + /// @@@ListComputation-Line2|all the days of the year.@@@ + let daysList = + [ for month in 1 .. 12 do + for day in 1 .. System.DateTime.DaysInMonth(2017, month) do + yield System.DateTime(2017, month, day) ] + + // @@@PrintList2|Print the first 5 elements of 'daysList' using 'List.take'.@@@ + printfn "The first 5 days of 2017 are: %A" (daysList |> List.take 5) + + /// @@@ListComputationConditional-Line1|Computations can include conditionals. This is a list containing the tuples@@@ + /// @@@ListComputationConditional-Line2|which are the coordinates of the black squares on a chess board.@@@ + let blackSquares = + [ for i in 0 .. 7 do + for j in 0 .. 7 do + if (i+j) % 2 = 1 then + yield (i, j) ] + + /// @@@ListMap-Line1|Lists can be transformed using 'List.map' and other functional programming combinators.@@@ + /// @@@ListMap-Line2|This definition produces a new list by squaring the numbers in numberList, using the pipeline@@@ + /// @@@ListMap-Line3|operator to pass an argument to List.map.@@@ + let squares = + numberList + |> List.map (fun x -> x*x) + + /// @@@ListFilter-Line1|There are many other list combinations. The following computes the sum of the squares of the@@@ + /// @@@ListFilter-Line2|numbers divisible by 3.@@@ + let sumOfSquares = + numberList + |> List.filter (fun x -> x % 3 = 0) + |> List.sumBy (fun x -> x * x) + + printfn "The sum of the squares of numbers up to 1000 that are divisible by 3 is: %d" sumOfSquares + + +/// @@@Arrays-Line1|Arrays are fixed-size, mutable collections of elements of the same type.@@@ +/// +/// @@@Arrays-Line2|Although they are similar to Lists (they support enumeration and have similar combinators for data processing),@@@ +/// @@@Arrays-Line3|they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable.@@@ +/// +/// @@@Arrays-Line4|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays@@@ +module Arrays = + + /// @@@EmptyArray|This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead.@@@ + let array1 = [| |] + + /// @@@ArrayConstructionList|Arrays are specified using the same range of constructs as lists.@@@ + let array2 = [| "hello"; "world"; "and"; "hello"; "world"; "again" |] + + /// @@@ArrayConstructionRange|This is an array of numbers from 1 to 1000.@@@ + let array3 = [| 1 .. 1000 |] + + /// @@@ArrayComputationConstruction|This is an array containing only the words "hello" and "world".@@@ + let array4 = + [| for word in array2 do + if word.Contains("l") then + yield word |] + + /// @@@ArrayInit|This is an array initialized by index and containing the even numbers from 0 to 2000.@@@ + let evenNumbers = Array.init 1001 (fun n -> n * 2) + + /// @@@ArraySlicing|Sub-arrays are extracted using slicing notation.@@@ + let evenNumbersSlice = evenNumbers.[0..500] + + /// @@@ArrayLooping|You can loop over arrays and lists using 'for' loops.@@@ + for word in array4 do + printfn "word: %s" word + + // @@@ArrayAssignment-Line1|You can modify the contents of an an array element by using the left arrow assignment operator.@@@ + // + // @@@ArrayAssignment-Line2|To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables@@@ + array2.[1] <- "WORLD!" + + /// @@@ArrayMap-Line1|You can transform arrays using 'Array.map' and other functional programming operations.@@@ + /// @@@ArrayMap-Line2|The following calculates the sum of the lengths of the words that start with 'h'.@@@ + let sumOfLengthsOfWords = + array2 + |> Array.filter (fun x -> x.StartsWith "h") + |> Array.sumBy (fun x -> x.Length) + + printfn "The sum of the lengths of the words in Array 2 is: %d" sumOfLengthsOfWords + + +/// @@@Sequences-Line1|Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays.@@@ +/// +/// @@@Sequences-Line2|Sequences are evaluated on-demand and are re-evaluated each time they are iterated.@@@ +/// @@@Sequences-Line3|An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>.@@@ +/// +/// @@@Sequences-Line4|Sequence processing functions can be applied to Lists and Arrays as well.@@@ +/// +/// @@@Sequences-Line5|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences@@@ +module Sequences = + + /// @@@EmptySequence|This is the empty sequence.@@@ + let seq1 = Seq.empty + + /// @@@SequenceOfValues|This a sequence of values.@@@ + let seq2 = seq { yield "hello"; yield "world"; yield "and"; yield "hello"; yield "world"; yield "again" } + + /// @@@OnDemandSequence|This is an on-demand sequence from 1 to 1000.@@@ + let numbersSeq = seq { 1 .. 1000 } + + /// @@@SequenceComposition|This is a sequence producing the words "hello" and "world"@@@ + let seq3 = + seq { for word in seq2 do + if word.Contains("l") then + yield word } + + /// @@@SequenceInit|This sequence producing the even numbers up to 2000.@@@ + let evenNumbers = Seq.init 1001 (fun n -> n * 2) + + let rnd = System.Random() + + /// @@@InfiniteSequence-Line1|This is an infinite sequence which is a random walk.@@@ + /// @@@InfiniteSequence-Line2|This example uses yield! to return each element of a subsequence.@@@ + let rec randomWalk x = + seq { yield x + yield! randomWalk (x + rnd.NextDouble() - 0.5) } + + /// @@@Sequence100Elements|This example shows the first 100 elements of the random walk.@@@ + let first100ValuesOfRandomWalk = + randomWalk 5.0 + |> Seq.truncate 100 + |> Seq.toList + + printfn "First 100 elements of a random walk: %A" first100ValuesOfRandomWalk + + +/// @@@RecursiveFunctions-Line1|Recursive functions can call themselves. In F#, functions are only recursive@@@ +/// @@@RecursiveFunctions-Line2|when declared using 'let rec'.@@@ +/// +/// @@@RecursiveFunctions-Line3|Recursion is the preferred way to process sequences or collections in F#.@@@ +/// +/// @@@RecursiveFunctions-Line4|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions@@@ +module RecursiveFunctions = + + /// @@@RecFunDef-Line1|This example shows a recursive function that computes the factorial of an@@@ + /// @@@RecRunDef-Line2|integer. It uses 'let rec' to define a recursive function.@@@ + let rec factorial n = + if n = 0 then 1 else n * factorial (n-1) + + printfn "Factorial of 6 is: %d" (factorial 6) + + /// @@@RecGcd-Line1|Computes the greatest common factor of two integers.@@@ + /// + /// @@@RecGcd-Line2|Since all of the recursive calls are tail calls,@@@ + /// @@@RecGcd-Line3|the compiler will turn the function into a loop,@@@ + /// @@@RecGcd-Line4|which improves performance and reduces memory consumption.@@@ + let rec greatestCommonFactor a b = + if a = 0 then b + elif a < b then greatestCommonFactor a (b - a) + else greatestCommonFactor (a - b) b + + printfn "The Greatest Common Factor of 300 and 620 is %d" (greatestCommonFactor 300 620) + + /// @@@RecSumList|This example computes the sum of a list of integers using recursion.@@@ + let rec sumList xs = + match xs with + | [] -> 0 + | y::ys -> y + sumList ys + + /// @@@RecSumListTail|This makes 'sumList' tail recursive, using a helper function with a result accumulator.@@@ + let rec private sumListTailRecHelper accumulator xs = + match xs with + | [] -> accumulator + | y::ys -> sumListTailRecHelper (accumulator+y) ys + + /// @@@RecSumListTailInvoke-Line1|This invokes the tail recursive helper function, providing '0' as a seed accumulator.@@@ + /// @@@RecSumListTailInvoke-Line2|An approach like this is common in F#.@@@ + let sumListTailRecursive xs = sumListTailRecHelper 0 xs + + let oneThroughTen = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] + + printfn "The sum 1-10 is %d" (sumListTailRecursive oneThroughTen) + + +/// @@@Records-Line1|Records are an aggregate of named values, with optional members (such as methods).@@@ +/// @@@Records-Line2|They are immutable and have structural equality semantics.@@@ +/// +/// @@@Records-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records@@@ +module RecordTypes = + + /// @@@RecordDefinition|This example shows how to define a new record type.@@@ + type ContactCard = + { Name : string + Phone : string + Verified : bool } + + /// @@@RecordInstantiation1|This example shows how to instantiate a record type.@@@ + let contact1 = + { Name = "Alf" + Phone = "(206) 555-0157" + Verified = false } + + /// @@@RecordInstantiation2|You can also do this on the same line with ';' separators.@@@ + let contactOnSameLine = { Name = "Alf"; Phone = "(206) 555-0157"; Verified = false } + + /// @@@UpdateRecord-Line1|This example shows how to use "copy-and-update" on record values. It creates@@@ + /// @@@UpdateRecord-Line2|a new record value that is a copy of contact1, but has different values for@@@ + /// @@@UpdateRecord-Line3|the 'Phone' and 'Verified' fields.@@@ + /// + /// @@@UpdateRecord-Line4|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions@@@ + let contact2 = + { contact1 with + Phone = "(206) 555-0112" + Verified = true } + + /// @@@ProcessRecord-Line1|This example shows how to write a function that processes a record value.@@@ + /// @@@ProcessRecord-Line2|It converts a 'ContactCard' object to a string.@@@ + let showContactCard (c: ContactCard) = + c.Name + " Phone: " + c.Phone + (if not c.Verified then " (unverified)" else "") + + printfn "Alf's Contact Card: %s" (showContactCard contact1) + + /// @@@RecordWithMember-Line1|This is an example of a Record with a member.@@@ + type ContactCardAlternate = + { Name : string + Phone : string + Address : string + Verified : bool } + + /// @@@RecordWithMember-Line2|Members can implement object-oriented members.@@@ + member this.PrintedContactCard = + this.Name + " Phone: " + this.Phone + (if not this.Verified then " (unverified)" else "") + this.Address + + let contactAlternate = + { Name = "Alf" + Phone = "(206) 555-0157" + Verified = false + Address = "111 Alf Street" } + + // @@@RecordAccess|Members are accessed via the '.' operator on an instantiated type.@@@ + printfn "Alf's alternate contact card is %s" contactAlternate.PrintedContactCard + + /// @@@RecordStruct-Line1|Records can also be represented as structs via the 'Struct' attribute.@@@ + /// @@@RecordStruct-Line2|This is helpful in situations where the performance of structs outweighs@@@ + /// @@@RecordStruct-Line3|the flexibility of reference types.@@@ + [] + type ContactCardStruct = + { Name : string + Phone : string + Verified : bool } + + +/// @@@DiscriminatedUnions-Line1|Discriminated Unions (DU for short) are values which could be a number of named forms or cases.@@@ +/// @@@DiscriminatedUnions-Line2|Data stored in DUs can be one of several distinct values.@@@ +/// +/// @@@DiscriminatedUnions-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions@@@ +module DiscriminatedUnions = + + /// @@@CardSuit|The following represents the suit of a playing card.@@@ + type Suit = + | Hearts + | Clubs + | Diamonds + | Spades + + /// @@@CardRank|A Disciminated Union can also be used to represent the rank of a playing card.@@@ + type Rank = + /// @@@CardRankValue|Represents the rank of cards 2 .. 10@@@ + | Value of int + | Ace + | King + | Queen + | Jack + + /// @@@CardMember|Discriminated Unions can also implement object-oriented members.@@@ + static member GetAllRanks() = + [ yield Ace + for i in 2 .. 10 do yield Value i + yield Jack + yield Queen + yield King ] + + /// @@@CardType-Line1|This is a record type that combines a Suit and a Rank.@@@ + /// @@@CardType-Line2|It's common to use both Records and Disciminated Unions when representing data.@@@ + type Card = { Suit: Suit; Rank: Rank } + + /// @@@ComputeFullDeck|This computes a list representing all the cards in the deck.@@@ + let fullDeck = + [ for suit in [ Hearts; Diamonds; Clubs; Spades] do + for rank in Rank.GetAllRanks() do + yield { Suit=suit; Rank=rank } ] + + /// @@@CardToString|This example converts a 'Card' object to a string.@@@ + let showPlayingCard (c: Card) = + let rankString = + match c.Rank with + | Ace -> "Ace" + | King -> "King" + | Queen -> "Queen" + | Jack -> "Jack" + | Value n -> string n + let suitString = + match c.Suit with + | Clubs -> "clubs" + | Diamonds -> "diamonds" + | Spades -> "spades" + | Hearts -> "hearts" + rankString + " of " + suitString + + /// @@@PrintAllCards|This example prints all the cards in a playing deck.@@@ + let printAllCards() = + for card in fullDeck do + printfn "%s" (showPlayingCard card) + + // @@@SingleCaseDu-Line1|Single-case DUs are often used for domain modeling. This can buy you extra type safety@@@ + // @@@SingleCaseDu-Line2|over primitive types such as strings and ints.@@@ + // + // @@@SingleCaseDu-Line3|Single-case DUs cannot be implicitly converted to or from the type they wrap.@@@ + // @@@SingleCaseDu-Line4|For example, a function which takes in an Address cannot accept a string as that input,@@@ + // @@@SingleCaseDu-Line5|or vive/versa.@@@ + type Address = Address of string + type Name = Name of string + type SSN = SSN of int + + // @@@InstantiateSingleCaseDu|You can easily instantiate a single-case DU as follows.@@@ + let address = Address "111 Alf Way" + let name = Name "Alf" + let ssn = SSN 1234567890 + + /// @@@UnwrapSingleCaseDu|When you need the value, you can unwrap the underlying value with a simple function.@@@ + let unwrapAddress (Address a) = a + let unwrapName (Name n) = n + let unwrapSSN (SSN s) = s + + // @@@PrintSingleCaseDu|Printing single-case DUs is simple with unwrapping functions.@@@ + printfn "Address: %s, Name: %s, and SSN: %d" (address |> unwrapAddress) (name |> unwrapName) (ssn |> unwrapSSN) + + /// @@@DuRecursiveDef-Line1|Disciminated Unions also support recursive definitions.@@@ + /// + /// @@@DuRecursiveDef-Line2|This represents a Binary Search Tree, with one case being the Empty tree,@@@ + /// @@@DuRecursiveDef-Line3|and the other being a Node with a value and two subtrees.@@@ + type BST<'T> = + | Empty + | Node of value:'T * left: BST<'T> * right: BST<'T> + + /// @@@SearchBinaryTree-Line1|Check if an item exists in the binary search tree.@@@ + /// @@@SearchBinaryTree-Line2|Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false.@@@ + let rec exists item bst = + match bst with + | Empty -> false + | Node (x, left, right) -> + if item = x then true + elif item < x then (exists item left) // @@@CheckLeftSubtree|Check the left subtree.@@@ + else (exists item right) // @@@CheckRightSubtree|Check the right subtree.@@@ + + /// @@@BinaryTreeInsert-Line1|Inserts an item in the Binary Search Tree.@@@ + /// @@@BinaryTreeInsert-Line2|Finds the place to insert recursively using Pattern Matching, then inserts a new node.@@@ + /// @@@BinaryTreeInsert-Line3|If the item is already present, it does not insert anything.@@@ + let rec insert item bst = + match bst with + | Empty -> Node(item, Empty, Empty) + | Node(x, left, right) as node -> + if item = x then node // @@@BinaryTreeInsert-Line4|No need to insert, it already exists; return the node.@@@ + elif item < x then Node(x, insert item left, right) // @@@BinaryTreeInsert-Line5|Call into left subtree.@@@ + else Node(x, left, insert item right) // @@@BinaryTreeInsert-Line6|Call into right subtree.@@@ + + /// @@@DuStruct-Line1|Discriminated Unions can also be represented as structs via the 'Struct' attribute.@@@ + /// @@@DuStruct-Line2|This is helpful in situations where the performance of structs outweighs@@@ + /// @@@DuStruct-Line3|the flexibility of reference types.@@@ + /// + /// @@@DuStruct-Line4|However, there are two important things to know when doing this:@@@ + /// @@@DuStruct-Line5|1. A struct DU cannot be recursively-defined.@@@ + /// @@@DuStruct-Line6|2. A struct DU must have unique names for each of its cases.@@@ + [] + type Shape = + | Circle of radius: float + | Square of side: float + | Triangle of height: float * width: float + + +/// @@@PatternMatching-Line1|Pattern Matching is a feature of F# that allows you to utilize Patterns,@@@ +/// @@@PatternMatching-Line2|which are a way to compare data with a logical structure or structures,@@@ +/// @@@PatternMatching-Line3|decompose data into constituent parts, or extract information from data in various ways.@@@ +/// @@@PatternMatching-Line4|You can then dispatch on the "shape" of a pattern via Pattern Matching.@@@ +/// +/// @@@PatternMatching-Line5|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching@@@ +module PatternMatching = + + /// @@@PersonRecord|A record for a person's first and last name@@@ + type Person = { + First : string + Last : string + } + + /// @@@EmployeeDu|A Discriminated Union of 3 different kinds of employees@@@ + type Employee = + | Engineer of engineer: Person + | Manager of manager: Person * reports: List + | Executive of executive: Person * reports: List * assistant: Employee + + /// @@@CountEmployees-Line1|Count everyone underneath the employee in the management hierarchy,@@@ + /// @@@CountEmployees-Line2|including the employee.@@@ + let rec countReports(emp : Employee) = + 1 + match emp with + | Engineer(id) -> + 0 + | Manager(id, reports) -> + reports |> List.sumBy countReports + | Executive(id, reports, assistant) -> + (reports |> List.sumBy countReports) + countReports assistant + + + /// @@@FindDave-Line1|Find all managers/executives named "Dave" who do not have any reports.@@@ + /// @@@FindDave-Line2|This uses the 'function' shorthand to as a lambda expression.@@@ + let rec findDaveWithOpenPosition(emps : List) = + emps + |> List.filter(function + | Manager({First = "Dave"}, []) -> true // @@@MatchEmptyList|[] matches an empty list.@@@ + | Executive({First = "Dave"}, [], _) -> true + | _ -> false) // @@@MatchWildcard-Line1|'_' is a wildcard pattern that matches anything.@@@ + // @@@MatchWildCard-Line2|This handles the "or else" case.@@@ + + /// @@@MatchShorthand-Line1|You can also use the shorthand function construct for pattern matching,@@@ + /// @@@MatchShorthand-Line2|which is useful when you're writing functions which make use of Partial Application.@@@ + let private parseHelper f = f >> function + | (true, item) -> Some item + | (false, _) -> None + + let parseDateTimeOffset = parseHelper DateTimeOffset.TryParse + + let result = parseDateTimeOffset "1970-01-01" + match result with + | Some dto -> printfn "It parsed!" + | None -> printfn "It didn't parse!" + + // @@@ParseHelpers|Define some more functions which parse with the helper function.@@@ + let parseInt = parseHelper Int32.TryParse + let parseDouble = parseHelper Double.TryParse + let parseTimeSpan = parseHelper TimeSpan.TryParse + + // @@@ActivePatterns-Line1|Active Patterns are another powerful construct to use with pattern matching.@@@ + // @@@ActivePatterns-Line2|They allow you to partition input data into custom forms, decomposing them at the pattern match call site.@@@ + // + // @@@ActivePatterns-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns@@@ + let (|Int|_|) = parseInt + let (|Double|_|) = parseDouble + let (|Date|_|) = parseDateTimeOffset + let (|TimeSpan|_|) = parseTimeSpan + + /// @@@MatchActivePattern|Pattern Matching via 'function' keyword and Active Patterns often looks like this.@@@ + let printParseResult = function + | Int x -> printfn "%d" x + | Double x -> printfn "%f" x + | Date d -> printfn "%s" (d.ToString()) + | TimeSpan t -> printfn "%s" (t.ToString()) + | _ -> printfn "Nothing was parse-able!" + + // @@@PrintParse|Call the printer with some different values to parse.@@@ + printParseResult "12" + printParseResult "12.045" + printParseResult "12/28/2016" + printParseResult "9:01PM" + printParseResult "banana!" + + +/// @@@Option-Line1|Option values are any kind of value tagged with either 'Some' or 'None'.@@@ +/// @@@Option-Line2|They are used extensively in F# code to represent the cases where many other@@@ +/// @@@Option-Line3|languages would use null references.@@@ +/// +/// @@@Option-Line4|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options@@@ +module OptionValues = + + /// @@@ZipCode|First, define a zipcode defined via Single-case Discriminated Union.@@@ + type ZipCode = ZipCode of string + + /// @@@Customer|Next, define a type where the ZipCode is optional.@@@ + type Customer = { ZipCode: ZipCode option } + + /// @@@ShippingCalculator-Line1|Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code,@@@ + /// @@@ShippingCalculator-Line2|given implementations for the 'getState' and 'getShippingZone' abstract methods.@@@ + type ShippingCalculator = + abstract GetState : ZipCode -> string option + abstract GetShippingZone : string -> int + + /// @@@CalcShippingZone-Line1|Next, calculate a shipping zone for a customer using a calculator instance.@@@ + /// @@@CalcShippingZone-Line2|This uses combinators in the Option module to allow a functional pipeline for@@@ + /// @@@CalcShippingZone-Line3|transforming data with Optionals.@@@ + let CustomerShippingZone (calculator: ShippingCalculator, customer: Customer) = + customer.ZipCode + |> Option.bind calculator.GetState + |> Option.map calculator.GetShippingZone + + +/// @@@UnitsOfMeasure-Line1|Units of measure are a way to annotate primitive numeric types in a type-safe way.@@@ +/// @@@UnitsOfMeasure-Line2|You can then perform type-safe arithmetic on these values.@@@ +/// +/// @@@UnitsOfMeasure-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure@@@ +module UnitsOfMeasure = + + /// @@@CommonUnits|First, open a collection of common unit names@@@ + open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames + + /// @@@DefineUnitConstant|Define a unitized constant@@@ + let sampleValue1 = 1600.0 + + /// @@@MileUnit|Next, define a new unit type@@@ + [] + type mile = + /// @@@MileToMeter|Conversion factor mile to meter.@@@ + static member asMeter = 1609.34 + + /// @@@DefineMileConstant|Define a unitized constant@@@ + let sampleValue2 = 500.0 + + /// @@@ComputeMileToMeter|Compute metric-system constant@@@ + let sampleValue3 = sampleValue2 * mile.asMeter + + // @@@PrintUnitsOfMeasure|Values using Units of Measure can be used just like the primitive numeric type for things like printing.@@@ + printfn "After a %f race I would walk %f miles which would be %f meters" sampleValue1 sampleValue2 sampleValue3 + + +/// @@@Classes-Line1|Classes are a way of defining new object types in F#, and support standard Object-oriented constructs.@@@ +/// @@@Classes-Line2|They can have a variety of members (methods, properties, events, etc.)@@@ +/// +/// @@@Classes-Line3|To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes@@@ +/// +/// @@@Classes-Line4|To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members@@@ +module DefiningClasses = + + /// @@@Vector-Line1|A simple two-dimensional Vector class.@@@ + /// + /// @@@Vector-Line2|The class's constructor is on the first line,@@@ + /// @@@Vector-Line3|and takes two arguments: dx and dy, both of type 'double'.@@@ + type Vector2D(dx : double, dy : double) = + + /// @@@ClassInternalField-Line1|This internal field stores the length of the vector, computed when the@@@ + /// @@@ClassInternalField-Line2|object is constructed@@@ + let length = sqrt (dx*dx + dy*dy) + + // @@@ThisKeyword-Line1|'this' specifies a name for the object's self identifier.@@@ + // @@@ThisKeyword-Line2|In instance methods, it must appear before the member name.@@@ + member this.DX = dx + + member this.DY = dy + + member this.Length = length + + /// @@@MemberMethod|This member is a method. The previous members were properties.@@@ + member this.Scale(k) = Vector2D(k * this.DX, k * this.DY) + + /// @@@InstantiateClass|This is how you instantiate the Vector2D class.@@@ + let vector1 = Vector2D(3.0, 4.0) + + /// @@@ScaledVector|Get a new scaled vector object, without modifying the original object.@@@ + let vector2 = vector1.Scale(10.0) + + printfn "Length of vector1: %f\nLength of vector2: %f" vector1.Length vector2.Length + + +/// @@@GenericClasses-Line1|Generic classes allow types to be defined with respect to a set of type parameters.@@@ +/// @@@GenericClasses-Line2|In the following, 'T is the type parameter for the class.@@@ +/// +/// @@@GenericClasses-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/@@@ +module DefiningGenericClasses = + + type StateTracker<'T>(initialElement: 'T) = + + /// @@@InternalField|This internal field store the states in a list.@@@ + let mutable states = [ initialElement ] + + /// @@@AddElement|Add a new element to the list of states.@@@ + member this.UpdateState newState = + states <- newState :: states // @@@MutableAssignment|use the '<-' operator to mutate the value.@@@ + + /// @@@History|Get the entire list of historical states.@@@ + member this.History = states + + /// @@@Current|Get the latest state.@@@ + member this.Current = states.Head + + /// @@@InferredTypeParameter|An 'int' instance of the state tracker class. Note that the type parameter is inferred.@@@ + let tracker = StateTracker 10 + + // @@@AddState|Add a state@@@ + tracker.UpdateState 17 + + +/// @@@Interfaces-Line1|Interfaces are object types with only 'abstract' members.@@@ +/// @@@Interfaces-Line2|Object types and object expressions can implement interfaces.@@@ +/// +/// @@@Interfaces-Line3|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces@@@ +module ImplementingInterfaces = + + /// @@@IDisposable|This is a type that implements IDisposable.@@@ + type ReadFile() = + + let file = new System.IO.StreamReader("readme.txt") + + member this.ReadLine() = file.ReadLine() + + // @@@IDisposableImplementation|This is the implementation of IDisposable members.@@@ + interface System.IDisposable with + member this.Dispose() = file.Close() + + + /// @@@IDisposableObjectExpression-Line1|This is an object that implements IDisposable via an Object Expression@@@ + /// @@@IDisposableObjectExpression-Line2|Unlike other languages such as C# or Java, a new type definition is not needed@@@ + /// @@@IDisposableObjectExpression-Line3|to implement an interface.@@@ + let interfaceImplementation = + { new System.IDisposable with + member this.Dispose() = printfn "disposed" } + + +/// @@@Parallel-Line1|The FSharp.Core library defines a range of parallel processing functions. Here@@@ +/// @@@Parallel-Line2|you use some functions for parallel processing over arrays.@@@ +/// +/// @@@Parallel-Line3|To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D@@@ +module ParallelArrayProgramming = + + /// @@@InputArray|First, an array of inputs.@@@ + let oneBigArray = [| 0 .. 100000 |] + + // @@@ExpensiveFunction|Next, define a functions that does some CPU intensive computation.@@@ + let rec computeSomeFunction x = + if x <= 2 then 1 + else computeSomeFunction (x - 1) + computeSomeFunction (x - 2) + + // @@@ParallelMap|Next, do a parallel map over a large input array.@@@ + let computeResults() = + oneBigArray + |> Array.Parallel.map (fun x -> computeSomeFunction (x % 20)) + + // @@@PrintParallel|Next, print the results.@@@ + printfn "Parallel computation results: %A" (computeResults()) + + + +/// @@@Events-Line1|Events are a common idiom for .NET programming, especially with WinForms or WPF applications.@@@ +/// +/// @@@Events-Line2|To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events@@@ +module Events = + + /// @@@SimpleEvent|First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger).@@@ + let simpleEvent = new Event() + + // @@@AddEventHandler1|Next, add handler to the event.@@@ + simpleEvent.Publish.Add( + fun x -> printfn "this handler was added with Publish.Add: %d" x) + + // @@@TriggerEvent|Next, trigger the event.@@@ + simpleEvent.Trigger(5) + + // @@@EventWithArgs|Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs).@@@ + let eventForDelegateType = new Event() + + // @@@AddEventHandler2|Next, add a handler for this new event.@@@ + eventForDelegateType.Publish.AddHandler( + EventHandler(fun _ _ -> printfn "this handler was added with Publish.AddHandler")) + + // @@@TriggerEventWithArgs|Next, trigger this event (note that sender argument should be set).@@@ + eventForDelegateType.Trigger(null, EventArgs.Empty) + + + +#if COMPILED +module BoilerPlateForForm = + [] + do () + do System.Windows.Forms.Application.Run() +#endif diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.vstemplate b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.vstemplate new file mode 100644 index 0000000000..adb7d6e230 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.vstemplate @@ -0,0 +1,31 @@ + + + + + + + Microsoft.FSharp.Tutorial + FSharp + 4.5 + 1 + true + Tutorial + true + true + + + + Tutorial.fsx + + + + NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + NuGet.VisualStudio.TemplateWizard + + + + + + + + diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.cs.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.cs.xlf new file mode 100644 index 0000000000..6de826791a --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.cs.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Tato ukázka vás provede elementy jazyka F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Pokud chcete kód provést v nástroji F# Interactive, zvýrazněte oddíl kódu a stiskněte Alt-Enter nebo klikněte pravým tlačítkem myši + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + a vyberte Provést v Interactive. Okno F# Interactive můžete otevřít z nabídky Zobrazit. + + + + For more about F#, see: + Další informace o F# najdete na: + + + + To see this tutorial in documentation form, see: + Na tomto webu najdete tento kurz v podobě dokumentace: + + + + To learn more about applied F# programming, use + K získání dalších informací o použitém programovém kódu F# použijte + + + + To install the Visual F# Power Tools, use + K instalaci Visual F# Power Tools použijte + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + Nástroje --> Rozšíření a aktualizace --> Online a potom hledejte + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Další šablony, které můžete používat s F#, najdete tak, že v sadě Visual Studio vyberete Online šablony, + + + + 'New Project' --> 'Online Templates' + Nový projekt --> Online šablony. + + + + F# supports three kinds of comments: + F# podporuje tři typy komentářů: + + + + 1. Double-slash comments. These are used in most situations. + 1. Komentáře se dvěma lomítky. Ty se používají ve většině situací. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Blokové komentáře ve stylu ML. Ty se moc často nepoužívají. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Komentáře se třemi lomítky. Ty se používají k dokumentaci funkcí, typů a podobně. + + + + They will appear as text when you hover over something which is decorated with these comments. + Když na elementy s těmito komentáři nastavíte ukazatel myši, zobrazí se komentáře jako text. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Podporují se také komentáře XML ve stylu .NET, které umožňují generovat referenční dokumentaci. + + + + and they also allow editors (such as Visual Studio) to extract information from them. + Umožňují také, aby z nich editory (jako například Visual Studio) extrahovaly informace. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Otevírejte obory názvů pomocí klíčového slova open. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Modul je seskupení kódu F#, například hodnot, typů a hodnot funkcí. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Seskupování kódu do modulů pomáhá zachovat související kód pohromadě a vyhnout se v programu konfliktům názvů. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Toto je ukázkové celé číslo. + + + + This is a sample floating point number. + Toto je ukázkové číslo s plovoucí desetinnou čárkou. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Tady se pomocí aritmetiky vypočítalo nové číslo. Číselné typy se převádějí pomocí + + + + functions 'int', 'double' and so on. + funkcí int, double atd. + + + + This is a list of the numbers from 0 to 99. + Toto je seznam čísel od 0 do 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Toto je seznam všech řazených kolekcí členů obsahujících všechna čísla od 0 do 99 a jejich druhé mocniny. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + Další řádek vytiskne seznam, který zahrnuje řazené kolekce členů, s použitím %A pro obecný tisk. + + + + This is a sample integer with a type annotation + Toto je ukázkové celé číslo s anotací typu. + + + + Values in F# are immutable by default. They cannot be changed + Hodnoty v F# jsou ve výchozím nastavení neměnné. Nedají se změnit + + + + in the course of a program's execution unless explicitly marked as mutable. + během provádění programu, pokud nejsou explicitně označené jako měnitelné. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Po navázání hodnoty na název pomocí klíčového slova „let“ se hodnota stane neměnnou. + + + + The second line of code fails to compile because 'number' is immutable and bound. + Druhý řádek kódu nejde zkompilovat, protože proměnná number je neměnná a vázaná. + + + + Re-defining 'number' to be a different value is not allowed in F#. + Předefinování položky number na jinou hodnotu se v jazyce F# nepovoluje. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Změnitelná vazba. Je to nutné, aby bylo možné měnit hodnotu otherNumber. + + + + When mutating a value, use '<-' to assign a new value. + Při změnách hodnoty použijte <- pro přiřazení nové hodnoty. + + + + You could not use '=' here for this purpose since it is used for equality + Znak = tady pro tento účel nemůžete použít, protože se používá pro rovnost + + + + or other contexts such as 'let' or 'module' + nebo jiné kontexty jako let nebo module + + + + Much of F# programming consists of defining functions that transform input data to produce + Velká část programování v F# spočívá v definování funkcí, které transformují vstupní data na + + + + useful results. + užitečné výsledky. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Pomocí klíčového slova „let“ můžete definovat funkci. Tato přebírá celočíselný argument a vrací celé číslo. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Závorky jsou pro argumenty funkce nepovinné – s výjimkou použití anotace explicitního typu. + + + + Apply the function, naming the function return result using 'let'. + Použití funkce a pojmenování výsledku vrácení funkce pomocí klíčového slova let + + + + The variable type is inferred from the function return type. + Typ proměnné je odvozený z návratového typu funkce. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Tento řádek používá %d k vytištění výsledku jako celého čísla. Je to typově bezpečné. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Pokud by result1 nebyl typu int, pak by se kompilace řádku nezdařila. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + V případě potřeby anotujte typ názvu parametru pomocí (argument:typ). Závorky jsou povinné. + + + + Conditionals use if/then/elid/elif/else. + Podmíněné výrazy používají příkazy if, then, elid, elif, else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Všimněte si, že F# používá syntaxi rozpoznávající odsazení pomocí mezer – je to podobné jako u jazyků, jako je Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Tento řádek používá %f k vytištění výsledku jako hodnoty s plovoucí desetinnou čárkou. Stejně jako u výše uvedeného parametru %d je to typově bezpečné. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Logické hodnoty představují základní datové typy v jazyce F#. Tady je několik příkladů logických hodnot a podmíněné logiky. + + + + To learn more, see: + Další informace: + + + + and + a + + + + Booleans values are 'true' and 'false'. + Logické hodnoty jsou true a false. + + + + Operators on booleans are 'not', '&&' and '||'. + Operátory u logických hodnot jsou not, && a ||. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Tento řádek používá %b k vytištění logické hodnoty. Je to typově bezpečné. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Řetězce představují základní datové typy v jazyce F#. Tady je několik příkladů řetězců a základní manipulace s nimi. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Pro řetězce se používají dvojité uvozovky. + + + + Strings can also use @ to create a verbatim string literal. + V řetězcích je také možné použít @ k vytvoření řetězcového literálu verbatim. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Tím se budou ignorovat řídicí znaky jako \, \n, \t apod. + + + + String literals can also use triple-quotes. + Řetězcové literály můžou používat také trojité uvozovky. + + + + String concatenation is normally done with the '+' operator. + Zřetězení se obvykle provádí operátorem +. + + + + This line uses '%s' to print a string value. This is type-safe. + Tento řádek používá %s k vytištění řetězcové hodnoty. Je to typově bezpečné. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Podřetězce používají notaci indexeru. Tento řádek extrahuje prvních 7 znaků jako podřetězec. + + + + Note that like many languages, Strings are zero-indexed in F#. + Všimněte si, že jako v mnoha jiných jazycích mají řetězce v jazyce F# nulový index. + + + + Tuples are simple combinations of data values into a combined value. + Řazená kolekce členů představuje jedinou hodnotu vytvořenou jednoduchým zkombinováním hodnot dat. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Jednoduchá řazená kolekce členů v podobě celých čísel. + + + + A function that swaps the order of two values in a tuple. + Funkce, která zamění pořadí dvou hodnot v řazené kolekci členů + + + + F# Type Inference will automatically generalize the function to have a generic type, + Odvození typu proměnné v jazyce F# automaticky generalizuje funkci tak, aby byla obecného typu, + + + + meaning that it will work with any type. + což znamená, že bude fungovat s jakýmkoli typem. + + + + A tuple consisting of an integer, a string, + Řazená kolekce členů skládající se z celého čísla, řetězce + + + + and a double-precision floating point number. + a čísla s plovoucí desetinnou čárkou a dvojitou přesností + + + + A simple tuple of integers with a type annotation. + Jednoduchá řazená kolekce členů celých čísel s anotací typu + + + + Type annotations for tuples use the * symbol to separate elements + Anotace typů pro řazené kolekce členů používají k oddělování elementů symbol *. + + + + Tuples are normally objects, but they can also be represented as structs. + Řazené kolekce členů jsou obvykle objekty, ale můžou být vyjádřeny i jako struktury. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Ty zcela spolupracují se strukturami v jazycích C# a Visual Basic .NET. Platí ale, že + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + řazené kolekce členů představující struktury nejsou implicitně převeditelné na řazené kolekce členů představující objekty (často označované jako řazené kolekce členů odkazů). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + Kompilace druhého řádku uvedeného níže se z tohoto důvodu nezdaří. Odkomentujte ho a podívejte se, co se stane. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Mezi řazenými kolekcemi členů představujícími struktury a řazenými kolekcemi členů odkazů nemůžete provést implicitní převod, + + + + you can explicitly convert via pattern matching, as demonstrated below. + ale můžete převod provést explicitně přes porovnávání vzorů, jak je znázorněno níže. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Operátory kanálu (|>, <| atd.) a operátory složení (>>, <<) v jazyce F# + + + + are used extensively when processing data. These operators are themselves functions + se při zpracovávání dat používají ve velkém měřítku. Tyto operátory představují samy o sobě funkce, + + + + which make use of Partial Application. + které využívají částečné použití argumentů. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Další informace o těchto operátorech: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Další informace o částečném použití argumentů: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Umocní hodnotu na druhou. + + + + Adds 1 to a value. + Přičte 1 k hodnotě. + + + + Tests if an integer value is odd via modulo. + Otestuje, jestli je celočíselná hodnota lichá na základě zbytku po dělení. + + + + A list of 5 numbers. More on lists later. + Seznam 5 čísel. Více o seznamech později. + + + + Given a list of integers, it filters out the even numbers, + V daném seznamu celých čísel odfiltruje sudá čísla, + + + + squares the resulting odds, and adds 1 to the squared odds. + umocní výsledná lichá čísla na druhou a přičte 1 k lichým číslům umocněným na druhou. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Kratší způsob, jak napsat squareOddValuesAndAddOne, je vnořit jednotlivé + + + + sub-result into the function calls themselves. + dílčí výsledky přímo do volání funkcí. + + + + This makes the function much shorter, but it's difficult to see the + Díky tomu může být funkce mnohem kratší, ale je obtížné sledovat + + + + order in which the data is processed. + pořadí, v jakém se data zpracovávají. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Preferovaným způsobem, jak napsat squareOddValuesAndAddOne, je použití operátorů kanálu v jazyce F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + To vám umožní vyhnout se vytváření mezivýsledků, ale je to mnohem čitelnější + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + než vnoření volání funkcí, jak je vidět v squareOddValuesAndAddOneNested. + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + Můžete zkrátit squareOddValuesAndAddOnePipeline přesunutím druhého volání List.map + + + + into the first, using a Lambda Function. + do prvního, pomocí funkce lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Všimněte si, že kanály se používají i ve funkci lambda. Operátory kanálu v jazyce F# + + + + can be used for single values as well. This makes them very powerful for processing data. + se dají použít i pro jednotlivé hodnoty. Díky tomu jsou velmi efektivní při zpracovávání dat. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + A konečně, můžete eliminovat nutnost explicitně převzít values jako parametr pomocí >> + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + s cílem sestavit dvě základní operace: odfiltrování sudých čísel a následné umocnění na druhou a přičtení jedné. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Obdobně není nutná část výrazu lambda „fun x -> ...“, protože x se jednoduše + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + v tomto oboru definuje tak, aby ho bylo možné předat jako funkční kanál. Proto je tam >> možné použít + + + + there as well. + také. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Výsledek squareOddValuesAndAddOneComposition je sám o sobě další funkcí, která přebírá + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + jako vstup seznam celých čísel. Pokud provedete squareOddValuesAndAddOneComposition se seznamem + + + + of integers, you'll notice that it produces the same results as previous functions. + celých čísel, všimnete si, že dává stejné výsledky jako předchozí funkce. + + + + This is using what is known as function composition. This is possible because functions in F# + Označuje se to jako složení funkcí. Je to možné, protože funkce v jazyce F# + + + + use Partial Application and the input and output types of each data processing operation match + používají částečné použití argumentů a vstupní a výstupní typy každé operace zpracování dat odpovídají + + + + the signatures of the functions we're using. + signaturám funkcí, které používáme. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Seznamy jsou uspořádané, neměnné a jednorázově propojené. Velmi dynamicky se vyhodnocují. + + + + This module shows various ways to generate lists and process lists with some functions + Tento modul zobrazuje různé způsoby, jak generovat seznamy a jak je zpracovat pomocí některých funkcí + + + + in the 'List' module in the F# Core Library. + v modulu List v knihovně F# Core. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Seznamy se definují pomocí syntaxe [ ... ]. Toto je prázdný seznam. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Toto je seznam se 3 elementy. K oddělení prvků na stejném řádku se používá středník (;). + + + + You can also separate elements by placing them on their own lines. + Elementy můžete oddělit i jejich umístěním na samostatné řádky. + + + + This is a list of integers from 1 to 1000 + Toto je seznam celých čísel od 1 do 1000 + + + + Lists can also be generated by computations. This is a list containing + Seznamy je možné generovat pomocí výpočtů. Toto je seznam obsahující + + + + all the days of the year. + všechny dny v roce. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Vytiskněte prvních 5 elementů daysList pomocí List.take. + + + + Computations can include conditionals. This is a list containing the tuples + Výpočty můžou obsahovat podmíněné výrazy. Toto je seznam obsahující řazené kolekce členů + + + + which are the coordinates of the black squares on a chess board. + což jsou souřadnice černých polí na šachovnici. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Seznamy se dají transformovat pomocí souboru List.map a dalších funkčních programových kombinátorů. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Tato definice vytvoří nový seznam vypočítáním druhých mocnin hodnot v seznamu numberList pomocí kanálu + + + + operator to pass an argument to List.map. + operátor pro předání argumentu do souboru List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Existuje mnoho dalších kombinací seznamů. Následující kód vypočítá součet druhých mocnin + + + + numbers divisible by 3. + čísel dělitelných 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Pole jsou měnitelné kolekce s pevně stanovenou velikostí, které obsahují elementy stejného typu. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + I když se podobají seznamům (podporují výčet a mají podobné kombinátory pro zpracování dat), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + jsou obecně rychlejší a podporují rychlý náhodný přístup. Nevýhodou je nižší zabezpečení, protože je možné je měnit. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Toto je prázdné pole. Všimněte si, že syntaxe je podobná seznamům, ale používá se [| ... |]. + + + + Arrays are specified using the same range of constructs as lists. + Pole jsou definovaná pomocí stejného rozsahu konstruktorů jako seznamy. + + + + This is an array of numbers from 1 to 1000. + Toto je pole čísel od 1 do 1000. + + + + This is an array containing only the words "hello" and "world". + Toto je pole obsahující pouze slova hello a world. + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Toto je pole inicializované indexem, které obsahuje sudá čísla od 0 do 2000. + + + + Sub-arrays are extracted using slicing notation. + Dílčí pole se extrahují pomocí slicingové notace. + + + + You can loop over arrays and lists using 'for' loops. + Přes pole a seznamy se můžete přesunovat pomocí smyček for. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Můžete upravit obsah elementu pole pomocí operátoru přiřazení s šipkou doleva. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Další informace o tomto operátoru: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Pole můžete transformovat pomocí Array.map a dalších funkčních programových operací. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Následující kód vypočítá součet délek slov, která začínají na „h“. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Sekvence jsou logické řady elementů, které jsou všechny stejného typu. Jedná se o obecnější typ než seznamy a pole. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Sekvence se vyhodnocují na vyžádání a při každé iteraci se vyhodnocují znovu. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Sekvence F# je alias pro .NET System.Collections.Generic.IEnumerable<'T>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Funkce na zpracování sekvencí je možné použít také na seznamy a pole. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Toto je prázdná sekvence. + + + + This a sequence of values. + Toto je sekvence hodnot. + + + + This is an on-demand sequence from 1 to 1000. + Toto je sekvence na vyžádání od 1 do 1000. + + + + This is a sequence producing the words "hello" and "world" + Toto je sekvence, která vrátí slova hello a world + + + + This sequence producing the even numbers up to 2000. + Tato sekvence vrátí sudá čísla až do 2000. + + + + This is an infinite sequence which is a random walk. + Toto je nekonečná sekvence, která je náhodnou funkcí walk. + + + + This example uses yield! to return each element of a subsequence. + Tento příklad vrací pomocí příkazu yield! jednotlivé elementy dílčí sekvence. + + + + This example shows the first 100 elements of the random walk. + Tento příklad ukazuje prvních 100 elementů náhodné funkce walk. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Rekurzivní funkce můžou volat samy sebe. V F# jsou všechny funkce rekurzivní + + + + when declared using 'let rec'. + při deklarování pomocí let rec. + + + + Recursion is the preferred way to process sequences or collections in F#. + Rekurze je preferovaný způsob zpracování sekvencí nebo kolekcí v jazyce F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Tento příklad ukazuje rekurzivní funkci, která vypočítá faktoriál + + + + integer. It uses 'let rec' to define a recursive function. + integer. Pomocí let rec se definuje rekurzivní funkce. + + + + Computes the greatest common factor of two integers. + Vypočítá největšího společného dělitele dvou celých čísel. + + + + Since all of the recursive calls are tail calls, + Vzhledem k tomu, že všechna rekurzivní volání jsou volání funkce Tail, + + + + the compiler will turn the function into a loop, + kompilátor změní funkci na smyčku, + + + + which improves performance and reduces memory consumption. + což zvyšuje výkon a snižuje spotřebu paměti. + + + + This example computes the sum of a list of integers using recursion. + Tento příklad zjistí součet seznamu celých čísel pomocí rekurze. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Tím se funkce Tail sumList stane rekurzivní, a to s použitím pomocné funkce s akumulátorem výsledků. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Tím se vyvolá rekurzivní pomocná funkce Tail, poskytující 0 jako zdrojový akumulátor. + + + + An approach like this is common in F#. + Takový postup je v jazyce F# běžný. + + + + Records are an aggregate of named values, with optional members (such as methods). + Záznamy jsou agregátem pojmenovaných hodnot s volitelnými členy (jako jsou metody). + + + + They are immutable and have structural equality semantics. + Jsou neměnné a mají sémantiku se strukturální rovností. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Tento příklad ukazuje, jak definovat nový typ záznamu. + + + + This example shows how to instantiate a record type. + Tento příklad ukazuje, jak vytvořit instanci typu záznamu. + + + + You can also do this on the same line with ';' separators. + Můžete to udělat i na stejném řádku se středníky (;) jako oddělovači. + + + + This example shows how to use "copy-and-update" on record values. It creates + Tento příklad ukazuje, jak použít copy-and-update pro hodnoty záznamu. Vytvoří + + + + a new record value that is a copy of contact1, but has different values for + hodnotu nového záznamu, která je kopií záznamu contact1, ale má jiné hodnoty pro + + + + the 'Phone' and 'Verified' fields. + pole Telefon a Ověřeno. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Tento příklad ukazuje, jak napsat funkci, která zpracuje hodnotu záznamu. + + + + It converts a 'ContactCard' object to a string. + Převádí objekt ContactCard na řetězec. + + + + This is an example of a Record with a member. + Toto je příklad záznamu se členem. + + + + Members can implement object-oriented members. + Členové můžou implementovat objektově orientované členy. + + + + Members are accessed via the '.' operator on an instantiated type. + Ke členům se přistupuje prostřednictvím operátoru „.“ u typu tvořícího instanci. + + + + Records can also be represented as structs via the 'Struct' attribute. + Záznamy můžou být vyjádřeny i jako struktury prostřednictvím atributu Struct. + + + + This is helpful in situations where the performance of structs outweighs + To je užitečné v situacích, kdy má výkon struktur větší váhu než + + + + the flexibility of reference types. + flexibilita odkazových typů. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Rozlišovaná sjednocení (zkratka: DU) jsou hodnoty, které můžou představovat celou řadu pojmenovaných forem nebo případů. + + + + Data stored in DUs can be one of several distinct values. + Data uložená v DU můžou představovat jednu z několika různých hodnot. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + Následující příklad představuje barvu hrací karty. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Rozlišované sjednocení může také představovat hodnotu hrací karty. + + + + Represents the rank of cards 2 .. 10 + Představuje hodnotu karet 2 .. 10. + + + + Discriminated Unions can also implement object-oriented members. + Rozlišovaná sjednocení můžou také implementovat objektově orientované členy. + + + + This is a record type that combines a Suit and a Rank. + Toto je typ záznamu, který kombinuje barvu a hodnotu hrací karty. + + + + It's common to use both Records and Disciminated Unions when representing data. + Při vyjadřování dat se běžně používají záznamy i rozlišovaná sjednocení. + + + + This computes a list representing all the cards in the deck. + Tady se vypočítá seznam představující všechny karty z balíčku. + + + + This example converts a 'Card' object to a string. + Tento příklad převede objekt Card na řetězec. + + + + This example prints all the cards in a playing deck. + Tento příklad vytiskne všechny karty v hracím balíčku. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Rozlišovaná sjednocení s jedním případem se často používají pro modelování domén. Tím můžete získat dodatečnou bezpečnost typů + + + + over primitive types such as strings and ints. + oproti primitivním typům, jako jsou řetězce a celá čísla. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Rozlišovaná sjednocení s jedním případem nejde implicitně převést na typ nebo z typu, který obalují. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Například funkce, která přebírá adresu, nemůže jako vstup převzít řetězec + + + + or vive/versa. + a naopak. + + + + You can easily instantiate a single-case DU as follows. + Instanci rozlišovaného sjednocení s jedním případem můžete snadno vytvořit následujícím způsobem. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Pokud danou hodnotu potřebujete, můžete základní hodnotu rozbalit pomocí jednoduché funkce. + + + + Printing single-case DUs is simple with unwrapping functions. + Tisk rozlišovaných sjednocení s jedním případem je jednoduchý s použitím rozbalovacích funkcí. + + + + Disciminated Unions also support recursive definitions. + Rozlišovaná sjednocení podporují i rekurzivní definice. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Toto představuje binární vyhledávací strom, přičemž jeden případ je prázdný strom + + + + and the other being a Node with a value and two subtrees. + a druhý je uzel s hodnotou a dvěma podstromy. + + + + Check if an item exists in the binary search tree. + Zkontroluje, jestli položka existuje v binárním vyhledávacím stromu. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Rekurzivně vyhledává porovnáváním vzorů. Vrátí hodnotu true, pokud existuje; v opačném případě false. + + + + Check the left subtree. + Zkontroluje levý podstrom. + + + + Check the right subtree. + Zkontroluje pravý podstrom. + + + + Inserts an item in the Binary Search Tree. + Vloží položku do binárního vyhledávacího stromu. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Najde místo pro rekurzivní vložení pomocí porovnávání vzorů a pak vloží nový uzel. + + + + If the item is already present, it does not insert anything. + Pokud je už položka přítomna, nevloží nic. + + + + No need to insert, it already exists; return the node. + Nemusí se vkládat, už existuje; vrátí se uzel. + + + + Call into left subtree. + Provede volání do levého podstromu. + + + + Call into right subtree. + Provede volání do pravého podstromu. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Rozlišovaná sjednocení můžou být vyjádřena i jako struktury prostřednictvím atributu Struct. + + + + This is helpful in situations where the performance of structs outweighs + To je užitečné v situacích, kdy má výkon struktur větší váhu než + + + + the flexibility of reference types. + flexibilita odkazových typů. + + + + However, there are two important things to know when doing this: + Při tomto postupu je ale třeba vědět dvě důležité věci: + + + + 1. A struct DU cannot be recursively-defined. + 1. Rozlišované sjednocení typu struktura nemůže být definované rekurzivně. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Rozlišované sjednocení typu struktura musí mít jedinečné názvy pro každý ze svých případů. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Porovnávání vzorů je funkce jazyka F#, která umožňuje používat vzory, + + + + which are a way to compare data with a logical structure or structures, + což představuje způsob, jak porovnávat data s logickou strukturou nebo strukturami, + + + + decompose data into constituent parts, or extract information from data in various ways. + jak rozložit data na základní části nebo extrahovat informace z dat různými způsoby. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Odesílání pak můžete provádět na základě vzoru v rámci porovnávání vzorů. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Záznam pro jméno a příjmení daného člověka + + + + A Discriminated Union of 3 different kinds of employees + Rozlišované sjednocení se 3 různými typy zaměstnanců + + + + Count everyone underneath the employee in the management hierarchy, + Spočítají se všichni zaměstnanci pod daným zaměstnancem v hierarchii řízení, + + + + including the employee. + včetně tohoto zaměstnance. + + + + Find all managers/executives named "Dave" who do not have any reports. + Vyhledá všechny nadřízené/výkonné pracovníky se jménem Dave, kteří nemají žádné podřízené. + + + + This uses the 'function' shorthand to as a lambda expression. + Tady se používá zkrácený název function jako výraz lambda. + + + + [] matches an empty list. + [] odpovídá prázdnému seznamu. + + + + '_' is a wildcard pattern that matches anything. + „_“ je zástupný vzor, kterému odpovídá úplně všechno. + + + + This handles the "or else" case. + Toto řeší případ „or else“ + + + + You can also use the shorthand function construct for pattern matching, + Můžete také použít zkrácenou konstrukci function pro porovnávání vzorů, + + + + which is useful when you're writing functions which make use of Partial Application. + což je užitečné při psaní funkcí, které využívají částečné použití argumentů. + + + + Define some more functions which parse with the helper function. + Definujte pár dalších funkcí, které se analyzují s pomocnou funkcí. + + + + Active Patterns are another powerful construct to use with pattern matching. + Aktivní vzory představují další efektivní konstrukci pro použití s porovnáváním vzorů. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Umožňují rozdělit vstupní data do vlastních forem, přičemž se rozkládají v místě volání porovnávání vzorů. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Porovnávání vzorů přes klíčové slovo function a aktivní vzory často vypadá takto. + + + + Call the printer with some different values to parse. + Volání tiskárny s nějakými jinými hodnotami k parsování + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Hodnotami parametru můžou být hodnoty jakéhokoliv typu s označením Some (Nějaké) nebo None (Žádné). + + + + They are used extensively in F# code to represent the cases where many other + Používají se často v kódu F#, kde reprezentují případy, ve kterých by se v řadě jiných + + + + languages would use null references. + jazyků používaly odkazy null. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Nejprve definujte PSČ prostřednictvím rozlišovaného sjednocení s jedním případem. + + + + Next, define a type where the ZipCode is optional. + Dále definujte typ, kde je PSČ volitelné. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Potom definujte typ rozhraní, který bude představovat objekt pro výpočet expediční oblasti pro PSČ zákazníka + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + se zohledněním implementací pro abstraktní metody getState a getShippingZone. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Dále vypočítejte expediční oblast pro zákazníka pomocí instance kalkulačky. + + + + This uses combinators in the Option module to allow a functional pipeline for + Tady se používají kombinátory v modulu Option, pomocí kterých se povoluje funkční kanál pro + + + + transforming data with Optionals. + transformaci dat s volitelnými hodnotami. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Měrné jednotky jsou způsob, jak anotovat primitivní číselné typy typově bezpečnou metodou. + + + + You can then perform type-safe arithmetic on these values. + Pak u těchto hodnot můžete provádět typově bezpečnou aritmetiku. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Nejdříve otevřete kolekci běžných názvů jednotek. + + + + Define a unitized constant + Definovat unifikovanou konstantu + + + + Next, define a new unit type + Potom definujte nový typ jednotky + + + + Conversion factor mile to meter. + Přepočtový koeficient pro přepočet mílí na metry + + + + Define a unitized constant + Definovat unifikovanou konstantu + + + + Compute metric-system constant + Vypočítat konstantu v metrickém systému + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Hodnoty s měrnými jednotkami je možné používat stejně jako primitivní číselný typ pro operace, jako je tisk. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Třídy představují způsob definice nových objektových typů v jazyce F# a podporují standardní objektově orientované konstrukce. + + + + They can have a variety of members (methods, properties, events, etc.) + Můžou mít celou řadu členů (metody, vlastnosti, události atd.). + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Další informace o třídách: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Další informace o členech: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Jednoduchá dvojrozměrná vektorová třída. + + + + The class's constructor is on the first line, + Konstruktor třídy je na prvním řádku + + + + and takes two arguments: dx and dy, both of type 'double'. + a přebírá dva argumenty: dx a dy, oba typu double. + + + + This internal field stores the length of the vector, computed when the + Toto interní pole ukládá délku vektoru vypočítanou při + + + + object is constructed + zkonstruování objektu + + + + 'this' specifies a name for the object's self identifier. + this určuje název identifikátoru samotného objektu. + + + + In instance methods, it must appear before the member name. + V metodách instancí se musí objevovat před názvem člena. + + + + This member is a method. The previous members were properties. + Tento člen je metoda. Předchozí členové představují vlastnosti. + + + + This is how you instantiate the Vector2D class. + Toto je způsob, jak vytvořit instanci třídy Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Získá nový škálovaný vektorový objekt, aniž by se změnil původní objekt. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Obecné třídy umožňují definování typů s ohledem na sadu parametrů typu. + + + + In the following, 'T is the type parameter for the class. + V následujícím příkladu „T“ představuje parametr typu pro třídu. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Toto interní pole ukládá stavy v seznamu. + + + + Add a new element to the list of states. + Přidá nový element do seznamu stavů. + + + + use the '<-' operator to mutate the value. + Použije operátor <- ke změně (mutaci) hodnoty. + + + + Get the entire list of historical states. + Získá celý seznam historických stavů. + + + + Get the latest state. + Získá nejnovější stav. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Instance int třídy pro sledování stavů. Poznámka: Parametr typu je odvozený. + + + + Add a state + Přidat stav + + + + Interfaces are object types with only 'abstract' members. + Rozhraní jsou typy objektů pouze s členy abstract. + + + + Object types and object expressions can implement interfaces. + Objektové typy a výrazy můžou implementovat rozhraní. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Toto je typ, který implementuje rozhraní IDisposable. + + + + This is the implementation of IDisposable members. + Toto je implementace členů IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Toto je objekt, který implementuje IDisposable pomocí výrazu objektu. + + + + Unlike other languages such as C# or Java, a new type definition is not needed + Na rozdíl od jiných jazyků, jako jsou C# nebo Java, není nutná nová definice typu + + + + to implement an interface. + pro implementaci rozhraní. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + Knihovna FSharp.Core definuje rozsah funkcí paralelního zpracování. Tady + + + + you use some functions for parallel processing over arrays. + použijete některé funkce pro paralelní zpracování polí. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Další informace: https://msdn.microsoft.com/cs-cz/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Nejdříve pole vstupů. + + + + Next, define a functions that does some CPU intensive computation. + Dále definujte funkci, která bude provádět výpočty náročné na procesor. + + + + Next, do a parallel map over a large input array. + Dále proveďte paralelní mapování přes velké vstupní pole. + + + + Next, print the results. + Potom vytiskněte výsledky. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Události jsou běžné základní struktury programového kódu .NET, zejména s aplikacemi WinForms nebo WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Další informace: https://docs.microsoft.com/cs-cz/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Nejdříve vytvořte instanci objektu Event, který se bude skládat z bodu odběru (event.Publish) a aktivační události (event.Trigger). + + + + Next, add handler to the event. + Potom přidejte obslužnou rutinu pro událost. + + + + Next, trigger the event. + Potom spusťte událost. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Potom vytvořte instanci objektu Event podle standardní konvence .NET: (sender, EventArgs). + + + + Next, add a handler for this new event. + Dále přidejte obslužnou rutinu pro tuto novou událost. + + + + Next, trigger this event (note that sender argument should be set). + Potom spusťte tuto událost (poznámka: musí být nastavený argument odesílatele). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.de.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.de.xlf new file mode 100644 index 0000000000..0908855049 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.de.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Dieses Beispiel zeigt Ihnen verschiedene Elemente der F#-Programmiersprache. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Markieren Sie zum Ausführen des Codes in F# Interactive einen Codeabschnitt, und drücken Sie dann entweder ALT+EINGABETASTE oder klicken Sie mit der rechten Maustaste + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + und wählen Sie "In Interactive ausführen" aus. Sie können das F# Interactive-Fenster über das Menü "Ansicht" öffnen. + + + + For more about F#, see: + Weitere Informationen zu F# finden Sie unter: + + + + To see this tutorial in documentation form, see: + Dieses Tutorial ist auch als Dokumentation verfügbar. Siehe hierzu: + + + + To learn more about applied F# programming, use + Verwenden Sie Folgendes, um weitere Informationen zur praktischen F#-Programmierung zu erhalten: + + + + To install the Visual F# Power Tools, use + Verwenden Sie Folgendes, um die Visual F# Power Tools zu installieren: + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + "Extras" > "Erweiterungen und Updates" > "Online", und suchen Sie nach + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Weitere Vorlagen zum Verwenden mit F# finden Sie in Visual Studio unter "Onlinevorlagen", + + + + 'New Project' --> 'Online Templates' + "Neue Projekte" > "Onlinevorlagen". + + + + F# supports three kinds of comments: + F# unterstützt drei Arten von Kommentaren: + + + + 1. Double-slash comments. These are used in most situations. + 1. Kommentare mit doppeltem Schrägstrich. Diese werden in den meisten Situationen verwendet. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Blockkommentare im ML-Stil. Diese werden nicht sehr häufig verwendet. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Kommentare mit drei Schrägstrichen. Diese werden zum Dokumentieren von Funktionen, Typen usw. verwendet. + + + + They will appear as text when you hover over something which is decorated with these comments. + Sie erscheinen als Text, wenn Sie den Mauszeiger über einem Element positionieren, das mit diesen Kommentaren versehen ist. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Sie bieten außerdem Unterstützung für XML-Kommentare im .NET-Stil zum Generieren von Referenzdokumentation, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + und sie ermöglichen das Extrahieren von Informationen über Editoren (z.B. Visual Studio). + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/xml-documentation. + + + + Open namespaces using the 'open' keyword. + Öffnen Sie Namespaces mit dem Schlüsselwort "open". + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Weitere Informationen finden Sie hier: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword. + + + + A module is a grouping of F# code, such as values, types, and function values. + Ein Modul ist eine Gruppierung von F#-Code, z.B. Werte, Typen und Funktionswerte. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Die Codegruppierung in Modulen ermöglicht das Zusammenfassen von zueinander in Beziehung stehendem Code sowie das Vermeiden von Namenskonflikten in Ihrem Programm. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/modules. + + + + This is a sample integer. + Dies ist ein Beispiel für eine Ganzzahl. + + + + This is a sample floating point number. + Dies ist ein Beispiel für eine Gleitkommazahl. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Hier wird mithilfe einer arithmetischen Operation eine neue Zahl berechnet. Numerische Typen werden unter Verwendung der + + + + functions 'int', 'double' and so on. + Funktionen "int", "double" usw. konvertiert. + + + + This is a list of the numbers from 0 to 99. + Dies ist eine Liste der Zahlen von 0 bis 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Dies ist eine Liste aller Tupel, die alle Zahlen von 0 bis 99 sowie Ihre Quadratzahlen enthalten. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + Die nächste Zeile gibt eine Liste mit Tupeln aus, wobei "%A" für die generische Ausgabe verwendet wird. + + + + This is a sample integer with a type annotation + Dies ist ein Beispiel für eine ganze Zahl mit einer Typanmerkung. + + + + Values in F# are immutable by default. They cannot be changed + Werte in F# sind standardmäßig unveränderlich. Sie können im Verlauf + + + + in the course of a program's execution unless explicitly marked as mutable. + der Ausführung eines Programms nicht geändert werden – es sei denn, sie sind explizit als änderbar gekennzeichnet. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Wenn ein Wert mithilfe von "let" an einen Namen gebunden wird, ist er unveränderlich. + + + + The second line of code fails to compile because 'number' is immutable and bound. + Die zweite Codezeile kann nicht kompiliert werden, da "number" unveränderlich und gebunden ist. + + + + Re-defining 'number' to be a different value is not allowed in F#. + "number" darf in F# nicht als ein anderer Wert neu definiert werden. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Eine veränderliche Bindung. Dies ist erforderlich, damit der Wert von "otherNumber" verändert werden kann. + + + + When mutating a value, use '<-' to assign a new value. + Wenn Sie einen Wert verändern, weisen Sie mithilfe von "<-" einen neuen Wert zu. + + + + You could not use '=' here for this purpose since it is used for equality + Sie können "=" hier nicht verwenden, da es für Gleichheit verwendet wird. + + + + or other contexts such as 'let' or 'module' + oder andere Kontexte wie "let" oder "module" + + + + Much of F# programming consists of defining functions that transform input data to produce + Bei der F#-Programmierung werden größtenteils Funktionen definiert, die Eingabedaten in hilfreiche + + + + useful results. + Ergebnisse umwandelt. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Verwenden Sie "let", um eine Funktion zu definieren. Diese akzeptiert ein Integer-Argument und gibt einen Integer zurück. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Klammern sind für Funktionsargumente optional, außer wenn Sie eine explizite Typanmerkung verwenden. + + + + Apply the function, naming the function return result using 'let'. + Die Funktion anwenden, und das Rückgabeergebnis der Funktion mithilfe von "let" benennen. + + + + The variable type is inferred from the function return type. + Der Variablentyp wird vom Rückgabetyp der Funktion abgeleitet. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Diese Zeile verwendet "%d", um das Ergebnis als Integer zu drucken. Dies ist typsicher. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Wenn "result1" nicht vom Typ "int" wäre, käme es bei der Kompilierung der Zeile zu einem Fehler. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Blenden Sie bei Bedarf den Typ eines Parameternamens mithilfe von "(argument:type)" ein. Klammern sind erforderlich. + + + + Conditionals use if/then/elid/elif/else. + Für Bedingungen wird Folgendes verwendet: if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Bei der Syntax von F# werden ebenso wie bei Sprachen wie Python leerzeichenbasierte Einzüge beachtet. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Diese Zeile verwendet "%f", um das Ergebnis als float-Eigenschaft zu drucken. Wie auch zuvor bei "%d" ist dies typsicher. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Boolesche Werte sind grundlegende Datentypen in F#. Hier finden Sie einige Beispiele für boolesche Werte und Bedingungen. + + + + To learn more, see: + Weitere Informationen finden Sie unter: + + + + and + Und + + + + Booleans values are 'true' and 'false'. + Boolesche Werte sind "true" und "false". + + + + Operators on booleans are 'not', '&&' and '||'. + Operatoren für boolesche Werte sind "not", "&&" und "||". + + + + This line uses '%b'to print a boolean value. This is type-safe. + Diese Zeile verwendet "%b" zum Drucken eines booleschen Werts. Dies ist typsicher. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Zeichenfolgen sind grundlegende Datentypen in F#. Hier finden Sie einige Beispiele für Zeichenfolgen und Zeichenfolgenmanipulationen. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Für Zeichenfolgen werden doppelte Anführungszeichen verwendet. + + + + Strings can also use @ to create a verbatim string literal. + Mit "@" lassen sich ausführliche Zeichenfolgenliterale erstellen. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Dadurch werden Escapezeichen wie "\", "\n", "\t" usw. ignoriert. + + + + String literals can also use triple-quotes. + Für Zeichenfolgen können auch dreifache Anführungszeichen verwendet werden. + + + + String concatenation is normally done with the '+' operator. + Die Verkettung von Zeichenfolgen erfolgt in der Regel mit dem Operator "+". + + + + This line uses '%s' to print a string value. This is type-safe. + Diese Zeile verwendet "%s" zum Drucken eines Zeichenfolgewerts. Dies ist typsicher. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Für Teilzeichenfolgen wird die Indexernotation verwendet. Diese Zeile extrahiert die ersten sieben Zeichen als Teilzeichenfolge. + + + + Note that like many languages, Strings are zero-indexed in F#. + Im Gegensatz zu den meisten anderen Sprachen sind Zeichenfolgen in F# nullindiziert. + + + + Tuples are simple combinations of data values into a combined value. + Tupel sind einfache Datenwertkombinationen. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Ein einfaches Tupel aus Integerwerten. + + + + A function that swaps the order of two values in a tuple. + Eine Funktion, die die Reihenfolge von zwei Werten in einem Tupel austauscht. + + + + F# Type Inference will automatically generalize the function to have a generic type, + Der F#-Typrückschluss generalisiert die Funktion automatisch und erstellt einen generischen Typ, + + + + meaning that it will work with any type. + d. h. er funktioniert mit jedem Typ. + + + + A tuple consisting of an integer, a string, + Ein Tupel aus einem Integer, einer Zeichenfolge + + + + and a double-precision floating point number. + und einer Gleitkommazahl mit doppelter Genauigkeit. + + + + A simple tuple of integers with a type annotation. + Ein einfaches Tupel aus Integerwerten mit einer Typanmerkung. + + + + Type annotations for tuples use the * symbol to separate elements + Typanmerkungen für Tupel trennen Elemente durch das *-Symbol. + + + + Tuples are normally objects, but they can also be represented as structs. + Tupel sind normalerweise Objekte, sie können aber auch als Strukturen dargestellt werden. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Sie arbeiten mit Strukturen in C# und Visual Basic.Net vollständig zusammen. + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + Strukturtupel sind jedoch nicht implizit mit Objekttupeln (häufig als Referenztupel bezeichnet) konvertierbar. + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + Die unten angezeigte zweite Zeile kann aus diesem Grund nicht kompiliert werden. Heben Sie die Auskommentierung auf, und sehen Sie, was passiert. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Sie können zwar nicht implizit zwischen Strukturtupeln und Verweistupeln konvertieren, + + + + you can explicitly convert via pattern matching, as demonstrated below. + Sie können aber wie unten gezeigt eine explizite Konvertierung über den Musterabgleich durchführen. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Die F#-PipeOperatoren ("|>", "<|" usw.) und die F#-Zusammensetzungsoperatoren (">>", "<<") + + + + are used extensively when processing data. These operators are themselves functions + werden bei der Datenverarbeitung umfassend eingesetzt. Diese Operatoren sind Funktionen, + + + + which make use of Partial Application. + die die partielle Anwendung nutzen. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Weitere Informationen zu diesen Operatoren finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Weitere Informationen zur partiellen Anwendung finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Quadriert einen Wert. + + + + Adds 1 to a value. + Addiert 1 zu einem Wert hinzu. + + + + Tests if an integer value is odd via modulo. + Testet mit Modulo, ob ein Integerwert gerade ist. + + + + A list of 5 numbers. More on lists later. + Eine Liste mit fünf Nummern. Weitere Informationen zu Listen finden Sie später. + + + + Given a list of integers, it filters out the even numbers, + Aus einer Liste mit Integern werden die geraden Zahlen herausgefiltert, + + + + squares the resulting odds, and adds 1 to the squared odds. + die sich ergebenden ungeraden Zahlen werden quadratiert, und zu dem Ergebnis wird 1 hinzuaddiert. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Eine kürzere Möglichkeit zum Schreiben von "squareOddValuesAndAddOne" besteht im Verschachteln von jedem + + + + sub-result into the function calls themselves. + Teilergebnis im Funktionsaufruf selbst. + + + + This makes the function much shorter, but it's difficult to see the + Dadurch wird die Funktion viel kürzer, + + + + order in which the data is processed. + die Reihenfolge der Datenverarbeitung ist jedoch schlechter sichtbar. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Eine bevorzugte Möglichkeit zum Schreiben von "squareOddValuesAndAddOne" besteht in der Verwendung von F#-Pipe-Operatoren. + + + + This allows you to avoid creating intermediate results, but is much more readable + Dadurch können Sie verhindern, dass Zwischenergebnisse erstellt werden, dies ist jedoch besser lesbar + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + als verschachtelte Funktionsaufrufe wie "squareOddValuesAndAddOneNested". + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + Sie können "squareOddValuesAndAddOnePipeline" kürzen, indem Sie den zweiten "List.map"-Aufruf + + + + into the first, using a Lambda Function. + mithilfe einer Lambda-Funktion in den ersten verschieben. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Pipelines werden auch innerhalb der Lambda-Funktion verwendet. F#-Pipe-Operatoren + + + + can be used for single values as well. This makes them very powerful for processing data. + können auch für einzelne Werte verwendet werden. So ist eine leistungsstarke Datenverarbeitung möglich. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + Es ist nicht mehr erforderlich, "values" als Parameter aufzunehmen, indem Sie mithilfe von ">>" + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + die beiden zentralen Vorgänge erstellen: Herausfiltern von geraden Zahlen, Quadratieren und Addieren von 1. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Der Teil "fun x -> ..." des Lambdaausdrucks ist dementsprechend ebenfalls nicht erforderlich, da "x" lediglich + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + in dem Bereich definiert wird, damit es an eine Funktionspipeline übergeben werden kann. Daher kann ">>" + + + + there as well. + dort ebenfalls verwendet werden. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Das Ergebnis von "squareOddValuesAndAddOneComposition" selbst ist eine andere Funktion, die eine + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + Liste von Integern als Eingabe verwendet. Wenn Sie "squareOddValuesAndAddOneComposition" mit einer Liste + + + + of integers, you'll notice that it produces the same results as previous functions. + von Integern ausführen, erhalten Sie das gleiche Ergebnis wie bei vorherigen Funktionen. + + + + This is using what is known as function composition. This is possible because functions in F# + Dabei wird die so genannte Funktionskomposition verwendet. Das ist möglich, da Funktionen in F# + + + + use Partial Application and the input and output types of each data processing operation match + die partielle Anwendung nutzen, und die Ein- und Ausgabetypen jedes Datenverarbeitungsvorgangs + + + + the signatures of the functions we're using. + mit den Signaturen der verwendeten Funktionen übereinstimmen. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Listen sind geordnete, unveränderliche, einfach verknüpfte Listen. Ihre Auswertung ist streng. + + + + This module shows various ways to generate lists and process lists with some functions + Dieses Modul zeigt verschiedene Möglichkeiten zum Erstellen von Listen und Prozesslisten mit einigen Funktionen + + + + in the 'List' module in the F# Core Library. + im Modul "List" in der F#-Kernbibliothek. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Listen werden mithilfe von "[ ... ]" definiert. Dies ist eine leere Liste. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Dies ist eine Liste mit drei Elementen. ";" dient dazu, Elemente in der gleichen Zeile zu trennen. + + + + You can also separate elements by placing them on their own lines. + Sie können Elemente auch trennen, indem Sie sie in separaten Zeilen einfügen. + + + + This is a list of integers from 1 to 1000 + Dies ist eine Liste mit ganzen Zahlen von 1 bis 1000. + + + + Lists can also be generated by computations. This is a list containing + Listen können auch mithilfe von Berechnungen generiert werden. Dies ist eine Liste mit + + + + all the days of the year. + allen Tagen des Jahres. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Drucken Sie mithilfe von "List.take" die ersten fünf Elemente in "daysList". + + + + Computations can include conditionals. This is a list containing the tuples + Berechnungen können Bedingungen enthalten. Dies ist eine Liste mit den Tupeln, + + + + which are the coordinates of the black squares on a chess board. + bei denen es sich um die Koordinaten der schwarzen Felder auf einem Schachbrett handelt. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Listen können mithilfe von "List.map" und anderen funktionalen Programmierkombinatoren umgewandelt werden. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Diese Definition erzeugt eine neue Liste, indem die Zahlen in "numberList" quadriert werden. Dabei wird der Pipeline- + + + + operator to pass an argument to List.map. + Operator verwendet, um ein Argument an "List.map" zu übergeben. + + + + There are many other list combinations. The following computes the sum of the squares of the + Es stehen noch viele andere Listenkombinationen zur Verfügung. Mit dem Folgenden wird die Summe der Quadrate der + + + + numbers divisible by 3. + durch 3 teilbaren Zahlen berechnet. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Arrays sind veränderliche Sammlungen fester Größe, die Elemente des gleichen Typs enthalten. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Sie ähneln Listen (sie unterstützen Enumeration und haben ähnliche Combinators für die Datenverarbeitung), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + sind im Allgemeinen jedoch schneller und unterstützen einen schnellen wahlfreien Zugriff. Dafür sind sie jedoch weniger sicher, da sie veränderlich sind. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Dies ist das leere Array. Die Syntax ähnelt der von Listen, verwendet jedoch stattdessen "[| ... |]". + + + + Arrays are specified using the same range of constructs as lists. + Arrays werden mithilfe der gleichen Konstrukte angegeben wie Listen. + + + + This is an array of numbers from 1 to 1000. + Dies ist ein Array mit Zahlen von 1 bis 1000. + + + + This is an array containing only the words "hello" and "world". + Dieses Array enthält nur die Wörter "hello" und "world". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Dieses Array wurde per Index initialisiert und enthält gerade Zahlen von 0 bis 2000. + + + + Sub-arrays are extracted using slicing notation. + Teilarrays werden mithilfe der Segmentnotation extrahiert. + + + + You can loop over arrays and lists using 'for' loops. + Mit For-Schleifen können Sie bei Arrays und Listen Schleifen ausführen. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Sie können die Inhalte eines Arrayelements mithilfe des Zuweisungsoperators "Pfeil nach links" ändern. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Weitere Informationen zu diesem Operator finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Sie können Arrays mithilfe von "Array.map" und anderen funktionalen Programmiervorgängen umwandeln. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Mit Folgendem wird die Summe der Längen von Wörtern berechnet, die mit "h" beginnen. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Sequenzen sind logische Serien von Elementen, die alle vom gleichen Typ sind. Ihr Typ ist allgemeiner als Listen und Arrays. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Sequenzen werden bei Bedarf ausgewertet und bei jeder Iteration erneut ausgewertet. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Eine F#-Sequenz ist ein Alias für .NET System.Collections.Generic.IEnumerable<'T>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Funktionen mit Sequenzverarbeitung können auch auf Listen und Arrays angewendet werden. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Dies ist die leere Sequenz. + + + + This a sequence of values. + Dies ist eine Sequenz mit Werten. + + + + This is an on-demand sequence from 1 to 1000. + Dies ist eine bedarfsbasierte Sequenz von 1 bis 1000. + + + + This is a sequence producing the words "hello" and "world" + Diese Sequenz generiert die Wörter "hello" und "world". + + + + This sequence producing the even numbers up to 2000. + Diese Sequenz erzeugt gerade Zahlen bis 2000. + + + + This is an infinite sequence which is a random walk. + Dies ist eine unendliche Sequenz und ermöglicht Zufallsdurchläufe. + + + + This example uses yield! to return each element of a subsequence. + In diesem Beispiel werden mithilfe von "yield!" die einzelnen Elemente einer Untersequenz zurückgegeben. + + + + This example shows the first 100 elements of the random walk. + Dieses Beispiel zeigt die ersten 100 Elemente des Zufallsdurchlaufs. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Rekursive Funktionen können sich selbst aufrufen. In F# sind Funktionen nur rekursiv, + + + + when declared using 'let rec'. + für die Deklaration mithilfe von "let rec". + + + + Recursion is the preferred way to process sequences or collections in F#. + Rekursion ist die bevorzugte Möglichkeit zum Verarbeiten von Sequenzen oder Sammlungen in F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Dieses Beispiel zeigt eine rekursive Funktion, die die Fakultät einer ganzen + + + + integer. It uses 'let rec' to define a recursive function. + Zahl berechnet. Zum Definieren einer rekursiven Funktion wird "let rec" verwendet. + + + + Computes the greatest common factor of two integers. + Berechnet den höchsten gemeinsamen Faktor von zwei Integern. + + + + Since all of the recursive calls are tail calls, + Da alle rekursiven Aufrufe Endeaufrufe sind, + + + + the compiler will turn the function into a loop, + wandelt der Compiler die Funktion in eine Schleife um, + + + + which improves performance and reduces memory consumption. + was die Leistung verbessert und die Arbeitsspeicherbedarf reduziert. + + + + This example computes the sum of a list of integers using recursion. + Dieses Beispiel berechnet mithilfe von Rekursion die Summe einer Liste von Integern. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Mithilfe einer Hilfsfunktion mit einem Ergebnisakkumulator wird "sumList" endrekursiv. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Dies ruft die endrekursive Hilfsfunktion auf und verwendet "0" als Startwertakkumulator. + + + + An approach like this is common in F#. + Dies ist eine häufige Vorgehensweise in F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Datensätze sind ein Aggregat aus benannten Werten mit optionalen Membern (wie etwa Methoden). + + + + They are immutable and have structural equality semantics. + Sie sind nicht veränderlich und verfügen über eine strukturelle Gleichheitssemantik. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Dieses Beispiel zeigt, wie ein neuer Datensatztyp definiert wird. + + + + This example shows how to instantiate a record type. + In diesem Beispiel erfahren Sie, wie Sie einen Datensatztyp instanziieren. + + + + You can also do this on the same line with ';' separators. + Das ist in der gleichen Zeile auch mit dem Trennzeichen ";" möglich. + + + + This example shows how to use "copy-and-update" on record values. It creates + Dieses Beispiel zeigt die Verwendung von "Kopieren und aktualisieren" für Datensatzwerte. Es wird + + + + a new record value that is a copy of contact1, but has different values for + ein neuer Datensatz als Kopie von "contact1" erstellt, der jedoch über andere Werte + + + + the 'Phone' and 'Verified' fields. + für die Felder "Phone" und "Verified" verfügt. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Dieses Beispiel veranschaulicht das Schreiben einer Funktion zum Verarbeiten eines Datensatzwerts. + + + + It converts a 'ContactCard' object to a string. + Es konvertiert ein Objekt vom Typ "ContactCard" in eine Zeichenfolge. + + + + This is an example of a Record with a member. + Dies ist ein Beispiel für einen Datensatz mit einem Member. + + + + Members can implement object-oriented members. + Member können objektorientierte Member implementieren. + + + + Members are accessed via the '.' operator on an instantiated type. + Auf Member wird über den Operator "." in einem instanziierten Typ zugegriffen. + + + + Records can also be represented as structs via the 'Struct' attribute. + Datensätze können mithilfe des Attributs "Struct" auch als Strukturen dargestellt werden. + + + + This is helpful in situations where the performance of structs outweighs + Dies ist in Situationen hilfreich, in denen die Leistung der Strukturen wichtiger ist als + + + + the flexibility of reference types. + die Flexibilität der Verweistypen. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Diskriminierte Unions (DUs) sind Werte, die eine Anzahl benannter Formen oder Fälle sein können. + + + + Data stored in DUs can be one of several distinct values. + In DUs gespeicherte Daten können einer von verschiedenen eindeutigen Werten sein. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + Folgendes stellt die Farbe einer Spielkarte dar. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Eine diskriminierte Union kann auch verwendet werden, um den Rang einer Spielkarte darzustellen. + + + + Represents the rank of cards 2 .. 10 + Stellt den Rang der Karten 2 bis 10 dar 10 + + + + Discriminated Unions can also implement object-oriented members. + Diskriminierte Unions können objektorientierte Member implementieren. + + + + This is a record type that combines a Suit and a Rank. + Dieser Datensatztyp kombiniert eine Farbe und einen Rang. + + + + It's common to use both Records and Disciminated Unions when representing data. + Beim Darstellen von Daten werden häufig sowohl Datensätze als auch diskriminierte Unions verwendet. + + + + This computes a list representing all the cards in the deck. + Dies berechnet eine Liste mit allen Karten im Stapel. + + + + This example converts a 'Card' object to a string. + Dieses Beispiel konvertiert ein Objekt vom Typ "Card" in eine Zeichenfolge. + + + + This example prints all the cards in a playing deck. + Dieses Beispiel gibt alle Karten in einem Kartenstapel aus. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Einzelfall-DUs werden häufig für die Domänenmodellierung verwendet. Dadurch erhalten Sie zusätzliche Typsicherheit + + + + over primitive types such as strings and ints. + für primitive Typen wie Zeichenfolgen und Integer. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Eine implizite Konvertierung von Einzelfall-DUs in den umschlossenen Typ oder aus diesem Typ ist nicht möglich. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Beispielsweise eine Funktion, die eine Adresse akzeptiert, kann keine Zeichenfolge als Eingabe akzeptieren + + + + or vive/versa. + (oder umgekehrt). + + + + You can easily instantiate a single-case DU as follows. + Sie können Einzelfall-DUs folgendermaßen instanziieren. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Wenn Sie den Wert benötigen, können Sie den zugrunde liegenden Wert mit einer einfachen Funktion entpacken. + + + + Printing single-case DUs is simple with unwrapping functions. + Mit entpackten Funktionen lassen sich Einzelfall-DUs einfach drucken. + + + + Disciminated Unions also support recursive definitions. + Diskriminierte Unions unterstützen auch rekursive Definitionen. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Dies stellt eine Struktur für die Binärsuche dar, wobei ein Fall eine leere Struktur ist + + + + and the other being a Node with a value and two subtrees. + und der andere Fall einen Knoten mit einem Wert und zwei Unterstrukturen darstellt. + + + + Check if an item exists in the binary search tree. + Prüfen Sie, ob die Struktur für die Binärsuche ein Element enthält. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Sucht rekursiv mithilfe des Musterabgleichs. Gibt bei vorhandenem Element "true" aus, andernfalls "false". + + + + Check the left subtree. + Prüfen Sie die linke Unterstruktur. + + + + Check the right subtree. + Prüfen Sie die rechte Unterstruktur. + + + + Inserts an item in the Binary Search Tree. + Fügt in die Struktur für die Binärsuche ein Element ein. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Findet die Position für das rekursive Einfügen mithilfe des Musterabgleichs und fügt anschließend einen neuen Knoten ein. + + + + If the item is already present, it does not insert anything. + Wenn das Element bereits vorhanden ist, wird nichts eingefügt. + + + + No need to insert, it already exists; return the node. + Einfügen nicht erforderlich, da bereits vorhanden; Knoten zurückgeben. + + + + Call into left subtree. + Aufruf in linker Unterstruktur. + + + + Call into right subtree. + Aufruf in rechter Unterstruktur. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Diskriminierte Unions können mithilfe des Attributs "Struct" auch als Struktur dargestellt werden. + + + + This is helpful in situations where the performance of structs outweighs + Dies ist in Situationen hilfreich, in denen die Leistung der Strukturen wichtiger ist als + + + + the flexibility of reference types. + die Flexibilität der Verweistypen. + + + + However, there are two important things to know when doing this: + Dabei sind jedoch zwei Punkte zu beachten: + + + + 1. A struct DU cannot be recursively-defined. + 1. Eine Struktur-DU kann nicht rekursiv definiert werden. + + + + 2. A struct DU must have unique names for each of its cases. + 2. In einer Struktur-DU muss jeder Fall einen eindeutigen Namen haben. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Der Musterabgleich ist eine Funktion von F#, die Ihnen die Verwendung von Mustern ermöglicht, + + + + which are a way to compare data with a logical structure or structures, + die eine Möglichkeit sind, um Daten mit logischen Strukturen oder Strukturen zu vergleichen, + + + + decompose data into constituent parts, or extract information from data in various ways. + Daten in ihre Einzelteile zu zerlegen oder auf verschiedene Weise Informationen aus Daten zu extrahieren. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Das Verteilen ist anschließend mithilfe des Musterabgleichs anhand der Form eines Musters möglich. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Ein Datensatz für den Vor- und Nachnamen einer Person + + + + A Discriminated Union of 3 different kinds of employees + Eine diskriminierte Union mit drei verschiedenen Arten von Mitarbeitern + + + + Count everyone underneath the employee in the management hierarchy, + Zählen Sie alle Personen unterhalb des Angestellten in der Verwaltungshierarchie, + + + + including the employee. + einschließlich des Angestellten. + + + + Find all managers/executives named "Dave" who do not have any reports. + Suchen Sie alle Manager/Führungskräfte mit dem Namen "Dave", die über keine Berichte verfügen. + + + + This uses the 'function' shorthand to as a lambda expression. + Dies verwendet die Kurzform "function" als Lambdaausdruck. + + + + [] matches an empty list. + [] entspricht einer leeren Liste. + + + + '_' is a wildcard pattern that matches anything. + "_" ist ein Platzhaltermuster, das mit allem übereinstimmt + + + + This handles the "or else" case. + Dies behandelt den "or else"-Fall. + + + + You can also use the shorthand function construct for pattern matching, + Sie können das Kurzform-Funktionskonstrukt auch für den Musterabgleich verwenden, + + + + which is useful when you're writing functions which make use of Partial Application. + was beim Schreiben von Funktionen, die die partielle Anwendung nutzen, hilfreich ist. + + + + Define some more functions which parse with the helper function. + Definieren Sie weitere Funktionen, die eine Analyse mithilfe der Hilfsfunktion durchführen. + + + + Active Patterns are another powerful construct to use with pattern matching. + Aktive Muster sind ein weiteres leistungsstarkes Konstrukt, das beim Musterabgleich verwendet werden kann. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Sie ermöglichen eine Partitionierung der Eingabedaten in benutzerdefinierte Formen, wobei sie an der Musterabgleichs-Aufrufsite zerlegt werden. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Der Musterabgleich mithilfe des Schlüsselworts "function" und das aktive Muster sehen häufig wie folgt aus. + + + + Call the printer with some different values to parse. + Rufen Sie den Drucker mit unterschiedlichen zu analysierenden Werten auf. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Bei Optionswerten handelt es sich um eine beliebige Art von Werten, die entweder mit "Some" oder mit "None" markiert sind. + + + + They are used extensively in F# code to represent the cases where many other + Sie werden in F#-Code umfassend verwendet, um die Fälle darzustellen, in denen viele + + + + languages would use null references. + Sprachen NULL-Verweise verwenden würden. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Definieren Sie als Erstes eine Postleitzahl, die über eine diskriminierte Einzelfall-Union definiert ist. + + + + Next, define a type where the ZipCode is optional. + Definieren Sie als Nächstes einen Typ, bei dem "ZipCode" optional ist. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Definieren Sie dann einen Schnittstellentyp, der ein Objekt zum Berechnen der Versandkosten für die Postleitzahl des Kunden repräsentiert, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + sofern Implementierungen für die abstrakten Methoden "getState" und "getShippingZone" vorhanden sind. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Berechnen Sie nun mithilfe einer Rechnerinstanz die Versandkosten für einen Kunden. + + + + This uses combinators in the Option module to allow a functional pipeline for + Dies verwendet Kombinatoren im Option-Modul für eine funktionale Pipeline zum + + + + transforming data with Optionals. + Transformieren von Daten mit Optionen. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Maßeinheiten sind eine Möglichkeit, um für primitive numerische Typen typsicher den Änderungsverlauf einzublenden. + + + + You can then perform type-safe arithmetic on these values. + Anschließend können Sie für diese Werte die typsichere Arithmetik ausführen. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Öffnen Sie zunächst eine Auflistung mit allgemeinen Einheitennamen. + + + + Define a unitized constant + Definieren Sie eine einheitliche Konstante. + + + + Next, define a new unit type + Definieren Sie als Nächstes einen neuen Einheitentyp. + + + + Conversion factor mile to meter. + Faktor für die Umrechnung von Meilen in Meter. + + + + Define a unitized constant + Definieren Sie eine einheitliche Konstante. + + + + Compute metric-system constant + Berechnen Sie die Konstante für das metrische System. + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Werte, die Maßeinheiten verwenden, können wie der primitive numerische Typ z.B. zum Drucken genutzt werden. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Klassen sind eine Möglichkeit zum Definieren neuer Objekttypen in F#. Sie unterstützen standardmäßige objektorientierte Konstrukte. + + + + They can have a variety of members (methods, properties, events, etc.) + Sie können über verschiedene Member verfügen (Methoden, Eigenschaften, Ereignisse usw.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Weitere Informationen zu Klassen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Weitere Informationen zu Membern finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Eine einfache, zweidimensionale Vektorklasse. + + + + The class's constructor is on the first line, + Der Konstruktor der Klasse befindet sich in der ersten Zeile + + + + and takes two arguments: dx and dy, both of type 'double'. + und akzeptiert zwei Argumente: dx und dy, beide vom Typ "double". + + + + This internal field stores the length of the vector, computed when the + Dieses interne Feld speichert die Länge des Vektors, die berechnet wird, wenn + + + + object is constructed + das Objekt konstruiert wird. + + + + 'this' specifies a name for the object's self identifier. + "this" gibt einen Namen für den Selbstbezeichner des Objekts an. + + + + In instance methods, it must appear before the member name. + In Instanzmethoden muss dies vor dem Membernamen angegeben werden. + + + + This member is a method. The previous members were properties. + Dieser Member ist eine Methode. Die vorherigen Member waren Eigenschaften. + + + + This is how you instantiate the Vector2D class. + So instanziieren Sie die Vector2D-Klasse. + + + + Get a new scaled vector object, without modifying the original object. + Rufen Sie ein neues skaliertes Vektorobjekt ab, ohne das ursprüngliche Objekt zu verändern. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Generische Klassen ermöglichen das Definieren von Typen in Bezug auf eine Gruppe von Typparametern. + + + + In the following, 'T is the type parameter for the class. + Im Folgenden ist 'T der Typparameter für die Klasse. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Dieses interne Feld speichert die Zustände in einer Liste. + + + + Add a new element to the list of states. + Der Liste der Zustände ein neues Element hinzufügen + + + + use the '<-' operator to mutate the value. + Den "<-"-Operator verwenden, um den Wert zu mutieren + + + + Get the entire list of historical states. + Die gesamte Liste der Verlaufszustände abrufen + + + + Get the latest state. + Den aktuellen Zustand abrufen + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Eine int-Instanz der state tracker-Klasse. Beachten Sie, dass der Typ-Parameter abgeleitet wird. + + + + Add a state + Einen Zustand hinzufügen + + + + Interfaces are object types with only 'abstract' members. + Schnittstellen sind Objekttypen, die nur über abstrakte Member verfügen. + + + + Object types and object expressions can implement interfaces. + Objekttypen und Objektausdrücke können Schnittstellen implementieren. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Dieser Typ implementiert "IDisposable". + + + + This is the implementation of IDisposable members. + Dies ist die Implementierung von IDisposable-Membern. + + + + This is an object that implements IDisposable via an Object Expression + Dies ist ein Objekt, das IDisposable über einen Objektausdruck implementiert. + + + + Unlike other languages such as C# or Java, a new type definition is not needed + Im Gegensatz zu anderen Sprachen wie C# oder Java ist keine neue Typendefinition erforderlich, + + + + to implement an interface. + um eine Schnittstelle zu implementieren. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + Die Bibliothek "FSharp.Core" definiert eine Reihe paralleler Verarbeitungsfunktionen. Hier + + + + you use some functions for parallel processing over arrays. + verwenden Sie einige Funktionen zur parallelen Verarbeitung über Arrays. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Weitere Informationen finden Sie unter: https://msdn.microsoft.com/de-de/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Definieren Sie zunächst ein Array mit Eingaben. + + + + Next, define a functions that does some CPU intensive computation. + Definieren Sie dann eine Funktion mit CPU-intensiven Berechnungen. + + + + Next, do a parallel map over a large input array. + Führen Sie als Nächstes eine parallele Zuordnung für ein umfangreiches Eingabearray durch. + + + + Next, print the results. + Geben Sie die Ergebnisse aus. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Ereignisse sind ein gängiger Begriff bei der .NET-Programmierung, v. a. bei WinForms oder WPF-Anwendungen. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Weitere Informationen finden Sie unter: https://docs.microsoft.com/de-de/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Erstellen Sie zunächst eine Instanz des Event-Objekts mit Abonnementpunkt (event.Publish) und Ereignisauslöser (event.Trigger). + + + + Next, add handler to the event. + Fügen Sie dem Ereignis einen Handler hinzu. + + + + Next, trigger the event. + Lösen Sie das Ereignis aus. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Erstellen Sie als Nächstes eine Event-Instanz gemäß der .NET-Standardkonvention: (sender, EventArgs) + + + + Next, add a handler for this new event. + Fügen Sie einen Handler für das neue Ereignis hinzu. + + + + Next, trigger this event (note that sender argument should be set). + Lösen Sie das Ereignis aus. (Hinweis: das sender-Argument muss festgelegt sein.) + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.es.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.es.xlf new file mode 100644 index 0000000000..692964c713 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.es.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Este ejemplo le guiará por los elementos del lenguaje F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Para ejecutar el código en F# interactivo, resalte una sección de código y presione Alt+Entrar, o bien haga clic con el botón secundario + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + y seleccione "Ejecutar en modo interactivo". Puede abrir la ventana de F# interactivo desde el menú "Ver". + + + + For more about F#, see: + Para obtener más información acerca de F#, vea: + + + + To see this tutorial in documentation form, see: + Para ver este tutorial en forma de documentación, vea: + + + + To learn more about applied F# programming, use + Para obtener más información sobre la programación de F# aplicada, use + + + + To install the Visual F# Power Tools, use + Para instalar Visual F# Power Tools, use + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + "Herramientas" --> "Extensiones y actualizaciones" --> "En línea" y busque + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Para obtener plantillas adicionales para su uso con F#, consulte 'Plantillas en línea' en Visual Studio, + + + + 'New Project' --> 'Online Templates' + "Nuevo proyecto" --> "Plantillas en línea" + + + + F# supports three kinds of comments: + F# admite tres tipos de comentarios: + + + + 1. Double-slash comments. These are used in most situations. + 1. Comentarios con doble barra diagonal. Se usan en la mayoría de las situaciones. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Comentarios de bloque de estilo ML. No se usan con tanta frecuencia. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Comentarios de triple barra diagonal. Se utilizan para funciones de documentación, tipos, etc. + + + + They will appear as text when you hover over something which is decorated with these comments. + Aparecerán como texto al mantener el puntero por encima de algo decorado con estos comentarios. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + También admiten comentarios XML de estilo .NET, que le permite generar documentación de referencia, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + y también permite a los editores (como Visual Studio) extraer información de ellos. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Abra los espacios de nombres con la palabra clave "open". + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Un módulo es una agrupación de código de F#, como valores, tipos y valores de función. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + El código de agrupación de los módulos ayuda a mantener el código relacionado en conjunto y ayuda a evitar los conflictos de nombres en su programa. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Este es un entero de ejemplo. + + + + This is a sample floating point number. + Este es un número de punto flotante de ejemplo. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Se calcula un número nuevo aplicando cierta aritmética. Los tipos numéricos se convierten mediante + + + + functions 'int', 'double' and so on. + funciones "int", "double", etc. + + + + This is a list of the numbers from 0 to 99. + Esta es una lista de números del 0 al 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Esta es una lista de todas las tuplas que contienen todos los números de 0 a 99 y sus cuadrados. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + La línea siguiente imprime una lista que incluye tuplas, utilizando "%A" para la impresión genérica. + + + + This is a sample integer with a type annotation + Este es un entero de ejemplo con una anotación de tipo + + + + Values in F# are immutable by default. They cannot be changed + Los valores de F# son inmutables de manera predeterminada. No se pueden cambiar + + + + in the course of a program's execution unless explicitly marked as mutable. + en el transcurso de la ejecución de un programa a menos que se marquen explícitamente como mutable. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Al enlazar un valor a un nombre con "let", se convierte en inmutable. + + + + The second line of code fails to compile because 'number' is immutable and bound. + La segunda línea de código no se compila porque "number" es inmutable y está enlazado. + + + + Re-defining 'number' to be a different value is not allowed in F#. + En F#, no se puede redefinir "number" para darle otro valor. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Enlace mutable. Es necesario para poder mutar el valor de "otherNumber". + + + + When mutating a value, use '<-' to assign a new value. + Para la mutación de un valor, use "<-" para asignar un valor nuevo. + + + + You could not use '=' here for this purpose since it is used for equality + No pudo usar "=" con este propósito, porque se usa para la igualdad + + + + or other contexts such as 'let' or 'module' + u otros contextos, como "let" o "module" + + + + Much of F# programming consists of defining functions that transform input data to produce + Gran parte de la programación de F# consiste en definir funciones que transforman los datos de entrada para generar + + + + useful results. + resultados útiles. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + "let" se utiliza para definir una función. En este caso, acepta un argumento de entero y devuelve un entero. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Los paréntesis son opcionales para argumentos de función, excepto cuando se utiliza una anotación de tipo explícito. + + + + Apply the function, naming the function return result using 'let'. + Aplicar la función, asignando un nombre al resultado devuelto por la función mediante 'let'. + + + + The variable type is inferred from the function return type. + El tipo de variable se infiere del tipo de valor devuelto por la función. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Esta línea utiliza "%d" para imprimir el resultado de un entero. Cuenta con seguridad de tipos. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Si "result1" no fuese de tipo "int", la línea no se compilaría. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Si es necesario, anote el tipo de un nombre de parámetro usando "(argument:type)". Los paréntesis son obligatorios. + + + + Conditionals use if/then/elid/elif/else. + Los condicionales usan if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Tenga en cuenta que F# utiliza una sintaxis que tiene en cuenta la sangría de espacios en blanco, de forma parecida a lenguajes como Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Esta línea utiliza "%f" para imprimir el resultado como un valor float. Al igual que "%d", cuenta con seguridad de tipos. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Los valores booleanos son tipos de datos fundamentales en F#. Estos son algunos ejemplos de valores booleanos y lógica condicional. + + + + To learn more, see: + Para obtener más información, vea: + + + + and + Y + + + + Booleans values are 'true' and 'false'. + Los valores booleanos son "true" y "false". + + + + Operators on booleans are 'not', '&&' and '||'. + Los operadores de valores booleanos son "not", "&&" y "||". + + + + This line uses '%b'to print a boolean value. This is type-safe. + Esta línea utiliza "%b" para imprimir un valor booleano. Cuenta con seguridad de tipos. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Las cadenas son tipos de datos fundamentales en F#. Estos son algunos ejemplos de cadenas y de manipulación básica de cadenas. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Las cadenas usan comillas dobles. + + + + Strings can also use @ to create a verbatim string literal. + Las cadenas también pueden usar @ para crear un literal de cadena textual. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + No tiene en cuenta los caracteres de escape, como "\", "\n", "\t", etc. + + + + String literals can also use triple-quotes. + Los literales de cadena también pueden usar comillas triples. + + + + String concatenation is normally done with the '+' operator. + La concatenación de cadenas suele hacerse con el operador "+". + + + + This line uses '%s' to print a string value. This is type-safe. + Esta línea utiliza "%s" para imprimir un valor de cadena. Cuenta con seguridad de tipos. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Las subcadenas utilizan la notación del indexador. Esta línea extrae los 7 primeros caracteres como una subcadena. + + + + Note that like many languages, Strings are zero-indexed in F#. + Tenga en cuenta que, al igual que en otros muchos lenguajes, las cadenas tienen índice 0 en F#. + + + + Tuples are simple combinations of data values into a combined value. + Las tuplas son combinaciones simples de valores de datos en un valor combinado. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Tupla de enteros sencilla. + + + + A function that swaps the order of two values in a tuple. + Una función que intercambia el orden de dos valores en una tupla. + + + + F# Type Inference will automatically generalize the function to have a generic type, + La inferencia de tipos de F# generalizará la función de forma automática para que tenga un tipo genérico, + + + + meaning that it will work with any type. + lo que significa que funcionará con cualquier tipo. + + + + A tuple consisting of an integer, a string, + Una tupla que consta de un entero, una cadena, + + + + and a double-precision floating point number. + y un número de punto flotante de doble precisión. + + + + A simple tuple of integers with a type annotation. + Una tupla de enteros sencilla con una anotación de tipo. + + + + Type annotations for tuples use the * symbol to separate elements + Las anotaciones de tipo para las tuplas usan el símbolo * para separar los elementos + + + + Tuples are normally objects, but they can also be represented as structs. + Las tuplas suelen ser objetos, pero también se pueden representar como estructuras. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Interoperan completamente con estructuras de C# y Visual Basic.NET; sin embargo, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + las tuplas de estructuras no son implícitamente convertibles con tuplas de objeto (a menudo denominadas tuplas de referencia). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + La segunda línea no se compilará por esto. Quite las marcas de comentario para ver qué ocurre. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Aunque no puede convertir tuplas de struct en tuplas de referencia y viceversa de forma implícita, + + + + you can explicitly convert via pattern matching, as demonstrated below. + puede hacer la conversión de forma explícita mediante coincidencia de patrones, como se muestra a continuación. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Los operadores de canalización ("|>", "<|", etc.) y de composición (">>", "<<") de F# + + + + are used extensively when processing data. These operators are themselves functions + se utilizan mucho en el procesamiento de datos. Estos operadores son en sí mismos funciones. + + + + which make use of Partial Application. + que usan aplicación parcial. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Para obtener más información sobre estos operadores, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Para obtener más información sobre la aplicación parcial, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Eleva un valor la cuadrado. + + + + Adds 1 to a value. + Suma 1 a un valor. + + + + Tests if an integer value is odd via modulo. + Comprueba si un valor entero es impar mediante un módulo. + + + + A list of 5 numbers. More on lists later. + Lista de 5 números. Más adelante, se proporciona más información sobre listas. + + + + Given a list of integers, it filters out the even numbers, + Dada una lista de enteros, aplica un filtro para excluir los números pares, + + + + squares the resulting odds, and adds 1 to the squared odds. + eleva al cuadrado los impares resultantes y les suma 1. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Una forma más corta de escribir "squareOddValuesAndAddOne" es anidar cada + + + + sub-result into the function calls themselves. + subresultado en las propias llamadas a la función. + + + + This makes the function much shorter, but it's difficult to see the + Esto hace la función mucho más corta, pero es difícil ver el + + + + order in which the data is processed. + orden en el que se procesan los datos. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Una forma recomendable de escribir "squareOddValuesAndAddOne" es usar operadores de canalización de F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + Esto permite evitar que se creen resultados intermedios, pero es mucho más fácil de leer + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + que anidar las llamadas a la función como "squareOddValuesAndAddOneNested" + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + No puede acortar "squareOddValuesAndAddOnePipeline" moviendo la segunda llamada de "List.map" + + + + into the first, using a Lambda Function. + a la primera, usando una función lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Tenga en cuenta que las canalizaciones se usan también en la función lambda. Los operadores de canalización de F# + + + + can be used for single values as well. This makes them very powerful for processing data. + se puede usar también para valores individuales. Esto les confiere una gran capacidad para el procesamiento de datos. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + Por último, puede eliminar la necesidad de tomar "valores" de forma explícita como parámetro usando ">>" + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + para componer las dos operaciones principales: aplicar un filtro para excluir los números pares, elevar al cuadrado y sumar uno. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + De igual modo, no se necesita tampoco la parte "fun x -> ..." de la expresión lambda, porque "x" + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + se define en ese ámbito para poderlo pasar a una canalización funcional. Por tanto, ">>" se pude usar + + + + there as well. + aquí también. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + El resultado de "squareOddValuesAndAddOneComposition" es en sí mismo otra función que toma una + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + lista de enteros como entrada. Si ejecuta "squareOddValuesAndAddOneComposition" con una lista + + + + of integers, you'll notice that it produces the same results as previous functions. + de enteros, notará que produce los mismos resultados que las funciones anteriores. + + + + This is using what is known as function composition. This is possible because functions in F# + Aquí se utiliza lo que se conoce como composición de funciones. Es posible porque las funciones en F# + + + + use Partial Application and the input and output types of each data processing operation match + utilizan aplicación parcial y los tipos de entrada y salida de cada operación de procesamiento de datos buscan + + + + the signatures of the functions we're using. + las signaturas de las funciones que estamos usando. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Las listas están ordenadas, son inmutables y están vinculadas individualmente. Son diligentes en su evaluación. + + + + This module shows various ways to generate lists and process lists with some functions + Este módulo muestra varias formas de generar listas y procesarlas con algunas funciones + + + + in the 'List' module in the F# Core Library. + en el módulo "List" de la biblioteca principal de F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Las listas se definen mediante [ ... ]. Esta es una lista vacía. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Esta es una lista de 3 elementos. Se utiliza ";" para separar los elementos que están en la misma línea. + + + + You can also separate elements by placing them on their own lines. + También puede separar los elementos poniendo cada uno en su propia línea. + + + + This is a list of integers from 1 to 1000 + Esta es una lista de enteros del 1 al 1000 + + + + Lists can also be generated by computations. This is a list containing + Las listas también pueden generarse mediante cálculos. Esta es una lista que contiene + + + + all the days of the year. + todos los días del año. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Imprime los 5 primeros elementos de "daysList" usando "List.take". + + + + Computations can include conditionals. This is a list containing the tuples + Los cálculos pueden incluir condicionales. Esta es una lista que contiene las tuplas + + + + which are the coordinates of the black squares on a chess board. + que son las coordenadas de los cuadrados negros de un tablero de ajedrez. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Las listas se pueden transformas mediante "List.map" y otros combinadores de programación funcionales. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Esta definición genera una nueva lista al elevar al cuadrado los números incluidos en numberList y usa el operador + + + + operator to pass an argument to List.map. + de canalización para pasar un argumento a List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Hay otras muchas combinaciones de listas. La siguiente, calcula la suma de los cuadrados de los + + + + numbers divisible by 3. + números divisibles por 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Las matrices son colecciones mutables de tamaño fijo de elementos del mismo tipo. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Aunque son parecidas a las listas (admiten enumeración y tienen combinadores parecidos para el procesamiento de datos), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + suelen ser más rápidas y admitir acceso aleatorio rápido. A cambio, tiene el inconveniente de que es menos seguro porque es mutable. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Esta es una matriz vacía. Observe que la sintaxis es parecida a la de las listas, pero utiliza "[| ... |]" en su lugar. + + + + Arrays are specified using the same range of constructs as lists. + Las matrices se especifican con el mismo intervalo de construcciones que las listas. + + + + This is an array of numbers from 1 to 1000. + Esta es una matriz de números del 1 al 1000. + + + + This is an array containing only the words "hello" and "world". + Esta es una matriz que solo contiene las palabras "hola" y "todos". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Esta es una matriz inicializada con un índice que contiene los números pares del 0 al 2000. + + + + Sub-arrays are extracted using slicing notation. + Las submatrices se extraen mediante la notación divisoria. + + + + You can loop over arrays and lists using 'for' loops. + Puede ejecutar un bucle en matrices y listas usando bucles "for". + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Puede modificar el contenido de un elemento de matriz mediante el operador de asignación de flecha izquierda. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Para obtener más información sobre este operador, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Para transformar matrices, use "Array.map" y otras operaciones de programación funcionales. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + La operación siguiente calcula la suma de las longitudes de las palabras que empiezan por "h". + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Las secuencias son una serie lógica de elementos del mismo tipo. Son de un tipo más general que las listas o las matrices. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Las secuencias se evalúan previa petición y se vuelven a evaluar cada vez que se recorren en iteración. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Una secuencia de F# es un alias para un elemento System.Collections.Generic.IEnumerable<'T> de .NET. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Las funciones de procesamiento de secuencias también pueden aplicarse a las listas y a las matrices. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Esta es una secuencia vacía. + + + + This a sequence of values. + Esta es una secuencia de valores. + + + + This is an on-demand sequence from 1 to 1000. + Esta es una secuencia a petición del 1 al 1000. + + + + This is a sequence producing the words "hello" and "world" + Esta es una secuencia que genera las palabras "hola" y "todos" + + + + This sequence producing the even numbers up to 2000. + Esta secuencia genera los números pares hasta el 2000. + + + + This is an infinite sequence which is a random walk. + Esta es una secuencia infinita que constituye un recorrido aleatorio. + + + + This example uses yield! to return each element of a subsequence. + Este ejemplo usa yield! para devolver cada uno de los elementos de una subsecuencia. + + + + This example shows the first 100 elements of the random walk. + Este ejemplo muestra los 100 primeros elementos del recorrido aleatorio. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Las funciones recursivas pueden llamarse a sí mismas. En F#, las funciones solo son recursivas + + + + when declared using 'let rec'. + cuando se declara con "let rec". + + + + Recursion is the preferred way to process sequences or collections in F#. + La recursión es la forma recomendada de procesar secuencias o colecciones en F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Este ejemplo muestra una función recursiva que calcula el factorial de un + + + + integer. It uses 'let rec' to define a recursive function. + entero. Usa "let rec" para definir una función recursiva. + + + + Computes the greatest common factor of two integers. + Calcula el mayor factor común de dos enteros. + + + + Since all of the recursive calls are tail calls, + Puesto que todas las llamadas recursivas son llamadas de cola, + + + + the compiler will turn the function into a loop, + el compilador devolverá la función en un bucle, + + + + which improves performance and reduces memory consumption. + lo que mejora el rendimiento y reduce el consumo de memoria. + + + + This example computes the sum of a list of integers using recursion. + Este ejemplo calcula la suma de una lista de enteros con recursión. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Esto convierte la función "sumList" en recursiva de cola, usando una función auxiliar con un acumulador de resultados. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Este código invoca la función auxiliar recursiva de cola, proporcionando "0" como acumulador de valores de inicialización. + + + + An approach like this is common in F#. + Este método es habitual en F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Los registros son un agregado de valores con nombre, con miembros opcionales (como los métodos). + + + + They are immutable and have structural equality semantics. + Son inmutables y tienen semántica de igualdad estructural. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Este ejemplo muestra cómo definir un nuevo tipo de registro. + + + + This example shows how to instantiate a record type. + Este ejemplo muestra cómo crear una instancia de un tipo de registro. + + + + You can also do this on the same line with ';' separators. + También puede hacer esto en la misma línea usando ";" como separador. + + + + This example shows how to use "copy-and-update" on record values. It creates + Este ejemplo muestra cómo usar "copy-and-update" en los valores de registro. Crea + + + + a new record value that is a copy of contact1, but has different values for + un nuevo valor de registro que es una copia de contact1, pero con valores distintos para + + + + the 'Phone' and 'Verified' fields. + los campos "Phone" y "Verified". + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Este ejemplo muestra cómo escribir una función que procesa un valor del registro. + + + + It converts a 'ContactCard' object to a string. + Convierte un objeto "ContactCard" en una cadena. + + + + This is an example of a Record with a member. + Este es un ejemplo de un registro con un miembro. + + + + Members can implement object-oriented members. + Los miembros pueden implementar miembros orientados a objetos. + + + + Members are accessed via the '.' operator on an instantiated type. + A los miembros se accede con el operador "." en un tipo del que se ha creado una instancia. + + + + Records can also be represented as structs via the 'Struct' attribute. + Los registros se pueden representar también como estructuras con el atributo "Struct". + + + + This is helpful in situations where the performance of structs outweighs + Esto es útil en situaciones donde el rendimiento de las estructuras es superior a + + + + the flexibility of reference types. + la flexibilidad de los tipos de referencia. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Las uniones discriminadas (DU) son valores que podrían ser un gran número de formas o casos con nombre. + + + + Data stored in DUs can be one of several distinct values. + Los datos almacenados en uniones discriminadas pueden ser uno de varios valores diferentes. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + El siguiente código representa el palo de una carta. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + También se puede usar una unión discriminada para representar el rango de una carta. + + + + Represents the rank of cards 2 .. 10 + Representa el rango de cartas 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + Las uniones discriminadas pueden implementar también miembros orientados a objetos. + + + + This is a record type that combines a Suit and a Rank. + Este es un tipo de registro que combina un palo y un rango. + + + + It's common to use both Records and Disciminated Unions when representing data. + Es habitual utilizar tanto registros como uniones discriminadas cuando se representan datos. + + + + This computes a list representing all the cards in the deck. + Este código calcula una lista que representa todas las cartas de la baraja. + + + + This example converts a 'Card' object to a string. + Este ejemplo convierte un objeto "Card" en una cadena. + + + + This example prints all the cards in a playing deck. + Este ejemplo imprime todas las cartas de una baraja. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Las uniones discriminadas de un solo caso se usan con frecuencia en el modelado de dominios. Esto puede aportar mayor seguridad de tipos + + + + over primitive types such as strings and ints. + en tipos primitivos, como cadenas y enteros. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Las uniones discriminadas de un solo caso no se pueden convertir de forma implícita en el tipo que encapsulan, ni viceversa. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Por ejemplo, una función que toma una dirección no puede aceptar una cadena como esa entrada, + + + + or vive/versa. + o viceversa. + + + + You can easily instantiate a single-case DU as follows. + Puede crear fácilmente una instancia de una unión discriminada de un solo caso del siguiente modo. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Cuando necesite el valor, puede desencapsular el valor subyacente con una función sencilla. + + + + Printing single-case DUs is simple with unwrapping functions. + Imprimir uniones discriminadas de un solo caso es muy sencillo con funciones de desencapsulamiento. + + + + Disciminated Unions also support recursive definitions. + Las uniones discriminadas admiten también definiciones recursivas. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Esto representa un árbol de búsqueda binaria, donde un caso es el árbol vacío + + + + and the other being a Node with a value and two subtrees. + y el otro es un nodo con un valor y dos subárboles. + + + + Check if an item exists in the binary search tree. + Comprueba si existe un elemento en el árbol de búsqueda binaria. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Hace búsquedas de forma recursiva usando coincidencia de patrones. Devuelve true si existe; de lo contrario, false. + + + + Check the left subtree. + Comprueba el subárbol de la izquierda. + + + + Check the right subtree. + Comprueba el subárbol de la derecha. + + + + Inserts an item in the Binary Search Tree. + Inserta un elemento en el árbol de búsqueda binaria. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Busca dónde insertar de forma recursiva un nuevo nodo usando coincidencia de patrones y lo inserta. + + + + If the item is already present, it does not insert anything. + Si el elemento ya está presente, no inserta nada. + + + + No need to insert, it already exists; return the node. + No es necesario insertarlo, ya existe; devuelve el nodo. + + + + Call into left subtree. + Llama al subárbol de la izquierda. + + + + Call into right subtree. + Llama al subárbol de la derecha. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Las uniones discriminadas se pueden representar también como estructuras con el atributo "Struct". + + + + This is helpful in situations where the performance of structs outweighs + Esto es útil en situaciones donde el rendimiento de las estructuras es superior a + + + + the flexibility of reference types. + la flexibilidad de los tipos de referencia. + + + + However, there are two important things to know when doing this: + No obstante, hay dos cosas importantes que deben tenerse en cuenta cuando se hace esto: + + + + 1. A struct DU cannot be recursively-defined. + 1. Una unión discriminada de estructura no se puede definir de forma recursiva. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Una unión discriminada de estructura debe tener un nombre único para cada uno de sus casos. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + La coincidencia de patrones es una característica de F# que permite utilizar patrones, + + + + which are a way to compare data with a logical structure or structures, + que son una forma de comparar datos con estructuras lógicas, + + + + decompose data into constituent parts, or extract information from data in various ways. + descomponer datos en partes constituyentes o extraer información de datos de varias formas. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Después, puede hacer envíos en función de la "forma" de un patrón mediante coincidencia de patrones. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Un registro para el nombre y los apellidos de una persona + + + + A Discriminated Union of 3 different kinds of employees + Una unión discriminada de 3 tipos de empleados diferentes + + + + Count everyone underneath the employee in the management hierarchy, + Cuenta a todos por debajo del empleado en la jerarquía de administración, + + + + including the employee. + incluido el empleado. + + + + Find all managers/executives named "Dave" who do not have any reports. + Buscar a todos los directores o ejecutivos que se llamen "Dave" que no tengan jefes. + + + + This uses the 'function' shorthand to as a lambda expression. + Aquí se utiliza la forma abreviada "function" como una expresión lambda. + + + + [] matches an empty list. + [] coincide con una lista vacía. + + + + '_' is a wildcard pattern that matches anything. + "_" es un patrón comodín que busca cualquier cosa. + + + + This handles the "or else" case. + Este código controla el caso "or else". + + + + You can also use the shorthand function construct for pattern matching, + También puede usar la construcción abreviada de funciones para la coincidencia de patrones, + + + + which is useful when you're writing functions which make use of Partial Application. + que es muy útil cuando se escriben funciones que utilizan aplicación parcial. + + + + Define some more functions which parse with the helper function. + Define algunas funciones más que se analizan con la función auxiliar. + + + + Active Patterns are another powerful construct to use with pattern matching. + Los patrones activos son también una construcción muy eficaz para usarla con coincidencia de patrones. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Permiten particionar los datos de entrada en formas personalizadas, descomponiéndolos en el sitio de llamada de coincidencia de patrones. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + La coincidencia de patrones con la palabra clave "function" y patrones activos suele ser similar a este código. + + + + Call the printer with some different values to parse. + Llamar a la impresora con algunos valores diferentes para analizar. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Los valores de opción son cualquier tipo de valor etiquetado como 'Some' o 'None'. + + + + They are used extensively in F# code to represent the cases where many other + Se usan de forma exhaustiva en el código de F# para representar los casos en los que muchos otros + + + + languages would use null references. + lenguajes usarían referencias NULL. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + En primer lugar, defina un código postal con una unión discriminada de un solo caso. + + + + Next, define a type where the ZipCode is optional. + Después, defina un tipo donde ZipCode sea opcional. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Después, defina un tipo de interfaz que represente un objeto para calcular la zona de envío del código postal del cliente, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + especificando implementaciones para los métodos abstractos 'getState' y 'getShippingZone'. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Después, calcule una zona de envío para un cliente con una instancia de la calculadora. + + + + This uses combinators in the Option module to allow a functional pipeline for + Aquí se utilizan combinadores en el módulo Option para permitir que una canalización funcional + + + + transforming data with Optionals. + transforme datos con valores opcionales. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Las unidades de medida son una forma de anotar tipos numéricos primitivos con seguridad de tipos. + + + + You can then perform type-safe arithmetic on these values. + Después, puede realizar operaciones aritméticas con seguridad de tipos en estos valores. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Primero, abra una colección de nombres de unidad comunes + + + + Define a unitized constant + Defina una constante dividida en unidades + + + + Next, define a new unit type + Después, defina un nuevo tipo de unidad + + + + Conversion factor mile to meter. + Factor de conversión de millas a metros. + + + + Define a unitized constant + Defina una constante dividida en unidades + + + + Compute metric-system constant + Calcular constante del sistema métrico + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Los valores que usan unidades de medida se pueden usar simplemente como tipo numérico primitivo para cosas como la impresión. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Las clases son una forma de definir tipos de objeto nuevos en F# y admiten construcciones orientadas a objetos estándar. + + + + They can have a variety of members (methods, properties, events, etc.) + Pueden tener una gran variedad de miembros (métodos, propiedades, eventos, etc.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Para obtener más información sobre las clases, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Para obtener más información sobre miembros, vea https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Clase Vector bidimensional sencilla. + + + + The class's constructor is on the first line, + El constructor de la clase está en la primera línea + + + + and takes two arguments: dx and dy, both of type 'double'. + y toma dos argumentos: dx y dy, ambos de tipo "double". + + + + This internal field stores the length of the vector, computed when the + Este campo interno almacena la longitud del vector, que se calcula cuando + + + + object is constructed + se construye el objeto + + + + 'this' specifies a name for the object's self identifier. + 'this' especifica un nombre para el propio identificador del objeto. + + + + In instance methods, it must appear before the member name. + En los métodos de instancia, debe aparecer delante del nombre del miembro. + + + + This member is a method. The previous members were properties. + Este miembro es un método. Los miembros anteriores eran propiedades. + + + + This is how you instantiate the Vector2D class. + Así es cómo se crea una instancia de la clase Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Obtener un nuevo objeto de vector a escala sin modificar el objeto original. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Las clases genéricas permiten definir tipos con respecto a un conjunto de parámetros de tipo. + + + + In the following, 'T is the type parameter for the class. + En el siguiente código, 'T es el parámetro de tipo para la clase. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Este campo interno almacena los estados en una lista. + + + + Add a new element to the list of states. + Agregar un nuevo elemento a la lista de estados. + + + + use the '<-' operator to mutate the value. + Use el operador "<-" para mutar el valor. + + + + Get the entire list of historical states. + Obtener la lista completa de estados históricos. + + + + Get the latest state. + Obtener el último estado. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Una instancia 'int' de la clase del rastreador de estados. Observe que se ha inferido el parámetro de tipo. + + + + Add a state + Agregar un estado + + + + Interfaces are object types with only 'abstract' members. + Las interfaces son tipos de objeto que solo tienen miembros "abstract". + + + + Object types and object expressions can implement interfaces. + Los tipos de objeto y las expresiones de objeto pueden implementar interfaces. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Este es un tipo que implementa IDisposable. + + + + This is the implementation of IDisposable members. + Esta es la implementación de los miembros de IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Este es un objeto que implementa IDisposable mediante una expresión de objeto + + + + Unlike other languages such as C# or Java, a new type definition is not needed + A diferencia de otros lenguajes, como C# o Java, no es necesaria una nueva definición de tipo + + + + to implement an interface. + para implementar una interfaz. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + La biblioteca FSharp.Core define un intervalo de funciones de procesamiento paralelo. Aquí + + + + you use some functions for parallel processing over arrays. + se usan algunas funciones de procesamiento paralelo en matrices. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Para obtener más información, vea: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Primero, una matriz de entradas. + + + + Next, define a functions that does some CPU intensive computation. + Después, defina una función que realice algunos cálculos con gran consumo de CPU. + + + + Next, do a parallel map over a large input array. + Después, realice una asignación en paralelo en una matriz de entrada grande. + + + + Next, print the results. + Después, imprima los resultados. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Los eventos son algo habitual en la programación para .NET, especialmente con aplicaciones de WinForms o WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Para obtener más información, vea: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Primero, cree una instancia del objeto Event que conste de un punto de suscripción (event.Publish) y un desencadenador de eventos (event.Trigger). + + + + Next, add handler to the event. + Después, agregue un controlador al evento. + + + + Next, trigger the event. + Después, desencadene el evento. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Después, cree una instancia de Event que siga la convención estándar de .NET: (sender, EventArgs). + + + + Next, add a handler for this new event. + Después, agregue un controlador para este nuevo evento. + + + + Next, trigger this event (note that sender argument should be set). + Después, desencadene este evento (tenga en cuenta que el argumento sender debe estar establecido). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.fr.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.fr.xlf new file mode 100644 index 0000000000..ecef37c188 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.fr.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Cet exemple est destiné à vous montrer les différents éléments du langage F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Pour exécuter le code dans F# Interactive, mettez en surbrillance une portion du code, puis appuyez sur Alt+Entrée ou cliquez avec le bouton droit, + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + puis sélectionnez Exécuter en mode interactif. Pour ouvrir la fenêtre F# Interactive, accédez au menu Affichage. + + + + For more about F#, see: + Pour en savoir plus sur F#, consultez : + + + + To see this tutorial in documentation form, see: + Pour afficher ce didacticiel au format documentation, consultez : + + + + To learn more about applied F# programming, use + Pour en savoir plus sur la programmation F# appliquée, utilisez + + + + To install the Visual F# Power Tools, use + Pour installer Visual F# Power Tools, utilisez + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + 'Outils' --> 'Extensions et mises à jour' --> `En ligne` et rechercher + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Pour consulter d'autres modèles d'utilisation du langage F#, cliquez sur Modèles en ligne dans Visual Studio, + + + + 'New Project' --> 'Online Templates' + 'Nouveau projet' --> 'Modèles en ligne' + + + + F# supports three kinds of comments: + F# prend en charge trois genres de commentaires : + + + + 1. Double-slash comments. These are used in most situations. + 1. Commentaires avec double barre oblique (utilisés dans la plupart des cas). + + + + 2. ML-style Block comments. These aren't used that often. + 2. Commentaires de bloc de style ML (rarement utilisés). + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Commentaires avec triple barre oblique (utilisés pour documenter les fonctions, les types, etc.). + + + + They will appear as text when you hover over something which is decorated with these comments. + Ils apparaissent sous forme de texte quand vous pointez sur un élément décoré avec ces commentaires. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Ils prennent également en charge les commentaires XML de style .NET, ce qui vous permet de générer une documentation de référence. + + + + and they also allow editors (such as Visual Studio) to extract information from them. + Les éditeurs tels que Visual Studio peuvent également extraire des informations à partir de ces commentaires. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Ouvrir des espaces de noms à l'aide du mot clé 'open'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Un module est un regroupement d’éléments de code F#, comme des valeurs, des types et des valeurs de fonction. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Le regroupement du code dans les modules permet de conserver le code associé ensemble et d'éviter les conflits de noms dans votre programme. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Exemple d'entier. + + + + This is a sample floating point number. + Exemple de nombre à virgule flottante. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Nouveau nombre calculé par une opération arithmétique. Les types numériques sont convertis à l'aide des + + + + functions 'int', 'double' and so on. + fonctions 'int', 'double', etc. + + + + This is a list of the numbers from 0 to 99. + Liste des nombres de 0 à 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Liste de tous les tuples contenant tous les nombres de 0 à 99 et leur carré. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + La ligne suivante imprime une liste comprenant des tuples, en utilisant '%A' pour l'impression générique. + + + + This is a sample integer with a type annotation + Exemple d'entier avec une annotation de type. + + + + Values in F# are immutable by default. They cannot be changed + Les valeurs en F# sont immuables par défaut. Elles ne peuvent pas être changées + + + + in the course of a program's execution unless explicitly marked as mutable. + durant l'exécution d'un programme, sauf si elles sont explicitement marquées comme mutables. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Le fait de lier une valeur à un nom au moyen de 'let' la rend non modifiable. + + + + The second line of code fails to compile because 'number' is immutable and bound. + La compilation de la deuxième ligne de code échoue, car 'number' est non modifiable et lié. + + + + Re-defining 'number' to be a different value is not allowed in F#. + La redéfinition de 'number' en une valeur différente n'est pas autorisée dans F#. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Liaison mutable. Obligatoire pour muter la valeur de 'otherNumber'. + + + + When mutating a value, use '<-' to assign a new value. + En cas de mutation d'une valeur, utilisez '<-' pour assigner une nouvelle valeur. + + + + You could not use '=' here for this purpose since it is used for equality + Vous ne pouvez pas utiliser '=' ici à cet effet, car il est utilisé pour l'égalité + + + + or other contexts such as 'let' or 'module' + ou autres contextes tels que 'let' ou 'module' + + + + Much of F# programming consists of defining functions that transform input data to produce + La programmation F# consiste en grande partie à définir des fonctions qui transforment des données d'entrée pour produire des + + + + useful results. + résultats utiles. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Utilisez 'let' pour définir une fonction. Celle-ci accepte un argument entier et retourne un entier. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Les parenthèses sont facultatives pour les arguments de fonction, sauf quand vous utilisez une annotation de type explicite. + + + + Apply the function, naming the function return result using 'let'. + Appliquez la fonction, en nommant le résultat de retour de la fonction à l'aide de 'let'. + + + + The variable type is inferred from the function return type. + Le type de variable est déduit du type de retour de la fonction. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Cette ligne utilise '%d' pour imprimer le résultat comme entier. Cette opération est de type sécurisé. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Si 'result1' n'est pas de type 'int', la compilation de la ligne échoue. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Si nécessaire, annotez le type d'un nom de paramètre en utilisant '(argument:type)'. Les parenthèses sont obligatoires. + + + + Conditionals use if/then/elid/elif/else. + Les conditions utilisent if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Notez que F# utilise une syntaxe prenant en charge la mise en retrait à l'aide d'espaces, comme Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Cette ligne utilise '%f' pour imprimer le résultat comme float. Comme '%d' ci-dessus, cette opération est de type sécurisé. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Les booléens sont des types de données fondamentaux en F#. Voici quelques exemples illustrant des booléens et la logique conditionnelle. + + + + To learn more, see: + Pour en savoir plus, consultez : + + + + and + Et + + + + Booleans values are 'true' and 'false'. + Les valeurs booléennes sont 'true' et 'false'. + + + + Operators on booleans are 'not', '&&' and '||'. + Les opérateurs sur les booléens sont 'not', '&&' et '||'. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Cette ligne utilise '%b' pour imprimer une valeur booléenne. Cette opération est de type sécurisé. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Les chaînes sont des types de données fondamentaux en F#. Voici quelques exemples illustrant des chaînes et la manipulation de chaînes de base. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Les chaînes utilisent des guillemets doubles. + + + + Strings can also use @ to create a verbatim string literal. + Les chaînes peuvent également utiliser @ pour créer un littéral de chaîne textuelle. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Les caractères d'échappement tels que '\', '\n', '\t', etc. sont ainsi ignorés. + + + + String literals can also use triple-quotes. + Les littéraux de chaîne peuvent également utiliser des guillemets triples. + + + + String concatenation is normally done with the '+' operator. + L'opérateur '+' est généralement utilisé pour la concaténation de chaînes. + + + + This line uses '%s' to print a string value. This is type-safe. + Cette ligne utilise '%s' pour imprimer une valeur de chaîne. Cette opération est de type sécurisé. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Les sous-chaînes utilisent la notation de l'indexeur. Cette ligne extrait les 7 premiers caractères comme sous-chaîne. + + + + Note that like many languages, Strings are zero-indexed in F#. + Comme dans bien d'autres langages, les chaînes ont un index de base zéro en F#. + + + + Tuples are simple combinations of data values into a combined value. + Les tuples sont des combinaisons simples de valeurs de données formant une valeur combinée. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Tuple simple d'entiers. + + + + A function that swaps the order of two values in a tuple. + Fonction qui inverse l'ordre de deux valeurs d'un tuple. + + + + F# Type Inference will automatically generalize the function to have a generic type, + L'inférence de type F# généralise automatiquement la fonction pour qu'elle soit de type générique, + + + + meaning that it will work with any type. + ce qui signifie qu'elle peut fonctionner avec n'importe quel type. + + + + A tuple consisting of an integer, a string, + Tuple constitué d'un entier, d'une chaîne + + + + and a double-precision floating point number. + et d'un nombre à virgule flottante à double précision. + + + + A simple tuple of integers with a type annotation. + Tuple simple d'entiers avec une annotation de type. + + + + Type annotations for tuples use the * symbol to separate elements + Annotations de type pour les tuples qui utilisent le symbole * afin de séparer les éléments + + + + Tuples are normally objects, but they can also be represented as structs. + Les tuples sont généralement des objets, mais peuvent aussi être représentés sous forme de structs. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Ils interagissent entièrement avec les structs en C# et Visual Basic .NET ; cependant, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + les tuples de type struct ne sont pas implicitement convertibles avec des tuples d'objet (souvent appelés tuples de référence). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + La compilation de la deuxième ligne ci-dessous échoue à cause de cela. Supprimez les marques de commentaire pour voir ce qui se passe. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Bien que vous ne puissiez pas effectuer de conversion implicite entre les tuples de type struct et les tuples de type référence, + + + + you can explicitly convert via pattern matching, as demonstrated below. + vous pouvez effectuer une conversion explicite à l'aide de critères spéciaux, comme indiqué ci-dessous. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Les opérateurs de canal F# ('|>', '<|', etc.) et les opérateurs de composition F# ('>>', '<<') + + + + are used extensively when processing data. These operators are themselves functions + sont très utilisés de façon pour le traitement des données. Ces opérateurs sont eux-mêmes des fonctions + + + + which make use of Partial Application. + qui utilisent l'application partielle. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Pour en savoir plus sur ces opérateurs, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Pour en savoir plus sur l'application partielle, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Met une valeur au carré. + + + + Adds 1 to a value. + Ajoute 1 à une valeur. + + + + Tests if an integer value is odd via modulo. + Teste si une valeur entière est impaire à l'aide d'une opération modulo. + + + + A list of 5 numbers. More on lists later. + Liste de 5 nombres. Nous reviendrons sur les listes plus tard. + + + + Given a list of integers, it filters out the even numbers, + Pour une liste d'entiers donnée, élimine les nombres pairs par filtrage, + + + + squares the resulting odds, and adds 1 to the squared odds. + met au carré les nombres impairs résultants, puis ajoute 1 au carré des nombres impairs. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Pour écrire plus rapidement 'squareOddValuesAndAddOne', imbriquez chaque + + + + sub-result into the function calls themselves. + sous-résultat dans les appels de fonction. + + + + This makes the function much shorter, but it's difficult to see the + La fonction est ainsi considérablement raccourcie, mais il est difficile de voir + + + + order in which the data is processed. + l'ordre dans lequel les données sont traitées. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Pour écrire 'squareOddValuesAndAddOne', utilisez de préférence des opérateurs de canal F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + Aucun résultat intermédiaire n'est créé, mais la syntaxe est beaucoup plus lisible + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + que d'imbriquer des appels de fonction comme 'squareOddValuesAndAddOneNested' + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + Vous pouvez raccourcir 'squareOddValuesAndAddOnePipeline' en déplaçant le second appel 'List.map' + + + + into the first, using a Lambda Function. + dans le premier en utilisant une fonction lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Notez que les pipelines sont également utilisés dans la fonction lambda. Les opérateurs de canal F# + + + + can be used for single values as well. This makes them very powerful for processing data. + peuvent également être utilisés pour des valeurs uniques. Ils sont donc très efficaces dans le traitement des données. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + Enfin, vous pouvez éliminer la nécessité d'accepter explicitement 'values' comme paramètre en utilisant '>>' + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + pour composer les deux opérations principales : élimination des nombres pairs par filtrage, puis mise au carré et ajout d'une unité. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + De même, la partie 'fun x -> ...' de l'expression lambda n'est pas nécessaire, car 'x' est simplement + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + défini dans cette portée pour pouvoir être passé à un pipeline fonctionnel. Vous pouvez donc utiliser '>>' + + + + there as well. + ici aussi. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Le résultat de 'squareOddValuesAndAddOneComposition' est une autre fonction qui accepte une + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + liste d'entiers comme entrée. Si vous exécutez 'squareOddValuesAndAddOneComposition' avec une liste + + + + of integers, you'll notice that it produces the same results as previous functions. + d'entiers, les résultats sont identiques à ceux des fonctions précédentes. + + + + This is using what is known as function composition. This is possible because functions in F# + C'est ce qui s'appelle la composition de fonctions. Cela vient du fait que les fonctions dans F# + + + + use Partial Application and the input and output types of each data processing operation match + utilisent l'application partielle et que les types d'entrée et de sortie de chaque opération de traitement de données correspondent + + + + the signatures of the functions we're using. + aux signatures des fonctions que nous utilisons. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Les listes sont ordonnées, non modifiables et liées individuellement. Elles font l'objet d'une évaluation stricte. + + + + This module shows various ways to generate lists and process lists with some functions + Ce module montre différentes façons de générer et de traiter des listes à l'aide de fonctions + + + + in the 'List' module in the F# Core Library. + du module 'List' de la bibliothèque principale F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Les listes sont définies à l'aide de [ ... ]. Il s'agit d'une liste vide. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Il s'agit d'une liste avec 3 éléments. ';' permet de séparer des éléments sur la même ligne. + + + + You can also separate elements by placing them on their own lines. + Vous pouvez également séparer des éléments en les plaçant chacun sur une ligne. + + + + This is a list of integers from 1 to 1000 + Il s'agit de la liste des entiers de 1 à 1 000 + + + + Lists can also be generated by computations. This is a list containing + Les listes peuvent également être générées par calculs. Il s'agit d'une liste contenant + + + + all the days of the year. + tous les jours de l'année. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Imprimez les 5 premiers éléments de 'daysList' en utilisant 'List.take'. + + + + Computations can include conditionals. This is a list containing the tuples + Les calculs peuvent inclure des conditions. Il s'agit d'une liste contenant les tuples + + + + which are the coordinates of the black squares on a chess board. + qui sont les coordonnées des cases noires d'un échiquier. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Les listes peuvent être transformées à l'aide de 'List.map' et d'autres combinateurs de programmation fonctionnelle. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Cette définition produit une nouvelle liste en mettant au carré les nombres de numberList à l'aide de + + + + operator to pass an argument to List.map. + l'opérateur du pipeline pour passer un argument à List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Il existe de nombreuses autres combinaisons de listes. La combinaison suivante calcule la somme des carrés des + + + + numbers divisible by 3. + nombres divisibles par 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Les tableaux sont des collections de taille fixe et mutables d'éléments du même type. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Bien qu'ils soient semblables aux listes (prise en charge de l'énumération et combinateurs similaires pour le traitement des données), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + ils offrent généralement une vitesse accrue et prennent en charge l'accès aléatoire rapide. Ils sont toutefois moins sécurisés du fait de leur mutabilité. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Tableau vide. Notez que la syntaxe est semblable à celle des listes, mais '[| ... |]' est utilisé à la place. + + + + Arrays are specified using the same range of constructs as lists. + Les tableaux sont spécifiés à l'aide de la même plage de constructions que les listes. + + + + This is an array of numbers from 1 to 1000. + Il s'agit d'un tableau de nombres de 1 à 1 000. + + + + This is an array containing only the words "hello" and "world". + Il s'agit d'un tableau contenant uniquement les mots "hello" et "world". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Il s'agit d'un tableau lancé par index, qui contient les nombres pairs de 0 à 2 000. + + + + Sub-arrays are extracted using slicing notation. + Les sous-tableaux sont extraits à l'aide de la notation de découpage. + + + + You can loop over arrays and lists using 'for' loops. + Vous pouvez effectuer une boucle sur des tableaux et des listes à l'aide de boucles 'for'. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Vous pouvez modifier le contenu d'un élément de tableau à l'aide de l'opérateur d'assignation flèche gauche. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Pour en savoir plus sur cet opérateur, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Vous pouvez transformer des tableaux à l'aide de 'Array.map' et d'autres opérations de programmation fonctionnelle. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + L'opération suivante calcule la somme des longueurs des mots qui commencent par 'h'. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Les séquences sont des séries logiques d'éléments du même type. Elles sont plus générales que les listes et les tableaux. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Les séquences sont évaluées sur demande et sont réévaluées à chacune de leur itération. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Une séquence F# est un alias pour un System.Collections.Generic.IEnumerable .NET<'T>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Les fonctions de traitement de séquence peuvent être appliquées aux listes et aux tableaux également. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Il s'agit de la séquence vide. + + + + This a sequence of values. + Il s'agit d'une séquence de valeurs. + + + + This is an on-demand sequence from 1 to 1000. + Séquence à la demande de 1 à 1000. + + + + This is a sequence producing the words "hello" and "world" + Il s'agit d'une séquence produisant les mots "hello" et "world" + + + + This sequence producing the even numbers up to 2000. + Cette séquence produit les nombres pairs jusqu'à 2 000. + + + + This is an infinite sequence which is a random walk. + Il s'agit d'une séquence infinie correspondant à une marche aléatoire. + + + + This example uses yield! to return each element of a subsequence. + Cet exemple utilise yield! pour retourner chaque élément d'une sous-séquence. + + + + This example shows the first 100 elements of the random walk. + Cet exemple montre les 100 premiers éléments de la marche aléatoire. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Les fonctions récursives peuvent s'appeler elles-mêmes. En F#, les fonctions sont uniquement récursives + + + + when declared using 'let rec'. + en cas de déclaration avec 'let rec'. + + + + Recursion is the preferred way to process sequences or collections in F#. + Il est recommandé d'utiliser la récursivité pour traiter des séquences ou des collections en F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Cet exemple montre une fonction récursive qui calcule la factorielle d'un + + + + integer. It uses 'let rec' to define a recursive function. + entier. Il utilise 'let rec' pour définir une fonction récursive. + + + + Computes the greatest common factor of two integers. + Calcule le plus grand commun diviseur de deux entiers. + + + + Since all of the recursive calls are tail calls, + Comme tous les appels récursifs sont des appels terminaux, + + + + the compiler will turn the function into a loop, + le compilateur transforme la fonction en boucle, + + + + which improves performance and reduces memory consumption. + ce qui améliore le niveau de performance et réduit la consommation de mémoire. + + + + This example computes the sum of a list of integers using recursion. + Cet exemple calcule la somme d'une liste d'entiers à l'aide de la récursivité. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + 'sumList' est converti en fonction à récursivité terminale, en utilisant une fonction d'assistance avec accumulateur de résultats. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + La fonction d'assistance de récursivité terminale est appelée et fournit '0' comme accumulateur de valeurs initiales. + + + + An approach like this is common in F#. + Une telle approche est courante en F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Les enregistrements sont des agrégats de valeurs nommées, avec des membres facultatifs (comme des méthodes). + + + + They are immutable and have structural equality semantics. + Ils ne sont pas modifiables et ont une sémantique d'égalité structurelle. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Cet exemple montre comment définir un nouveau type d'enregistrement. + + + + This example shows how to instantiate a record type. + Cet exemple montre comment instancier un type d'enregistrement. + + + + You can also do this on the same line with ';' separators. + Vous pouvez également effectuer cette opération sur la même ligne avec des séparateurs ';'. + + + + This example shows how to use "copy-and-update" on record values. It creates + Cet exemple montre comment utiliser "copy-and-update" sur des valeurs d'enregistrement. Il crée + + + + a new record value that is a copy of contact1, but has different values for + une nouvelle valeur d'enregistrement qui est une copie de contact1, mais qui a différentes valeurs pour + + + + the 'Phone' and 'Verified' fields. + les champs 'Phone' et 'Verified'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Cet exemple montre comment écrire une fonction qui traite une valeur d'enregistrement. + + + + It converts a 'ContactCard' object to a string. + Il convertit un objet 'ContactCard' en chaîne. + + + + This is an example of a Record with a member. + Il s'agit d'un exemple d'enregistrement avec un membre. + + + + Members can implement object-oriented members. + Les membres peuvent implémenter des membres orientés objet. + + + + Members are accessed via the '.' operator on an instantiated type. + Les membres sont accessibles au moyen de l'opérateur '.' sur un type instancié. + + + + Records can also be represented as structs via the 'Struct' attribute. + Les enregistrements peuvent également être représentés sous forme de structs par le biais de l'attribut 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Cela peut s'avérer utile dans les situations où le niveau de performance des structs l'emporte + + + + the flexibility of reference types. + sur la flexibilité des types de référence. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Les unions discriminées sont des valeurs qui peuvent correspondre à un certain nombre de formulaires ou de cas nommés. + + + + Data stored in DUs can be one of several distinct values. + Les données stockées dans les unions discriminées peuvent prendre une valeur parmi plusieurs valeurs distinctes. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + Ce qui suit représente la couleur d'une carte à jouer. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Une union discriminée peut également servir à représenter le rang d'une carte à jouer. + + + + Represents the rank of cards 2 .. 10 + Représente le rang des cartes 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + Les unions discriminées peuvent également implémenter des membres orientés objet. + + + + This is a record type that combines a Suit and a Rank. + Il s'agit d'un type d'enregistrement qui combine une couleur et un rang. + + + + It's common to use both Records and Disciminated Unions when representing data. + Il est fréquent d'utiliser à la fois des enregistrements et des unions discriminées pour représenter des données. + + + + This computes a list representing all the cards in the deck. + Ceci calcule une liste représentant toutes les cartes du paquet. + + + + This example converts a 'Card' object to a string. + Cet exemple convertit un objet 'Card' en chaîne. + + + + This example prints all the cards in a playing deck. + Cet exemple imprime toutes les cartes d'un jeu de cartes. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Les unions discriminées à cas unique sont souvent utilisées pour la modélisation de domaines. Il peut en résulter une meilleure cohérence des types + + + + over primitive types such as strings and ints. + sur des types primitifs tels que les chaînes et les entiers. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Les unions discriminées à cas unique ne peuvent pas être converties implicitement vers ou à partir du type qu'elles incluent dans un wrapper. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Par exemple, une fonction qui accepte une adresse ne peut pas accepter une chaîne comme entrée + + + + or vive/versa. + ou vice versa. + + + + You can easily instantiate a single-case DU as follows. + Vous pouvez facilement instancier une union discriminée à cas unique comme suit. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Quand vous avez besoin de la valeur, vous pouvez exclure la valeur sous-jacente du wrapper à l'aide d'une fonction simple. + + + + Printing single-case DUs is simple with unwrapping functions. + Les fonctions d'exclusion d'un wrapper facilitent l'impression d'unions discriminées à cas unique. + + + + Disciminated Unions also support recursive definitions. + Les unions discriminées prennent également en charge les définitions récursives. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Ceci représente un arbre de recherche binaire, l'un des cas étant l'arbre vide + + + + and the other being a Node with a value and two subtrees. + et l'autre étant un nœud avec une valeur et deux sous-arbres. + + + + Check if an item exists in the binary search tree. + Vérifiez si un élément existe dans l'arbre de recherche binaire. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Effectue une recherche récursive à l'aide de critères spéciaux. Retourne true si l'élément existe ; sinon, false. + + + + Check the left subtree. + Vérifiez le sous-arbre gauche. + + + + Check the right subtree. + Vérifiez le sous-arbre droit. + + + + Inserts an item in the Binary Search Tree. + Insère un élément dans l'arbre de recherche binaire. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Recherche l'emplacement de l'insertion récursive à l'aide de critères spéciaux, puis insère un nouveau nœud. + + + + If the item is already present, it does not insert anything. + Si l'élément est déjà présent, rien n'est inséré. + + + + No need to insert, it already exists; return the node. + Insertion inutile, car l'élément existe déjà ; retournez le nœud. + + + + Call into left subtree. + Appelez le sous-arbre gauche. + + + + Call into right subtree. + Appelez le sous-arbre droit. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Les unions discriminées peuvent également être représentées sous forme de structs au moyen de l'attribut 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Cela peut s'avérer utile dans les situations où le niveau de performance des structs l'emporte + + + + the flexibility of reference types. + sur la flexibilité des types de référence. + + + + However, there are two important things to know when doing this: + Cependant, retenez les deux points suivants si vous procédez de la sorte : + + + + 1. A struct DU cannot be recursively-defined. + 1. Une union discriminée struct ne peut pas être définie de manière récursive. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Une union discriminée struct doit avoir des noms uniques pour chacun de ses cas. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Les critères spéciaux sont une fonctionnalité de F# qui vous permet d'utiliser des modèles + + + + which are a way to compare data with a logical structure or structures, + pour comparer des données avec une ou plusieurs structures logiques, + + + + decompose data into constituent parts, or extract information from data in various ways. + décomposer des données en parties constitutives ou extraire des informations à partir de données de plusieurs façons. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Vous pouvez ensuite effectuer une répartition selon la "forme" d'un modèle à l'aide de critères spéciaux. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Enregistrement contenant le nom et le prénom d'une personne + + + + A Discriminated Union of 3 different kinds of employees + Union discriminée de 3 genres d'employés différents + + + + Count everyone underneath the employee in the management hierarchy, + Comptez tout le monde sous l'employé dans la hiérarchie de gestion + + + + including the employee. + (employé inclus). + + + + Find all managers/executives named "Dave" who do not have any reports. + Recherchez tous les responsables ou cadres dont le prénom est "Dave" et qui ne disposent d'aucun rapport. + + + + This uses the 'function' shorthand to as a lambda expression. + Le raccourci 'function' est utilisé comme expression lambda. + + + + [] matches an empty list. + [] correspond à une liste vide. + + + + '_' is a wildcard pattern that matches anything. + '_' est un modèle générique qui correspond à n'importe quel élément. + + + + This handles the "or else" case. + Ceci permet de gérer le cas "or else". + + + + You can also use the shorthand function construct for pattern matching, + Vous pouvez également utiliser la construction de fonction raccourcie pour les critères spéciaux, + + + + which is useful when you're writing functions which make use of Partial Application. + ce qui peut s'avérer utile quand vous écrivez des fonctions qui utilisent l'application partielle. + + + + Define some more functions which parse with the helper function. + Définissez d'autres fonctions d'analyse avec la fonction d'assistance. + + + + Active Patterns are another powerful construct to use with pattern matching. + Les modèles actifs sont une autre construction efficace à utiliser avec les critères spéciaux. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Ils permettent de partitionner des données d'entrée dans des formulaires personnalisés, en les décomposant au niveau du site d'appel de correspondance au modèle. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Les critères spéciaux avec le mot clé 'function' et les modèles actifs ressemblent souvent à ceci. + + + + Call the printer with some different values to parse. + Appelez l'imprimante avec des valeurs différentes à analyser. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Les valeurs d'option sont tout type de valeur marquée avec 'Some' ou 'None'. + + + + They are used extensively in F# code to represent the cases where many other + Elles sont très utilisées dans le code F# pour représenter les cas où de nombreux autres + + + + languages would use null references. + langages utilisent des références null. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Commencez par définir un code postal au moyen d'une union discriminée à cas unique. + + + + Next, define a type where the ZipCode is optional. + Définissez ensuite un type où ZipCode est facultatif. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Ensuite, définissez un type d'interface qui représente un objet pour calculer la zone d'expédition correspondant au code postal du client, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + en fonction des implémentations des méthodes abstraites 'getState' et 'getShippingZone'. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Ensuite, calculez une zone d'expédition pour un client à l'aide d'une instance de calculatrice. + + + + This uses combinators in the Option module to allow a functional pipeline for + Des combinateurs du module Option sont utilisés pour permettre à un pipeline fonctionnel de + + + + transforming data with Optionals. + transformer les données avec Optionals. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Les unités de mesure sont un moyen d'annoter les types numériques primitifs de manière sécurisée pour les types. + + + + You can then perform type-safe arithmetic on these values. + Vous pouvez ensuite effectuer des opérations arithmétiques de type sécurisé sur ces valeurs. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Pour commencer, ouvrez une collection de noms d'unité courants + + + + Define a unitized constant + Définissez une constante unifiée + + + + Next, define a new unit type + Ensuite, définissez un nouveau type d'unité + + + + Conversion factor mile to meter. + Facteur de conversion mile en mètre. + + + + Define a unitized constant + Définissez une constante unifiée + + + + Compute metric-system constant + Calculez la constante de système métrique + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Les valeurs avec des unités de mesure s'utilisent de la même façon que le type numérique primitif dans des opérations comme l'impression. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Les classes sont un moyen de définir de nouveaux types d'objet en F#. Elles prennent en charge les constructions orientées objet standard. + + + + They can have a variety of members (methods, properties, events, etc.) + Elles peuvent avoir différents membres (méthodes, propriétés, événements, etc.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Pour en savoir plus sur les classes, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Pour en savoir plus sur les membres, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Classe Vector à deux dimensions simple. + + + + The class's constructor is on the first line, + Le constructeur de la classe est sur la première ligne + + + + and takes two arguments: dx and dy, both of type 'double'. + et accepte deux arguments : dx et dy (tous deux de type 'double'). + + + + This internal field stores the length of the vector, computed when the + Ce champ interne stocke la longueur du vecteur, calculée quand + + + + object is constructed + l'objet est construit + + + + 'this' specifies a name for the object's self identifier. + 'this' spécifie un nom pour l'auto-identificateur de l'objet. + + + + In instance methods, it must appear before the member name. + Dans les méthodes d'instance, il doit apparaître avant le nom du membre. + + + + This member is a method. The previous members were properties. + Ce membre est une méthode. Les membres précédents étaient des propriétés. + + + + This is how you instantiate the Vector2D class. + Voici comment instancier la classe Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Obtenez un nouvel objet vector mis à l'échelle, sans modifier l'objet d'origine. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Les classes génériques autorisent la définition des types par rapport à un jeu de paramètres de type. + + + + In the following, 'T is the type parameter for the class. + Dans ce qui suit, 'T est le paramètre de type pour la classe. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Ce champ interne stocke les états dans une liste. + + + + Add a new element to the list of states. + Ajoutez un nouvel élément à la liste d'états. + + + + use the '<-' operator to mutate the value. + utilisez l'opérateur '<-' pour muter la valeur. + + + + Get the entire list of historical states. + Obtenez la liste complète des états historiques. + + + + Get the latest state. + Obtenez le dernier état. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Instance 'int' de la classe de suivi des états. Notez que le paramètre de type est déduit. + + + + Add a state + Ajouter un état + + + + Interfaces are object types with only 'abstract' members. + Les interfaces sont des types d'objet avec des membres 'abstract' uniquement. + + + + Object types and object expressions can implement interfaces. + Les types et expressions d'objet peuvent implémenter des interfaces. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Type qui implémente IDisposable. + + + + This is the implementation of IDisposable members. + Implémentation de membres IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Objet qui implémente IDisposable à l'aide d'une expression d'objet + + + + Unlike other languages such as C# or Java, a new type definition is not needed + Contrairement à d'autres langages tels que C# ou Java, une nouvelle définition de type n'est pas nécessaire + + + + to implement an interface. + pour implémenter une interface. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + La bibliothèque FSharp.Core définit une plage de fonctions de traitement parallèle. Ici + + + + you use some functions for parallel processing over arrays. + vous utilisez des fonctions pour le traitement parallèle des tableaux. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Pour en savoir plus, consultez : https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Tout d'abord, un tableau d'entrées. + + + + Next, define a functions that does some CPU intensive computation. + Ensuite, définissez une fonction qui effectue un calcul nécessitant une utilisation intensive du processeur. + + + + Next, do a parallel map over a large input array. + Ensuite, effectuez un mappage parallèle sur un grand tableau d'entrée. + + + + Next, print the results. + Ensuite, imprimez les résultats. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Les événements sont un idiome courant de la programmation .NET, en particulier avec les applications WinForms ou WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Pour en savoir plus, consultez : https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Pour commencer, créez une instance d'objet Event qui se compose d'un point d'abonnement (event.Publish) et d'un déclencheur d'événements (event.Trigger). + + + + Next, add handler to the event. + Ensuite, ajoutez un gestionnaire à l'événement. + + + + Next, trigger the event. + Ensuite, déclenchez l'événement. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Ensuite, créez une instance d'événement qui respecte la convention .NET standard : (sender, EventArgs). + + + + Next, add a handler for this new event. + Ensuite, ajoutez un gestionnaire à ce nouvel événement. + + + + Next, trigger this event (note that sender argument should be set). + Ensuite, déclenchez cet événement (notez que l'argument sender doit être défini). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.it.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.it.xlf new file mode 100644 index 0000000000..ecd508e58b --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.it.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Questo esempio consente all'utente di familiarizzare con gli elementi del linguaggio F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Per eseguire il codice in F# Interactive, evidenziare una sezione di codice e premere ALT-INVIO oppure fare clic con il pulsante destro del mouse + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + e selezionare "Esegui in Interactive". È possibile aprire la finestra di F# Interactive dal menu "Visualizza". + + + + For more about F#, see: + Per altre informazioni su F#, vedere: + + + + To see this tutorial in documentation form, see: + Per visualizzare questa esercitazione sotto forma di documentazione, vedere: + + + + To learn more about applied F# programming, use + Per altre informazioni sulla programmazione F# applicata, usare + + + + To install the Visual F# Power Tools, use + Per installare Visual F# Power Tools, usare + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + 'Strumenti' --> 'Estensioni e aggiornamenti' --> `Online` e cercare + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Per altri modelli da usare con F#, vedere 'Modelli online' in Visual Studio, + + + + 'New Project' --> 'Online Templates' + 'Nuovo progetto' --> 'Modelli online' + + + + F# supports three kinds of comments: + In F# sono supportati tre tipi di commenti: + + + + 1. Double-slash comments. These are used in most situations. + 1. Commenti introdotti da una doppia barra. Vengono usati nella maggior parte delle situazioni. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Commenti per il blocco in stile ML. Non vengono usati molto spesso. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Commenti introdotti da una tripla barra. Vengono usati per la documentazione di funzioni, tipi e così via. + + + + They will appear as text when you hover over something which is decorated with these comments. + Verranno visualizzati come testo quando si passa con il puntatore su un elemento decorato con questi commenti. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Supportano anche commenti XML in stile .NET, che consentono di generare documentazione di riferimento. + + + + and they also allow editors (such as Visual Studio) to extract information from them. + Consentono anche agli editor, come Visual Studio, di estrarre informazioni. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Aprire gli spazi dei nomi con la parola chiave 'open'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Un modulo è un raggruppamento di codice F#, ad esempio valori, tipi e valori di funzione. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Il raggruppamento del codice nei moduli consente di riunire il codice correlato e contribuisce a evitare conflitti di nome nel programma. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Questo è un valore integer di esempio. + + + + This is a sample floating point number. + Questo è un numero a virgola mobile di esempio. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Questo ha calcolato un nuovo numero in base a una certa aritmetica. I tipi numerici vengono convertiti con + + + + functions 'int', 'double' and so on. + funzioni 'int', 'double' e così via. + + + + This is a list of the numbers from 0 to 99. + Questo è un elenco di numeri compresi tra 0 e 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Questo è un elenco di tutte le tuple che contengono tutti i numeri compresi tra 0 e 99 e i relativi quadrati. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + La riga successiva stampa un elenco che include le tuple, usando '%A' per la stampa generica. + + + + This is a sample integer with a type annotation + Questo è un intero di esempio con un'annotazione di tipo + + + + Values in F# are immutable by default. They cannot be changed + Per impostazione predefinita, i valori in F# non sono modificabili e non è possibile cambiarli + + + + in the course of a program's execution unless explicitly marked as mutable. + durante l'esecuzione di un programma a meno che non siano contrassegnati esplicitamente come modificabili. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Il binding di un valore in un nome tramite 'let' lo rende non modificabile. + + + + The second line of code fails to compile because 'number' is immutable and bound. + La seconda riga di codice non viene compilata perché 'number' non è modificabile e ne è stato eseguito il binding. + + + + Re-defining 'number' to be a different value is not allowed in F#. + La ridefinizione di 'number' in un valore diverso non è consentita in F#. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Binding modificabile. È necessario per poter modificare il valore di 'otherNumber'. + + + + When mutating a value, use '<-' to assign a new value. + Durante la modifica di un valore, usare '<-' per assegnare un nuovo valore. + + + + You could not use '=' here for this purpose since it is used for equality + Non è possibile usare '=' in questo punto per questa finalità perché viene usato per l'uguaglianza + + + + or other contexts such as 'let' or 'module' + o altri contesti come 'let' o 'module' + + + + Much of F# programming consists of defining functions that transform input data to produce + Buona parte della programmazione F# consiste nella definizione di funzioni che trasformano i dati di input per produrre + + + + useful results. + risultati utili. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Usare 'let' per definire una funzione. Questa accetta un argomento Integer e restituisce un intero. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Le parentesi sono facoltative per gli argomenti di funzione, ad eccezione dei casi in cui si usa un'annotazione di tipo esplicita. + + + + Apply the function, naming the function return result using 'let'. + Applicare la funzione, denominando il risultato restituito della funzione tramite 'let'. + + + + The variable type is inferred from the function return type. + Il tipo variabile viene dedotto dal tipo restituito della funzione. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Questa riga usa '%d' per stampare il risultato in formato Integer. È indipendente dai tipi. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Se il tipo di 'result1' non fosse 'int', la riga non verrebbe compilata. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Quando necessario, annotare il tipo di un nome di parametro usando '(argument:type)'. Le parentesi sono obbligatorie. + + + + Conditionals use if/then/elid/elif/else. + Nelle istruzioni condizionali si usano if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Si noti che F# usa la sintassi con riconoscimento degli spazi vuoti di rientro, in modo analogo a linguaggi come Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Questa riga usa '%f' per stampare il risultato in formato float. Come con '%d' in precedenza, è indipendente dai tipi. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + I valori booleani sono tipi di dati fondamentali in F#. Ecco alcuni esempi di valori booleani e logica condizionale. + + + + To learn more, see: + Per altre informazioni, vedere: + + + + and + e + + + + Booleans values are 'true' and 'false'. + I valori booleani sono 'true' e 'false'. + + + + Operators on booleans are 'not', '&&' and '||'. + Gli operatori su valori booleani sono 'not', '&&' e '||'. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Questa riga usa '%b' per stampare un valore booleano. È indipendente dai tipi. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Le stringhe sono tipi di dati fondamentali in F#. Ecco alcuni esempi di stringhe e di manipolazione di base delle stringhe. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Per le stringhe si usano le virgolette doppie. + + + + Strings can also use @ to create a verbatim string literal. + Nelle stringhe si può anche usare @ per creare un valore letterale di stringa verbatim. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + In questo modo i caratteri di escape, come '\', '\n', '\t' e così via, verranno ignorati. + + + + String literals can also use triple-quotes. + Nei valori letterali si possono usare anche virgolette triple. + + + + String concatenation is normally done with the '+' operator. + Per la concatenazione di stringhe viene in genere usato l'operatore '+'. + + + + This line uses '%s' to print a string value. This is type-safe. + Questa riga usa '%s' per stampare un valore stringa. È indipendente dai tipi. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Nelle sottostringhe si usa la notazione dell'indicizzatore. Questa riga estrae i primi sette caratteri come sottostringa. + + + + Note that like many languages, Strings are zero-indexed in F#. + Si noti che, analogamente a molti linguaggi, le stringhe presentano indice zero in F#. + + + + Tuples are simple combinations of data values into a combined value. + Le tuple sono semplici combinazioni di valori dati in un valore combinato. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Tupla di interi semplice. + + + + A function that swaps the order of two values in a tuple. + Funzione che scambia l'ordine di due valori in una tupla. + + + + F# Type Inference will automatically generalize the function to have a generic type, + L'inferenza del tipo di F# consentirà di generalizzare automaticamente la funzione in modo che il relativo tipo sia generico, + + + + meaning that it will work with any type. + per indicare che funzionerà con qualsiasi tipo. + + + + A tuple consisting of an integer, a string, + Tupla costituita da un intero, una stringa + + + + and a double-precision floating point number. + e un numero a virgola mobile a precisione doppia. + + + + A simple tuple of integers with a type annotation. + Tupla di interi semplice con annotazione di tipo. + + + + Type annotations for tuples use the * symbol to separate elements + Nelle annotazioni di tipo per le tuple si usa il simbolo * per separare gli elementi + + + + Tuples are normally objects, but they can also be represented as structs. + Le tuple sono in genere oggetti, ma possono essere rappresentate anche come struct. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Questi interagiscono completamente con gli struct in C# e Visual Basic.NET; tuttavia, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + le tuple di struct non sono convertibili in modo implicito con tuple di oggetto (spesso chiamate tuple di riferimento). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + A causa di questo problema la seconda riga sotto non verrà compilata. Rimuovere il commento per vedere cosa succede. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Anche se non è possibile eseguire la conversione in modo implicito tra tuple della struttura e tuple di riferimento, + + + + you can explicitly convert via pattern matching, as demonstrated below. + è possibile eseguire la conversione in modo esplicito tramite i criteri di ricerca, come illustrato di seguito. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Gli operatori pipe di F# ('|>', '<|' e così via) e gli operatori di composizione di F# ('>>', '<<') + + + + are used extensively when processing data. These operators are themselves functions + sono particolarmente usati durante l'elaborazione dati. Questi operatori sono di per sé funzioni + + + + which make use of Partial Application. + che usano l'applicazione parziale. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Per altre informazioni su questi operatori, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Per altre informazioni sull'applicazione parziale, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Calcola il quadrato di un valore. + + + + Adds 1 to a value. + Aggiunge 1 a un valore. + + + + Tests if an integer value is odd via modulo. + Testa se un valore intero è dispari tramite modulo. + + + + A list of 5 numbers. More on lists later. + Elenco di cinque numeri. Per altre informazioni sugli elenchi, vedere più avanti. + + + + Given a list of integers, it filters out the even numbers, + Dato un elenco di interi, filtra i numeri pari, + + + + squares the resulting odds, and adds 1 to the squared odds. + calcola i quadrati dei numeri dispari risultati e aggiunge 1 ai numeri dispari quadrati. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Uno dei modi più brevi per scrivere 'squareOddValuesAndAddOne' consiste nell'annidare ogni + + + + sub-result into the function calls themselves. + risultato secondario nelle chiamate di funzione stesse. + + + + This makes the function much shorter, but it's difficult to see the + In questo modo la funzione è molto più breve, ma risulta più difficile visualizzare + + + + order in which the data is processed. + l'ordine in cui vengono elaborati i dati. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Uno dei modi preferiti per scrivere 'squareOddValuesAndAddOne' consiste nell'usare gli operatori pipe di F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + In tal modo sarà possibile evitare risultati intermedi, ma si migliora la leggibilità + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + rispetto all'annidamento di chiamate di funzione come 'squareOddValuesAndAddOneNested' + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + È possibile abbreviare 'squareOddValuesAndAddOnePipeline' spostando la seconda chiamata a `List.map` + + + + into the first, using a Lambda Function. + nella prima usando una funzione lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Si noti che le pipeline vengono usate anche all'interno della funzione lambda. Gli operatori pipe di F# + + + + can be used for single values as well. This makes them very powerful for processing data. + possono essere usati anche per singoli valori, di conseguenza sono particolarmente efficaci per l'elaborazione dei dati. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + È infine possibile evitare di accettare in modo esplicito 'values' come parametro usando '>>' + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + per comporre le due operazioni di base, ovvero filtrare i numeri pari, calcolare il quadrato e aggiungere 1. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Analogamente, anche la parte 'fun x -> ...' dell'espressione lambda non è necessaria perché 'x' viene semplicemente + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + definito in tale ambito in modo che sia possibile passarlo a una pipeline funzionale. In questo punto è quindi possibile + + + + there as well. + usare anche '>>'. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Il risultato di 'squareOddValuesAndAddOneComposition' è di per sé un'altra funzione che accetta come input un + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + elenco di interi. Se si esegue 'squareOddValuesAndAddOneComposition' con un elenco + + + + of integers, you'll notice that it produces the same results as previous functions. + di interi, si noterà che consente di ottenere gli stessi risultati delle funzioni precedenti. + + + + This is using what is known as function composition. This is possible because functions in F# + Usa la cosiddetta composizione di funzione. Tale operazione è possibile perché in F# le funzioni + + + + use Partial Application and the input and output types of each data processing operation match + usano l'applicazione parziale e i tipi di input e output di ogni operazione di elaborazione dati corrispondono + + + + the signatures of the functions we're using. + alle firme delle funzioni usate. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Gli elenchi sono elenchi a un solo collegamento ordinati e non modificabili la cui valutazione è di tipo eager. + + + + This module shows various ways to generate lists and process lists with some functions + Questo modulo mostra diversi modi per generare elenchi ed elenchi i processi con alcune funzioni + + + + in the 'List' module in the F# Core Library. + nel modulo 'List' della libreria di base di F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Per definire gli elenchi si usa [ ... ]. Questo è un elenco vuoto. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Questo è un elenco con tre elementi. Per delimitare gli elementi sulla stessa riga, viene usato il punto e virgola (';'). + + + + You can also separate elements by placing them on their own lines. + È anche possibile delimitare gli elementi posizionandoli su righe distinte. + + + + This is a list of integers from 1 to 1000 + Questo è un elenco di numeri interi tra 1 e 1000 + + + + Lists can also be generated by computations. This is a list containing + Gli elenchi possono anche essere generati da calcoli. Questo è un elenco contenente + + + + all the days of the year. + tutti i giorni dell'anno. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Stampa i primi cinque elementi di 'daysList' usando 'List.take'. + + + + Computations can include conditionals. This is a list containing the tuples + I calcoli possono contenere istruzioni condizionali. Questo è un elenco contenente le tuple + + + + which are the coordinates of the black squares on a chess board. + che rappresentano le coordinate dei quadrati neri su una scacchiera. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Per trasformare gli elenchi, è possibile usare 'List.map' e altri combinatori di programmazione funzionale. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Questa definizione consente di produrre un nuovo elenco mediante la quadratura dei numeri in numberList, usando l'operatore pipeline + + + + operator to pass an argument to List.map. + per passare un argomento a List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Esistono molte altre combinazioni di elenco. L'istruzione seguente calcola la somma dei quadrati dei + + + + numbers divisible by 3. + numeri divisibili per 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Le matrici sono raccolte modificabili di dimensioni fisse di elementi dello stesso tipo. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Anche se sono simili agli elenchi (supportano l'enumerazione e contengono combinatori simili per l'elaborazione dati), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + sono in genere più veloci e supportano l'accesso casuale rapido. La maggiore velocità implica però una minore sicurezza perché questi elementi sono modificabili. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Questa è la matrice vuota. Si noti che la sintassi è simile a quella degli elenchi, ma viene usato `[| ... |]`. + + + + Arrays are specified using the same range of constructs as lists. + Per specificare le matrici viene usato lo stesso intervallo di costrutti degli elenchi. + + + + This is an array of numbers from 1 to 1000. + Questo è una matrice di numeri compresi tra 1 e 1000. + + + + This is an array containing only the words "hello" and "world". + Questa è una matrice contenente solo le parole "hello" e "world". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Questa è una matrice inizializzata dall'indice e contenente i numeri pari compresi tra 0 e 2000. + + + + Sub-arrays are extracted using slicing notation. + Le sottomatrici vengono estratte mediante una notazione di sezionamento. + + + + You can loop over arrays and lists using 'for' loops. + Per eseguire il ciclo su matrici ed elenchi, si possono usare i cicli 'for'. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + È possibile modificare il contenuto di un elemento di matrice usando l'operatore di assegnazione freccia sinistra. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Per altre informazioni su questo operatore, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Per trasformare le matrici, è possibile usare 'Array.map' e altre operazioni di programmazione funzionale. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Il codice seguente consente di calcolare la somma delle lunghezze delle parole che iniziano con 'h'. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Le sequenze sono costituite da una serie logica di elementi, tutti dello stesso tipo. Sono di un tipo più generale rispetto ad elenchi e matrici. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Le sequenze vengono valutate su richiesta e rivalutate ogni volta che vengono iterate. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Una sequenza F# è un alias dell'elemento System.Collections.Generic.IEnumerable<'T> di .NET. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Le funzioni di elaborazione della sequenza possono essere applicate anche a elenchi e matrici. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Questa è la sequenza vuota. + + + + This a sequence of values. + Questa è una sequenza di valori. + + + + This is an on-demand sequence from 1 to 1000. + Questa è una sequenza su richiesta compresa tra 1 e 1000. + + + + This is a sequence producing the words "hello" and "world" + Questa è una sequenza che produce le parole "hello" e "world" + + + + This sequence producing the even numbers up to 2000. + Questa è la sequenza che produce i numeri pari fino a 2000. + + + + This is an infinite sequence which is a random walk. + Questa è una sequenza infinita, ovvero un percorso casuale. + + + + This example uses yield! to return each element of a subsequence. + In questo esempio si usa yield! per restituire ogni elemento di una sottosequenza. + + + + This example shows the first 100 elements of the random walk. + Questo esempio mostra i primi 100 elementi del percorso casuale. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Le funzioni ricorsive possono chiamarsi da sole. In F# le funzioni sono ricorsive solo + + + + when declared using 'let rec'. + quando per la dichiarazione si usa 'let rec'. + + + + Recursion is the preferred way to process sequences or collections in F#. + La ricorsione è il modo preferito per elaborare sequenze o raccolte in F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Questo esempio mostra una funzione ricorsiva che calcola il fattoriale di un + + + + integer. It uses 'let rec' to define a recursive function. + numero intero. Usa 'let rec' per definire una funzione ricorsiva. + + + + Computes the greatest common factor of two integers. + Calcola il fattore comune maggiore di due interi. + + + + Since all of the recursive calls are tail calls, + Dal momento che tutte le chiamate ricorsive sono chiamate tail, + + + + the compiler will turn the function into a loop, + il compilatore convertirà la funzione in un ciclo, + + + + which improves performance and reduces memory consumption. + in modo da migliorare le prestazioni e ridurre il consumo di memoria. + + + + This example computes the sum of a list of integers using recursion. + Questo esempio consente di calcolare la somma di un elenco di interi usando la ricorsione. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + In questo modo la funzione tail 'sumList' viene resa ricorsiva, usando una funzione helper con un accumulatore di risultati. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Viene chiamata la funzione helper tail ricorsiva, fornendo '0' come accumulatore di seeding. + + + + An approach like this is common in F#. + Un approccio di questo tipo è comune in F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + I record sono un aggregato di valori denominati, con membri facoltativi, ad esempio metodi. + + + + They are immutable and have structural equality semantics. + Non sono modificabili e includono la semantica di uguaglianza strutturale. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Questo esempio mostra come definire un nuovo tipo di record. + + + + This example shows how to instantiate a record type. + Questo esempio mostra come creare un'istanza di un tipo di record. + + + + You can also do this on the same line with ';' separators. + È possibile eseguire questa operazione sulla stessa riga usando i separatori ';'. + + + + This example shows how to use "copy-and-update" on record values. It creates + Questo esempio mostra come usare il metodo di copia e aggiornamento su valori di record. Crea + + + + a new record value that is a copy of contact1, but has different values for + un nuovo valore di record che è una copia di contact1, ma contiene valori diversi per + + + + the 'Phone' and 'Verified' fields. + i campi 'Phone' e 'Verified'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Questo esempio mostra come scrivere una funzione che elabora un valore di record. + + + + It converts a 'ContactCard' object to a string. + Converte un oggetto 'ContactCard' in una stringa. + + + + This is an example of a Record with a member. + Questo è un esempio di record con un membro. + + + + Members can implement object-oriented members. + I membri possono implementare membri orientati a oggetti. + + + + Members are accessed via the '.' operator on an instantiated type. + In un tipo di cui è stata creata un'istanza l'accesso ai membri avviene tramite l'operatore '.'. + + + + Records can also be represented as structs via the 'Struct' attribute. + I record possono essere rappresentati anche come struct tramite l'attributo 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Questo comportamento è utile in situazioni in cui la prestazioni degli struct sono prioritarie rispetto alla + + + + the flexibility of reference types. + flessibilità dei tipi di riferimento. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Le unioni discriminate sono valori che potrebbero corrispondere a un certo numero di case o form denominati. + + + + Data stored in DUs can be one of several distinct values. + I dati archiviati nelle unioni discriminate possono essere uno di diversi valori distinti. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + L'istruzione seguente rappresenta il seme di una carta da gioco. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + È possibile usare un'unione discriminata anche per rappresentare il valore di una carta da gioco. + + + + Represents the rank of cards 2 .. 10 + Rappresenta il valore delle carte da 2 a 10 + + + + Discriminated Unions can also implement object-oriented members. + Le unioni discriminate possono inoltre implementare membri orientati a oggetti. + + + + This is a record type that combines a Suit and a Rank. + Questo è un tipo di record che combina un seme e un valore. + + + + It's common to use both Records and Disciminated Unions when representing data. + Per la rappresentazione dei dati si usano in genere record e unioni discriminate. + + + + This computes a list representing all the cards in the deck. + Calcola un elenco che rappresenta tutte le carte del mazzo. + + + + This example converts a 'Card' object to a string. + Questo esempio consente di convertire un oggetto 'Card' in una stringa. + + + + This example prints all the cards in a playing deck. + Questo esempio consente di stampare tutte le carte di un mazzo. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Le unioni discriminate a case singolo vengono spesso usate per la modellazione dei domini. In questo modo è possibile garantire una maggiore sicurezza dei tipi + + + + over primitive types such as strings and ints. + rispetto a tipi primitivi come stringhe e valori int. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Le unioni discriminate a case singolo non possono essere convertite in modo implicito nel o dal tipo di cui eseguono il wrapping. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Ad esempio, una funzione che accetta un indirizzo non può accettare come input una stringa, + + + + or vive/versa. + o viceversa. + + + + You can easily instantiate a single-case DU as follows. + È possibile creare facilmente un'istanza di una unione discriminata a case singolo come descritto di seguito. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Quando è necessario il valore, è possibile annullare il wrapping del valore sottostante con una funzione semplice. + + + + Printing single-case DUs is simple with unwrapping functions. + Le funzioni di unwrapping semplificano la stampa di unioni discriminate a case singolo. + + + + Disciminated Unions also support recursive definitions. + Le unioni discriminate supportano anche definizioni ricorsive. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Rappresenta un albero di ricerca binaria, in cui un caso è l'albero vuoto, + + + + and the other being a Node with a value and two subtrees. + e l'altro è un nodo con un valore e due sottoalberi. + + + + Check if an item exists in the binary search tree. + Verifica l'esistenza di un elemento nell'albero della ricerca binaria. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Esegue la ricerca in modo ricorsivo usando i criteri di ricerca. Restituisce true se esiste; in caso contrario, false. + + + + Check the left subtree. + Verifica il sottoalbero di sinistra. + + + + Check the right subtree. + Verifica il sottoalbero di destra. + + + + Inserts an item in the Binary Search Tree. + Inserisce un elemento nell'albero della ricerca binaria. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Trova la posizione da inserire in modo ricorsivo con i criteri di ricerca, quindi inserisce un nuovo nodo. + + + + If the item is already present, it does not insert anything. + Se l'elemento è già presente, non inserisce nulla. + + + + No need to insert, it already exists; return the node. + Non è necessario inserirla perché esiste già; restituisce il nodo. + + + + Call into left subtree. + Chiamata nel sottoalbero di sinistra. + + + + Call into right subtree. + Chiamata nel sottoalbero di destra. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Le unioni discriminate possono essere rappresentate anche come struct tramite l'attributo 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Questo comportamento è utile in situazioni in cui la prestazioni degli struct sono prioritarie rispetto alla + + + + the flexibility of reference types. + flessibilità dei tipi di riferimento. + + + + However, there are two important things to know when doing this: + Quando si esegue questa operazione, è però importante conoscere due aspetti: + + + + 1. A struct DU cannot be recursively-defined. + 1. Un'unione discriminata di struct non può essere definita in modo ricorsivo. + + + + 2. A struct DU must have unique names for each of its cases. + 2. A ogni case di un'unione discriminata di struct deve essere assegnato un nome univoco. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + I criteri di ricerca sono una funzionalità di F# che consente di utilizzare i criteri, + + + + which are a way to compare data with a logical structure or structures, + che consentono di confrontare i dati con una o più strutture logiche, + + + + decompose data into constituent parts, or extract information from data in various ways. + scomporre i dati nelle parti costituenti o estrarre le informazioni dai dati in diversi modi. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + È quindi possibile intervenire sulla "forma" di un criterio tramite i criteri di ricerca. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Record per il nome e il cognome di una persona + + + + A Discriminated Union of 3 different kinds of employees + Unione discriminata di tre diversi tipi di dipendenti + + + + Count everyone underneath the employee in the management hierarchy, + Conta chiunque sotto il dipendente nella gerarchia di gestione, + + + + including the employee. + includendo il dipendente. + + + + Find all managers/executives named "Dave" who do not have any reports. + Trova tutti i manager/dirigenti il cui nome è "Dave" e per i quali non sono disponibili report. + + + + This uses the 'function' shorthand to as a lambda expression. + Usa la sintassi abbreviata di 'function' come espressione lambda. + + + + [] matches an empty list. + [] corrisponde a un elenco vuoto. + + + + '_' is a wildcard pattern that matches anything. + '_' è un carattere jolly che corrisponde a qualsiasi stringa. + + + + This handles the "or else" case. + Gestisce il caso "or else". + + + + You can also use the shorthand function construct for pattern matching, + Per i criteri di ricerca è anche possibile usare il costrutto di funzione a sintassi abbreviata, + + + + which is useful when you're writing functions which make use of Partial Application. + che risulta utile quando si scrivono funzioni che usano l'applicazione parziale. + + + + Define some more functions which parse with the helper function. + Consente di definire alcune altre funzioni che vengono analizzate con la funzione helper. + + + + Active Patterns are another powerful construct to use with pattern matching. + I criteri attivi sono un altro costrutto efficace da usare con i criteri di ricerca. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Consentono di partizionare i dati di input in form personalizzati, scomponendoli a livello del sito di chiamata dei criteri di ricerca. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + I criteri di ricerca con parola chiave 'function' e criteri attivi sono spesso simili a questi. + + + + Call the printer with some different values to parse. + Chiama la stampante con alcuni valori diversi da analizzare. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Il valore dell'opzione è qualsiasi valore con tag 'Some' o 'None'. + + + + They are used extensively in F# code to represent the cases where many other + Questi valori sono ampiamente utilizzati nel codice F# per rappresentare i casi in cui molti altri + + + + languages would use null references. + linguaggi utilizzerebbero riferimenti null. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Consente innanzitutto di definire un codice postale definito tramite l'unione discriminata a case singolo. + + + + Next, define a type where the ZipCode is optional. + Definire quindi un tipo in cui l'elemento ZipCode è facoltativo. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Definire quindi un tipo di interfaccia che rappresenta un oggetto per calcolare la zona di spedizione per il codice postale del cliente, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + date le implementazioni per i metodi astratti 'getState' e 'getShippingZone'. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Calcolare quindi una zona di spedizione per un cliente usando un'istanza della calcolatrice. + + + + This uses combinators in the Option module to allow a functional pipeline for + Usa i combinatori del modulo Option per consentire una pipeline funzionale per + + + + transforming data with Optionals. + la trasformazione di dati con Optionals. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Le unità di misura consentono di annotare tipi numerici primitivi in modo indipendente dai tipi. + + + + You can then perform type-safe arithmetic on these values. + È quindi possibile eseguire operazioni aritmetiche indipendenti dai tipi su questi valori. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Aprire innanzitutto una raccolta di nomi di unità comuni + + + + Define a unitized constant + Definire una costante unificata + + + + Next, define a new unit type + Definire quindi un nuovo tipo di unità + + + + Conversion factor mile to meter. + Fattore di conversione da miglia a metri. + + + + Define a unitized constant + Definire una costante unificata + + + + Compute metric-system constant + Calcola la costante del sistema metrico + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + I valori che usano unità di misura possono essere usati come il tipo numerico primitivo per elementi come la stampa. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Le classi sono un modo per definire nuovi tipi di oggetto in F# e supportano costrutti standard orientati a oggetti. + + + + They can have a variety of members (methods, properties, events, etc.) + Possono includere numerosi membri (metodi, proprietà, eventi e così via) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Per altre informazioni sulle classi, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Per altre informazioni sui membri, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Semplice classe di vettore bidimensionale. + + + + The class's constructor is on the first line, + Il costruttore della classe si trova sulla prima riga + + + + and takes two arguments: dx and dy, both of type 'double'. + e accetta due argomenti, dx e dy, entrambi di tipo 'double'. + + + + This internal field stores the length of the vector, computed when the + In questo campo interno è archiviata la lunghezza del vettore, calcolata durante + + + + object is constructed + la costruzione dell'oggetto + + + + 'this' specifies a name for the object's self identifier. + 'this' specifica un nome per l'autoidentificatore dell'oggetto. + + + + In instance methods, it must appear before the member name. + Nei metodi di istanza, deve trovarsi prima del nome del membro. + + + + This member is a method. The previous members were properties. + Questo membro è un metodo. I membri precedenti erano proprietà. + + + + This is how you instantiate the Vector2D class. + In questo modo viene creata un'istanza della classe Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Consente di ottenere un nuovo oggetto vettore scalato senza modificare l'oggetto originale. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Le classi generiche consentono di definire tipi rispetto a un set di parametri di tipo. + + + + In the following, 'T is the type parameter for the class. + Nel codice seguente 'T è il parametro di tipo per la classe. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Questo campo interno archivia gli stati in un elenco. + + + + Add a new element to the list of states. + Aggiunge un nuovo elemento all'elenco degli stati. + + + + use the '<-' operator to mutate the value. + usare l'operatore '<-' per modificare il valore. + + + + Get the entire list of historical states. + Consente di ottenere l'intero elenco degli stati cronologici. + + + + Get the latest state. + Consente di ottenere l'ultimo stato. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Istanza 'int' della classe di rilevamento stato. Si noti che il parametro di tipo è dedotto. + + + + Add a state + Viene aggiunto uno stato + + + + Interfaces are object types with only 'abstract' members. + Le interfacce sono tipi di oggetto contenenti solo membri 'abstract'. + + + + Object types and object expressions can implement interfaces. + I tipi di oggetto e le espressioni di oggetto possono implementare interfacce. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Questo è un tipo che implementa IDisposable. + + + + This is the implementation of IDisposable members. + Questa è l'implementazione dei membri di IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Questo è un oggetto che implementa IDisposable tramite un'espressione di oggetto + + + + Unlike other languages such as C# or Java, a new type definition is not needed + Diversamente da altri linguaggi, come C# o Java, non è necessaria una nuova definizione di tipo + + + + to implement an interface. + per implementare un'interfaccia. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + La libreria FSharp.Core definisce un intervallo di funzioni di elaborazione parallela. In questo caso + + + + you use some functions for parallel processing over arrays. + si usano alcune funzioni per l'elaborazione parallela sulle matrici. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Per altre informazioni, vedere: https://msdn.microsoft.com/it-it/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Definire innanzitutto una matrice di input. + + + + Next, define a functions that does some CPU intensive computation. + Definire quindi una funzione che esegue alcuni calcoli intensivi della CPU. + + + + Next, do a parallel map over a large input array. + Eseguire quindi un mapping parallelo su una matrice di input di grandi dimensioni. + + + + Next, print the results. + Stampare quindi i risultati. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Gli eventi sono un termine comune per la programmazione .NET, in particolare con le applicazioni Windows Form o WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Per altre informazioni, vedere: https://docs.microsoft.com/it-it/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Creare innanzitutto un'istanza dell'oggetto Event costituito dal punto di sottoscrizione (event.Publish) e dal trigger di evento (event.Trigger). + + + + Next, add handler to the event. + Aggiungere quindi il gestore all'evento. + + + + Next, trigger the event. + Attivare quindi l'evento. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Creare quindi un'istanza dell'oggetto Event che segue la convenzione .NET standard: (sender, EventArgs). + + + + Next, add a handler for this new event. + Aggiungere quindi un gestore per questo nuovo evento. + + + + Next, trigger this event (note that sender argument should be set). + Attivare quindi questo evento (si noti che è necessario impostare l'argomento sender). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ja.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ja.xlf new file mode 100644 index 0000000000..0eda61edb1 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ja.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + このサンプルは、F# 言語の要素を紹介します。 + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + F# インタラクティブでコードを実行するには、コードの一部を強調表示して、Alt キーを押しながら Enter キーを押すか、右マウス ボタンをクリックし + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + [対話形式で実行]5D; を選択します。[表示]5D; メニューから F# インタラクティブ ウィンドウを開くことができます。 + + + + For more about F#, see: + F# の詳細については、次のページを参照してください: + + + + To see this tutorial in documentation form, see: + このチュートリアルをドキュメント形式で表示するには、次を参照してください: + + + + To learn more about applied F# programming, use + 適用された F# プログラミングの詳細については、次を使用します + + + + To install the Visual F# Power Tools, use + Visual F# Power Tools をインストールするには、次を使用します + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + [ツール]5D; --> [拡張機能と更新プログラム]5D; --> [オンライン]5D; と検索 + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + F# で使用するその他のテンプレートについては、Visual Studio の 'オンライン テンプレート' を参照してください。 + + + + 'New Project' --> 'Online Templates' + ([新しいプロジェクト]5D; --> [オンライン テンプレート]5D;) を参照してください。 + + + + F# supports three kinds of comments: + F# は、3 種類のコメントをサポートしています: + + + + 1. Double-slash comments. These are used in most situations. + 1. ダブルスラッシュ コメント。これはほとんどの場合に使用されます。 + + + + 2. ML-style Block comments. These aren't used that often. + 2. ML スタイル ブロック コメント。これはそれほど頻繁には使用されません。 + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. トリプル スラッシュ コメント。これは、関数や型などの文書化に使用されます。 + + + + They will appear as text when you hover over something which is decorated with these comments. + このコメントで修飾されているものをポイントすると、これがテキストとして表示されます。 + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + これは .NET スタイルの XML コメントもサポートしています。このコメントを使用すると、リファレンス ドキュメントを生成できます。 + + + + and they also allow editors (such as Visual Studio) to extract information from them. + また、(Visual Studio などの) エディターでそこから情報を抽出することもできます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + 'open' キーワードを使用して名前空間を開きます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + モジュールは、値、型、関数値などの、F# コードのグループ化です。 + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + コードをモジュールにグループ化することで、関連コードを 1 つにまとめて、プログラムでの名前の競合を回避することができます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + これは、サンプルの整数値です。 + + + + This is a sample floating point number. + これは、サンプルの浮動小数点数です。 + + + + This computed a new number by some arithmetic. Numeric types are converted using + 算術によって新しい数値が算出されました。数値型は以下を使用するよう変換されています + + + + functions 'int', 'double' and so on. + 関数の 'int'、'double' などです。 + + + + This is a list of the numbers from 0 to 99. + これは 0 ~ 99 の数値のリストです。 + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + これは、0 ~ 99 のすべての数値とその二乗を含むすべてのタプルのリストです。 + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + 次の行は、タプルを含むリストを出力します。一般的な出力に '%A' を使用しています。 + + + + This is a sample integer with a type annotation + これは、型の注釈付きのサンプルの整数です + + + + Values in F# are immutable by default. They cannot be changed + 既定では、F# の値は不変です。明示的に変更可能として指定しない限り、 + + + + in the course of a program's execution unless explicitly marked as mutable. + プログラムの実行の過程で変更することはできません。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + 'let' を介して値を名前にバインドすると、変更できなくなります。 + + + + The second line of code fails to compile because 'number' is immutable and bound. + コードの 2 番目の行は、'number' が変更できず、バインドされているため、コンパイルに失敗します。 + + + + Re-defining 'number' to be a different value is not allowed in F#. + F# では、'number' を別の値に再定義することはできません。 + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + 変更可能なバインド。これは 'otherNumber' の値を変更できるようにするために必要です。 + + + + When mutating a value, use '<-' to assign a new value. + 値を変換する場合は、'<-' を使用して新しい値を割り当てます。 + + + + You could not use '=' here for this purpose since it is used for equality + この場合、'=' は等価を示すために使用するため、ここで使用することはできません + + + + or other contexts such as 'let' or 'module' + または、'let' や 'module' などの他のコンテキスト + + + + Much of F# programming consists of defining functions that transform input data to produce + F# プログラミングの多くは、生成する入力データを変換する定義する関数で構成されています + + + + useful results. + 有用な結果。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + 関数を定義するには、'let' を使用します。これは整数の引数を受け取り、整数を返します。 + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + 明示的な型の注釈を使用する場合を除いて、かっこは関数引数では省略可能です。 + + + + Apply the function, naming the function return result using 'let'. + 関数を適用します。'let' を使用し、関数の戻り値の結果に名前を付けます。 + + + + The variable type is inferred from the function return type. + 変数の型は、関数の戻り値の型から推論されます。 + + + + This line uses '%d' to print the result as an integer. This is type-safe. + この行は '%d' を使用して結果を整数として出力します。これはタイプ セーフです。 + + + + If 'result1' were not of type 'int', then the line would fail to compile. + 'result1' が 'int' 型でなかった場合、行はコンパイルに失敗します。 + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + 必要であれば、'(引数:型)' を使用してパラメーター名の型に注釈を付けます。かっこは必須です。 + + + + Conditionals use if/then/elid/elif/else. + 条件は、if/then/elid/elif/else を使用します。 + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + F# は Python などの言語のように、空白のインデント対応構文を使用することに注意してください。 + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + この行は '%f' を使用して結果を浮動小数として出力します。上記の '%d' と同様に、これはタイプ セーフです。 + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + ブール値は F# の基本のデータ型です。ブール値と条件ロジックの例をいくつか示します。 + + + + To learn more, see: + 詳細については、次を参照してください: + + + + and + AND + + + + Booleans values are 'true' and 'false'. + ブール型の値は 'true' と 'false' です。 + + + + Operators on booleans are 'not', '&&' and '||'. + ブール値の演算子は 'not'、'&&'、および '||' です。 + + + + This line uses '%b'to print a boolean value. This is type-safe. + この行は '%b' を使用してブール値を出力します。これはタイプ セーフです。 + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + 文字列は F# の基本のデータ型です。文字列と基本的な文字列操作の例をいくつか示します。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + 文字列は二重引用符を使用します。 + + + + Strings can also use @ to create a verbatim string literal. + 文字列は @ を使用して、verbatim 文字列リテラルを作成することもできます。 + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + これは、'\'、'\n'、'\t' などのエスケープ文字を無視します。 + + + + String literals can also use triple-quotes. + 文字列リテラルは三重引用符を使用することもできます。 + + + + String concatenation is normally done with the '+' operator. + 通常、文字列の連結は '+' 演算子を使用して実行されます。 + + + + This line uses '%s' to print a string value. This is type-safe. + この行は、'%s' を使用して文字列値を出力します。これはタイプ セーフです。 + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + サブ文字列はインデクサー表記を使用します。この行はサブ文字列として最初の 7 文字を抽出します。 + + + + Note that like many languages, Strings are zero-indexed in F#. + 多くの言語と同様に、F# では、文字列のインデックスは 0 から始まることに注意してください。 + + + + Tuples are simple combinations of data values into a combined value. + タプルは、データ値と合計値の単純な組み合わせです。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + 整数のシンプルなタプルです。 + + + + A function that swaps the order of two values in a tuple. + タプルの 2 つの値の順序を入れ替える関数。 + + + + F# Type Inference will automatically generalize the function to have a generic type, + F# 型の推定は、ジェネリック型を持つように関数を自動的に一般化し、 + + + + meaning that it will work with any type. + 任意の型で動作することを意味します。 + + + + A tuple consisting of an integer, a string, + タプルを構成するのは、整数、文字列、 + + + + and a double-precision floating point number. + および倍精度浮動小数点数です。 + + + + A simple tuple of integers with a type annotation. + 型の注釈が指定された整数のシンプルなタプル。 + + + + Type annotations for tuples use the * symbol to separate elements + タプルの型の注釈では、要素を区切るために * の記号を使用します + + + + Tuples are normally objects, but they can also be represented as structs. + タプルは通常はオブジェクトですが、構造体として表すこともできます。 + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + C# と Visual Basic.NET では、これらは構造体と完全に相互運用されます。ただし、 + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + 構造体のタプルは、オブジェクト タプル (参照タプルと呼ばれることが多い) と暗黙的に変換できません。 + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + このため、以下の 2 番目の行はコンパイルに失敗します。発生する事象を確認するには、コメントを解除します。 + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + 構造体タプルと参照タプル間で暗黙的に変換することはできませんが、 + + + + you can explicitly convert via pattern matching, as demonstrated below. + 以下に示すように、パターン マッチングを使用して明示的に変換できます。 + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + F# パイプ演算子 ('|>'、'<|' など) と F# 合成演算子 ('>>'、'<<') + + + + are used extensively when processing data. These operators are themselves functions + は、データの処理時に幅広く使用されます。これらの演算子はそれ自体が関数であり、 + + + + which make use of Partial Application. + 部分適用を利用します。 + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + これらの演算子の詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + 部分適用の詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + 値を 2 乗します。 + + + + Adds 1 to a value. + 値に 1 を追加します。 + + + + Tests if an integer value is odd via modulo. + 剰余を使って整数値が奇数であるかどうかをテストします。 + + + + A list of 5 numbers. More on lists later. + 5 個の数値のリストです。リストの詳細については後述。 + + + + Given a list of integers, it filters out the even numbers, + 整数のリストを指定すると、偶数を除外し、 + + + + squares the resulting odds, and adds 1 to the squared odds. + 結果の奇数を 2 乗し、2 乗した奇数に 1 を加算します。 + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + 'squareOddValuesAndAddOne' を記述するためのより簡単な方法は、 + + + + sub-result into the function calls themselves. + それぞれのサブ結果を関数呼び出し自体に入れ子にすることです。 + + + + This makes the function much shorter, but it's difficult to see the + これにより、関数は大幅に短くなりますが、データが処理される順序を + + + + order in which the data is processed. + 判別するのは難しくなります。 + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + 'squareOddValuesAndAddOne' を記述するための推奨される方法は、F# パイプ演算子を使用する方法です。 + + + + This allows you to avoid creating intermediate results, but is much more readable + これにより、中間結果を作成しなくてもよくなります。また、 + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + 'squareOddValuesAndAddOneNested' のような関数呼び出しを入れ子にするよりもはるかに読みやすくすることができます + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + ラムダ関数を使用して、2 番目の `List.map` 呼び出しを先頭に移動することにより、 + + + + into the first, using a Lambda Function. + 'squareOddValuesAndAddOnePipeline' を短くすることができます。 + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + パイプラインはラムダ関数の内部でも使用されることに注意してください。F# パイプ演算子は、 + + + + can be used for single values as well. This makes them very powerful for processing data. + 単一の値にも使用できます。これにより、データ処理能力が向上します。 + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + 最後に、'>>' を使用して次の 2 つのコア操作を作成すると、'values' をパラメーターとして + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + 明示的に受け取る必要がなくなります: 偶数を除外してから、2 乗して 1 を加算する。 + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + 同様に、ラムダ式の 'fun x -> ...' ビットも必要ありません。 'x' は単に、 + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + 関数型パイプラインに渡すことができるようにそのスコープ内で定義されているだけだからです。そのため、 + + + + there as well. + そこでも同様に '>>' を使用できます。 + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + 'squareOddValuesAndAddOneComposition' の結果は、それ自体が別の関数です。その関数は、 + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + 整数のリストを入力として受け取ります。整数のリストを指定して 'squareOddValuesAndAddOneComposition' を + + + + of integers, you'll notice that it produces the same results as previous functions. + 実行すると、前の関数と同じ結果が生成されることがわかります。 + + + + This is using what is known as function composition. This is possible because functions in F# + これは、関数合成と呼ばれるものを使用しています。これが可能なのは、F# の関数が + + + + use Partial Application and the input and output types of each data processing operation match + 部分適用を使用しており、各データ処理操作の入力と出力の型が、使用している + + + + the signatures of the functions we're using. + 関数のシグネチャと一致するためです。 + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + リストは、順序指定された、変更できない単方向リストです。 リストは集中評価されます。 + + + + This module shows various ways to generate lists and process lists with some functions + このモジュールは、リストを生成し、F# コア ライブラリ内の 'List' モジュールに含まれる + + + + in the 'List' module in the F# Core Library. + いくつかの関数を使用してリストを処理するためのさまざまな方法を示しています。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + リストは [ ... ] を使用して定義されます。これは空のリストです。 + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + これは 3 つの要素を含むリストです。';' は同じ行にある要素を区切るために使用されます。 + + + + You can also separate elements by placing them on their own lines. + 要素は、それぞれの行に配置することで分割することもできます。 + + + + This is a list of integers from 1 to 1000 + これは 1 ~ 1000 の整数のリストです + + + + Lists can also be generated by computations. This is a list containing + リストは計算によっても生成できます。これは、次を含むリストです: + + + + all the days of the year. + 1 年のすべての日。 + + + + Print the first 5 elements of 'daysList' using 'List.take'. + 'List.take' を使用して 'daysList' の最初の 5 つの要素を出力します。 + + + + Computations can include conditionals. This is a list containing the tuples + 計算には条件を含めることができます。これはタプルを含むリストです + + + + which are the coordinates of the black squares on a chess board. + チェス盤の黒いマス目の座標のタプルを含むリストです。 + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + リストは 'List.map' と他の関数型プログラミング連結子を使用して変換することができます。 + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + この定義は、パイプラインを使用して numberList 内の数値を 2 乗することによって新しいリストを生成します + + + + operator to pass an argument to List.map. + 引数を List.map に渡す演算子です。 + + + + There are many other list combinations. The following computes the sum of the squares of the + 他に多くのリストの組み合わせがあります。次の二乗和をコンピューティングします: + + + + numbers divisible by 3. + 3 で割り切れる数。 + + + + Arrays are fixed-size, mutable collections of elements of the same type. + 配列は、型が同じ要素の固定サイズの変更可能なコレクションです。 + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + これらはリストと似ています (列挙型をサポートし、データ処理のための同様の連結子を備えています) が、 + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + 一般的により高速であり、高速ランダム アクセスをサポートしています。その代わり、変更可能であるため安全性が低下します。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + これは空の配列です。構文はリストの構文と似ていますが、代わりに `[| ... |]` を使用することにご注意ください。 + + + + Arrays are specified using the same range of constructs as lists. + 配列は、リストと同じコンストラクトの範囲を使用して指定されます。 + + + + This is an array of numbers from 1 to 1000. + これは 1 ~ 1000 の数値の配列です。 + + + + This is an array containing only the words "hello" and "world". + これは "hello" と "world" のみを含む配列です。 + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + これはインデックスによって初期化され、0 ~ 2000 の間の偶数を含む配列です。 + + + + Sub-arrays are extracted using slicing notation. + サブ配列はスライス表記法を使用して抽出されます。 + + + + You can loop over arrays and lists using 'for' loops. + 'for' ループを使用して、配列とリストに渡ってループできます。 + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + 左矢印代入演算子を使用して、配列要素の内容を変更できます。 + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + この演算子の詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + 'Array.map' と他の関数型プログラミング操作を使用して、配列を変換できます。 + + + + The following calculates the sum of the lengths of the words that start with 'h'. + 以下は、'h' で始まる単語の長さの合計を計算します。 + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + シーケンスは論理的な一連の要素であり、すべてが同じ型です。これらはリストや配列よりも一般的な型です。 + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + シーケンスはオンデマンドで評価され、繰り返されるたびに再評価されます。 + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + F# シーケンスは .NET System.Collections.Generic.IEnumerable<'T> のエイリアスです。 + + + + Sequence processing functions can be applied to Lists and Arrays as well. + シーケンス処理関数はリストと配列にも適用できます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + これは空のシーケンスです。 + + + + This a sequence of values. + これは一連の値です。 + + + + This is an on-demand sequence from 1 to 1000. + これは 1 ~ 1000 のオンデマンドのシーケンスです。 + + + + This is a sequence producing the words "hello" and "world" + これは 単語 "hello" と "world" を生成するシーケンスです + + + + This sequence producing the even numbers up to 2000. + このシーケンスは、2000 までの偶数を生成します。 + + + + This is an infinite sequence which is a random walk. + これはランダム ウォークである無限シーケンスです。 + + + + This example uses yield! to return each element of a subsequence. + この例では、yield! を使用して、サブシーケンスの各要素を返します。 + + + + This example shows the first 100 elements of the random walk. + この例では、ランダム ウォークの最初の 100 要素を示します。 + + + + Recursive functions can call themselves. In F#, functions are only recursive + 再帰関数は自身を呼び出すことができます。F# では、関数は単に再帰的です + + + + when declared using 'let rec'. + 'let rec' を使用して宣言される場合。 + + + + Recursion is the preferred way to process sequences or collections in F#. + 再帰は、F# でシーケンスまたはコレクションを処理するための推奨される方法です。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + この例では、次の階乗をコンピューティングする再帰関数を示します + + + + integer. It uses 'let rec' to define a recursive function. + 整数。'let rec' を使用して、再帰関数を定義します。 + + + + Computes the greatest common factor of two integers. + 2 つの整数の最大公約数をコンピューティングします。 + + + + Since all of the recursive calls are tail calls, + すべての再帰呼び出しは末尾呼び出しであるため、 + + + + the compiler will turn the function into a loop, + コンパイラは関数をループにします + + + + which improves performance and reduces memory consumption. + これによりパフォーマンスが向上し、メモリの消費を抑えることができます。 + + + + This example computes the sum of a list of integers using recursion. + この例では、再帰を使用して整数のリストの合計をコンピューティングします。 + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + これは、ヘルパー関数を結果アキュムレータと共に使用して 'sumList' を末尾再帰にします。 + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + これは、シード アキュムレータとして '0' を指定して、末尾再帰的なヘルパー関数を呼び出します。 + + + + An approach like this is common in F#. + F# では、このようなアプローチは一般的です。 + + + + Records are an aggregate of named values, with optional members (such as methods). + レコードは、オプションのメンバー (メソッドなど) を含む名前付きの値の集約です。 + + + + They are immutable and have structural equality semantics. + これらは変更できず、構造上の等価セマンティクスを持ちます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + この例では、新しいレコード型を定義する方法を示します。 + + + + This example shows how to instantiate a record type. + この例では、レコードの種類をインスタンス化する方法を示します。 + + + + You can also do this on the same line with ';' separators. + ';' 区切りを使用して、同じ行でこれを行うこともできます。 + + + + This example shows how to use "copy-and-update" on record values. It creates + この例では、レコード値で "copy-and-update" を使用する方法を示します。次を作成します: + + + + a new record value that is a copy of contact1, but has different values for + contact1 のコピーであるレコード値。ただし、次の値は異なります: + + + + the 'Phone' and 'Verified' fields. + [電話番号]5D; および [検証済み]5D; フィールド。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + この例では、レコード値を処理する関数を書き込む方法を示します。 + + + + It converts a 'ContactCard' object to a string. + 'ContactCard' オブジェクトを文字列に変換します。 + + + + This is an example of a Record with a member. + これは、メンバーを含むレコードの例です。 + + + + Members can implement object-oriented members. + メンバーはオブジェクト指向のメンバーを実装できます。 + + + + Members are accessed via the '.' operator on an instantiated type. + メンバーには、インスタンス化された型に対する '.' 演算子を介してアクセスできます。 + + + + Records can also be represented as structs via the 'Struct' attribute. + レコードは 'Struct' 属性を介して構造体として表すこともできます。 + + + + This is helpful in situations where the performance of structs outweighs + これは、構造体のパフォーマンスが参照型の柔軟性よりも + + + + the flexibility of reference types. + 重要である場合に役立ちます。 + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + 判別共用体 (略して DU) は、多数の名前付きのフォームまたはケースである可能性のある値です。 + + + + Data stored in DUs can be one of several distinct values. + DU の格納データは、複数の個別の値のいずれかになります。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + たとえば、次は一揃いのトランプを表します。 + + + + A Disciminated Union can also be used to represent the rank of a playing card. + 判別共用体はトランプのランクを表すためにも使用できます。 + + + + Represents the rank of cards 2 .. 10 + 2 ~ 10 の札のランクを表します + + + + Discriminated Unions can also implement object-oriented members. + 判別共用体はオブジェクト指向のメンバーを実装することもできます。 + + + + This is a record type that combines a Suit and a Rank. + これは Suit と Rank を組み合わせたレコード型です。 + + + + It's common to use both Records and Disciminated Unions when representing data. + データを表すときには、レコードと判別共用体の両方を使用するのが一般的です。 + + + + This computes a list representing all the cards in the deck. + これは、一組のトランプのすべてのカードを表すリストをコンピューティングします。 + + + + This example converts a 'Card' object to a string. + この例では 'Card' オブジェクトを文字列に変換します。 + + + + This example prints all the cards in a playing deck. + この例では、一組のトランプのカードすべてを印刷します。 + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + 単一ケースの DU は、ドメイン モデリングで多く使用されます。これにより、文字列や整数などの + + + + over primitive types such as strings and ints. + プリミティブ型に加えて、さらにタイプ セーフが追加されます。 + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + 単一ケースの DU は、ラップする型との間で暗黙的に変換することはできません。 + + + + For example, a function which takes in an Address cannot accept a string as that input, + たとえば、アドレスを受け取る関数は文字列をその入力として受け入れることはできません + + + + or vive/versa. + (その逆もできません)。 + + + + You can easily instantiate a single-case DU as follows. + 次のように、単一ケースの DU のインスタンスを簡単に作成できます。 + + + + When you need the value, you can unwrap the underlying value with a simple function. + 値が必要な場合は、簡単な関数を使用して基になる値のラップを解除できます。 + + + + Printing single-case DUs is simple with unwrapping functions. + 単一ケースの DU は、関数のラップを解除するだけで出力できます。 + + + + Disciminated Unions also support recursive definitions. + 判別共用体は再帰的な定義もサポートしています。 + + + + This represents a Binary Search Tree, with one case being the Empty tree, + これはバイナリ検索ツリーを表します。片方のケースは空のツリーであり、 + + + + and the other being a Node with a value and two subtrees. + もう片方は値と 2 つのサブツリーを含む Node です。 + + + + Check if an item exists in the binary search tree. + バイナリ検索ツリーにアイテムが存在するかどうかを確認します。 + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + パターン マッチングを使用して再帰的に検索します。存在する場合は true を返し、そうでない場合は false を返します。 + + + + Check the left subtree. + 左側のサブツリーを確認します。 + + + + Check the right subtree. + 右側のサブツリーを確認します。 + + + + Inserts an item in the Binary Search Tree. + バイナリ検索ツリーにアイテムを挿入します。 + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + パターン マッチングを使用して再帰的に挿入する場所を検索し、新しいノードを挿入します。 + + + + If the item is already present, it does not insert anything. + アイテムが既に存在する場合は、何も挿入しません。 + + + + No need to insert, it already exists; return the node. + 既に存在しているため、挿入する必要はありません。ノードを返します。 + + + + Call into left subtree. + 左側のサブツリーに呼び出します。 + + + + Call into right subtree. + 右側のサブツリーに呼び出します。 + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + 判別共用体は、'Struct' 属性を介して構造体として表すこともできます。 + + + + This is helpful in situations where the performance of structs outweighs + これは、構造体のパフォーマンスが参照型の柔軟性よりも + + + + the flexibility of reference types. + 重要である場合に役立ちます。 + + + + However, there are two important things to know when doing this: + ただし、これを行うときに理解しておく必要のある重要な点が 2 つあります: + + + + 1. A struct DU cannot be recursively-defined. + 1. 構造体 DU は再帰的に定義できません。 + + + + 2. A struct DU must have unique names for each of its cases. + 2. 構造体 DU の名前は各ケースに対して一意である必要があります。 + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + パターン マッチングはパターンを使用できるようにする F# の機能です。 + + + + which are a way to compare data with a logical structure or structures, + これは、データと 1 つまたは複数の論理構造を比較したり、 + + + + decompose data into constituent parts, or extract information from data in various ways. + データを構成要素部分に分解したり、さまざまな方法でデータから情報を抽出したりするための方法です。 + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + その後、パターン マッチングを介してパターンの "形" でディスパッチできます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + 個人の姓および名のレコード + + + + A Discriminated Union of 3 different kinds of employees + 3 種類の社員の判別共用体 + + + + Count everyone underneath the employee in the management hierarchy, + 管理階層構造の中で、ある社員の下にいる全員の数を数えます + + + + including the employee. + (その社員自身を含む)。 + + + + Find all managers/executives named "Dave" who do not have any reports. + 名前が "Dave" で、レポートのないすべてのマネージャー/役員を検索します。 + + + + This uses the 'function' shorthand to as a lambda expression. + これは、ラムダ式として 'function' の短縮形を使用します。 + + + + [] matches an empty list. + [] は空白のリストに一致します。 + + + + '_' is a wildcard pattern that matches anything. + '_' は、任意のものに一致するワイルドカード パターンです。 + + + + This handles the "or else" case. + これは "or else" ケースを処理します。 + + + + You can also use the shorthand function construct for pattern matching, + パターン マッチングのために、短縮形の関数コンストラクトを使用することもできます。 + + + + which is useful when you're writing functions which make use of Partial Application. + これは、部分適用を利用する関数を記述している場合に役立ちます。 + + + + Define some more functions which parse with the helper function. + ヘルパー関数で解析する別の関数をいくつか定義します。 + + + + Active Patterns are another powerful construct to use with pattern matching. + アクティブなパターンは、パターン マッチングで使用するもう 1 つの強力なコンストラクトです。 + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + パターン マッチの呼び出しサイトで分解して、入力データをカスタム フォームにパーティション分割できるようにします。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + 'function' キーワードとアクティブ パターンによるパターン マッチングは、多くの場合、次のようになります。 + + + + Call the printer with some different values to parse. + 解析するいくつかの異なる値でプリンターを呼び出します。 + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + オプション値とは、'Some' または 'None' がタグされたあらゆる種類の値です。 + + + + They are used extensively in F# code to represent the cases where many other + F# コードで広く使用され、他の多くの言語で null 参照が使用される + + + + languages would use null references. + ケースを表します。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + まず、単一ケースの判別共用体を介して定義した郵便番号を定義します。 + + + + Next, define a type where the ZipCode is optional. + 次に、郵便番号が省略可能である型を定義します。 + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + 次に、オブジェクトを表すインターフェイスの型を定義して、顧客の郵便番号の出荷ゾーンをコンピューティングし、 + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + 'getState' および 'getShippingZone' 抽象メソッドの実装が指定されています。 + + + + Next, calculate a shipping zone for a customer using a calculator instance. + 次に、電卓のインスタンスを使用して顧客の出荷ゾーンを計算します。 + + + + This uses combinators in the Option module to allow a functional pipeline for + これは、オプション モジュール内の連結子を使用することにより、オプションを使用したデータ変換のために + + + + transforming data with Optionals. + 関数型パイプラインを使用できるようにします。 + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + 測定単位は、タイプ セーフな方法でプリミティブな数値型に注釈を付ける方法です。 + + + + You can then perform type-safe arithmetic on these values. + 次に、これらの値に対してタイプ セーフの算術を実行できます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + まず、共通の単位名のコレクションを開きます + + + + Define a unitized constant + 単位化された定数を定義します + + + + Next, define a new unit type + 次に、新しい単位の種類を定義します + + + + Conversion factor mile to meter. + マイルからメートルへの変換係数。 + + + + Define a unitized constant + 単位化された定数を定義します + + + + Compute metric-system constant + メートル法の定数をコンピューティングします + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + 測定単位を使用する値は、印刷などに対するプリミティブな数値型と同じように使用できます。 + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + クラスは、F# で新しいオブジェクト型を定義する方法であり、標準のオブジェクト指向のコンストラクトをサポートします。 + + + + They can have a variety of members (methods, properties, events, etc.) + さまざまなメンバー (メンバー、プロパティ、イベントなど) を含めることができます + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + クラスの詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + メンバーの詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + 単純な 2 次元のベクター クラス。 + + + + The class's constructor is on the first line, + クラスのコンストラクターは最初の行にあり、 + + + + and takes two arguments: dx and dy, both of type 'double'. + また、dx と dy の 2 つの引数を取ります。どちらも 'double' 型です。 + + + + This internal field stores the length of the vector, computed when the + この内部フィールドはベクトルの長さを格納します。これは、次の時点でにコンピューティングされます: + + + + object is constructed + オブジェクトが構築されます + + + + 'this' specifies a name for the object's self identifier. + 'this' は、オブジェクトの自己識別子の名前を指定します。 + + + + In instance methods, it must appear before the member name. + インスタンス メソッドでは、メンバー名の前に表示される必要があります。 + + + + This member is a method. The previous members were properties. + このメンバーはメソッドです。前のメンバーはプロパティでした。 + + + + This is how you instantiate the Vector2D class. + これは、Vector2D クラスのインスタンスを作成する方法です。 + + + + Get a new scaled vector object, without modifying the original object. + 元のオブジェクトを変更せずに、新しく調節されたベクター オブジェクトを取得します。 + + + + Generic classes allow types to be defined with respect to a set of type parameters. + ジェネリック クラスでは、型パラメーターのセットに対して型を定義することができます。 + + + + In the following, 'T is the type parameter for the class. + 以下では、'T はクラスの型パラメーターです。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + この内部フィールドは状態をリストに保存します。 + + + + Add a new element to the list of states. + 状態のリストに新しい要素を追加します。 + + + + use the '<-' operator to mutate the value. + '<-' 演算子を使用して、値を変換します。 + + + + Get the entire list of historical states. + 状態の履歴のリスト全体を取得します。 + + + + Get the latest state. + 最新の状態を取得します。 + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + 状態トラッカー クラスの 'int' インスタンス。型パラメーターは推論されていることに注意してください。 + + + + Add a state + 状態を追加します + + + + Interfaces are object types with only 'abstract' members. + インターフェイスは 'abstract' メンバーのみを持つオブジェクト型です。 + + + + Object types and object expressions can implement interfaces. + オブジェクト型とオブジェクト式はインターフェイスを実装できます。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + これは IDisposable を実装する型です。 + + + + This is the implementation of IDisposable members. + これは IDisposable メンバーの実装です。 + + + + This is an object that implements IDisposable via an Object Expression + これは、オブジェクト式を使用して IDisposable を実装するオブジェクトです + + + + Unlike other languages such as C# or Java, a new type definition is not needed + C# や Java などの他の言語とは異なり、インターフェイスを実装するために + + + + to implement an interface. + 新しい型定義は必要ありません。 + + + + The FSharp.Core library defines a range of parallel processing functions. Here + FSharp.Core ライブラリは並列処理関数の範囲を定義します。ここでは + + + + you use some functions for parallel processing over arrays. + アレイ全体で並列処理に対していくつかの関数を使用できます。 + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + 詳細については、次を参照してください: https://msdn.microsoft.com/ja-jp/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + まず、入力の配列です。 + + + + Next, define a functions that does some CPU intensive computation. + 次に、CPU 集約型の計算を実行する関数を定義します。 + + + + Next, do a parallel map over a large input array. + 次に、大きい入力配列に対して並列マップを実行します。 + + + + Next, print the results. + 次に、結果を印刷します。 + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + イベントは、特に WinForms または WPF アプリケーションでの .NET プログラミングの一般的な用法です。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + 詳細については、次を参照してください: https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + まず、サブスクリプション ポイント (event.Publish) およびイベント トリガー (event.Trigger) で構成されるイベント オブジェクトのインスタンスを作成します。 + + + + Next, add handler to the event. + 次に、ハンドラーをイベントに追加します。 + + + + Next, trigger the event. + 次に、イベントをトリガーします。 + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + 次に、標準的な .NET 表記規則に従うイベントのインスタンスを作成します: (sender, EventArgs)。 + + + + Next, add a handler for this new event. + 次に、この新しいイベントのハンドラーを追加します。 + + + + Next, trigger this event (note that sender argument should be set). + 次に、このイベントをトリガーします (sender 引数を設定する必要があります)。 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ko.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ko.xlf new file mode 100644 index 0000000000..7e8e4a4de4 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ko.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + 이 샘플에서는 F# 언어의 요소에 대해 안내합니다. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + F# 대화형에서 코드를 실행하려면 코드 섹션을 강조 표시하고 <Alt+Enter>를 누르거나 마우스 오른쪽 단추를 클릭한 다음 + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + "대화형으로 실행"을 선택하세요. "보기" 메뉴에서 F# 대화형 창을 열 수 있습니다. + + + + For more about F#, see: + F#에 대한 자세한 내용은 다음을 참조하세요. + + + + To see this tutorial in documentation form, see: + 이 자습서를 설명서 형식으로 보려면 다음을 참조하세요. + + + + To learn more about applied F# programming, use + 적용된 F# 프로그래밍에 대해 자세히 알아보려면 다음을 사용하세요. + + + + To install the Visual F# Power Tools, use + Visual F# Power 도구를 설치하려면 다음을 사용하세요. + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + '도구' --> '확장 및 업데이트' --> `온라인`으로 이동하고 검색합니다. + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + F#과 함께 사용할 수 있는 추가 템플릿은 Visual Studio의 다음 위치에서 '온라인 템플릿'을 참조하세요. + + + + 'New Project' --> 'Online Templates' + '새 프로젝트' --> '온라인 템플릿' + + + + F# supports three kinds of comments: + F#에서는 세 가지 종류의 주석을 지원합니다. + + + + 1. Double-slash comments. These are used in most situations. + 1. 이중 슬래시 주석은 대부분의 경우에 사용됩니다. + + + + 2. ML-style Block comments. These aren't used that often. + 2. ML 스타일 블록 주석은 자주 사용되지 않습니다. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. 삼중 슬래시 주석은 함수, 형식 등을 설명하는 경우에 사용됩니다. + + + + They will appear as text when you hover over something which is decorated with these comments. + 이러한 주석으로 데코레이트된 항목 위에 마우스를 올리면 텍스트로 표시됩니다. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + 참조 문서를 생성할 수 있는 .NET 스타일 XML 주석도 지원하며, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + 또한 편집기(예: Visual Studio)에서 정보를 추출할 수 있도록 합니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + 'open' 키워드를 사용하여 네임스페이스를 엽니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + 모듈은 값, 형식, 함수 값 같은 F# 코드의 그룹화입니다. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + 모듈로 코드를 그룹화하면 관련 코드를 함께 유지하고 프로그램에서 이름 충돌을 방지하는 데 도움이 됩니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + 샘플 정수입니다. + + + + This is a sample floating point number. + 샘플 부동 소수점 숫자입니다. + + + + This computed a new number by some arithmetic. Numeric types are converted using + 산술을 사용하여 새 수를 계산했습니다. 숫자 형식은 + + + + functions 'int', 'double' and so on. + 'int', 'double' 등의 함수를 사용하여 변환됩니다. + + + + This is a list of the numbers from 0 to 99. + 0에서 99까지의 숫자 목록입니다. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + 0에서 99까지의 모든 숫자와 제곱을 포함하는 모든 튜플 목록입니다. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + 다음 줄은 제네릭 출력에 대해 '%A'을(를) 사용하여 튜플을 포함하는 목록을 출력합니다. + + + + This is a sample integer with a type annotation + 형식 주석이 있는 샘플 정수입니다. + + + + Values in F# are immutable by default. They cannot be changed + F#의 값은 기본적으로 변경할 수 없습니다. 변경 가능으로 + + + + in the course of a program's execution unless explicitly marked as mutable. + 명시적으로 표시되지 않는 한 프로그램 실행 중 변경할 수 없습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + 'let'을 통해 값을 이름에 바인딩하면 값을 변경할 수 없게 됩니다. + + + + The second line of code fails to compile because 'number' is immutable and bound. + 'number'는 변경이 불가능하고 바인딩되어 있으므로 코드의 두 번째 줄이 컴파일되지 않습니다. + + + + Re-defining 'number' to be a different value is not allowed in F#. + F#에서는 'number'를 다른 값으로 다시 정의할 수 없습니다. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + 변경할 수 있는 바인딩은 'otherNumber' 값을 변경하기 위해 필요합니다. + + + + When mutating a value, use '<-' to assign a new value. + 값을 변경할 때는 '<-'를 사용하여 새 값을 할당하세요. + + + + You could not use '=' here for this purpose since it is used for equality + '='이 같음에 대해 사용되지 않으므로 여기에서 이 용도로 '='을 사용할 수 없습니다. + + + + or other contexts such as 'let' or 'module' + 또는 'let'이나 'module' 같은 기타 컨텍스트 + + + + Much of F# programming consists of defining functions that transform input data to produce + 대부분의 F# 프로그래밍은 유용한 결과를 생성하기 위해 입력 데이터를 변환하는 함수 정의로 + + + + useful results. + 구성됩니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + 'let'을 사용하여 정수 인수를 받고 정수를 반환하는 함수를 정의합니다. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + 괄호는 명시적 형식 주석을 사용하는 경우 외에는 함수 인수에 선택적으로 사용할 수 있습니다. + + + + Apply the function, naming the function return result using 'let'. + 함수를 적용하고, 'let'을 사용하여 함수 반환 결과에 이름을 지정합니다. + + + + The variable type is inferred from the function return type. + 변수 형식은 함수 반환 형식에서 유추됩니다. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + 이 줄은 '%d'을(를) 사용하여 결과를 integer로 인쇄합니다. 이 코드는 형식이 안전합니다. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + 'result1'이 'int' 형식이 아닌 경우 줄이 컴파일되지 않습니다. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + 필요한 경우 '(argument:type)'을 사용하여 매개 변수 이름 형식에 대한 주석을 답니다. 괄호가 필요합니다. + + + + Conditionals use if/then/elid/elif/else. + 조건은 if/then/elid/elif/else를 사용합니다. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + F#은 Python과 같은 언어처럼 공백 들여쓰기 인식 구문을 사용합니다. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + 이 줄은 '%f'을(를) 사용하여 결과를 float으로 인쇄합니다. 위의 '%d'처럼 이 코드는 형식이 안전합니다. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + 부울은 F#에서 기본적인 데이터 형식입니다. 다음은 부울 및 조건부 논리의 몇 가지 예입니다. + + + + To learn more, see: + 자세히 알아보려면 다음을 참조하세요. + + + + and + 그리고 + + + + Booleans values are 'true' and 'false'. + 부울 값은 'true' 및 'false'입니다. + + + + Operators on booleans are 'not', '&&' and '||'. + 부울의 연산자는 'not', '&&' 및 '||'입니다. + + + + This line uses '%b'to print a boolean value. This is type-safe. + 이 줄은 '%b'을(를) 사용하여 부울 값을 인쇄합니다. 이 코드는 형식이 안전합니다. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + 문자열은 F#에서 기본적인 데이터 형식입니다. 다음은 문자열 및 기본 문자열 조작의 몇 가지 예입니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + 문자열은 큰따옴표를 사용합니다. + + + + Strings can also use @ to create a verbatim string literal. + 또한 문자열은 @을 사용하여 축자 문자열 리터럴을 만듭니다. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + 이 경우 '\', '\n', '\t' 등과 같은 이스케이프 문자열을 무시합니다. + + + + String literals can also use triple-quotes. + 또한 문자열 리터럴은 세 따옴표를 사용합니다. + + + + String concatenation is normally done with the '+' operator. + 문자열 연결은 일반적으로 '+' 연산자로 합니다. + + + + This line uses '%s' to print a string value. This is type-safe. + 이 줄은 '%s'을(를) 사용하여 문자열 값을 인쇄합니다. 이 코드는 형식이 안전합니다. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + 부분 문자열은 인덱서 표기법을 사용합니다. 이 줄은 처음 7개 문자를 부분 문자열로 추출합니다. + + + + Note that like many languages, Strings are zero-indexed in F#. + 다른 여러 언어처럼 F#에서는 문자열이 0으로 인덱싱됩니다. + + + + Tuples are simple combinations of data values into a combined value. + 튜플은 데이터 값을 조합된 값으로 만드는 간단한 조합입니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + 단순한 정수 튜플입니다. + + + + A function that swaps the order of two values in a tuple. + 튜플에 있는 두 값의 순서를 바꾸는 함수입니다. + + + + F# Type Inference will automatically generalize the function to have a generic type, + F# 형식 유추에서는 자동으로 함수를 제너릭 형식으로 일반화하므로, + + + + meaning that it will work with any type. + 모든 형식에 사용할 수 있습니다. + + + + A tuple consisting of an integer, a string, + 정수, 문자열 및 배정밀도 부동 소수점 + + + + and a double-precision floating point number. + 숫자로 구성된 튜플입니다. + + + + A simple tuple of integers with a type annotation. + 형식 주석이 포함된 단순한 정수 튜플입니다. + + + + Type annotations for tuples use the * symbol to separate elements + 튜플에 대한 형식 주석은 * 기호를 사용하여 요소를 구분합니다. + + + + Tuples are normally objects, but they can also be represented as structs. + 튜플은 일반적으로 개체이지만 구조체로 나타낼 수도 있습니다. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + 이러한 구조체는 C# 및 Visual Basic.NET의 구조체와 완벽히 상호 운용되지만, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + 구조체 튜플은 개체 튜플(참조 튜플이라고도 함)로 암시적인 변환을 할 수 없습니다. + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + 이로써 아래 두 번째 줄은 컴파일되지 않으며 결과를 확인하려면 이 줄의 주석 처리를 제거하세요. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + 구조체 튜플과 참조 튜플 간을 암시적으로 변환할 수 없지만, + + + + you can explicitly convert via pattern matching, as demonstrated below. + 아래 설명된 것처럼 패턴 일치를 통해 명시적으로 변환할 수 있습니다. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + F# 파이프 연산자('|>', '<|' 등) 및 F# 합성 연산자('>>', '<<')는 + + + + are used extensively when processing data. These operators are themselves functions + 데이터를 처리할 때 광범위하게 사용됩니다. 이러한 연산자는 자체가 함수이며 + + + + which make use of Partial Application. + 부분 애플리케이션을 사용합니다. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + 이러한 연산자에 대해 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + 부분 애플리케이션에 대해 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + 값을 제곱합니다. + + + + Adds 1 to a value. + 값에 1을 더합니다. + + + + Tests if an integer value is odd via modulo. + 모듈로를 통해 정수 값이 홀수인지 테스트합니다. + + + + A list of 5 numbers. More on lists later. + 5개 숫자 목록입니다. 추가 숫자는 나중에 표시됩니다. + + + + Given a list of integers, it filters out the even numbers, + 정수 목록인 경우 짝수를 필터링하고, + + + + squares the resulting odds, and adds 1 to the squared odds. + 결과 홀수를 제곱하고 제곱한 홀수에 1을 더합니다. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + 'squareOddValuesAndAddOne'을 더 짧게 작성하려면 + + + + sub-result into the function calls themselves. + 각 하위 결과를 함수 호출 자체에 중첩합니다. + + + + This makes the function much shorter, but it's difficult to see the + 그러면 함수가 더 짧아지지만 데이터가 처리되는 순서를 + + + + order in which the data is processed. + 알아보기 어렵습니다. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + 'squareOddValuesAndAddOne'을 작성하려면 기본적으로 F# 파이프 연산자를 사용합니다. + + + + This allows you to avoid creating intermediate results, but is much more readable + 그러면 중간 결과를 생성하지 않아도 되며 + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + 'squareOddValuesAndAddOneNested'와 같이 함수 호출을 중첩할 때보다 읽기도 쉽습니다. + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + 'squareOddValuesAndAddOnePipeline'을 줄이려면 두 번째 `List.map` 호출을 + + + + into the first, using a Lambda Function. + 람다 함수를 사용하여 첫 번째로 이동합니다. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + 파이프라인은 람다 함수 내에도 사용됩니다. F# 파이프 연산자는 + + + + can be used for single values as well. This makes them very powerful for processing data. + 단일 값에도 사용할 수 있습니다. 따라서 데이터 처리에 매우 유용합니다. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + 마지막으로 명시적으로 'values'를 매개 변수로 사용할 필요가 없습니다. '>>'를 사용하여 + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + 짝수를 필터링한 다음 제곱하고 1을 더하는 두 가지 핵심 작업을 작성하면 됩니다. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + 마찬가지로 'fun x -> ...' 람다 식도 필요하지 않습니다. 'x'를 해당 범위에서 간단히 + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + 정의하여 함수 파이프라인에 전달할 수 있기 때문입니다. 따라서 여기에서도 '>>'를 + + + + there as well. + 사용할 수 있습니다. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + 'squareOddValuesAndAddOneComposition'의 결과 자체도 정수 목록을 입력으로 사용하는 + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + 다른 함수입니다. 'squareOddValuesAndAddOneComposition'을 정수 목록을 사용하여 + + + + of integers, you'll notice that it produces the same results as previous functions. + 실행하는 경우 이전 함수와 동일한 결과를 생성합니다. + + + + This is using what is known as function composition. This is possible because functions in F# + 여기서는 이른바 함수 컴퍼지션을 사용합니다. 이것이 가능한 이유는 F#의 함수가 + + + + use Partial Application and the input and output types of each data processing operation match + 부분 애플리케이션을 사용하고 각 데이터 처리 작업의 입력 및 출력 형식이 사용 중인 함수의 + + + + the signatures of the functions we're using. + 시그니처와 일치하기 때문입니다. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + 순서가 지정되고 변경 불가능한 단일 연결 목록으로 즉시 평가됩니다. + + + + This module shows various ways to generate lists and process lists with some functions + 이 모듈에서는 F# 주요 라이브러리의 'List' 모듈에 있는 일부 함수를 사용하여 목록을 생성하고 + + + + in the 'List' module in the F# Core Library. + 목록을 처리하는 다양한 방법을 보여 줍니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + 목록은 [ ... ]을 사용하여 정의됩니다. 이것은 빈 목록입니다. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + 3개 요소가 포함된 목록입니다. 동일한 줄에서 ';'을 사용하여 요소를 구분합니다. + + + + You can also separate elements by placing them on their own lines. + 요소를 다른 줄에 배치하여 요소를 구분할 수도 있습니다. + + + + This is a list of integers from 1 to 1000 + 이것은 1에서 1000까지의 정수 리스트입니다. + + + + Lists can also be generated by computations. This is a list containing + 리스트는 계산에 의해서도 생성될 수 있습니다. 다음은 + + + + all the days of the year. + 연중 모든 날짜를 포함하는 리스트입니다. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + 'daysList'의 처음 5개 요소를 'List.take'를 사용하여 인쇄합니다. + + + + Computations can include conditionals. This is a list containing the tuples + 계산은 조건을 포함할 수 있습니다. 다음은 + + + + which are the coordinates of the black squares on a chess board. + 체스 보드에서 검은색 칸의 좌표를 가리키는 튜플이 포함된 리스트입니다. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + 리스트는 'List.map' 및 기타 함수 프로그래밍 조합기를 사용하여 변환될 수 있습니다. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + 이 정의는 인수를 List.map으로 전달하기 위해 파이프라인 연산자를 사용하여 numberList의 숫자를 + + + + operator to pass an argument to List.map. + 제곱하여 새 리스트를 생성합니다. + + + + There are many other list combinations. The following computes the sum of the squares of the + 다른 리스트 조합이 많이 있습니다. 다음은 + + + + numbers divisible by 3. + 3으로 나눠지는 수의 제곱의 합을 계산합니다. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + 배열은 고정 크기이며 같은 형식의 요소로 구성된 변경 가능한 컬렉션입니다. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + 배열은 목록과 마찬가지로 열거형을 지원하고 데이터 처리를 위한 유사한 조합기를 사용하지만, + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + 배열은 일반적으로 더 빠르고 빠른 임의 액세스를 지원합니다. 변경이 가능하므로 덜 안전하다는 단점은 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + 빈 배열입니다. 목록의 구문과 유사하지만 `[| ... |]`을 대신 사용합니다. + + + + Arrays are specified using the same range of constructs as lists. + 배열은 리스트와 같은 범위의 구문을 사용하여 지정됩니다. + + + + This is an array of numbers from 1 to 1000. + 1에서 1000까지의 숫자 배열입니다. + + + + This is an array containing only the words "hello" and "world". + "hello"와 "world"라는 단어만 포함된 배열입니다. + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + 0에서 2000까지의 짝수가 포함되고 인덱스로 초기화된 배열입니다. + + + + Sub-arrays are extracted using slicing notation. + 하위 배열은 조각화 표기법을 사용하여 추출됩니다. + + + + You can loop over arrays and lists using 'for' loops. + 'for' 루프를 사용하여 배열 및 목록을 반복할 수 있습니다. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + 왼쪽 화살표 대입 연산자를 사용하여 배열 요소의 내용을 수정할 수 있습니다. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + 이 연산자에 대해 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + 'Array'map' 및 기타 함수 프로그래밍 연산을 사용하여 배열을 변환할 수 있습니다. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + 다음은 'h'로 시작하는 단어 길이의 합을 계산합니다. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + 시퀀스는 모두 형식이 같은 요소가 논리적으로 연속되는 것입니다. 목록 및 배열보다 일반적인 형식입니다. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + 시퀀스는 요청 시 계산되며 반복될 때마다 다시 계산됩니다. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + F# 시퀀스는 .NET System.Collections.Generic.IEnumerable<'T>의 별칭입니다. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + 시퀀스 처리 함수는 리스트와 배열 모두에 적용할 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + 빈 시퀀스입니다. + + + + This a sequence of values. + 시퀀스 값입니다. + + + + This is an on-demand sequence from 1 to 1000. + 1에서 1000까지의 요청 시 시퀀스입니다. + + + + This is a sequence producing the words "hello" and "world" + "hello"와 "world"라는 단어를 생성하는 시퀀스입니다. + + + + This sequence producing the even numbers up to 2000. + 2000까지의 짝수를 생성하는 시퀀스입니다. + + + + This is an infinite sequence which is a random walk. + 임의 행로인 무한 시퀀스입니다. + + + + This example uses yield! to return each element of a subsequence. + 이 예에서는 yield!를 사용하여 하위 시퀀스의 각 요소를 반환합니다. + + + + This example shows the first 100 elements of the random walk. + 이 예에서는 임의 행로의 처음 100개 요소를 보여 줍니다. + + + + Recursive functions can call themselves. In F#, functions are only recursive + 재귀 함수는 자신을 호출할 수 있습니다. F#에서 함수는 + + + + when declared using 'let rec'. + 'let rec'을 사용하여 선언할 때에만 반복됩니다. + + + + Recursion is the preferred way to process sequences or collections in F#. + 재귀는 F#에서 시퀀스 또는 컬렉션을 처리하는 기본 방법입니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + 자세히 알아보려면 https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions를 참조하세요. + + + + This example shows a recursive function that computes the factorial of an + 이 예에서는 정수의 계승을 계산하는 재귀 함수를 보여 줍니다. + + + + integer. It uses 'let rec' to define a recursive function. + 'let rec'를 사용하여 재귀 함수를 정의합니다. + + + + Computes the greatest common factor of two integers. + 두 정수의 최대 공약수를 계산합니다. + + + + Since all of the recursive calls are tail calls, + 모든 재귀 호출은 마무리 호출이므로, + + + + the compiler will turn the function into a loop, + 컴파일러에서는 함수를 루프로 전환합니다. + + + + which improves performance and reduces memory consumption. + 루프는 성능을 향상시키고 메모리 소비량을 줄여 줍니다. + + + + This example computes the sum of a list of integers using recursion. + 이 예제에서는 재귀를 사용하여 정수 목록의 합을 계산합니다. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + 도우미 함수와 결과 누적기를 사용하여 'sumList'를 마무리 재귀 함수로 만듭니다. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + '0'을 시드 누적기로 제공하여 마무리 재귀 도우미 함수를 호출합니다. + + + + An approach like this is common in F#. + F#에서 이와 같은 접근 방식이 일반적입니다. + + + + Records are an aggregate of named values, with optional members (such as methods). + 레코드는 명명된 값의 집계이며, 필요에 따라 메서드와 같은 선택적 멤버도 포함합니다. + + + + They are immutable and have structural equality semantics. + 레코드는 변경 불가능하며 구조적으로 같음 의미 체계가 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + 이 예에서는 새 레코드 형식을 정의하는 방법을 보여 줍니다. + + + + This example shows how to instantiate a record type. + 이 예제에서는 레코드 형식을 인스턴스화하는 방법을 보여 줍니다. + + + + You can also do this on the same line with ';' separators. + 동일한 줄에서 ';' 구분 기호를 사용하여 이 작업을 수행할 수도 있습니다. + + + + This example shows how to use "copy-and-update" on record values. It creates + 이 예에서는 레코드 값에 "copy-and-update"를 사용하는 방법을 보여 줍니다. + + + + a new record value that is a copy of contact1, but has different values for + contact1의 복사본인 새 레코드 값을 만들지만 + + + + the 'Phone' and 'Verified' fields. + 'Phone'과 'Verified' 필드의 값이 다릅니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + 이 예에서는 레코드 값을 처리하는 함수를 작성하는 방법을 보여 줍니다. + + + + It converts a 'ContactCard' object to a string. + 'ContactCard' 개체를 문자열로 변환합니다. + + + + This is an example of a Record with a member. + 멤버가 하나인 레코드의 예제입니다. + + + + Members can implement object-oriented members. + 멤버는 개체 지향 멤버를 구현할 수 있습니다. + + + + Members are accessed via the '.' operator on an instantiated type. + 인스턴스화된 형식에서 '.' 연산자를 통해 멤버에 액세스합니다. + + + + Records can also be represented as structs via the 'Struct' attribute. + 'Struct' 특성을 통해 레코드를 구조체로 나타낼 수도 있습니다. + + + + This is helpful in situations where the performance of structs outweighs + 구조체 성능이 참조 형식의 유연성보다 중요한 경우에 + + + + the flexibility of reference types. + 유용합니다. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + 구분된 공용 구조체(줄여서 DU)는 여러 명명된 폼 또는 케이스일 수 있는 값입니다. + + + + Data stored in DUs can be one of several distinct values. + DU에 저장된 데이터는 여러 고유한 값 중 하나일 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + 다음은 플레인 카드의 짝패를 나타냅니다. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + 구분된 공용 구조체를 사용하여 플레잉 카드의 순위를 나타낼 수도 있습니다. + + + + Represents the rank of cards 2 .. 10 + 카드 2부터 10까지의 순위를 나타냅니다. + + + + Discriminated Unions can also implement object-oriented members. + 구분된 공용 구조체는 개체 지향 멤버도 구현할 수 있습니다. + + + + This is a record type that combines a Suit and a Rank. + 짝패와 순위를 조합하는 레코드 형식입니다. + + + + It's common to use both Records and Disciminated Unions when representing data. + 일반적으로 레코드와 구분된 공용 구조체를 모두 사용하여 데이터를 나타냅니다. + + + + This computes a list representing all the cards in the deck. + 데크에 있는 모든 카드를 나타내는 목록을 계산합니다. + + + + This example converts a 'Card' object to a string. + 이 예에서는 'Card' 개체를 문자열로 변환합니다. + + + + This example prints all the cards in a playing deck. + 이 예에서는 플레잉 데크의 모든 카드를 인쇄합니다. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + 단일 케이스 DU를 도메인 모델링에 사용하는 경우가 많습니다. 그러면 문자열 및 정수와 같은 + + + + over primitive types such as strings and ints. + 기본 형식보다 형식 안전성을 추가로 얻을 수 있습니다. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + 단일 케이스 DU를 래핑하는 형식으로 암시적으로 변환하거나 반대로 변환할 수 없습니다. + + + + For example, a function which takes in an Address cannot accept a string as that input, + 예를 들어 주소에서 사용하는 함수는 문자열을 입력으로 사용할 수 없으며, + + + + or vive/versa. + 그 반대도 마찬가지입니다. + + + + You can easily instantiate a single-case DU as follows. + 다음과 같이 단일 케이스 DU를 쉽게 인스턴스화할 수 있습니다. + + + + When you need the value, you can unwrap the underlying value with a simple function. + 값이 필요하면 간단한 함수로 내부 값을 래핑 해제할 수 있습니다. + + + + Printing single-case DUs is simple with unwrapping functions. + 래핑 해제 함수로 단일 케이스 DU를 간단히 인쇄할 수 있습니다. + + + + Disciminated Unions also support recursive definitions. + 구분된 공용 구조체는 재귀 정의도 지원합니다. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + 이진 검색 트리를 나타냅니다. 여기서 한 케이스는 빈 트리이고 + + + + and the other being a Node with a value and two subtrees. + 다른 케이스는 값과 두 개의 하위 트리를 포함하는 노드입니다. + + + + Check if an item exists in the binary search tree. + 이진 검색 트리에 항목이 있는지 확인합니다. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + 패턴 일치를 사용하여 재귀적으로 검색합니다. 있으면 true를 반환하고 그렇지 않은 경우 false를 반환합니다. + + + + Check the left subtree. + 왼쪽 하위 트리를 확인합니다. + + + + Check the right subtree. + 오른쪽 하위 트리를 확인합니다. + + + + Inserts an item in the Binary Search Tree. + 이진 검색 트리에 항목을 삽입합니다. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + 패턴 일치를 사용하여 재귀적으로 삽입할 위치를 찾은 다음 새 노드를 삽입합니다. + + + + If the item is already present, it does not insert anything. + 항목이 이미 있으면 아무 항목도 삽입하지 않습니다. + + + + No need to insert, it already exists; return the node. + 이미 항목이 있으므로 삽입할 필요가 없습니다. 노드를 반환합니다. + + + + Call into left subtree. + 왼쪽 하위 트리를 호출합니다. + + + + Call into right subtree. + 오른쪽 하위 트리를 호출합니다. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + 'Struct' 특성을 통해 구분된 공용 구조체를 구조체로 나타낼 수도 있습니다. + + + + This is helpful in situations where the performance of structs outweighs + 구조체 성능이 참조 형식의 유연성보다 중요한 경우에 + + + + the flexibility of reference types. + 유용합니다. + + + + However, there are two important things to know when doing this: + 하지만 이 작업을 수행할 때는 다음 두 가지 중요한 사항을 알고 있어야 합니다. + + + + 1. A struct DU cannot be recursively-defined. + 1. 구조체 DU는 재귀적으로 정의할 수 없습니다. + + + + 2. A struct DU must have unique names for each of its cases. + 2. 각 케이스마다 구조체 DU의 이름이 고유해야 합니다. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + 패턴 일치는 패턴을 활용할 수 있는 F#의 기능이며, + + + + which are a way to compare data with a logical structure or structures, + 패턴을 사용하면 데이터를 논리 구조와 비교하거나, + + + + decompose data into constituent parts, or extract information from data in various ways. + 데이터를 구성 부분으로 분해하거나, 다양한 방법으로 데이터에서 정보를 추출할 수 있습니다. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + 그런 다음 패턴 일치를 사용하여 패턴의 "모양"을 디스패치할 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + 사람의 성과 이름에 대한 레코드입니다. + + + + A Discriminated Union of 3 different kinds of employees + 세 가지 다른 직원 유형이 있는 구분된 공용 구조체 + + + + Count everyone underneath the employee in the management hierarchy, + 관리 계층 구조에서 이 직원을 포함하여 이 아래에 있는 모든 직원의 수를 + + + + including the employee. + 셉니다. + + + + Find all managers/executives named "Dave" who do not have any reports. + 이름이 "Dave"이고 부하직원이 없는 모든 관리자/간부를 찾습니다. + + + + This uses the 'function' shorthand to as a lambda expression. + 여기서는 'function' 약어를 람다 식으로 사용합니다. + + + + [] matches an empty list. + []는 빈 목록과 일치합니다. + + + + '_' is a wildcard pattern that matches anything. + '_'는 모든 항목과 일치하는 와일드카드 패턴입니다. + + + + This handles the "or else" case. + 이 와일드카드 패턴은 "or else" 케이스를 처리합니다. + + + + You can also use the shorthand function construct for pattern matching, + 패턴 일치에 약어 형식 함수 구문을 사용할 수도 있습니다. + + + + which is useful when you're writing functions which make use of Partial Application. + 이 구문은 부분 애플리케이션을 사용하는 함수를 작성할 때 유용합니다. + + + + Define some more functions which parse with the helper function. + 도우미 함수를 사용하여 구문 분석하는 함수를 더 정의합니다. + + + + Active Patterns are another powerful construct to use with pattern matching. + 활성 패턴은 패턴 일치와 함께 사용하면 유용한 다른 구문입니다. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + 활성 패턴을 사용하면 입력 데이터를 사용자 지정 폼으로 분할하고, 패턴 일치 호출 사이트에서 이 폼을 분해할 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + 'function' 키워드 및 활성 패턴을 통한 패턴 일치는 이처럼 보이는 경우가 많습니다. + + + + Call the printer with some different values to parse. + 구문 분석할 다른 값을 사용하여 프린터를 호출합니다. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + 옵션 값에는 'Some' 또는 'None'으로 태그 처리된 모든 종류의 값을 사용할 수 있습니다. + + + + They are used extensively in F# code to represent the cases where many other + F# 코드에서 광범위하게 사용되어 다른 언어에서는 null 참조를 사용하는 케이스를 + + + + languages would use null references. + 나타냅니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + 먼저 단일 케이스 구분된 공용 구조체를 통해 정의된 우편 번호를 정의합니다. + + + + Next, define a type where the ZipCode is optional. + 다음으로 ZipCode가 선택 사항인 형식을 정의합니다. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + 그리고 고객의 우편 번호에 대한 배송 영역을 계산하기 위해 개체를 나타내는 인터페이스 형식을 정의합니다. + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + 고객의 우편 번호에 대한 쇼핑 지역을 계산하는 추상 클래스입니다. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + 다음으로 계산기 인스턴스를 사용하여 고객의 배송 영역을 계산합니다. + + + + This uses combinators in the Option module to allow a functional pipeline for + 여기서는 Option 모듈 내의 조합기를 사용하여 함수 파이프라인에서 + + + + transforming data with Optionals. + Optionals를 통해 데이터를 변환할 수 있게 합니다. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + 측정 단위를 사용하면 형식이 안전한 방식으로 기본 숫자 형식에 주석을 달 수 있습니다. + + + + You can then perform type-safe arithmetic on these values. + 그런 다음 이러한 값에 대해 형식이 안전한 산술 연산을 수행할 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + 먼저 일반적인 단위 이름의 컬렉션을 엽니다. + + + + Define a unitized constant + 결합된 상수 정의 + + + + Next, define a new unit type + 다음으로 새 단위 형식을 정의합니다. + + + + Conversion factor mile to meter. + 마일 대 미터 변환 비율입니다. + + + + Define a unitized constant + 결합된 상수 정의 + + + + Compute metric-system constant + 미터 단위 상수를 계산합니다. + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + 측정 단위를 사용하는 값은 인쇄와 같은 작업에 기본 숫자 형식처럼 사용할 수 있습니다. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + 클래스는 F#에서 새 개체 형식을 정의하는 방법이며 표준 개체 지향 구문을 지원합니다. + + + + They can have a variety of members (methods, properties, events, etc.) + 클래스는 다양한 멤버(메서드, 속성, 이벤트 등)를 포함할 수 있습니다. + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + 클래스에 대해 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + 멤버에 대해 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + 단순한 2차원 벡터 클래스입니다. + + + + The class's constructor is on the first line, + 클래스의 생성자는 첫 줄에 있고, + + + + and takes two arguments: dx and dy, both of type 'double'. + 'double' 형식의 두 인수 dx 및 dy를 사용합니다. + + + + This internal field stores the length of the vector, computed when the + 이 내부 필드는 개체가 생성될 때 계산된 벡터 길이를 + + + + object is constructed + 저장합니다. + + + + 'this' specifies a name for the object's self identifier. + 'this'는 개체 자체의 식별자에 대한 이름을 지정합니다. + + + + In instance methods, it must appear before the member name. + 인스턴스 메서드에서는 멤버 이름 앞에 와야 합니다. + + + + This member is a method. The previous members were properties. + 이 멤버는 메서드입니다. 이전 멤버는 속성이었습니다. + + + + This is how you instantiate the Vector2D class. + Vector2D 클래스를 인스턴스화하는 방법은 다음과 같습니다. + + + + Get a new scaled vector object, without modifying the original object. + 원래 개체를 수정하지 않고 비율이 조정된 새 벡터 개체를 가져옵니다. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + 제네릭 클래스를 통해 형식 매개변수 집합에 대해 형식을 정의할 수 있습니다. + + + + In the following, 'T is the type parameter for the class. + 다음에서 'T는 클래스의 형식 매개 변수입니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + 이 내부 필드는 목록에 상태를 저장합니다. + + + + Add a new element to the list of states. + 상태 리스트에 새 요소를 추가합니다. + + + + use the '<-' operator to mutate the value. + '<-' 연산자를 사용하여 값을 변경합니다. + + + + Get the entire list of historical states. + 기록 상태의 전체 목록을 가져옵니다. + + + + Get the latest state. + 최신 상태를 가져옵니다. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + 상태 추적기 클래스의 'int' 인스턴스입니다. 형식 매개 변수는 유추됩니다. + + + + Add a state + 상태를 추가합니다. + + + + Interfaces are object types with only 'abstract' members. + 인터페이스는 '추상' 멤버만 있는 개체 형식입니다. + + + + Object types and object expressions can implement interfaces. + 개체 형식 및 개체 식은 인터페이스를 구현할 수 있습니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + IDisposable를 구현하는 형식입니다. + + + + This is the implementation of IDisposable members. + IDisposable 멤버의 구현입니다. + + + + This is an object that implements IDisposable via an Object Expression + 개체 식을 통해 IDisposable을 구현하는 개체입니다. + + + + Unlike other languages such as C# or Java, a new type definition is not needed + C# 또는 Java와 같은 다른 언어와 달리 인터페이스를 구현하기 위해 새 형식 정의가 + + + + to implement an interface. + 필요하지 않습니다. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + FSharp.Core 라이브러리는 병렬 처리 함수 범위를 정의합니다. + + + + you use some functions for parallel processing over arrays. + 여기에서 배열에 대해 병렬 처리 함수를 사용합니다. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + 자세히 알아보려면 다음을 참조하세요. https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + 먼저 입력 배열입니다. + + + + Next, define a functions that does some CPU intensive computation. + 다음으로 CPU를 많이 사용하는 계산을 수행하는 함수를 정의합니다. + + + + Next, do a parallel map over a large input array. + 다음으로 큰 입력 배열에 대해 병렬 맵을 수행합니다. + + + + Next, print the results. + 다음으로 결과를 인쇄합니다. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + 이벤트는 특히 WinForms 또는 WPF 애플리케이션을 사용하는 .NET 프로그래밍에서 일반적으로 사용되는 말입니다. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + 자세히 알아보려면 다음을 참조하세요. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + 먼저 구독 지점(event.Publish)과 이벤트 트리거(event.Trigger)로 구성된 Event 개체의 인스턴스를 만듭니다. + + + + Next, add handler to the event. + 다음으로 이벤트에 처리기를 추가합니다. + + + + Next, trigger the event. + 다음으로 이벤트를 트리거합니다. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + 다음으로 표준 .NET 규칙(sender, EventArgs)을 따르는 Event의 인스턴스를 만듭니다. + + + + Next, add a handler for this new event. + 다음으로 이 새 이벤트에 대한 처리기를 추가합니다. + + + + Next, trigger this event (note that sender argument should be set). + 다음으로 이 이벤트를 트리거합니다(sender 인수를 설정해야 함). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pl.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pl.xlf new file mode 100644 index 0000000000..9ee0ae09ae --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pl.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Ten przykład zawiera opis elementów języka F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Aby wykonać kod w programie F# Interactive, zaznacz sekcję kodu i naciśnij kombinację klawiszy Alt-Enter lub kliknij prawym przyciskiem myszy, + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + a następnie wybierz opcję „Wykonaj w trybie interaktywnym”. Okno narzędzia F# Interactive można otworzyć z menu „Widok”. + + + + For more about F#, see: + Aby uzyskać więcej informacji o języku F#, zobacz: + + + + To see this tutorial in documentation form, see: + Aby wyświetlić ten samouczek w formie dokumentacji, zobacz: + + + + To learn more about applied F# programming, use + Aby dowiedzieć się więcej o programowaniu w języku F# w praktyce, użyj + + + + To install the Visual F# Power Tools, use + Aby zainstalować narzędzia Visual F# Power Tools, użyj + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + „Narzędzia” --> „Rozszerzenia i aktualizacje” --> „Online” i wyszukaj + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Aby uzyskać informacje o dodatkowych szablonach do użycia w języku F#, zobacz sekcję dotyczącą szablonów w trybie online w programie Visual Studio, + + + + 'New Project' --> 'Online Templates' + „Nowy projekt” --> „Szablony w trybie online” + + + + F# supports three kinds of comments: + Język F# obsługuje trzy rodzaje komentarzy: + + + + 1. Double-slash comments. These are used in most situations. + 1. Komentarze z podwójnym ukośnikiem. Są używane w większości sytuacji. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Komentarze blokowe w stylu ML. Nie są używane zbyt często. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Komentarze z potrójnymi ukośnikami. Są używane do dokumentowania funkcji, typów itd. + + + + They will appear as text when you hover over something which is decorated with these comments. + Będą wyświetlane jako tekst po zatrzymaniu wskaźnika myszy nad tym, do czego zostały dodane. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Obsługują także komentarze XML w stylu programu .NET, które pozwalają na generowanie dokumentacji referencyjnej, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + a także umożliwiają edytorom (takim jak program Visual Studio) na wydobywanie z nich informacji. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Aby dowiedzieć się więcej, zobacz: https://docs.microsoft.com/pl-pl/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Otwieraj przestrzenie nazw, używając słowa kluczowego „open”. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Aby dowiedzieć się więcej, zobacz: https://docs.microsoft.com/pl-pl/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Moduł to zbiór kodu w języku F#, takiego jak wartości, typy i wartości funkcji. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Grupowanie kodu w modułach pomaga trzymać razem powiązany kod i unikać konfliktów nazw w programie. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/pl-pl/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + To jest przykładowa liczba całkowita. + + + + This is a sample floating point number. + To jest przykładowa liczba zmiennoprzecinkowa. + + + + This computed a new number by some arithmetic. Numeric types are converted using + To obliczyło nową liczbę, wykonując pewne operacje arytmetyczne. Typy liczbowe są konwertowane za pomocą + + + + functions 'int', 'double' and so on. + funkcji „int”, „double” itd. + + + + This is a list of the numbers from 0 to 99. + To jest lista liczb od 0 do 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + To jest lista wszystkich krotek zawierających wszystkie liczby od 0 do 99 i ich kwadraty. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + Następny wiersz wyświetla listę z krotkami, używając symbolu „%A” do wyświetlania ogólnego. + + + + This is a sample integer with a type annotation + To jest przykładowa liczba całkowita z adnotacją typu + + + + Values in F# are immutable by default. They cannot be changed + Wartości w języku F# są domyślnie niezmienialne. Nie można ich modyfikować + + + + in the course of a program's execution unless explicitly marked as mutable. + w trakcie wykonywania programu, chyba że zostaną jawnie oznaczone jako zmienialne. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Powiązanie wartości z nazwą za pomocą polecenia „let” sprawia, że będzie ona niezmienna. + + + + The second line of code fails to compile because 'number' is immutable and bound. + Nie można skompilować drugiego wiersza kodu, ponieważ element „number” jest niezmienny i powiązany. + + + + Re-defining 'number' to be a different value is not allowed in F#. + Ponowne definiowanie elementu „number” na inną wartość nie jest dozwolone w języku F#. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Modyfikowalne powiązanie. Jest to wymagane w celu modyfikowania wartości elementu „otherNumber”. + + + + When mutating a value, use '<-' to assign a new value. + Podczas modyfikowania wartości użyj strzałki „<-”, aby przydzielić nową wartość. + + + + You could not use '=' here for this purpose since it is used for equality + Nie możesz w tym celu użyć tutaj znaku „=”, ponieważ jest on używany do oznaczania równości + + + + or other contexts such as 'let' or 'module' + lub innych kontekstów, np. „let” lub „module” + + + + Much of F# programming consists of defining functions that transform input data to produce + Duża część programowania w języku F# to definiowanie funkcji, które przekształcają dane wejściowe w celu utworzenia + + + + useful results. + przydatne wyniki. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Polecenia „let” używa się do definiowania funkcji. To polecenie akceptuje argument w postaci liczby całkowitej i zwraca liczbę całkowitą. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Nawiasy są opcjonalne w przypadku argumentów funkcji, z wyjątkiem użycia jawnego typu adnotacji. + + + + Apply the function, naming the function return result using 'let'. + Zastosuj funkcję i nadaj jej wynikowi zwrotnemu nazwę, używając instrukcji „let”. + + + + The variable type is inferred from the function return type. + Typ zmiennej jest wywnioskowany na podstawie zwracanego typu funkcji. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Ten wiersz używa elementu „%d”, aby wydrukować wynik jako liczbę całkowitą. Jest to bezpieczne. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Jeśli element „result1” nie miałby typu „int”, kompilacja wiersza zakończyłaby się niepowodzeniem. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + W razie potrzeby adnotuj typ nazwy parametru przy użyciu polecenia „(argument:typ)”. Nawiasy są wymagane. + + + + Conditionals use if/then/elid/elif/else. + Wyrażenia warunkowe używają słów kluczowych if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Należy zauważyć, że język F# używa składni uwzględniającej wcięcia w postaci odstępów, tak jak w przypadku języków podobnych do języka Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Ten wiersz używa elementu „%f”, aby wydrukować wynik jako liczbę zmiennoprzecinkową. Podobnie jak w przypadku elementu „%d” powyżej jest to bezpieczne. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Wartości logiczne są fundamentalnymi typami danych w języku F#. Oto kilka przykładów wartości logicznych i logiki warunkowej. + + + + To learn more, see: + Aby dowiedzieć się więcej, zobacz: + + + + and + oraz + + + + Booleans values are 'true' and 'false'. + Wartości logiczne przyjmują wartość „true” i „false”. + + + + Operators on booleans are 'not', '&&' and '||'. + Operatory wartości logicznych to „not”, „&&” i „||”. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Ten wiersz używa elementu „%b”, aby wydrukować wartość logiczną. Jest to bezpieczne. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Ciągi są fundamentalnymi typami danych w języku F#. Oto kilka przykładów ciągów i podstawowych manipulacji ciągami. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Ciągi używają cudzysłowów. + + + + Strings can also use @ to create a verbatim string literal. + W ciągach można także używać znaku @ do tworzenia dosłownych literałów ciągu. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Spowoduje to ignorowanie znaków ucieczki, np. „\”, „\n”, „\t” itp. + + + + String literals can also use triple-quotes. + Literały ciągu mogą także używać potrójnych cudzysłowów. + + + + String concatenation is normally done with the '+' operator. + Łączenie ciągów wykonuje się zazwyczaj przy użyciu operatora „+”. + + + + This line uses '%s' to print a string value. This is type-safe. + Ten wiersz używa elementu „%s”, aby wydrukować wartość ciągu. Jest to bezpieczne. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Podciągi używają notacji indeksatora. Ten wiersz wyodrębnia pierwsze 7 znaków w formie podciągu. + + + + Note that like many languages, Strings are zero-indexed in F#. + Należy zauważyć, że w języku F# ciągi znaków są indeksowane od zera, podobnie jak w wielu innych językach. + + + + Tuples are simple combinations of data values into a combined value. + Krotki to proste kombinacje wartości danych tworzące połączoną wartość. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Prosta krotka liczb całkowitych. + + + + A function that swaps the order of two values in a tuple. + Funkcja zamieniająca kolejność dwóch wartości w krotce. + + + + F# Type Inference will automatically generalize the function to have a generic type, + Wnioskowanie o typie języka F# będzie automatycznie uogólniać funkcję do typu ogólnego, + + + + meaning that it will work with any type. + co oznacza, że będzie działać z dowolnym typem. + + + + A tuple consisting of an integer, a string, + Krotka składająca się z liczby całkowitej, ciągu + + + + and a double-precision floating point number. + i liczby zmiennoprzecinkowej podwójnej precyzji. + + + + A simple tuple of integers with a type annotation. + Prosta krotka składająca się z liczb całkowitych z adnotacją typu. + + + + Type annotations for tuples use the * symbol to separate elements + Adnotacje typu w krotkach korzystają z symbolu * do oddzielania elementów + + + + Tuples are normally objects, but they can also be represented as structs. + Krotki są zazwyczaj obiektami, niemniej mogą być również reprezentowane w formie struktur. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Całkowicie współpracują ze strukturami w języku C# i Visual Basic.NET; niemniej + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + krotki w formie struktur nie mogą być niejawnie konwertowane na krotki w formie obiektów (często zwane krotkami odwołań). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + Z tego powodu nie będzie można skompilować drugiego wiersza poniżej. Usuń komentarz z tego wiersza, aby zobaczyć, co się stanie. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Mimo że nie możesz przeprowadzać niejawnej konwersji między krotkami struktury i krotkami odwołania, + + + + you can explicitly convert via pattern matching, as demonstrated below. + możesz konwertować jawnie za pośrednictwem dopasowywania do wzorców, jak pokazano poniżej. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Operatory potoków języka F# („|>”, „<|” itp.) oraz operatory kompozycji języka F# („>>”, „<<”) + + + + are used extensively when processing data. These operators are themselves functions + są często używane podczas przetwarzania danych. Operatory te są funkcjami + + + + which make use of Partial Application. + wykorzystującymi częściową aplikację. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Aby dowiedzieć się więcej o tych operatorach, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Aby dowiedzieć się więcej o częściowej aplikacji, zobacz: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Podnosi wartość do potęgi drugiej. + + + + Adds 1 to a value. + Dodaje 1 do wartości. + + + + Tests if an integer value is odd via modulo. + Sprawdza, czy wartość liczby całkowitej jest nieparzysta za pomocą operacji modulo. + + + + A list of 5 numbers. More on lists later. + Lista 5 liczb. Więcej informacji na temat list znajduje się dalej. + + + + Given a list of integers, it filters out the even numbers, + W oparciu o podaną listę liczb całkowitych funkcja filtruje liczby parzyste, + + + + squares the resulting odds, and adds 1 to the squared odds. + podnosi nieparzyste wyniki do potęgi drugiej, a następnie dodaje 1 do podniesionych do potęgi drugiej liczb nieparzystych. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Krótszym sposobem zapisu „squareOddValuesAndAddOne” jest zagnieżdżenie każdego + + + + sub-result into the function calls themselves. + wyniku podrzędnego w samych wywołaniach funkcji. + + + + This makes the function much shorter, but it's difficult to see the + Dzięki temu funkcja będzie znacznie krótsza, ale trudno będzie zobaczyć + + + + order in which the data is processed. + kolejność przetwarzania danych. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Preferowanym sposobem zapisu funkcji „squareOddValuesAndAddOne” jest użycie operatorów potoków języka F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + Dzięki temu unika się tworzenia wyników pośrednich, a całość jest znacznie bardziej czytelna + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + niż w przypadku zagnieżdżania wywołań funkcji, np. „squareOddValuesAndAddOneNested” + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + Możesz skrócić wywołanie „squareOddValuesAndAddOnePipeline” przez przeniesienie drugiego wywołania „List.map” + + + + into the first, using a Lambda Function. + do pierwszego, korzystając z funkcji lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Należy zauważyć, że potoki są również używane w funkcji lambda. Operatorów potoków języka F# + + + + can be used for single values as well. This makes them very powerful for processing data. + można również użyć w przypadku pojedynczych wartości. Dzięki temu jest to bardzo zaawansowane narzędzie do przetwarzania danych. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + W końcu możesz wyeliminować potrzebę jawnego przyjmowania elementu „values” jako parametru, używając wyrażenia „>>”, + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + aby zredagować dwie kluczowe operacje: odfiltrowywanie liczb parzystych, a następnie podnoszenie do potęgi drugiej i dodawanie jedynki. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Podobnie fragment „fun x -> ...” wyrażenia lambda nie jest wymagany, ponieważ wartość „x” jest po prostu + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + definiowana w tym zakresie w celu przekazania do potoku funkcyjnego. Dlatego można również użyć wyrażenia „>>” + + + + there as well. + w tym miejscu. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Wynikiem funkcji „squareOddValuesAndAddOneComposition” jest inna funkcja, która przyjmuje + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + listę liczb całkowitych w formie danych wejściowych. Jeśli wykonasz funkcję „squareOddValuesAndAddOneComposition” z listą + + + + of integers, you'll notice that it produces the same results as previous functions. + liczb całkowitych, funkcja będzie podawać takie same wyniki jak poprzednie funkcje. + + + + This is using what is known as function composition. This is possible because functions in F# + Używa się tu kompozycji funkcji. Jest to możliwe, ponieważ funkcje w języku F# + + + + use Partial Application and the input and output types of each data processing operation match + używają częściowej aplikacji, a typy danych wejściowych i wyjściowych dla każdej operacji przetwarzania danych są dopasowane do + + + + the signatures of the functions we're using. + podpisów funkcji, których używamy. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Listy są uporządkowane, niezmienne i jednokierunkowe. Są wartościowane przed przetworzeniem. + + + + This module shows various ways to generate lists and process lists with some functions + Ten moduł pokazuje różne sposoby generowania list i ich przetwarzania przy użyciu niektórych funkcji + + + + in the 'List' module in the F# Core Library. + w module „Lista” w bibliotece podstawowej języka F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Aby dowiedzieć się więcej, zobacz: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Listy definiuje się za pomocą zapisu [ ... ]. To jest pusta lista. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Jest to lista z 3 elementami. Znak „;” oddziela elementy w tym samym wierszu. + + + + You can also separate elements by placing them on their own lines. + Możesz również oddzielić elementy przez umieszczenie ich w osobnych wierszach. + + + + This is a list of integers from 1 to 1000 + To jest lista liczb całkowitych z zakresu od 1 do 1000 + + + + Lists can also be generated by computations. This is a list containing + Listy można także generować za pomocą obliczeń. To jest lista zawierająca + + + + all the days of the year. + wszystkie dni roku. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Wydrukuj 5 pierwszych elementów listy „daysList” przy użyciu wyrażenia „List.take”. + + + + Computations can include conditionals. This is a list containing the tuples + Obliczenia mogą obejmować wyrażenia warunkowe. To jest lista zawierająca krotki + + + + which are the coordinates of the black squares on a chess board. + które są współrzędnymi czarnych kwadratów na szachownicy. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Listy można przekształcać za pomocą elementu „List.map” i innych kombinatorów programowania funkcjonalnego. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Ta definicja umożliwia utworzenie nowej listy przez podniesienie do kwadratu elementów na liście numberList za pomocą potoku + + + + operator to pass an argument to List.map. + operatora, aby przekazać argument do elementu List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Istnieje wiele innych kombinacji listy. Następujący kod oblicza sumę kwadratów + + + + numbers divisible by 3. + liczby podzielne przez 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Tablice to zmienialne kolekcje o stałym rozmiarze, w których zawierają się elementy tego samego typu. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Chociaż są podobne do list (obsługują wyliczenia i mają podobne kombinatory przetwarzania danych), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + ogólnie są szybsze i obsługują szybki dostęp losowy. Niemniej oznacza to mniejsze bezpieczeństwo związane z możliwością ich modyfikacji. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + To jest pusta tablica. Należy zauważyć, że składnia jest podobna do składni list, ale tutaj używa się zapisu „[| ... |]”. + + + + Arrays are specified using the same range of constructs as lists. + Tablice określa się za pomocą tego samego zestawu konstrukcji co listy. + + + + This is an array of numbers from 1 to 1000. + To jest tablica liczb z zakresu od 1 do 1000. + + + + This is an array containing only the words "hello" and "world". + To jest tablica zawierająca tylko słowa „hello” i „world”. + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + To jest tablica zainicjowana za pomocą indeksu i zawierająca liczby parzyste z zakresu od 0 do 2000. + + + + Sub-arrays are extracted using slicing notation. + Tablice podrzędne wyodrębnia się za pomocą notacji wycinania. + + + + You can loop over arrays and lists using 'for' loops. + Możesz zapętlić tablice i listy przy użyciu pętli „for”. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Możesz zmodyfikować zawartość elementu tablicy za pomocą operatora przypisania „strzałka w lewo”. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Aby dowiedzieć się więcej o tym operatorze, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Możesz przekształcić tablice za pomocą operacji „Array.map” i innych operacji programowania funkcjonalnego. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Następujący kod oblicza sumę długości słów zaczynających się od litery „h”. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Sekwencje są logicznymi seriami elementów tego samego typu. Jest to typ bardziej ogólny niż listy i tablice. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Sekwencje są sprawdzane na żądanie, a ich ponowne sprawdzenie następuje za każdym razem, gdy są one iterowane. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Sekwencja języka F# jest aliasem dla elementu .NET System.Collections.Generic.IEnumerable<'T>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Funkcje przetwarzania sekwencji można także zastosować dla list i tablic. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + To jest pusta sekwencja. + + + + This a sequence of values. + To jest sekwencja wartości. + + + + This is an on-demand sequence from 1 to 1000. + To jest sekwencja na żądanie zawierająca liczby od 1 do 1000. + + + + This is a sequence producing the words "hello" and "world" + To jest sekwencja generująca słowa „hello” i „world” + + + + This sequence producing the even numbers up to 2000. + Ta sekwencja generuje numery parzyste nie większe niż 2000. + + + + This is an infinite sequence which is a random walk. + To jest nieskończona sekwencja stanowiąca losowe przechodzenie. + + + + This example uses yield! to return each element of a subsequence. + W tym przykładzie użyto instrukcji yield! do zwrócenia każdego elementu sekwencji podrzędnej. + + + + This example shows the first 100 elements of the random walk. + Ten przykład przedstawia pierwszych 100 elementów losowego przechodzenia. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Funkcje rekursywne mogą wywoływać same siebie. W języku F# funkcje to jedyne rekursywne + + + + when declared using 'let rec'. + w przypadku deklarowania przy użyciu wyrażenia „let rec”. + + + + Recursion is the preferred way to process sequences or collections in F#. + Rekursja jest preferowanym sposobem przetwarzania sekwencji lub kolekcji w języku F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Ten przykład przedstawia funkcję rekursywną, która oblicza silnię + + + + integer. It uses 'let rec' to define a recursive function. + liczba całkowita. Używa deklaratora „let rec” do zdefiniowania funkcji rekursywnej. + + + + Computes the greatest common factor of two integers. + Oblicza największy wspólny dzielnik dwóch liczb całkowitych. + + + + Since all of the recursive calls are tail calls, + Jako że wszystkie wywołania rekurencyjne są wywołaniami ogonowymi, + + + + the compiler will turn the function into a loop, + kompilator zamieni funkcję w pętlę, + + + + which improves performance and reduces memory consumption. + która umożliwi zwiększenie wydajności i zmniejszenie zużycia pamięci. + + + + This example computes the sum of a list of integers using recursion. + Ten przykład oblicza sumę listy liczb całkowitych przy użyciu rekursji. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Operacja zamieni listę „sumList” w listę z rekursją ogonową przy użyciu funkcji pomocniczej z akumulatorem wyników. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Spowoduje to wywołanie funkcji pomocniczej z rekursją ogonową, z wartością „0” jako akumulatorem początkowym. + + + + An approach like this is common in F#. + Takie podejście jest typowe dla języka F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Rekordy są agregacjami nazwanych wartości z opcjonalnymi elementami członkowskimi (np. metodami). + + + + They are immutable and have structural equality semantics. + Są niezmienne i mają semantykę równości strukturalnej. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Ten przykład przedstawia sposób definiowania nowego typu rekordu. + + + + This example shows how to instantiate a record type. + W tym przykładzie pokazano sposób tworzenia wystąpienia typu rekordu. + + + + You can also do this on the same line with ';' separators. + Możesz to również zrobić w tym samym wierszu, korzystając z separatorów „;”. + + + + This example shows how to use "copy-and-update" on record values. It creates + Ten przykład przedstawia sposób użycia operacji „kopiuj i aktualizuj” na wartościach rekordu. Tworzy + + + + a new record value that is a copy of contact1, but has different values for + nową wartość rekordu, która jest kopią elementu contact1, lecz ma inne wartości dla + + + + the 'Phone' and 'Verified' fields. + pola „Phone” i „Verified”. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Ten przykład przedstawia, jak napisać funkcję przetwarzającą wartość rekordu. + + + + It converts a 'ContactCard' object to a string. + Konwertuje obiekt „ContactCard” na ciąg. + + + + This is an example of a Record with a member. + Jest to przykład rekordu z elementem członkowskim. + + + + Members can implement object-oriented members. + Elementy członkowskie mogą implementować elementy członkowskie zorientowane obiektowo. + + + + Members are accessed via the '.' operator on an instantiated type. + Do elementów członkowskich uzyskuje się dostęp za pośrednictwem operatora „.” w typie skonkretyzowanym. + + + + Records can also be represented as structs via the 'Struct' attribute. + Rekordy można również reprezentować jako struktury za pośrednictwem atrybutu „Struct”. + + + + This is helpful in situations where the performance of structs outweighs + Jest to przydatne w sytuacjach, w których wydajność struktur przewyższa + + + + the flexibility of reference types. + elastyczność typów odwołań. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Unie rozłączne (DU, Discriminated Union) są wartościami, które mogą być liczbą nazwanych formularzy lub przypadków. + + + + Data stored in DUs can be one of several distinct values. + Dane przechowywane w uniach rozłącznych mogą mieć jedną z kilku różnych wartości. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + Następująca wartość reprezentuje kolor karty do gry. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Unii rozłącznej można również użyć do reprezentowania wartości karty do gry. + + + + Represents the rank of cards 2 .. 10 + Reprezentuje wartości kart 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + Unie rozłączne mogą również implementować elementy członkowskie zorientowane obiektowo. + + + + This is a record type that combines a Suit and a Rank. + To jest typ rekordu łączący kolor i wysokość. + + + + It's common to use both Records and Disciminated Unions when representing data. + Często używa się rekordów i unii rozłącznych w przypadku reprezentowania danych. + + + + This computes a list representing all the cards in the deck. + Operacja oblicza listę reprezentującą wszystkie karty w talii. + + + + This example converts a 'Card' object to a string. + Ten przykład umożliwia przekonwertowanie elementu „Card” na ciąg. + + + + This example prints all the cards in a playing deck. + Ten przykład umożliwia wyświetlenie wszystkich kart w talii. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Unie rozłączne o pojedynczych przypadkach są często używane podczas modelowania domeny. Może to zapewnić większe bezpieczeństwo typów + + + + over primitive types such as strings and ints. + niż typy pierwotne, np. ciągi i liczby całkowite. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Unie rozłączne o pojedynczych przypadkach nie mogą być niejawnie konwertowane do lub z typu przez nich opakowywanego. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Przykładowo funkcja przyjmująca adres nie może zaakceptować ciągu jako danych wejściowych + + + + or vive/versa. + i na odwrót. + + + + You can easily instantiate a single-case DU as follows. + Możesz z łatwością utworzyć wystąpienie dla unii rozłącznej o pojedynczym przypadku w następujący sposób. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Jeśli potrzebujesz wartości, możesz cofnąć opakowywanie wartości bazowej za pomocą prostej funkcji. + + + + Printing single-case DUs is simple with unwrapping functions. + Drukowanie unii rozłącznych o pojedynczych przypadkach jest proste z funkcjami cofającymi opakowywanie. + + + + Disciminated Unions also support recursive definitions. + Unie rozłączne obsługują również definicje rekursywne. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Reprezentuje to binarne drzewo wyszukiwania, gdzie jeden przypadek jest pustym drzewem, + + + + and the other being a Node with a value and two subtrees. + a drugi węzłem z wartością i dwoma poddrzewami. + + + + Check if an item exists in the binary search tree. + Sprawdź, czy element istnieje w binarnym drzewie wyszukiwania. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Wyszukuje rekursywnie przy użyciu dopasowywania wzorca. Zwraca wartość true, jeśli element istnieje; w przeciwnym wypadku zwraca wartość false. + + + + Check the left subtree. + Sprawdź lewe poddrzewo. + + + + Check the right subtree. + Sprawdź prawe poddrzewo. + + + + Inserts an item in the Binary Search Tree. + Wstawia element do binarnego drzewa wyszukiwania. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Znajduje miejsce do wstawienia rekursywnego przy użyciu dopasowania wzorca, a następnie wstawia nowy węzeł. + + + + If the item is already present, it does not insert anything. + Jeśli element jest już obecny, nie wstawia niczego. + + + + No need to insert, it already exists; return the node. + Wstawianie nie jest konieczne, element już istnieje; zwróć węzeł. + + + + Call into left subtree. + Wywołanie do lewego poddrzewa. + + + + Call into right subtree. + Wywołanie do prawego poddrzewa. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Unie rozłączne mogą być również reprezentowane w formie struktur za pośrednictwem atrybutu „Struct”. + + + + This is helpful in situations where the performance of structs outweighs + Jest to przydatne w sytuacjach, w których wydajność struktur przewyższa + + + + the flexibility of reference types. + elastyczność typów odwołań. + + + + However, there are two important things to know when doing this: + Niemniej w przypadku tej operacji należy pamiętać o dwóch ważnych rzeczach: + + + + 1. A struct DU cannot be recursively-defined. + 1. Unii rozłącznej w formie struktury nie można zdefiniować rekursywnie. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Unia rozłączna w formie struktury musi mieć unikatowe nazwy dla każdego ze swoich przypadków. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Dopasowywanie wzorca jest funkcją języka F# umożliwiającą wykorzystywanie wzorców, + + + + which are a way to compare data with a logical structure or structures, + które są sposobem na porównywanie danych ze strukturami logicznymi lub strukturami, + + + + decompose data into constituent parts, or extract information from data in various ways. + rozkładanie danych na części składowe lub wyodrębnianie informacji z danych na różne sposoby. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Następnie możesz wysłać „kształt” wzorca za pośrednictwem funkcji dopasowywania wzorca. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Rekord zawierający imię i nazwisko osoby + + + + A Discriminated Union of 3 different kinds of employees + Unia rozłączna 3 różnych rodzajów pracowników + + + + Count everyone underneath the employee in the management hierarchy, + Licz wszystkich podlegających pracownikowi w hierarchii zarządzania, + + + + including the employee. + z uwzględnieniem pracownika. + + + + Find all managers/executives named "Dave" who do not have any reports. + Znajdź wszystkich kierowników/dyrektorów o imieniu „Dave”, którzy nie mają żadnych podwładnych. + + + + This uses the 'function' shorthand to as a lambda expression. + Operacja używa skrótu słowa „function” jako wyrażenia lambda. + + + + [] matches an empty list. + [] dopasuje pustą listę. + + + + '_' is a wildcard pattern that matches anything. + „_” to wzorzec wieloznaczny, który pasuje do wszystkiego. + + + + This handles the "or else" case. + Obsługuje przypadek „w przeciwnym razie”. + + + + You can also use the shorthand function construct for pattern matching, + Możesz również użyć konstrukcji funkcji skrótu w przypadku dopasowywania wzorców, + + + + which is useful when you're writing functions which make use of Partial Application. + co jest przydatne podczas pisania funkcji wykorzystujących częściową aplikację. + + + + Define some more functions which parse with the helper function. + Zdefiniuj więcej funkcji, które będą analizować przy użyciu funkcji pomocniczej. + + + + Active Patterns are another powerful construct to use with pattern matching. + Wzorce aktywne to kolejna zaawansowana konstrukcja do zastosowania podczas dopasowywania wzorców. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Umożliwiają one partycjonowanie danych wejściowych do formularzy niestandardowych przez ich rozkładanie w lokacji wywołania dopasowania wzorca. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Dopasowywanie wzorców za pośrednictwem słowa kluczowego „function” i wzorców aktywnych często wygląda w następujący sposób. + + + + Call the printer with some different values to parse. + Wywołaj drukarkę za pomocą innych wartości do przeanalizowania. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Wartości opcji to dowolne wartości otagowane jako „Some” lub „None”. + + + + They are used extensively in F# code to represent the cases where many other + Są one bardzo często używane w kodzie języka F# do reprezentowania przypadków, w których w wielu innych + + + + languages would use null references. + językach użyte zostałyby odwołania o wartości null. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Najpierw zdefiniuj kod pocztowy zdefiniowany za pośrednictwem unii rozłącznej o pojedynczym przypadku. + + + + Next, define a type where the ZipCode is optional. + Następnie zdefiniuj typ, w którym element ZipCode jest opcjonalny. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Następnie zdefiniuj typ interfejsu reprezentujący obiekt, aby obliczyć strefę wysyłki dla kodu pocztowego klienta + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + przy użyciu danych implementacji metod abstrakcyjnych „getState” i „getShippingZone”. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Następnie oblicz strefę wysyłki dla klienta za pomocą wystąpienia kalkulatora. + + + + This uses combinators in the Option module to allow a functional pipeline for + Operacja używa kombinatorów w module opcji, aby umożliwiać potokowi funkcjonalnemu + + + + transforming data with Optionals. + przekształcanie danych z wykorzystaniem elementów opcjonalnych. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Jednostki miary są bezpiecznym sposobem dodawania adnotacji do pierwotnych typów numerycznych. + + + + You can then perform type-safe arithmetic on these values. + Następnie możesz przeprowadzić bezpieczne operacje arytmetyczne dla tych wartości. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Najpierw otwórz kolekcję typowych nazw jednostek + + + + Define a unitized constant + Definiuj stałą w jednostkach + + + + Next, define a new unit type + Następnie zdefiniuj nowy typ jednostki + + + + Conversion factor mile to meter. + Współczynnik konwersji mil na metry. + + + + Define a unitized constant + Definiuj stałą w jednostkach + + + + Compute metric-system constant + Oblicz stałą systemu metryk + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Wartości używające jednostek miary można dostosować tak jak pierwotny typ numeryczny, np. w przypadku drukowania. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Klasy są sposobem definiowania nowych typów obiektów w języku F# i obsługują standardowe konstrukcje zorientowane obiektowo. + + + + They can have a variety of members (methods, properties, events, etc.) + Mogą mieć różne elementy członkowskie (metody, właściwości, zdarzenia itp.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Aby dowiedzieć się więcej o klasach, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Aby dowiedzieć się więcej o elementach członkowskich, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Prosta, dwuwymiarowa klasa Vector. + + + + The class's constructor is on the first line, + Konstruktor klasy znajduje się w pierwszym wierszu + + + + and takes two arguments: dx and dy, both of type 'double'. + i przyjmuje dwa argumenty: dx i dy, oba typu „double”. + + + + This internal field stores the length of the vector, computed when the + To pole wewnętrzne przechowuje długość wektora obliczoną podczas + + + + object is constructed + obiekt jest skonstruowany + + + + 'this' specifies a name for the object's self identifier. + Wyraz „this” określa nazwę własnego identyfikatora obiektu. + + + + In instance methods, it must appear before the member name. + W metodach wystąpień musi on znajdować się przed nazwą elementu członkowskiego. + + + + This member is a method. The previous members were properties. + Ten element członkowski jest metodą. Poprzednie elementy członkowskie były właściwościami. + + + + This is how you instantiate the Vector2D class. + Jest to sposób tworzenia wystąpienia dla klasy Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Pobierz nowy skalowany obiekt wektora bez modyfikowania obiektu oryginalnego. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Klasy ogólne umożliwiają definiowanie typów z uwzględnieniem zestawu parametrów typu. + + + + In the following, 'T is the type parameter for the class. + W następującym przykładzie 'T jest parametrem typu dla klasy. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + To wewnętrzne pole przechowuje stany na liście. + + + + Add a new element to the list of states. + Dodaj nowy element do listy stanów. + + + + use the '<-' operator to mutate the value. + użyj operatora „<-”, aby zmodyfikować wartość. + + + + Get the entire list of historical states. + Pobierz całą listę stanów historycznych. + + + + Get the latest state. + Pobierz najnowszy stan. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Wystąpienie typu „int” klasy procedury śledzenia stanu. Należy zwrócić uwagę, że parametr typu jest wywnioskowany. + + + + Add a state + Dodaj stan + + + + Interfaces are object types with only 'abstract' members. + Interfejsy to typy obiektu, których wszystkie elementy członkowskie są abstrakcyjne. + + + + Object types and object expressions can implement interfaces. + Typy obiektu i wyrażenia obiektu mogą implementować interfejsy. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + To jest typ implementujący interfejs IDisposable. + + + + This is the implementation of IDisposable members. + To jest implementacja elementów członkowskich interfejsu IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + To jest obiekt implementujący interfejs IDisposable za pośrednictwem wyrażenia obiektu + + + + Unlike other languages such as C# or Java, a new type definition is not needed + W przeciwieństwie do innych języków, np. C# lub Java, nowy typ definicji nie jest wymagany + + + + to implement an interface. + do zaimplementowania interfejsu. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + Biblioteka FSharp.Core definiuje zestaw funkcji przetwarzania równoległego. Tutaj + + + + you use some functions for parallel processing over arrays. + niektóre funkcje są używane do równoległego przetwarzania tablic. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Aby dowiedzieć się więcej, zobacz https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Najpierw tablica wartości wejściowych. + + + + Next, define a functions that does some CPU intensive computation. + Następnie zdefiniuj funkcje, które wykonują obliczenia intensywnie korzystające z procesora. + + + + Next, do a parallel map over a large input array. + Następnie wykonaj równoległe mapowanie dla dużej tablicy wejściowej. + + + + Next, print the results. + Następnie wyświetl wyniki. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Zdarzenia są wspólnym idiomem dla programowania na platformie .NET, zwłaszcza przy użyciu aplikacji WinForms lub WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Aby dowiedzieć się więcej, zobacz https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Najpierw utwórz wystąpienie obiektu Event, które składa się z punktu subskrypcji (event.Publish) i wyzwalacza zdarzenia (event.Trigger). + + + + Next, add handler to the event. + Następnie dodaj procedurę obsługi do zdarzenia. + + + + Next, trigger the event. + Następnie wyzwól zdarzenie. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Następnie utwórz wystąpienie zdarzenia zgodne ze standardową konwencją platformy .NET: (sender, EventArgs). + + + + Next, add a handler for this new event. + Następnie dodaj procedurę obsługi dla tego nowego zdarzenia. + + + + Next, trigger this event (note that sender argument should be set). + Następnie wyzwól to zdarzenie (zwróć uwagę, że argument elementu wysyłającego powinien być ustawiony). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pt-BR.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pt-BR.xlf new file mode 100644 index 0000000000..64df6c8506 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.pt-BR.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Esta amostra guiará você pelos elementos da linguagem F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Para executar o código no F# Interativo, realce uma seção de código e pressione Alt-Enter ou clique com botão direito do mouse + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + e selecione "Executar em Interativo". Você pode abrir a janela F# Interativo no menu "Exibir". + + + + For more about F#, see: + Para obter mais informações sobre F#, consulte: + + + + To see this tutorial in documentation form, see: + Para ver este tutorial em forma de documentação, consulte: + + + + To learn more about applied F# programming, use + Para saber mais sobre a programação F# aplicada, use + + + + To install the Visual F# Power Tools, use + Para instalar o Visual F# Power Tools, use + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + 'Ferramentas' --> 'Extensões e Atualizações' --> `Online` e pesquise + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Para obter modelos adicionais a serem usados com F#, consulte 'Modelos online' no Visual Studio, + + + + 'New Project' --> 'Online Templates' + 'Novo projeto --> 'Modelos online' + + + + F# supports three kinds of comments: + F# dá suporte a três tipos de comentários: + + + + 1. Double-slash comments. These are used in most situations. + 1. Comentários de barra dupla. São usados na maioria das situações. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Comentários de bloco em estilo de ML. Eles não são usados com muita frequência. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Comentários de barra tripla. São usados para funções de documentação, tipos, etc. + + + + They will appear as text when you hover over something which is decorated with these comments. + Eles aparecerão como texto quando você passar o mouse sobre algo decorado com esses comentários. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Eles também dão suporte a comentários XML em estilo .NET, que permitem que você gere documentação de referência, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + além de permitirem que editores (como o Visual Studio) extraiam informações deles. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Abra os namespaces usando a palavra-chave 'open'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Um módulo é um agrupamento de código F#, assim como valores, valores de função e tipos. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Agrupar código em módulos ajuda a manter o código relacionado junto e ajuda a evitar conflitos de nome em seu programa. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Este é um inteiro de exemplo. + + + + This is a sample floating point number. + Esta é uma amostra de número de ponto flutuante. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Isso computou um novo número por meio de alguma aritmética. Tipos numéricos são convertidos usando + + + + functions 'int', 'double' and so on. + funções 'int', 'double' e assim por diante. + + + + This is a list of the numbers from 0 to 99. + Esta é uma lista de números de 0 a 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Isso é uma lista de todas as tuplas contendo todos os números de 0 a 99 e seus quadrados. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + A próxima linha imprime uma lista que inclui tuplas, usando '%A' para impressão genérica. + + + + This is a sample integer with a type annotation + Este é um inteiro de exemplo com uma anotação de tipo + + + + Values in F# are immutable by default. They cannot be changed + Os valores em F# são imutáveis por padrão. Eles não podem ser alterados + + + + in the course of a program's execution unless explicitly marked as mutable. + no decorrer da execução de um programa a menos que explicitamente marcados como mutáveis. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Associar um valor a um nome via 'let' o torna imutável. + + + + The second line of code fails to compile because 'number' is immutable and bound. + A compilação da segunda linha de código falha porque 'number' é imutável e limitado. + + + + Re-defining 'number' to be a different value is not allowed in F#. + Não é permitido redefinir 'number' para um valor diferente em F#. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Uma associação mutável. Isso é necessário para que se possa modificar o valor de 'otherNumber'. + + + + When mutating a value, use '<-' to assign a new value. + Ao converter um valor, use '<-' para atribuir um novo valor. + + + + You could not use '=' here for this purpose since it is used for equality + Você não pode usar '=' aqui para essa finalidade, já que ele é usado para igualdade + + + + or other contexts such as 'let' or 'module' + ou outros contextos como 'let' ou 'module' + + + + Much of F# programming consists of defining functions that transform input data to produce + Grande parte da programação F# consiste em definir funções que transformam os dados de entrada para produzir + + + + useful results. + resultados úteis. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Use 'let' para definir uma função. Ele aceita um argumento inteiro e retorna um inteiro. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Parênteses são opcionais para os argumentos da função, exceto quando você usa uma anotação de tipo explícito. + + + + Apply the function, naming the function return result using 'let'. + Aplique a função, nomeando o resultado de retorno de função usando 'let'. + + + + The variable type is inferred from the function return type. + O tipo de variável é deduzido do tipo de retorno de função. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Esta linha usa '%d' para imprimir o resultado como um inteiro. Isso é fortemente tipado. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Se 'result1' não fosse do tipo 'int', a linha falharia na compilação. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Quando necessário, anote o tipo de um nome de parâmetro usando '(argument:type)'. É necessário usar parênteses. + + + + Conditionals use if/then/elid/elif/else. + Condicionais usam if/then/elid/elif/else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Observe que F# usa sintaxe com reconhecimento de recuo de espaço em branco, semelhante a linguagens como Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Esta linha usa '%f' para imprimir o resultado como um float. Como em '%d' acima, isso é fortemente tipado. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Boolianos são tipos de dados fundamentais em F#. Aqui estão alguns exemplos de Boolianos e lógica condicional. + + + + To learn more, see: + Para saber mais, acesse: + + + + and + E + + + + Booleans values are 'true' and 'false'. + Valores booliano são 'true' e 'false'. + + + + Operators on booleans are 'not', '&&' and '||'. + Operadores em boolianos são 'not', '&&' e '||'. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Esta linha usa '%b' para imprimir um valor booliano. Isso é fortemente tipado. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Cadeias de caracteres são tipos de dados fundamentais em F#. Aqui estão alguns exemplos de Cadeias de caracteres e a manipulação básicas de Cadeia de caracteres. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Cadeias de caracteres usam aspas duplas. + + + + Strings can also use @ to create a verbatim string literal. + Cadeias de caracteres também podem usar @ para criar um literal de cadeia de caracteres textual. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Isso vai ignorar caracteres de escapada como '\', '\n', '\t', etc. + + + + String literals can also use triple-quotes. + Literais de cadeia de caracteres também podem usar aspas triplas. + + + + String concatenation is normally done with the '+' operator. + A concatenação de cadeia de caracteres normalmente é feita com o operador '+'. + + + + This line uses '%s' to print a string value. This is type-safe. + Esta linha usa '%s' para imprimir um valor de cadeia de caracteres. Isso é fortemente tipado. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Subcadeias de caracteres usam a notação de indexador. Essa linha extrai os sete primeiros caracteres como uma subcadeia de caracteres. + + + + Note that like many languages, Strings are zero-indexed in F#. + Observe que, como muitas linguagens, Cadeias de Caracteres são indexadas com zero em F#. + + + + Tuples are simple combinations of data values into a combined value. + Tuplas são combinações simples de valores de dados em um valor combinado. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Uma tupla simples de inteiros. + + + + A function that swaps the order of two values in a tuple. + Uma função que troca a ordem de dois valores em uma tupla. + + + + F# Type Inference will automatically generalize the function to have a generic type, + Inferência de Tipos F# generalizará automaticamente a função para ter um tipo genérico, + + + + meaning that it will work with any type. + significando que ele funcionará com qualquer tipo. + + + + A tuple consisting of an integer, a string, + Uma tupla consistindo em um inteiro, uma cadeia de caracteres, + + + + and a double-precision floating point number. + e um número de ponto flutuante de precisão dupla. + + + + A simple tuple of integers with a type annotation. + Uma tupla simples de números inteiros com uma anotação de tipo. + + + + Type annotations for tuples use the * symbol to separate elements + As anotações de tipo para tuplas usam o símbolo * para separar elementos + + + + Tuples are normally objects, but they can also be represented as structs. + Tuplas normalmente são objetos, mas também podem ser representados como structs. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Esses interoperam completamente com structs em C# e Visual Basic.NET; entretanto, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + tuplas de struct não são implicitamente conversíveis com tuplas de objeto (geralmente chamadas de tuplas de referência). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + A compilação da segunda linha abaixo falhará por causa disso. Remova a marca de comentário para ver o que acontece. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Embora não seja possível converter implicitamente entre tuplas de struct e tuplas de referência, + + + + you can explicitly convert via pattern matching, as demonstrated below. + você pode converter explicitamente via correspondência de padrões, conforme demonstrado abaixo. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Os operadores de pipe F# ('|>', '<|', etc.) e os operadores de composição F# ('>>', '<<') + + + + are used extensively when processing data. These operators are themselves functions + são usadas extensivamente durante o processamento de dados. Esses operadores são funções + + + + which make use of Partial Application. + que fazem uso do Aplicativo Parcial. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Para saber mais sobre esses operadores, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Para saber mais sobre Aplicativo Parcial, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Eleva um valor ao quadrado. + + + + Adds 1 to a value. + Adiciona 1 a um valor. + + + + Tests if an integer value is odd via modulo. + Testa se um valor inteiro for ímpar por meio do módulo. + + + + A list of 5 numbers. More on lists later. + Uma lista de cinco números. Mais sobre listas posteriormente. + + + + Given a list of integers, it filters out the even numbers, + Dada uma lista de inteiros, ele filtra os números pares, + + + + squares the resulting odds, and adds 1 to the squared odds. + eleva os ímpares resultantes ao quadrado e adiciona 1 aos ímpares elevados ao quadrado. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Uma maneira mais curta para gravar 'squareOddValuesAndAddOne' é aninhar cada + + + + sub-result into the function calls themselves. + sub-resultado em função invoca a si mesmo. + + + + This makes the function much shorter, but it's difficult to see the + Isso faz com que a função fique muito menor, mas é difícil ver a + + + + order in which the data is processed. + ordem em que os dados são processados. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Uma maneira preferencial para gravar 'squareOddValuesAndAddOne' é usar operadores de pipe F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + Isso permite que você evite criar resultados intermediários, mas é muito mais legível + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + que a função de aninhamento invoca como 'squareOddValuesAndAddOneNested' + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + Você pode reduzir 'squareOddValuesAndAddOnePipeline' movendo a segunda chamada `List.map` + + + + into the first, using a Lambda Function. + no primeiro, usando uma Função Lambda. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Observe que pipelines também estão sendo usados dentro da função lambda. Operadores de pipe F# + + + + can be used for single values as well. This makes them very powerful for processing data. + podem ser usados para valores únicos também. Isso os torna muito eficientes para o processamento de dados. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + Por fim, você pode eliminar a necessidade de incluir explicitamente 'valores' como um parâmetro usando '>>' + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + para compor as duas principais operações: filtrar números pares e, em seguida, elevar ao quadrado e adicionar um. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Da mesma forma, o bit 'fun x -> ...' da expressão lambda também não é necessário porque 'x' é simplesmente + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + sendo definido nesse escopo para que possa ser passada a um pipeline funcional. Portanto, '>>' pode ser usado + + + + there as well. + lá também. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + O resultado de 'squareOddValuesAndAddOneComposition' é em si outra função que leva um + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + lista de inteiros como sua entrada. Se você executar 'squareOddValuesAndAddOneComposition' com uma lista + + + + of integers, you'll notice that it produces the same results as previous functions. + de inteiros, você observará que ela produz os mesmos resultados que as funções anteriores. + + + + This is using what is known as function composition. This is possible because functions in F# + Isso está usando o que é conhecido como composição de função. Isso é possível porque funções em F# + + + + use Partial Application and the input and output types of each data processing operation match + use Aplicativo Parcial e os tipos de entrada e saída de cada correspondência de operação de processamento de dados + + + + the signatures of the functions we're using. + as assinaturas das funções que estamos usando. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + As listas são listas ordenadas, imutáveis, vinculadas de modo único. Elas são adiantadas em sua avaliação. + + + + This module shows various ways to generate lists and process lists with some functions + Este módulo mostra várias formas de gerar listas e listas de processo com algumas funções + + + + in the 'List' module in the F# Core Library. + no módulo 'Lista' na Biblioteca Principal de F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + As listas são definidas usando [ ... ]. Esta é uma lista vazia. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Esta é uma lista com 3 elementos. ';' é usado para separar elementos na mesma linha. + + + + You can also separate elements by placing them on their own lines. + Você também pode separar elementos colocando-os em suas próprias linhas. + + + + This is a list of integers from 1 to 1000 + Esta é uma lista de inteiros de 1 a 1.000 + + + + Lists can also be generated by computations. This is a list containing + Listas também podem ser geradas pelos cálculos. Esta é uma lista contendo + + + + all the days of the year. + todos os dias do ano. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Imprima os primeiros cinco elementos de 'daysList' usando 'List.take'. + + + + Computations can include conditionals. This is a list containing the tuples + Cálculos podem incluir condicionais. Esta é uma lista contendo as tuplas + + + + which are the coordinates of the black squares on a chess board. + que são as coordenadas dos quadrados pretos em um tabuleiro de xadrez. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Listas podem ser transformadas usando 'List. map' e outros combinadores de programação funcional. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Essa definição produz uma nova lista ao elevar ao quadrado os números em numberList, usando o pipeline + + + + operator to pass an argument to List.map. + operador para passar um argumento para List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Há muitas outras combinações de lista. O exemplo a seguir computa a soma dos quadrados dos + + + + numbers divisible by 3. + números divisíveis por 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Matrizes são coleções de tamanho fixo, mutáveis de elementos do mesmo tipo. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Embora elas sejam semelhantes às Listas (eles dão suporte à enumeração e têm combinadores semelhantes para processamento de dados), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + elas geralmente são mais rápidas e dão suporte ao acesso aleatório rápido. Isso vem com o custo de ser menos seguro por ser mutável. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Esta é a matriz vazia. Observe que a sintaxe é semelhante à de Listas, mas usa '[| ... |]' em vez disso. + + + + Arrays are specified using the same range of constructs as lists. + Matrizes são especificadas usando o mesmo intervalo de construções usado em listas. + + + + This is an array of numbers from 1 to 1000. + Esta é uma matriz de números de 1 a 1.000. + + + + This is an array containing only the words "hello" and "world". + Esta é uma matriz que contém apenas as palavras "olá" e "mundo". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Esta é uma matriz inicializada pelo índice e que contém os números pares de 0 a 2.000. + + + + Sub-arrays are extracted using slicing notation. + Submatrizes são extraídas usando a notação de divisão. + + + + You can loop over arrays and lists using 'for' loops. + Você pode executar um loop através de matrizes e listas usando loops 'for'. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Você pode modificar o conteúdo de um elemento de matriz usando o operador de atribuição de seta para a esquerda. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Para saber mais sobre esse operador, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Você pode transformar as matrizes usando 'Array.map' e outras operações de programação funcional. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + O exemplo a seguir calcula a soma dos tamanhos de palavras que começam com 'h'. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Sequências são uma série lógica de elementos, todos do mesmo tipo. Eles são um tipo mais geral que Listas e Matrizes. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + As sequências são avaliada sob demanda e reavaliadas sempre que são repetidas. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Uma sequência de F# é um alias para um System.Collections.Generic.IEnumerable .NET<' t>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Funções de processamento de sequência também podem ser aplicadas a matrizes e listas. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Esta é a sequência vazia. + + + + This a sequence of values. + Esta é uma sequência de valores. + + + + This is an on-demand sequence from 1 to 1000. + Esta é uma sequência sob demanda de 1 a 1000. + + + + This is a sequence producing the words "hello" and "world" + Esta é uma sequência produzindo as palavras "olá" e "mundo" + + + + This sequence producing the even numbers up to 2000. + Esta sequência produzindo os números pares até 2.000. + + + + This is an infinite sequence which is a random walk. + Esta é uma sequência infinita, que é um exame aleatório. + + + + This example uses yield! to return each element of a subsequence. + Este exemplo usa yield! para retornar cada elemento de uma subsequência. + + + + This example shows the first 100 elements of the random walk. + Este exemplo mostra os primeiros 100 elementos do exame aleatório. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Funções recursivas podem chamar a si mesmas. Em F#, funções são recursivas somente + + + + when declared using 'let rec'. + quando declarada usando 'let rec'. + + + + Recursion is the preferred way to process sequences or collections in F#. + Recursão é a maneira preferencial de processar sequências ou coleções em F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Este exemplo mostra uma função recursiva que computa o fatorial de um + + + + integer. It uses 'let rec' to define a recursive function. + inteiro. Ele usa 'let gra' para definir uma função recursiva. + + + + Computes the greatest common factor of two integers. + Calcula o máximo divisor comum de dois inteiros. + + + + Since all of the recursive calls are tail calls, + Como todas as chamadas recursivas são chamadas tail, + + + + the compiler will turn the function into a loop, + o compilador transformará a função em um loop, + + + + which improves performance and reduces memory consumption. + que melhora o desempenho e reduz o consumo de memória. + + + + This example computes the sum of a list of integers using recursion. + Este exemplo calcula a soma de uma lista de inteiros usando recursão. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Isso torna a cauda de 'sumList' recursiva usando uma função auxiliar com um acumulador de resultado. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Isso invoca a cauda da função auxiliar recursiva, fornecendo '0' como um acumulador de semente. + + + + An approach like this is common in F#. + Uma abordagem como essa é comum em F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Registros são uma agregação de valores nomeados com membros opcionais (como métodos). + + + + They are immutable and have structural equality semantics. + Eles são imutáveis e têm semântica de igualdade estrutural. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Este exemplo mostra como definir um novo tipo de registro. + + + + This example shows how to instantiate a record type. + Este exemplo mostra como criar uma instância de um tipo de registro. + + + + You can also do this on the same line with ';' separators. + Você também pode fazer isso na mesma linha com separadores ';'. + + + + This example shows how to use "copy-and-update" on record values. It creates + Este exemplo mostra como usar o "copiar e atualizar" em valores do Registro. Ele cria + + + + a new record value that is a copy of contact1, but has different values for + um novo valor de registro é uma cópia de contact1, mas tem valores diferentes para + + + + the 'Phone' and 'Verified' fields. + os campos 'Telefone' e 'Verificado'. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Este exemplo mostra como escrever uma função que processa um valor de Registro. + + + + It converts a 'ContactCard' object to a string. + Converte um objeto 'ContactCard' em uma cadeia de caracteres. + + + + This is an example of a Record with a member. + Este é um exemplo de um Registro com um membro. + + + + Members can implement object-oriented members. + Os membros podem implementar membros orientados a objeto. + + + + Members are accessed via the '.' operator on an instantiated type. + Os membros são acessados por meio do operador '.' em um tipo instanciado. + + + + Records can also be represented as structs via the 'Struct' attribute. + Registros também podem ser representados como structs por meio do atributo 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Isso é útil em situações em que o desempenho de structs é superior + + + + the flexibility of reference types. + a flexibilidade de tipos de referência. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Uniões Discriminadas (UD) são valores que podem ser vários formulários nomeados ou casos. + + + + Data stored in DUs can be one of several distinct values. + Dados armazenados em DUs podem ser um dos vários valores distintos. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + O exemplo a seguir representa o naipe de uma carta de baralho. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Uma União Discriminada também pode ser usada para representar a classificação de uma carta de baralho. + + + + Represents the rank of cards 2 .. 10 + Representa posição das cartas 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + Uniões Discriminadas também podem implementar membros orientados a objeto. + + + + This is a record type that combines a Suit and a Rank. + Este é um tipo de registro que combina um Naipe e uma Classificação. + + + + It's common to use both Records and Disciminated Unions when representing data. + É comum usar Registros e Uniões Discriminadas ao representar dados. + + + + This computes a list representing all the cards in the deck. + Isto calcula uma lista que representa todas as cartas do baralho. + + + + This example converts a 'Card' object to a string. + Este exemplo converte um objeto 'Carta' em uma cadeia de caracteres. + + + + This example prints all the cards in a playing deck. + Este exemplo imprime todas as cartas de um baralho de jogo. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + UDs de caso único são frequentemente usadas para modelagem de domínio. Isso pode significar um tipo extra de segurança para você + + + + over primitive types such as strings and ints. + sobre tipos primitivos como cadeias de caracteres e inteiros. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + UDs de caso único não podem ser convertidas implicitamente de ou para o tipo que elas encapsulam. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Por exemplo, uma função que compreende um Endereço não pode aceitar uma sequência de caracteres como essa entrada, + + + + or vive/versa. + ou vice-versa. + + + + You can easily instantiate a single-case DU as follows. + Você pode facilmente criar uma instância em uma UD de único caso conforme mostrado a seguir. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Quando precisar do valor, você pode decodificar o valor subjacente com uma função simples. + + + + Printing single-case DUs is simple with unwrapping functions. + Imprimir UDs de caso único é simples com funções não encapsuladas. + + + + Disciminated Unions also support recursive definitions. + Uniões Discriminadas também dão suporte a definições recursivas. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Isso representa uma Árvore de Pesquisa Binária, com um caso sendo a árvore Vazia, + + + + and the other being a Node with a value and two subtrees. + e o outro sendo um Nó com um valor e duas subárvores. + + + + Check if an item exists in the binary search tree. + Verifique se um item existe na árvore de pesquisa binária. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Pesquisa recursivamente usando Correspondência de Padrões. Retorna verdadeiro se existir; caso contrário, falso. + + + + Check the left subtree. + Verifique a subárvore à esquerda. + + + + Check the right subtree. + Verifique a subárvore à direita. + + + + Inserts an item in the Binary Search Tree. + Insere um item na Árvore de Pesquisa Binária. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Encontra o local para inserir recursivamente usando Correspondência de Padrões e, em seguida, insere um novo nó. + + + + If the item is already present, it does not insert anything. + Se o item já estiver presente, ele não insere nada. + + + + No need to insert, it already exists; return the node. + Não é preciso inseri-lo, ele já existe; retorne o nó. + + + + Call into left subtree. + Chamar subárvore à esquerda. + + + + Call into right subtree. + Chamar subárvore à direita. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Uniões Discriminadas também podem ser representadas como structs por meio do atributo 'Struct'. + + + + This is helpful in situations where the performance of structs outweighs + Isso é útil em situações em que o desempenho de structs é superior + + + + the flexibility of reference types. + a flexibilidade de tipos de referência. + + + + However, there are two important things to know when doing this: + No entanto, existem duas coisas importantes a saber ao fazer isso: + + + + 1. A struct DU cannot be recursively-defined. + 1. Uma UD struct não pode ser definida recursivamente. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Uma UD struct deve ter nomes exclusivos para cada um dos seus casos. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Correspondência de padrões é um recurso do F# que permite que você utilize Padrões, + + + + which are a way to compare data with a logical structure or structures, + que são uma forma de comparar dados com uma estrutura lógica ou com estruturas, + + + + decompose data into constituent parts, or extract information from data in various ways. + decompor os dados em partes constituintes ou extrair informações de dados de diversas maneiras. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Em seguida, você pode expedir na "forma" de um padrão por meio da Correspondência de Padrões. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Um registro de nome e sobrenome de uma pessoa + + + + A Discriminated Union of 3 different kinds of employees + Uma União Discriminada de 3 tipos diferentes de funcionários + + + + Count everyone underneath the employee in the management hierarchy, + Conta todos abaixo do funcionário na hierarquia de gerenciamento, + + + + including the employee. + incluindo o funcionário. + + + + Find all managers/executives named "Dave" who do not have any reports. + Localize todos os gerentes/executivos chamados "Dave" que não têm nenhum relatório. + + + + This uses the 'function' shorthand to as a lambda expression. + Isso usa a forma abreviada de 'function' como uma expressão lambda. + + + + [] matches an empty list. + [] corresponde a uma lista vazia. + + + + '_' is a wildcard pattern that matches anything. + '_' é um padrão de caractere curinga que coincide com qualquer coisa. + + + + This handles the "or else" case. + Isso identifica o caso "ou também". + + + + You can also use the shorthand function construct for pattern matching, + Você também pode usar o constructo da função abreviada para correspondência de padrões, + + + + which is useful when you're writing functions which make use of Partial Application. + que é útil quando você está gravando funções que fazem uso do Aplicativo Parcial. + + + + Define some more functions which parse with the helper function. + Defina mais algumas funções que são analisadas com a função auxiliar. + + + + Active Patterns are another powerful construct to use with pattern matching. + Padrões Ativos são outro constructo avançado para usar com correspondência de padrões. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Eles permitem particionar os dados de entrada em formulários personalizados, decompondo-os no local da chamada de correspondência de padrão. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Correspondência de Padrões por meio de palavra-chave 'function' e Padrões Ativos geralmente têm essa aparência. + + + + Call the printer with some different values to parse. + Chamar a impressora com alguns valores diferentes para analisar. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Os valores de opção são qualquer tipo de valor marcado com 'Algum' ou 'Nenhum'. + + + + They are used extensively in F# code to represent the cases where many other + Eles são usados extensivamente no código F# para representar os casos em que muitos outros + + + + languages would use null references. + idiomas usariam referências nulas. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + Primeiro, determine um CEP definido por meio de União Discriminada de Único Caso. + + + + Next, define a type where the ZipCode is optional. + Em seguida, defina um tipo em que o CEP é opcional. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Em seguida, defina um tipo de interface que representa um objeto para computar a zona de remessa para o CEP do cliente, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + determinadas implementações para os métodos abstratos 'getState' e 'getShippingZone'. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Em seguida, calcule uma zona de remessa para um cliente usando uma instância da calculadora. + + + + This uses combinators in the Option module to allow a functional pipeline for + Isso usa combinadores no módulo Option para permitir um pipeline funcional para + + + + transforming data with Optionals. + transformando dados com Opcionais. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Unidades de medida são uma forma de anotar tipos numéricos primitivos de um modo fortemente tipado. + + + + You can then perform type-safe arithmetic on these values. + Então, você pode executar a aritmética fortemente tipada nesses valores. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + Primeiro, abra uma coleção de nomes comuns de unidade + + + + Define a unitized constant + Definir uma constante unitizada + + + + Next, define a new unit type + Em seguida, defina um novo tipo de unidade + + + + Conversion factor mile to meter. + Fator de conversão de milha para metro. + + + + Define a unitized constant + Definir uma constante unitizada + + + + Compute metric-system constant + Computar a constante de sistema métrico + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Valores que usam Unidades de Medida podem ser usados exatamente como o tipo numérico primitivo para coisas como impressão. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Classes são uma maneira de definir novos tipos de objetos em F# e dão suporte a constructos padrão Orientados a objeto. + + + + They can have a variety of members (methods, properties, events, etc.) + Elas podem ter uma variedade de membros (métodos, propriedades, eventos, etc.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Para saber mais sobre Classes, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Para saber mais sobre Membros, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Uma classe de vetor bidimensional simples. + + + + The class's constructor is on the first line, + O construtor da classe está na primeira linha, + + + + and takes two arguments: dx and dy, both of type 'double'. + e leva dois argumentos: dx e dy, ambos do tipo 'duplo'. + + + + This internal field stores the length of the vector, computed when the + Este campo interno armazena o comprimento do vetor, computado quando o + + + + object is constructed + objeto é construído + + + + 'this' specifies a name for the object's self identifier. + 'this' especifica um nome para o identificador automático do objeto. + + + + In instance methods, it must appear before the member name. + Em métodos de instância, ele deve aparecer antes do nome do membro. + + + + This member is a method. The previous members were properties. + Esse membro é um método. Os membros anteriores eram propriedades. + + + + This is how you instantiate the Vector2D class. + É assim que você cria uma instância de classe Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Obter um novo objeto de vetor em escala, sem modificar o objeto original. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Classes genéricas permitem que os tipos sejam definidos em relação a um conjunto de parâmetros de tipo. + + + + In the following, 'T is the type parameter for the class. + No exemplo a seguir, 'T é o parâmetro de tipo para a classe. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Este campo interno armazena os estados em uma lista. + + + + Add a new element to the list of states. + Adicione um novo elemento à lista de estados. + + + + use the '<-' operator to mutate the value. + use o operador '<-' para modificar o valor. + + + + Get the entire list of historical states. + Obter a lista completa de estados históricos. + + + + Get the latest state. + Obter o estado mais recente. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Uma instância ' int' da classe de controlador do estado. Observe que o parâmetro de tipo é deduzido. + + + + Add a state + Adicionar um estado + + + + Interfaces are object types with only 'abstract' members. + As interfaces são tipos de objeto com apenas membros 'abstract'. + + + + Object types and object expressions can implement interfaces. + Tipos de objeto e expressões de objeto podem implementar interfaces. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Este é um tipo que implementa IDisposable. + + + + This is the implementation of IDisposable members. + Essa é a implementação de membros IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Este é um objeto que implementa IDisposable por meio de uma Expressão de Objeto + + + + Unlike other languages such as C# or Java, a new type definition is not needed + Diferentemente de outras linguagens, como C# ou Java, uma nova definição de tipo não é necessária + + + + to implement an interface. + para implementar uma interface. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + A biblioteca FSharp.Core define várias funções de processamento paralelo. Aqui + + + + you use some functions for parallel processing over arrays. + você usa algumas funções para processamento paralelo por matrizes. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Para saber mais, acesse: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + Primeiro, uma matriz de entradas. + + + + Next, define a functions that does some CPU intensive computation. + Em seguida, defina uma função que realiza computação com uso intensivo de CPU. + + + + Next, do a parallel map over a large input array. + Em seguida, faça um mapa paralelo por uma grande matriz de entrada. + + + + Next, print the results. + Em seguida, imprima os resultados. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Eventos são uma linguagem comum para programação em .NET, especialmente com aplicativos WinForms ou WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Para saber mais, acesse: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Primeiro, crie a instância do objeto Evento que consiste em ponto de assinatura (event.Publish) e gatilho de eventos (event.Trigger). + + + + Next, add handler to the event. + Em seguida, adicione o manipulador ao evento. + + + + Next, trigger the event. + Em seguida, dispare o evento. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Em seguida, crie uma instância do evento que segue a convenção padrão do .NET: (sender, EventArgs). + + + + Next, add a handler for this new event. + Em seguida, adicione um manipulador para este novo evento. + + + + Next, trigger this event (note that sender argument should be set). + Em seguida, dispare esse evento (observe que o argumento do remetente deve ser definido). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ru.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ru.xlf new file mode 100644 index 0000000000..6bded45999 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.ru.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Этот пример поможет узнать о различных элементах языка F#. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Чтобы выполнить код в F# Interactive, выделите фрагмент кода и нажмите ALT+ВВОД или щелкните правой кнопкой мыши + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + и выберите команду "Выполнение в интерактивном режиме". Интерактивное окно F# можно также открыть из меню "Вид". + + + + For more about F#, see: + Дополнительные сведения о F# см. по адресу: + + + + To see this tutorial in documentation form, see: + Чтобы просмотреть это руководство в виде документа, см.: + + + + To learn more about applied F# programming, use + Чтобы получить дополнительные сведения о прикладном программировании на языке F#, воспользуйтесь + + + + To install the Visual F# Power Tools, use + Чтобы установить Visual F# Power Tools, используйте + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + "Сервис" --> "Расширения и обновления" --> "В сети" и выполните поиск + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + Дополнительные шаблоны, которые можно использовать с F#, см. в разделе "Шаблоны в Интернете" в Visual Studio. + + + + 'New Project' --> 'Online Templates' + "Создать проект --> Шаблоны в Интернете" + + + + F# supports three kinds of comments: + F# поддерживает три типа комментариев: + + + + 1. Double-slash comments. These are used in most situations. + 1. Комментарии с двойной косой чертой. Они используются в большинстве ситуаций. + + + + 2. ML-style Block comments. These aren't used that often. + 2. Комментарии блоков в стиле ML. Они используются довольно редко. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Комментарии с тройной косой чертой. Они используются для документирования функций, типов и т. д. + + + + They will appear as text when you hover over something which is decorated with these comments. + При наведении указателя мыши на код, задекорированный этими комментариями, они отображаются в виде текста. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Кроме того, они поддерживают XML-комментарии в стиле .NET, делая возможным формирование справочной документации, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + а также позволяют редакторам (таким как Visual Studio) извлекать из них информацию. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Подробности: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + Открывайте пространства имен с помощью ключевого слова "open". + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Подробности: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Модуль представляет собой группирование кода F#, например значений, типов и значений функций. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Группирование кода в модулях помогает держать связанный код в одном месте и предотвратить конфликты имен в программе. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Подробности: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Это пример целого числа. + + + + This is a sample floating point number. + Это пример числа с плавающей запятой. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Это новое число, вычисленное с помощью некоторых арифметических операций. Числовые типы преобразуются с помощью + + + + functions 'int', 'double' and so on. + функций "int", "double" и т. п. + + + + This is a list of the numbers from 0 to 99. + Это список чисел от 0 до 99. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Это список всех кортежей, содержащих все числа от 0 до 99 и их квадраты. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + Следующая строка выводит список, включающий в себя кортежи, используя "%A" для универсальной печати. + + + + This is a sample integer with a type annotation + Это пример целого числа с аннотацией типа + + + + Values in F# are immutable by default. They cannot be changed + В F# значения по умолчанию неизменяемы. Их невозможно изменить + + + + in the course of a program's execution unless explicitly marked as mutable. + во время выполнения программы, если только они явно не помечены как изменяемые. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Привязка значения к имени через let делает его неизменяемым. + + + + The second line of code fails to compile because 'number' is immutable and bound. + Сбой компиляции второй строки кода происходит, так как number неизменяем и привязан. + + + + Re-defining 'number' to be a different value is not allowed in F#. + Переопределение number в другое значение запрещено в F#. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Изменяемая привязка. Она необходима, чтобы иметь возможность изменять значение otherNumber. + + + + When mutating a value, use '<-' to assign a new value. + При изменении значения используйте "<-", чтобы присвоить новое значение. + + + + You could not use '=' here for this purpose since it is used for equality + Не удалось использовать "=" здесь и для этой цели, так как знак используется как оператор равенства. + + + + or other contexts such as 'let' or 'module' + или другие контексты, такие как "let" или "module" + + + + Much of F# programming consists of defining functions that transform input data to produce + Программирование на языке F# в основном заключается в определении функций, которые преобразуют входные данные и выдают + + + + useful results. + полезные результаты. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + let используется для определения функции. Эта функция принимает целочисленный аргумент и возвращает целое число. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + Круглые скобки необязательны для аргументов функции, если только не используется явная аннотация типа. + + + + Apply the function, naming the function return result using 'let'. + Применяйте функции, именуя возвращаемый функцией результат с помощью let. + + + + The variable type is inferred from the function return type. + Тип переменной определяется типом возвращаемого значения функции. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + В этой строке используется "%d" для вывода результата как целого числа. Это типобезопасно. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + Если бы result1 не принадлежал к типу int, при компиляции строки произошел бы сбой. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + При необходимости аннотируйте тип имени параметра при помощи "(argument:type)". Скобки обязательны. + + + + Conditionals use if/then/elid/elif/else. + В условных выражениях используются операторы if, then, elid, elif и else. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + Обратите внимание, что в F# используется синтаксис с отступами в виде пробелов, аналогично таким языкам, как Python. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Эта строка использует "%f" для вывода результата в виде числа с плавающей запятой. Как и в случае с "%d" выше, это типобезопасно. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Логические значения являются основными типами данных в F#. Ниже приведен ряд примеров логических типов данных и условной логики. + + + + To learn more, see: + Подробности: + + + + and + И + + + + Booleans values are 'true' and 'false'. + Логические значения — это true и false. + + + + Operators on booleans are 'not', '&&' and '||'. + Операторы для логических значений — not, && и ||. + + + + This line uses '%b'to print a boolean value. This is type-safe. + В этой строке "%b" используется для вывода логического значения. Это типобезопасно. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Строки являются основными типами данных в F#. Ниже приведено несколько примеров строк и основных действий с ними. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + В строках используются двойные кавычки. + + + + Strings can also use @ to create a verbatim string literal. + В строках также может использоваться @ для создания буквальных (verbatim) строковых литералов. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Будут пропускаться escape-символы, такие как "\", "\n", "\t" и т. д. + + + + String literals can also use triple-quotes. + В строковых литералах также используются тройные кавычки. + + + + String concatenation is normally done with the '+' operator. + Сцепление строк обычно выполняется при помощи оператора "+". + + + + This line uses '%s' to print a string value. This is type-safe. + В этой строке "%s" используется для вывода строкового значения. Это типобезопасно. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Подстроки используют нотацию индексатора. Эта строка кода извлекает первые семь символов в виде подстроки. + + + + Note that like many languages, Strings are zero-indexed in F#. + Учтите, что, как и во многих других языках, в F# строки индексируются от нуля. + + + + Tuples are simple combinations of data values into a combined value. + Кортеж — это простое сочетание значений данных в виде объединенного значения. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Простой кортеж целых чисел. + + + + A function that swaps the order of two values in a tuple. + Функция, меняющая местами два значения в кортеже. + + + + F# Type Inference will automatically generalize the function to have a generic type, + Определение типа F# будет автоматически назначать функции универсальный тип, + + + + meaning that it will work with any type. + что означает, что он будет работать с любым типом. + + + + A tuple consisting of an integer, a string, + Кортеж, состоящий из целого числа, строки + + + + and a double-precision floating point number. + и числа двойной точности с плавающей запятой. + + + + A simple tuple of integers with a type annotation. + Простой кортеж целых чисел с аннотацией типа. + + + + Type annotations for tuples use the * symbol to separate elements + Аннотации типов для кортежей используют символ * для разделения элементов. + + + + Tuples are normally objects, but they can also be represented as structs. + Кортежи обычно являются объектами, но они также могут быть представлены как структуры. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Они полноценно взаимодействуют со структурами в C# и Visual Basic.NET; тем не менее + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + кортежи структур нельзя явно преобразовать в кортежи объектов (часто называемые эталонными кортежами). + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + Из-за этого произойдет сбой компиляции второй строки ниже. Раскомментируйте ее, чтобы увидеть, что произойдет. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Хотя кортежи-структуры и ссылочные кортежи невозможно преобразовывать неявно, + + + + you can explicitly convert via pattern matching, as demonstrated below. + вы можете явно преобразовывать их с помощью сопоставления шаблонов, как показано ниже. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + Операторы конвейера F# ("|>", "<|" и т. д.) и операторы объединения F# (">>", "<<") + + + + are used extensively when processing data. These operators are themselves functions + широко используются при обработке данных. Эти операторы сами по себе являются функциями, + + + + which make use of Partial Application. + использующими частичное применение. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Подробности об этих операторах: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining. + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Подробности о частичном применении: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments. + + + + Squares a value. + Возводит значение в квадрат. + + + + Adds 1 to a value. + Добавляет 1 к значению. + + + + Tests if an integer value is odd via modulo. + Проверяет, является ли целое число нечетным по модулю. + + + + A list of 5 numbers. More on lists later. + Список из 5 чисел. Дополнительно о списках позднее. + + + + Given a list of integers, it filters out the even numbers, + При наличии списка целых чисел выполняет фильтрацию по номерам событий, + + + + squares the resulting odds, and adds 1 to the squared odds. + возводит полученные нечетные в квадрат, а затем добавляет 1 к нечетным, возведенным в квадрат. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + Более короткий способ записи squareOddValuesAndAddOne — вложить каждый + + + + sub-result into the function calls themselves. + вложенный результат в сами вызовы функции. + + + + This makes the function much shorter, but it's difficult to see the + Это позволяет значительно сократить функцию, но будет сложно увидеть + + + + order in which the data is processed. + порядок, в котором обрабатываются данные. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + Предпочтительный способ записи squareOddValuesAndAddOne — использовать операторы конвейера F#. + + + + This allows you to avoid creating intermediate results, but is much more readable + Это позволяет избежать создания промежуточных результатов, и при этом более удобно для чтения, + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + чем вложение вызовов функций, таких как squareOddValuesAndAddOneNested. + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + squareOddValuesAndAddOnePipeline можно сократить, переместив второй вызов List.map + + + + into the first, using a Lambda Function. + в первый, используя лямбда-функцию. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Учтите, что конвейеры также используются внутри лямбда-функции. Операторы конвейера F# + + + + can be used for single values as well. This makes them very powerful for processing data. + можно также использовать для отдельных значений. Это делает их очень эффективными при обработке данных. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + И наконец, можно исключить необходимость явного принятия значений в качестве параметра при помощи ">>" + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + для объединения двух основных операций: фильтрации четных чисел, а затем возведения в квадрат и добавления единицы. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Аналогично, часть "fun x -> ..." лямбда-выражения также не требуется, так как x просто + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + определяется в этой области действия, чтобы его можно было передать в функциональный конвейер. Таким образом, здесь также можно + + + + there as well. + использовать ">>". + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + Результат squareOddValuesAndAddOneComposition сам по себе является другой функцией, которая принимает + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + список целых чисел в качестве входных данных. Если squareOddValuesAndAddOneComposition выполняется со списком + + + + of integers, you'll notice that it produces the same results as previous functions. + целых чисел, вы заметите, что результаты соответствуют результатам предыдущих функций. + + + + This is using what is known as function composition. This is possible because functions in F# + Используется так называемая композиция функций. Это возможно, так как функции в F# + + + + use Partial Application and the input and output types of each data processing operation match + используют частичное применение, а входные и выходные типы каждой операции обработки данных соответствуют + + + + the signatures of the functions we're using. + сигнатурам функций, которые мы используем. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Списки — это упорядоченные, неизменяемые однонаправленные списки. При вычислении они являются безотложными. + + + + This module shows various ways to generate lists and process lists with some functions + Этот модуль демонстрирует различные способы создания и обработки списков при помощи некоторых функций + + + + in the 'List' module in the F# Core Library. + в модуле List основной библиотеки F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/lists. + + + + Lists are defined using [ ... ]. This is an empty list. + Списки определяются с помощью [ ... ]. Это пустой список. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Это — список с тремя элементами. Символ ";" используется для разделения элементов в одной строке. + + + + You can also separate elements by placing them on their own lines. + Элементы можно также разделить, поместив их в отдельные строки. + + + + This is a list of integers from 1 to 1000 + Это список целых чисел от 1 до 1000. + + + + Lists can also be generated by computations. This is a list containing + Списки также могут создаваться в результате вычислений. Это список, содержащий + + + + all the days of the year. + все дни года. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + Вывод первых пяти элементов daysList при помощи List.take. + + + + Computations can include conditionals. This is a list containing the tuples + Вычисления могут включать условные выражения. Это список, содержащий кортежи + + + + which are the coordinates of the black squares on a chess board. + являющиеся координатами черных квадратов на шахматной доске. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Списки можно преобразовывать с помощью List.map и других методов объединения, применяемых в функциональном программировании. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Это определение создает новый список путем возведения в квадрат чисел из numberList с помощью конвейера. + + + + operator to pass an argument to List.map. + оператор для передачи аргумента в List.map. + + + + There are many other list combinations. The following computes the sum of the squares of the + Существует множество других сочетаний списков. Приведенный ниже код вычисляет сумму квадратов. + + + + numbers divisible by 3. + числа, кратные 3. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Массивы — это изменяемые коллекции фиксированного размера, содержащие элементы одного типа. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Хотя они и похожи на списки (поддерживают перечисление и включают схожие методы объединения для обработки данных), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + они, как правило, быстрее и поддерживают быстрый случайный доступ. С другой стороны, они менее безопасны, так как изменяемы. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/arrays. + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Это — пустой массив. Обратите внимание, что синтаксис похож на синтаксис списков, но используются квадратные скобки "[| ... |]". + + + + Arrays are specified using the same range of constructs as lists. + Массивы задаются с помощью того же диапазона конструкций в виде списков. + + + + This is an array of numbers from 1 to 1000. + Это массив чисел от 1 до 1000. + + + + This is an array containing only the words "hello" and "world". + Это — массив, содержащий только слова "hello" и "world". + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Это — массив, инициализируемый по индексу и содержащий четные числа от 0 до 2000. + + + + Sub-arrays are extracted using slicing notation. + Подмассивы извлекаются с помощью нотации выделения фрагмента. + + + + You can loop over arrays and lists using 'for' loops. + Можно выполнять перебор массивов и списков при помощи циклов for. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Изменить содержимое элемента массива можно с помощью оператора присваивания в виде стрелки влево. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Подробности об этом операторе: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/values/index#mutable-variables. + + + + You can transform arrays using 'Array.map' and other functional programming operations. + Вы можете преобразовывать массивы при помощи Array.map и других операций функционального программирования. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Следующий фрагмент вычисляет сумму длин слов, которые начинаются с буквы "h". + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Последовательности — это логические серии элементов одного типа. Это — более общий тип, чем списки и массивы. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Последовательности вычисляются по требованию и заново вычисляются при каждом их переборе. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + Последовательность F# является псевдонимом для .NET System.Collections.Generic.IEnumerable<'T>. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Функции обработки последовательностей можно также применять к спискам и массивам. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Это пустая последовательность. + + + + This a sequence of values. + Это последовательность значений. + + + + This is an on-demand sequence from 1 to 1000. + Это последовательность по требованию от 1 до 1000. + + + + This is a sequence producing the words "hello" and "world" + Это последовательность, создающая слова hello и world. + + + + This sequence producing the even numbers up to 2000. + Эта последовательность выдает целые числа до 2000. + + + + This is an infinite sequence which is a random walk. + Это бесконечная последовательность, представляющая случайное блуждание. + + + + This example uses yield! to return each element of a subsequence. + В этом примере используется оператор yield! для получения каждого элемента подпоследовательности. + + + + This example shows the first 100 elements of the random walk. + В этом примере показаны первые 100 элементов случайного блуждания. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Рекурсивные функции могут вызывать сами себя. В F# функции являются рекурсивными только + + + + when declared using 'let rec'. + при объявлении с помощью let rec. + + + + Recursion is the preferred way to process sequences or collections in F#. + Рекурсия — это предпочтительный способ обработки последовательностей или коллекций в F#. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions. + + + + This example shows a recursive function that computes the factorial of an + В этом примере показана рекурсивная функция, вычисляющая факториал + + + + integer. It uses 'let rec' to define a recursive function. + целое число. В нем используется "let rec" для определения рекурсивной функции. + + + + Computes the greatest common factor of two integers. + Вычисляет наибольший общий делитель двух целых чисел. + + + + Since all of the recursive calls are tail calls, + Так как все рекурсивные вызовы являются хвостовыми вызовами, + + + + the compiler will turn the function into a loop, + компилятор сделает из функции цикл, + + + + which improves performance and reduces memory consumption. + что повысит производительность и снизит потребление памяти. + + + + This example computes the sum of a list of integers using recursion. + Этот пример вычисляет сумму списка целых чисел при помощи рекурсии. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + При этом sumList становится функцией с хвостовой рекурсией, использующей вспомогательную функцию с аккумулятором результатов. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Вызывается вспомогательная функция хвостовой рекурсии, предоставляющая "0" в качестве аккумулятора начальных значений. + + + + An approach like this is common in F#. + Подобный подход широко распространен в F#. + + + + Records are an aggregate of named values, with optional members (such as methods). + Записи являются агрегатами именованных значений с необязательными элементами (такими как методы). + + + + They are immutable and have structural equality semantics. + Они являются неизменяемыми и обладают семантикой структурного равенства. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/records. + + + + This example shows how to define a new record type. + В этом примере показано, как определить новый тип записи. + + + + This example shows how to instantiate a record type. + В этом примере показано создание экземпляра типа записи. + + + + You can also do this on the same line with ';' separators. + Это также можно сделать в одной строке при помощи разделителя ";", + + + + This example shows how to use "copy-and-update" on record values. It creates + В этом примере показано, как использовать функцию "копировать и обновить" применительно к значениям записей. В нем создается + + + + a new record value that is a copy of contact1, but has different values for + новое значение записи, которое является копией contact1, но имеет другие значения для + + + + the 'Phone' and 'Verified' fields. + поля Phone и Verified. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions. + + + + This example shows how to write a function that processes a record value. + В этом примере показано, как создать функцию, обрабатывающую значение записи. + + + + It converts a 'ContactCard' object to a string. + Он преобразует объект ContactCard в строку. + + + + This is an example of a Record with a member. + Это — пример записи с элементом. + + + + Members can implement object-oriented members. + Элементы могут реализовать объектно-ориентированные элементы. + + + + Members are accessed via the '.' operator on an instantiated type. + Доступ к элементам осуществляется через оператор "." для экземпляра типа. + + + + Records can also be represented as structs via the 'Struct' attribute. + Записи также могут быть представлены как структуры при помощи атрибута Struct. + + + + This is helpful in situations where the performance of structs outweighs + Это удобно в ситуациях, когда производительность структур важнее + + + + the flexibility of reference types. + гибкости ссылочных типов. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Размеченные объединения (DU) — это значения, которые могут состоять из нескольких именованных форм или ветвей. + + + + Data stored in DUs can be one of several distinct values. + Данные, хранимые в размеченных объединениях, могут являться одними из нескольких различных значений. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/discriminated-unions. + + + + The following represents the suit of a playing card. + Следующий код представляет масть игральной карты. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Размеченное объединение также может использоваться для представления ранга игральной карты. + + + + Represents the rank of cards 2 .. 10 + Представляет достоинство карт 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + Кроме того, размеченные объединения могут реализовать объектно-ориентированные элементы. + + + + This is a record type that combines a Suit and a Rank. + Это тип записи, объединяющий масть и достоинство. + + + + It's common to use both Records and Disciminated Unions when representing data. + Как правило, при представлении данных используются как записи, так и размеченные объединения. + + + + This computes a list representing all the cards in the deck. + Вычисляется список, представляющий все карты в колоде. + + + + This example converts a 'Card' object to a string. + В этом примере объект Card преобразуется в строку. + + + + This example prints all the cards in a playing deck. + В этом примере печатаются все карты колоды. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Размеченные объединения с одной ветвью часто используются для моделирования доменов. Это более типобезопасно, чем использование + + + + over primitive types such as strings and ints. + примитивных типов, таких как строки и целые числа. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Размеченные объединения с одной ветвью нельзя неявно преобразовать в тип или из типа, оболочкой которого они служат. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Например, функция, которая принимает адрес, не может принять в качестве входных данных строку + + + + or vive/versa. + или наоборот. + + + + You can easily instantiate a single-case DU as follows. + Можно легко создать экземпляр размеченного объединения с одной ветвью следующим образом. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Если вам требуется значение, вы можете распаковать базовое значение при помощи простой функции. + + + + Printing single-case DUs is simple with unwrapping functions. + Вывод размеченных объединений с одной ветвью не представляет сложности при использовании функций распаковки. + + + + Disciminated Unions also support recursive definitions. + Размеченные объединения также поддерживают рекурсивные определения. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Это представляет двоичное дерево поиска, в котором одна ветвь является пустым деревом, + + + + and the other being a Node with a value and two subtrees. + а другая — узлом со значением и двумя поддеревьями. + + + + Check if an item exists in the binary search tree. + Проверка наличия элемента в двоичном дереве поиска. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Рекурсивный поиск при помощи сопоставления шаблонов. Возвращает значение True, если существует; в противном случае — значение False. + + + + Check the left subtree. + Проверка левого поддерева. + + + + Check the right subtree. + Проверка правого поддерева. + + + + Inserts an item in the Binary Search Tree. + Вставляет элемент в двоичное дерево поиска. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Находит место для рекурсивной вставки при помощи сопоставления шаблонов, а затем вставляет новый узел. + + + + If the item is already present, it does not insert anything. + Если элемент уже существует, ничего не вставляется. + + + + No need to insert, it already exists; return the node. + Нет необходимости вставки, так как она уже существует; возврат узла. + + + + Call into left subtree. + Вызов левого поддерева. + + + + Call into right subtree. + Вызов правого поддерева. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Размеченные объединения также могут быть представлены как структуры при помощи атрибута Struct. + + + + This is helpful in situations where the performance of structs outweighs + Это удобно в ситуациях, когда производительность структур важнее + + + + the flexibility of reference types. + гибкости ссылочных типов. + + + + However, there are two important things to know when doing this: + Но при этом следует помнить о следующих двух важных вещах: + + + + 1. A struct DU cannot be recursively-defined. + 1. Размеченное объединение структуры не может определяться рекурсивно. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Каждой из ветвей размеченного объединения структуры должны быть присвоены уникальные названия. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Сопоставление шаблонов — это возможность F#, которая позволяет использовать шаблоны, + + + + which are a way to compare data with a logical structure or structures, + что представляет способ сравнения данных с логической структурой или структурами, + + + + decompose data into constituent parts, or extract information from data in various ways. + разложение данных на составные части или извлечение информации из данных различными способами. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Затем можно передать "форму" шаблона при помощи сопоставления шаблонов. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/pattern-matching. + + + + A record for a person's first and last name + Запись с именем и фамилией человека + + + + A Discriminated Union of 3 different kinds of employees + Размеченное соединение трех разных типов сотрудников + + + + Count everyone underneath the employee in the management hierarchy, + Подсчет всех сотрудников на уровнях иерархии управления, следующих за этим сотрудником, + + + + including the employee. + включая этого сотрудника. + + + + Find all managers/executives named "Dave" who do not have any reports. + Поиск всех менеджеров и руководителей с именем Dave, не имеющих отчетов. + + + + This uses the 'function' shorthand to as a lambda expression. + При этом используется сокращение функции до лямбда-выражения. + + + + [] matches an empty list. + [] соответствует пустому списку. + + + + '_' is a wildcard pattern that matches anything. + "_" — подстановочный знак, обозначающий любой набор символов. + + + + This handles the "or else" case. + Обрабатывается ветвь "or else". + + + + You can also use the shorthand function construct for pattern matching, + Для сопоставления шаблонов можно также использовать краткую форму конструкции функции, + + + + which is useful when you're writing functions which make use of Partial Application. + что удобно при написании функций, использующих частичное применение. + + + + Define some more functions which parse with the helper function. + Определение некоторых других функций, которые выполняют анализ при помощи вспомогательной функции. + + + + Active Patterns are another powerful construct to use with pattern matching. + Активные шаблоны — это еще одна эффективная конструкция, используемая при сопоставлении шаблонов. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Они позволяют сегментировать входные данные в настраиваемые формы с декомпозицией в месте вызова сопоставления шаблонов. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/active-patterns. + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + Сопоставление шаблонов по ключевому слову function и активным шаблонам часто выглядит следующим образом. + + + + Call the printer with some different values to parse. + Вызов принтера с несколькими разными значениями для анализа. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Опциональные значения - это любой тип значений, отмеченных ключевым словом Some или None. + + + + They are used extensively in F# code to represent the cases where many other + Они широко используются в коде F# для представления случаев, когда во многих + + + + languages would use null references. + других языках используются пустые ссылки. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/options. + + + + First, define a zipcode defined via Single-case Discriminated Union. + Во-первых, определите индекс при помощи размеченного объединения с одной ветвью. + + + + Next, define a type where the ZipCode is optional. + Далее определите тип, в котором ZipCode является необязательным. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Далее определите тип интерфейса, представляющий объект для вычисления зоны доставки по почтовому индексу заказчика, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + при заданных реализациях абстрактных методов getState и getShippingZone. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Затем определите зону доставки для заказчика при помощи экземпляра калькулятора. + + + + This uses combinators in the Option module to allow a functional pipeline for + При этом используются методы объединения в модуле Option, чтобы обеспечить работу функционального конвейера для + + + + transforming data with Optionals. + преобразования данных с помощью Optionals. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Единицы измерения — это способ аннотации примитивных числовых типов типобезопасным способом. + + + + You can then perform type-safe arithmetic on these values. + Затем с этими значениями можно выполнять типобезопасные арифметические действия. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/units-of-measure. + + + + First, open a collection of common unit names + Сначала откройте коллекцию стандартных названий единиц измерения. + + + + Define a unitized constant + Определите константу с единицей измерения. + + + + Next, define a new unit type + Далее определите новый тип единицы. + + + + Conversion factor mile to meter. + Коэффициент пересчета миль в метры. + + + + Define a unitized constant + Определите константу с единицей измерения. + + + + Compute metric-system constant + Вычислите константу в метрической системе. + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Значения, использующие единицы измерения, можно применять как примитивные числовые типы для таких действий, как печать. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Классы — это способ определения новых типов объектов в F#. Они поддерживают стандартные объектно-ориентированные конструкции. + + + + They can have a variety of members (methods, properties, events, etc.) + Они могут содержать различные элементы (методы, свойства, события и т. д.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Подробности о классах: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/classes. + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Подробности об элементах: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/members. + + + + A simple two-dimensional Vector class. + Простой двухмерный класс Vector. + + + + The class's constructor is on the first line, + Конструктор класса находится в первой строке + + + + and takes two arguments: dx and dy, both of type 'double'. + и принимает два аргумента: dx и dy, оба имеют тип double. + + + + This internal field stores the length of the vector, computed when the + В этом внутреннем поле хранится длина вектора, вычисляемая, когда + + + + object is constructed + объект создается + + + + 'this' specifies a name for the object's self identifier. + Ключевое слово this задает имя идентификатора самого объекта. + + + + In instance methods, it must appear before the member name. + В методах экземпляров оно должно находиться перед именем элемента. + + + + This member is a method. The previous members were properties. + Этот элемент является методом. Предыдущие элементы были свойствами. + + + + This is how you instantiate the Vector2D class. + Вот как выполняется создание экземпляра класса Vector2D. + + + + Get a new scaled vector object, without modifying the original object. + Получение нового объекта масштабируемого вектора без изменения исходного объекта. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Универсальные классы позволяют определять типы с набором параметров типа. + + + + In the following, 'T is the type parameter for the class. + В следующем примере 'T — это параметр типа для класса. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/generics/. + + + + This internal field store the states in a list. + В этом внутреннем поле хранятся состояния в списке. + + + + Add a new element to the list of states. + Добавление нового элемента в список состояний. + + + + use the '<-' operator to mutate the value. + Оператор "<-" служит для изменения значения. + + + + Get the entire list of historical states. + Получение полного списка исторических состояний. + + + + Get the latest state. + Получение последнего состояния. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Экземпляр int класса отслеживания состояний. Обратите внимание, что параметр типа подразумевается. + + + + Add a state + Добавление состояния + + + + Interfaces are object types with only 'abstract' members. + Интерфейсы — это типы объектов, которые имеют только абстрактные члены. + + + + Object types and object expressions can implement interfaces. + Типы объектов и выражения объектов могут реализовывать интерфейсы. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/interfaces. + + + + This is a type that implements IDisposable. + Это — тип, который реализует интерфейс IDisposable. + + + + This is the implementation of IDisposable members. + Это — реализация элементов интерфейса IDisposable. + + + + This is an object that implements IDisposable via an Object Expression + Это — объект, реализующий интерфейс IDisposable через выражение объекта. + + + + Unlike other languages such as C# or Java, a new type definition is not needed + В отличие от других языков, таких как C# или Java, новое определение типа не требуется + + + + to implement an interface. + для реализации интерфейса. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + В библиотеке FSharp.Core определен ряд функций параллельной обработки. Здесь + + + + you use some functions for parallel processing over arrays. + вы используете определенные функции для параллельной обработки массивов. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Подробности: https://msdn.microsoft.com/ru-ru/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D. + + + + First, an array of inputs. + Сначала — массив входных данных. + + + + Next, define a functions that does some CPU intensive computation. + Далее определите функции, выполняющие ряд вычислений с интенсивным использованием ЦП. + + + + Next, do a parallel map over a large input array. + Затем выполните параллельное сопоставление по большому входному массиву. + + + + Next, print the results. + Далее напечатайте результаты. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + События представляют собой стандартные идиомы программирования .NET, особенно для приложений WinForms или WPF. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Подробности: https://docs.microsoft.com/ru-ru/dotnet/articles/fsharp/language-reference/members/events. + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + Сначала создайте экземпляр объекта Event, состоящий из точки подписки (event.Publish) и триггера события (event.Trigger). + + + + Next, add handler to the event. + Затем добавьте обработчик для события. + + + + Next, trigger the event. + Затем активируйте событие. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Затем создайте экземпляр события в соответствии со стандартным соглашением .NET: (sender, EventArgs). + + + + Next, add a handler for this new event. + Затем добавьте обработчик для этого нового события. + + + + Next, trigger this event (note that sender argument should be set). + Затем вызовите событие (обратите внимание на то, что аргумент sender должен быть задан). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.tr.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.tr.xlf new file mode 100644 index 0000000000..2fcd8d0f2c --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.tr.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + Bu örnek, size F# dilinin öğelerini gösterir. + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + Kodu F# Etkileşimli’de yürütmek için kodun bir bölümünü vurgulayın ve Alt-Enter'a basın veya sağ tıklatın + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + ve "Etkileşimlide Yürüt" seçeneğini belirleyin. F# Etkileşimli Penceresini "Görünüm" menüsünden açabilirsiniz. + + + + For more about F#, see: + F# hakkında daha fazla bilgi için bkz: + + + + To see this tutorial in documentation form, see: + Bu öğreticiyi belge biçiminde görmek için, bkz: + + + + To learn more about applied F# programming, use + Uygulamalı F# programlama hakkında daha fazla bilgi edinmek için şunu kullanın: + + + + To install the Visual F# Power Tools, use + Visual F# Power Tools'u yüklemek için + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + 'Araçlar' --> 'Uzantılar ve Güncelleştirmeler' --> `Çevrimiçi` seçeneğini kullanın ve arama yapın + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + F# ile kullanabileceğiniz ek şablonlar için Visual Studio'daki 'Çevrimiçi Şablonlar'a bakın, + + + + 'New Project' --> 'Online Templates' + 'Yeni Proje' --> 'Çevrimiçi Şablonlar' + + + + F# supports three kinds of comments: + F# üç açıklama türünü destekler: + + + + 1. Double-slash comments. These are used in most situations. + 1. Çift eğik çizgili açıklamalar. Çoğu durumda bunlar kullanılır. + + + + 2. ML-style Block comments. These aren't used that often. + 2. ML stili Blok açıklamaları. Bunlar sık kullanılmaz. + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. Üç eğik çizgili açıklamalar. Bunlar işlevleri, türleri vb. belgelemek için kullanılır. + + + + They will appear as text when you hover over something which is decorated with these comments. + Bu açıklamalarla belirlenmiş bir öğenin üzerine geldiğinizde, açıklamalar metin olarak görüntülenir. + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + Ayrıca başvuru belgeleri oluşturmanıza olanak sağlayan .NET stili XML açıklamalarını destekler, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + bilgi ayıklamak için düzenleyicilerin (örneğin Visual Studio) kullanılmasına da olanak sağlar. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + 'Open' anahtar sözcüğünü kullanarak ad alanlarını açın. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + Modül; değer, tür ve işlev değeri gibi bir F# kodu gruplandırmasıdır. + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + Kodu modüller içinde gruplandırmak ilgili kodların bir arada bulunmasını sağlar ve programınızda ad çakışmalarını önlemeye yardımcı olur. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + Bu, örnek bir tamsayıdır. + + + + This is a sample floating point number. + Bu, örnek bir kayan noktalı sayıdır. + + + + This computed a new number by some arithmetic. Numeric types are converted using + Bu, aritmetik kullanarak yeni bir sayı hesaplar. Sayısal türler + + + + functions 'int', 'double' and so on. + 'int', 'double' vb. işlevler kullanılarak dönüştürülür. + + + + This is a list of the numbers from 0 to 99. + Bu, 0'dan 99'a kadar olan sayıların listesidir. + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + Bu, 0'dan 99'a kadar olan sayıları ve bunların karelerini içeren bir listedir. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + Sonraki satır genel yazdırma için '%A' kullanarak demetleri içeren bir liste yazdırır. + + + + This is a sample integer with a type annotation + Bu tür açıklaması olan örnek bir tamsayıdır + + + + Values in F# are immutable by default. They cannot be changed + F# değerleri varsayılan olarak sabittir. Bu değerler + + + + in the course of a program's execution unless explicitly marked as mutable. + değiştirilebilir olarak açıkça işaretlenmediği sürece bir programın yürütülmesi sırasında değiştirilemez. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + Bir değeri 'let' ile bir ada bağlamak, değeri sabit yapar. + + + + The second line of code fails to compile because 'number' is immutable and bound. + 'Number' değişmez ve bağlı olduğu için ikinci kod satırı derlenemiyor. + + + + Re-defining 'number' to be a different value is not allowed in F#. + F# içinde 'number' değerini farklı bir değer olarak yeniden tanımlamaya izin verilmez. + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + Değiştirilebilir bir bağlama. Bu, 'otherNumber' değerini değiştirmek için gereklidir. + + + + When mutating a value, use '<-' to assign a new value. + Bir değeri değiştirirken, yeni bir değer atamak için '<-' kullanın. + + + + You could not use '=' here for this purpose since it is used for equality + Eşitlik amacıyla kullanıldığından, burada '=' kullanamazsınız + + + + or other contexts such as 'let' or 'module' + veya 'let' ya da 'module' gibi diğer bağlamlar + + + + Much of F# programming consists of defining functions that transform input data to produce + F# programlama çoğunlukla, giriş verilerini kullanışlı sonuçlara dönüştüren işlevleri + + + + useful results. + tanımlamaktan oluşur. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + Bir işlevi tanımlamak için 'let' kullanın. Bu, bir tamsayı bağımsız değişkenini kabul ederek bir tamsayı döndürür. + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + İşlev bağımsız değişkenlerinde ayraçlar, açık tür ek açıklaması kullanılan durumlar dışında isteğe bağlıdır. + + + + Apply the function, naming the function return result using 'let'. + İşlev döndürme sonucunu 'let' ile adlandırarak işlevi uygulayın. + + + + The variable type is inferred from the function return type. + Değişken türü, işlev dönüş türü olarak algılanır. + + + + This line uses '%d' to print the result as an integer. This is type-safe. + Bu satır, sonucu bir tamsayı olarak yazdırmak için '%d' kullanır. Tür kullanımıyla uyumludur. + + + + If 'result1' were not of type 'int', then the line would fail to compile. + 'Result1' 'int' türünde değilse, satır derleme işlemi başarısız olur. + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + Gerekli olduğunda, '(argument:type)' kullanarak parametre adı türü için ek açıklama girin. Ayraçlar gereklidir. + + + + Conditionals use if/then/elid/elif/else. + Koşullu deyimlerde if/then/elid/elif/else kullanılır. + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + F#'ın, Python gibi diller ile benzer şekilde, boşluk girintisini tanıyan söz dizimi kullandığını unutmayın. + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + Bu satır, sonucu kayan noktalı sayı olarak yazdırmak için '%f' kullanır. Yukarıdaki '%d' gibi bu da tür kullanımıyla uyumludur. + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + Boole değerleri, F# içindeki temel veri türleridir. Aşağıda bazı Boole ve koşullu mantık örnekleri verilmiştir. + + + + To learn more, see: + Daha fazla bilgi için bkz. + + + + and + ve + + + + Booleans values are 'true' and 'false'. + Boole değerleri şunlardır: 'true' ve 'false'. + + + + Operators on booleans are 'not', '&&' and '||'. + Boole değerleri üzerindeki işleçler: 'not', '&&' ve '||'. + + + + This line uses '%b'to print a boolean value. This is type-safe. + Bu satır, bir boole değeri yazdırmak için '%b' kullanır. Tür kullanımıyla uyumludur. + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + Dizeler, F# içindeki temel veri türleridir. Aşağıda bazı Dizeler ve temel dize işleme örnekleri verilmiştir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + Dizeler çift tırnak kullanır. + + + + Strings can also use @ to create a verbatim string literal. + Dizeler ayrıca, tam harf dizisi oluşturmak için @ kullanabilir. + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + Bu; '\', '\n', '\t' vb. kaçış karakterlerini yoksayar. + + + + String literals can also use triple-quotes. + Harf dizileri ayrıca üçlü tırnak da kullanabilir. + + + + String concatenation is normally done with the '+' operator. + Dizi bitiştirme normalde '+' işleci ile yapılır. + + + + This line uses '%s' to print a string value. This is type-safe. + Bu satır, bir dize değeri yazdırmak için '%s' kullanır. Tür kullanımıyla uyumludur. + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + Alt dizeler dizin oluşturucu gösterimini kullanır. Bu satır, ilk 7 karakteri alt dize olarak ayıklar. + + + + Note that like many languages, Strings are zero-indexed in F#. + Birçok dilde olduğu gibi F#'ta da Dizeler sıfır dizinlidir. + + + + Tuples are simple combinations of data values into a combined value. + Demetler, veri değerlerinin birleşik bir değer halindeki basit bileşimleridir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + Basit bir tamsayı demeti. + + + + A function that swaps the order of two values in a tuple. + Bir demetteki iki değerin sırasını değiştiren bir işlev. + + + + F# Type Inference will automatically generalize the function to have a generic type, + F# Tür Çıkarımı, işlevi genel türe sahip olacak şekilde otomatik olarak genelleştirir, + + + + meaning that it will work with any type. + yani, herhangi bir tür ile çalışabilir. + + + + A tuple consisting of an integer, a string, + Bir tamsayı, bir dize ve bir çift duyarlıklı kayan nokta sayısından + + + + and a double-precision floating point number. + oluşan bir demet. + + + + A simple tuple of integers with a type annotation. + Tür ek açıklaması içeren basit bir tamsayı tanımlama grubu. + + + + Type annotations for tuples use the * symbol to separate elements + Tanımlama grupları için tür ek açıklamaları öğeleri ayırmak için * sembolünü kullanır + + + + Tuples are normally objects, but they can also be represented as structs. + Demetler, normalde nesnedir ancak yapı olarak da gösterilebilir. + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + Bunlar C# ve Visual Basic.NET ile tamamen uyumlu olarak birlikte çalışır ancak + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + yapı demetleri, nesne demetleri ile (genellikle başvuru demetleri olarak adlandırılır) örtük olarak dönüştürülebilir değildir. + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + Bu nedenle aşağıdaki ikinci satırı derleme işlemi başarısız olacak. Ne olacağını görmek için açıklamayı kaldırın. + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + Yapı demetleri ile başvuru demetleri arasında örtük dönüştürme gerçekleştiremezsiniz, ancak + + + + you can explicitly convert via pattern matching, as demonstrated below. + aşağıda gösterildiği gibi, desen eşleştirme aracılığıyla açık dönüştürme gerçekleştirebilirsiniz. + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + F# kanal işleçleri ('|>', '<|', vb.) ve F# birleştirme işleçleri ('>>', '<<') + + + + are used extensively when processing data. These operators are themselves functions + veriler işlenirken yaygın olarak kullanılır. Bu işleçler, başı başına birer işlevdir ve + + + + which make use of Partial Application. + Kısmi Uygulamadan yararlanır. + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + Bu işleçler hakkında daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + Kısmi Uygulama hakkında daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + Bir değerin karesini alır. + + + + Adds 1 to a value. + Bir değere 1 ekler. + + + + Tests if an integer value is odd via modulo. + Mod aracılığıyla bir tamsayı değerinin tek sayı olup olmadığını test eder. + + + + A list of 5 numbers. More on lists later. + 5 numaradan oluşan bir liste. Listeler hakkında daha fazla bilgiyi ilerleyen bölümlerde bulabilirsiniz. + + + + Given a list of integers, it filters out the even numbers, + Bir tamsayı listesinde, çift sayıları filtreler, + + + + squares the resulting odds, and adds 1 to the squared odds. + kalan tek sayıların karesini alır ve karesi alınan tek sayılara 1 ekler. + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + 'squareOddValuesAndAddOne' yazmanın daha kısa bir yolu, her bir + + + + sub-result into the function calls themselves. + alt sonucu işlev hücrelerinin kendisinde iç içe yerleştirmektir. + + + + This makes the function much shorter, but it's difficult to see the + Bu, işlevi çok daha kısa hale getirir ancak + + + + order in which the data is processed. + verilerin işlenme sırasını görmek zordur. + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + 'squareOddValuesAndAddOne' yazmanın tercih edilen bir yolu, F# kanal işleçlerini kullanmaktır. + + + + This allows you to avoid creating intermediate results, but is much more readable + Bu, ara sonuçlar oluşturmaktan kaçınmanızı sağlar ancak + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + 'squareOddValuesAndAddOneNested' gibi iç içe geçmiş işlev çağrılarından daha okunaklıdır + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + 'squareOddValuesAndAddOnePipeline' öğesini kısaltmak için ikinci `List.map` çağrısını + + + + into the first, using a Lambda Function. + bir Lambda İşlevi kullanarak birinciye taşıyabilirsiniz. + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + Komut zincirleri, lambda işlevi içinde de kullanılıyor. F# kanal işleçleri + + + + can be used for single values as well. This makes them very powerful for processing data. + tek değerler için de kullanılabilir. Bu, işleçlerin veri işleme işlevlerini geliştirir. + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + Son olarak, şu iki temel işlemi oluşturmak için '>>' kullanarak 'values' öğesini parametre olarak + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + açıkça alma ihtiyacını ortadan kaldırabilirsiniz: çift sayıları filtreleme ve ardından karelerini alıp bir ekleme. + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + Benzer şekilde, 'x' bir işlevsel komut zincirine geçirilmek için bu kapsamda tanımlandığından + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + lambda ifadesindeki 'fun x -> ...' bölümü de gerekli değildir. Bu nedenle, '>>' + + + + there as well. + burada da kullanılabilir. + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + 'squareOddValuesAndAddOneComposition' sonucunun kendisi, giriş olarak bir tamsayı listesi alan + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + diğer bir işlevdir. 'squareOddValuesAndAddOneComposition' öğesini bir tamsayı listesi ile + + + + of integers, you'll notice that it produces the same results as previous functions. + yürütürseniz, önceki işlevler ile aynı sonuçları ürettiğini fark görürsünüz. + + + + This is using what is known as function composition. This is possible because functions in F# + Bu, işlev kompozisyonu olarak bilinen işlemi kullanır. Bu, F# içindeki işlevler Kısmi Uygulama kullandığı + + + + use Partial Application and the input and output types of each data processing operation match + ve her bir bilgi işlem işleminin giriş ve çıkış türleri kullandığımız işlevlerin imzaları ile eşleştiği için + + + + the signatures of the functions we're using. + mümkün olmaktadır. + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + Listeler sıralı, sabit ve tek bağlantılıdır. Bu listelerde erken değerlendirme yapılır. + + + + This module shows various ways to generate lists and process lists with some functions + Bu modül, liste oluşturmanın çeşitli yollarını gösterir ve listeleri F# Core Kitaplığı'ndaki + + + + in the 'List' module in the F# Core Library. + 'List' modülünde yer alan işlevlerle işler. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + Listeler [ ... ] kullanılarak tanımlanır. Bu boş bir listedir. + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + Bu, 3 öğeden oluşan bir listedir. ';' aynı satırdaki öğeleri ayırmak için kullanılır. + + + + You can also separate elements by placing them on their own lines. + Öğeleri, ayrı satırlara yerleştirerek de ayırabilirsiniz. + + + + This is a list of integers from 1 to 1000 + Bu, 1'den 1000'e kadar olan tamsayıların listesidir + + + + Lists can also be generated by computations. This is a list containing + Listeler ayrıca hesaplamalar aracılığıyla da üretilebilir. Bu, yılın tüm + + + + all the days of the year. + günlerini içeren bir listedir. + + + + Print the first 5 elements of 'daysList' using 'List.take'. + 'List.take' kullanarak 'daysList'in ilk 5 öğesini yazdırın. + + + + Computations can include conditionals. This is a list containing the tuples + Hesaplamalar, koşullu deyimler içerebilir. Bu, bir satranç tahtasındaki siyah karelerin + + + + which are the coordinates of the black squares on a chess board. + koordinatları olan demetleri içeren bir listedir. + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + Listeler, 'List.map' ve diğer işlevsel programlama birleştiricileri kullanılarak dönüştürülebilir. + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + Bu tanım, numberList içindeki sayıların karelerini alıp, List.map'e bir bağımsız değişken geçirmek üzere + + + + operator to pass an argument to List.map. + komut zinciri işlecini kullanarak yeni bir liste oluşturur. + + + + There are many other list combinations. The following computes the sum of the squares of the + Başka birçok liste bileşimi daha vardır. Aşağıda, 3'e bölünebilen sayıların karelerinin + + + + numbers divisible by 3. + toplamı hesaplanır. + + + + Arrays are fixed-size, mutable collections of elements of the same type. + Diziler, aynı türdeki sabit boyutlu, değiştirilebilir öğe koleksiyonlarıdır. + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + Lists'e benzer olsalar da (numaralandırmayı desteklerler ve bilgi işlem için benzer birleştiricilere sahiptirler) + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + genellikle daha hızlıdırlar ve hızlı rastgele erişimi desteklerler. Buna karşılık, değişken oldukları için daha az güvenlidirler. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + Bu, boş dizidir. Söz diziminin Lists'e benzediğine ancak `[| ... |]` kullandığına dikkat edin. + + + + Arrays are specified using the same range of constructs as lists. + Diziler, listeler ile aynı yapı aralıkları kullanılarak belirtilir. + + + + This is an array of numbers from 1 to 1000. + Bu, 1'den 1000'e kadar olan sayıların dizisidir. + + + + This is an array containing only the words "hello" and "world". + Bu, yalnızca "hello" ve "world" sözcüklerini içeren bir dizidir. + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + Bu, dizin tarafından başlatılan ve 0'dan 2000'e kadar olan çift sayıları içeren bir dizidir. + + + + Sub-arrays are extracted using slicing notation. + Alt diziler dilimleme gösterimi aracılığıyla ayıklanır. + + + + You can loop over arrays and lists using 'for' loops. + Diziler ve listeler üzerinden döngü oluşturmak için 'for' döngülerini kullanabilirsiniz. + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + Bir dizi öğesinin içeriğini sol ok atama işlecini kullanarak değiştirebilirsiniz. + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + Bu işleç hakkında daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + 'Array.map' ve diğer işlevsel programlama işlemlerini kullanarak dizileri dönüştürebilirsiniz. + + + + The following calculates the sum of the lengths of the words that start with 'h'. + Aşağıdaki, 'h' ile başlayan sözcüklerin uzunluklarının toplamını hesaplar. + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + Sıralar, aynı türdeki öğelerden oluşan mantıksal öğe serileridir. Bunlar, Lists ve Arrays'e kıyasla daha genel türlerdir. + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + Sıralar isteğe bağlı olarak değerlendirilir ve her yinelendiklerinde yeniden değerlendirilir. + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + F# sırası, .NET System.Collections.Generic.IEnumerable<'T> için diğer addır. + + + + Sequence processing functions can be applied to Lists and Arrays as well. + Seri işleme işlevleri, Listeler ve Dizilere de uygulanabilir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + Bu, boş bir seridir. + + + + This a sequence of values. + Bu bir değerler serisidir. + + + + This is an on-demand sequence from 1 to 1000. + Bu, 1'den 1000'e kadar olan isteğe bağlı bir seridir. + + + + This is a sequence producing the words "hello" and "world" + Bu, "hello" ve "world" sözcüklerini üreten bir seridir + + + + This sequence producing the even numbers up to 2000. + Bu, 2000'e kadar olan çift sayıları üreten bir seridir. + + + + This is an infinite sequence which is a random walk. + Bu, rastgele olan sonsuz bir seridir. + + + + This example uses yield! to return each element of a subsequence. + Bu örnek, alt serinin her öğesini döndürmek için yield! kullanır. + + + + This example shows the first 100 elements of the random walk. + Bu örnek rastgele serinin ilk 100 öğesini gösterir. + + + + Recursive functions can call themselves. In F#, functions are only recursive + Özyinelemeli işlevler kendilerini çağırabilir. F# içinde, işlevler yalnızca + + + + when declared using 'let rec'. + 'let rec' kullanılarak bildirildiğinde özyinelemeli olur. + + + + Recursion is the preferred way to process sequences or collections in F#. + Özyineleme, F# içinde sıraları veya koleksiyonları işlemek için tercih edilen yöntemdir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + Bu örnek, bir tamsayının faktöriyelini hesaplayan özyinelemeli bir işlevi + + + + integer. It uses 'let rec' to define a recursive function. + gösterir. Özyinelemeli işlevi tanımlamak için 'let rec' kullanır. + + + + Computes the greatest common factor of two integers. + İki tamsayının en büyük ortak çarpanını hesaplar. + + + + Since all of the recursive calls are tail calls, + Özyinelemeli tüm çağrılar tail çağrısı olduğundan, + + + + the compiler will turn the function into a loop, + derleyici, işlevi bir döngüye dönüştürür, + + + + which improves performance and reduces memory consumption. + bu da performansı artırır ve bellek tüketimini azaltır. + + + + This example computes the sum of a list of integers using recursion. + Bu örnek, özyineleme kullanarak bir tamsayılar listesinin toplamını hesaplar. + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + Bu, bir sonuç biriktirici ile bir yardımcı işlev kullanarak 'sumList' tail öğesini özyinelemeli yapar. + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + Bu, çekirdek biriktirici olarak '0' sağlayarak özyinelemeli tail yardımcı işlevini çağırır. + + + + An approach like this is common in F#. + Benzer yaklaşımlar F# içinde yaygındır. + + + + Records are an aggregate of named values, with optional members (such as methods). + Kayıtlar, isteğe bağlı üyeleri (örneğin, metotlar) içeren adlandırılmış değerlerin kümesidir. + + + + They are immutable and have structural equality semantics. + Bunlar sabittir ve yapısal eşitlik semantiğine sahiptir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + Bu örnek yeni bir kayıt türü tanımlamayı gösterir. + + + + This example shows how to instantiate a record type. + Bu örnekte, bir kayıt türünün örneğinin nasıl oluşturulacağı gösterilmektedir. + + + + You can also do this on the same line with ';' separators. + Bunu ';' ayırıcıları ile aynı satırda da yapabilirsiniz. + + + + This example shows how to use "copy-and-update" on record values. It creates + Bu örnek kayıt değerlerinde "kopyalama ve güncelleştirme" kullanımını gösterir. contact1'in + + + + a new record value that is a copy of contact1, but has different values for + kopyası olan, ama 'Telefon' ve 'Doğrulanmış' alanları için farklı değerleri olan + + + + the 'Phone' and 'Verified' fields. + yeni bir kayıt değeri oluşturur. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + Bu örnek kayıt değerini işleyen bir işlev yazmayı gösterir. + + + + It converts a 'ContactCard' object to a string. + 'ContactCard' nesnesini dizeye dönüştürür. + + + + This is an example of a Record with a member. + Bu, üye içeren bir Kayıt örneğidir. + + + + Members can implement object-oriented members. + Üyeler, nesne yönelimli üyeleri uygulayabilir. + + + + Members are accessed via the '.' operator on an instantiated type. + Örnekli bir tür üzerinde, üyelere '.' işleci ile erişilir. + + + + Records can also be represented as structs via the 'Struct' attribute. + Kayıtlar 'Struct' özniteliği ile yapı olarak da gösterilebilir. + + + + This is helpful in situations where the performance of structs outweighs + Bu, yapıların performansının, başvuru türlerinin esnekliğinden daha önemli + + + + the flexibility of reference types. + olduğu durumlarda kullanışlıdır. + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + Ayırt Edici Birleşimler (kısaca DU), bir dizi adlandırılmış form veya durum olabilen değerleri ifade eder. + + + + Data stored in DUs can be one of several distinct values. + DU'larda depolanan veriler birkaç farklı değerden biri olabilir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + Aşağıdaki, bir iskambil kartının cinsini gösterir. + + + + A Disciminated Union can also be used to represent the rank of a playing card. + Bir iskambil kartının sırasını göstermek için bir Ayırt Edici Birleşim de kullanılabilir. + + + + Represents the rank of cards 2 .. 10 + 2 .. 10 arasındaki kartları temsil eder + + + + Discriminated Unions can also implement object-oriented members. + Ayırt Edici Birleşimler ayrıca nesne yönelimli üyeleri uygulayabilir. + + + + This is a record type that combines a Suit and a Rank. + Bu, Cins ve Sırayı birleştiren bir kayıt türüdür. + + + + It's common to use both Records and Disciminated Unions when representing data. + Verileri temsil ederken Kayıtları ve Ayırt Edici Birleşimleri birlikte kullanmak yaygındır. + + + + This computes a list representing all the cards in the deck. + Bu, destedeki tüm kartları gösteren bir liste hesaplar. + + + + This example converts a 'Card' object to a string. + Bu örnek, bir 'Card' nesnesini dizeye dönüştürür. + + + + This example prints all the cards in a playing deck. + Bu örnek bir iskambil destesindeki tüm kartları yazdırır. + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + Tek Olaylı DU'lar genellikle etki alanı modelleme için kullanılır. Bu, dizeler ve tamsayılar gibi temel türlere göre + + + + over primitive types such as strings and ints. + ek tür güvenliği sağlamanıza yardımcı olabilir. + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + Tek durumlu DU'lar, sarmaladıkları türe veya bu türden örtük olarak dönüştürülemez. + + + + For example, a function which takes in an Address cannot accept a string as that input, + Örneğin, Adres alan bir işlev bu giriş için dize kabul edemez + + + + or vive/versa. + veya bu durumun tersi olamaz. + + + + You can easily instantiate a single-case DU as follows. + Tek Olaylı DU'ları aşağıdaki gibi kolayca örnekleyebilirsiniz. + + + + When you need the value, you can unwrap the underlying value with a simple function. + Değere ihtiyacınız olduğunda, basit bir işlev ile temel değerin sarmalamasını açabilirsiniz. + + + + Printing single-case DUs is simple with unwrapping functions. + Sarmalama açma işlevleri ile tek olayı DU'ları yazdırmak kolaydır. + + + + Disciminated Unions also support recursive definitions. + Ayırt Edici Birleşimler ayrıca özyinelemeli tanımları da destekler. + + + + This represents a Binary Search Tree, with one case being the Empty tree, + Bu, bir olayı Boş ağacı ve diğeri bir değer ile iki alt ağaç içeren bir Düğüme sahip + + + + and the other being a Node with a value and two subtrees. + İkili Arama Ağacı'nı gösterir. + + + + Check if an item exists in the binary search tree. + İkili arama ağacında bir öğe olup olmadığını denetleyin. + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + Desen Eşleştirme kullanarak özyinelemeli olarak arar. Varsa true, aksi takdirde false döndürür. + + + + Check the left subtree. + Sol alt ağacı denetleyin. + + + + Check the right subtree. + Sağ alt ağacı denetleyin. + + + + Inserts an item in the Binary Search Tree. + İkili Arama Ağacı'na bir öğe ekler. + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + Desen Eşleştirme kullanarak özyinelemeli olarak eklenecek yeri bulur ve ardından yeni bir düğüm ekler. + + + + If the item is already present, it does not insert anything. + Öğe zaten varsa yeni bir öğe eklenmez. + + + + No need to insert, it already exists; return the node. + Eklemeye gerek yok, öğe zaten var; düğümü döndürün. + + + + Call into left subtree. + Sol alt ağaca çağırın. + + + + Call into right subtree. + Sağ alt ağaca çağırın. + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + Ayırt Edici Birleşimler, 'Struct' özniteliği aracılığıyla yapı olarak da gösterilebilir. + + + + This is helpful in situations where the performance of structs outweighs + Bu, yapıların performansının, başvuru türlerinin esnekliğinden daha önemli + + + + the flexibility of reference types. + olduğu durumlarda kullanışlıdır. + + + + However, there are two important things to know when doing this: + Ancak, bunu yaparken bilmeniz gereken iki önemli nokta vardır: + + + + 1. A struct DU cannot be recursively-defined. + 1. Bir yapı DU'su, özyinelemeli olarak tanımlanamaz. + + + + 2. A struct DU must have unique names for each of its cases. + 2. Bir yapı DU'su, her bir durumu için benzersiz adlara sahip olmalıdır. + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + Desen Eşleştirme, Desenleri kullanmanızı sağlayan bir F# özelliğidir. + + + + which are a way to compare data with a logical structure or structures, + Desenler, verileri mantıksal yapı veya yapılar ile karşılaştırmak, + + + + decompose data into constituent parts, or extract information from data in various ways. + verileri bileşenlerine ayırmak veya verilerden bilgileri çeşitli şekillerde ayıklamak için harika bir yol sunar. + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + Daha sonra Desen Eşleştirme ile bir desenin "şeklini" gönderebilirsiniz. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + Bir kişinin ad ve soyadı kaydı + + + + A Discriminated Union of 3 different kinds of employees + 3 farklı çalışan türünden oluşan bir Ayırt Edici Birleşim + + + + Count everyone underneath the employee in the management hierarchy, + Çalışan da dahil olmak üzere, yönetim hiyerarşisinde çalışanın altındaki + + + + including the employee. + herkesi sayın. + + + + Find all managers/executives named "Dave" who do not have any reports. + Herhangi bir raporu olmayan, "Dave" adlı tüm yöneticileri bulun. + + + + This uses the 'function' shorthand to as a lambda expression. + Bu, 'function' kısaltmasını bir lambda ifadesi olarak kullanır. + + + + [] matches an empty list. + [] boş bir liste ile eşleşir. + + + + '_' is a wildcard pattern that matches anything. + '_' herhangi bir öğeyle eşleşen bir joker karakter desenidir. + + + + This handles the "or else" case. + Bu, "or else" durumunu ele alır. + + + + You can also use the shorthand function construct for pattern matching, + Kısaltma özellik yapısını desen eşleştirme için de kullanabilirsiniz, + + + + which is useful when you're writing functions which make use of Partial Application. + bu Kısmi Uygulamayı kullanan işlevler yazarken kullanışlıdır. + + + + Define some more functions which parse with the helper function. + Yardımcı işlev ile ayrıştırılan birkaç işlev daha tanımlayın. + + + + Active Patterns are another powerful construct to use with pattern matching. + Etkin Desenler, desen eşleştirme ile kullanabileceğiniz diğer bir güçlü yapıdır. + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + Giriş verilerini desen eşleştirme çağrı sitesinde bölerek özel formlara ayırmanıza olanak sağlar. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + 'Function' anahtar sözcüğü ve Etkin Desenler aracılığıyla Desen Eşleştirme, genellikle böyle görünür. + + + + Call the printer with some different values to parse. + Ayrıştırılacak farklı değerlerle yazıcıyı çağırın. + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + Seçenek değerleri 'Some' veya 'None' ile etiketlenmiş herhangi bir değer türü olabilir. + + + + They are used extensively in F# code to represent the cases where many other + Bunlar yaygın olarak diğer birçok dilin null başvurular kullandığı durumları temsil + + + + languages would use null references. + etmek üzere F# kodunda kullanılır. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + İlk olarak, Tek Durumlu Ayırt Edici Birleşim ile tanımlanan bir posta kodu tanımlayın. + + + + Next, define a type where the ZipCode is optional. + Sonra, ZipCode’un isteğe bağlı olduğu bir tür tanımlayın. + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + Sonra, müşterinin posta kodu için sevkiyat alanını hesaplayan bir nesneyi temsil eden arabirim türünü tanımlayın, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + 'getState' ve 'getShippingZone' soyut metotları uygulamalarından faydalanır. + + + + Next, calculate a shipping zone for a customer using a calculator instance. + Sonra, hesaplayıcı örneğini kullanarak müşteri için sevkiyat bölgesi hesaplayın. + + + + This uses combinators in the Option module to allow a functional pipeline for + Bu, Optionals ile veri dönüştürülmesini sağlamak için + + + + transforming data with Optionals. + Option modülünde birleştiricilerin kullanılmasını sağlar. + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + Ölçü birimleri, basit sayısal türler için tür açısından güvenli bir şekilde ek açıklama girmenin bir yoludur. + + + + You can then perform type-safe arithmetic on these values. + Böylece bu değerler üzerinde tür açısından güvenli aritmetik gerçekleştirebilirsiniz. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + İlk olarak, ortak birim adlarından oluşan bir koleksiyon açın + + + + Define a unitized constant + Birimlere ayrılmış bir sabit tanımlayın + + + + Next, define a new unit type + Sonra, yeni bir birim türü tanımlayın + + + + Conversion factor mile to meter. + Milden metreye dönüştürme faktörü. + + + + Define a unitized constant + Birimlere ayrılmış bir sabit tanımlayın + + + + Compute metric-system constant + Metrik sistem sabitini hesaplayın + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + Ölçü Birimleri kullanan değerler, yazdırma gibi işler için temel sayısal tür ile aynı şekilde kullanılabilir. + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + Sınıflar, F# içinde yeni nesneleri tanımlamanın bir yoludur ve standart Nesne yönelimli yapıları destekler. + + + + They can have a variety of members (methods, properties, events, etc.) + Çeşitli üyelere sahip olabilirler (metotlar, özellikler, olaylar vb.) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + Sınıflar hakkında daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + Üyeler hakkında daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + Basit bir iki boyutlu Vektör sınıfı. + + + + The class's constructor is on the first line, + Sınıfın oluşturucusu ilk satırdadır + + + + and takes two arguments: dx and dy, both of type 'double'. + ve ikisi de 'double' türünde olan iki bağımsız değişken alır: dx ve dy. + + + + This internal field stores the length of the vector, computed when the + Bu dahili alan, nesne oluşturulduğunda hesaplanan vektör + + + + object is constructed + uzunluğunu depolar + + + + 'this' specifies a name for the object's self identifier. + 'this', nesnenin kendi tanımlayıcısı için bir ad belirtir. + + + + In instance methods, it must appear before the member name. + Örnek metotlarında üye adından önce gelmelidir. + + + + This member is a method. The previous members were properties. + Bu üye, bir metot. Önceki üyeler özellikti. + + + + This is how you instantiate the Vector2D class. + Vector2D sınıfının örneğini bu şekilde oluşturabilirsiniz. + + + + Get a new scaled vector object, without modifying the original object. + Özgün nesneyi değiştirmeden, yeni bir ölçekli vektör nesnesi alın. + + + + Generic classes allow types to be defined with respect to a set of type parameters. + Genel sınıflar, türlerin bir tür parametreleri kümesine göre tanımlanmasına izin verir. + + + + In the following, 'T is the type parameter for the class. + Aşağıda, 'T', sınıf için tür parametresidir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + Bu dahili alan, bir listedeki durumları depolar. + + + + Add a new element to the list of states. + Durumlar listesine yeni bir öğe ekleyin. + + + + use the '<-' operator to mutate the value. + değeri değiştirmek için '<-' işlecini kullanın. + + + + Get the entire list of historical states. + Geçmiş durumların tam listesini alın. + + + + Get the latest state. + Son durumu alın. + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + Durum izleyicisi sınıfının bir 'int' örneği. Tür parametresinin algılandığını unutmayın. + + + + Add a state + Durum ekle + + + + Interfaces are object types with only 'abstract' members. + Arabirimler, yalnızca 'abstract' üyelere sahip olan nesne türleridir. + + + + Object types and object expressions can implement interfaces. + Nesne türleri ve nesne ifadeleri arabirim uygulayabilir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + Bu, IDisposable uygulayan bir türdür. + + + + This is the implementation of IDisposable members. + Bu, IDisposable üyelerinin uygulamasıdır. + + + + This is an object that implements IDisposable via an Object Expression + Bu, bir Object İfadesi ile IDisposable uygulayan bir nesnedir + + + + Unlike other languages such as C# or Java, a new type definition is not needed + C# veya Java gibi diğer dillerin aksine, bir arabirim uygulamak için yeni bir tür tanımı + + + + to implement an interface. + gerekli değildir. + + + + The FSharp.Core library defines a range of parallel processing functions. Here + FSharp.Core kitaplığı bir paralel işleme işlevleri aralığı tanımlar. Burada + + + + you use some functions for parallel processing over arrays. + diziler üzerinde çeşitli paralel işleme işlevleri kullanırsınız. + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + Daha fazla bilgi için bkz. https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + İlk olarak, bir giriş dizisi. + + + + Next, define a functions that does some CPU intensive computation. + Sonra, yoğun CPU kullanarak hesaplama yapan bir işlev tanımlayın. + + + + Next, do a parallel map over a large input array. + Sonra, büyük bir giriş dizisi üzerinde paralel bir eşleme oluşturun. + + + + Next, print the results. + Sonra, sonuçları yazdırın. + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + Events, .NET programlamasında özellikle WinForms veya WPF uygulamaları ile yaygın olarak kullanılan bir deyimdir. + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + Daha fazla bilgi için bkz. https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + İlk olarak, abonelik noktası (event.Publish) ve olay tetikleyicisinden (event.Trigger) oluşan Olay nesnesi örneğini oluşturun. + + + + Next, add handler to the event. + Sonra, olaya işleyici ekleyin. + + + + Next, trigger the event. + Sonra, olayı tetikleyin. + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + Sonra, olayın standart .NET kuralını takip eden bir örneğini oluşturun: (sender, EventArgs). + + + + Next, add a handler for this new event. + Sonra, bu yeni olay için bir işleyici ekleyin. + + + + Next, trigger this event (note that sender argument should be set). + Sonra, bu olayı tetikleyin (sender bağımsız değişkeninin ayarlanmış olması gerektiğine dikkat edin). + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hans.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hans.xlf new file mode 100644 index 0000000000..cb0a1983af --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hans.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + 此示例将引导你了解 F# 语言的各个元素。 + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + 若要在 F# 交互窗口中执行代码,请突出显示一个代码节并按 Alt-Enter 或右击 + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + 并选择“在 Interactive 中执行”。 可从“视图”菜单中打开 F# 交互窗口。 + + + + For more about F#, see: + 有关 F# 的详细信息,请参见: + + + + To see this tutorial in documentation form, see: + 若要以文档的形式查看此教程,请参阅: + + + + To learn more about applied F# programming, use + 若要了解有关已应用的 F# 编程的详细信息,请使用 + + + + To install the Visual F# Power Tools, use + 若要安装 Visual F# Power Tools,请使用 + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + “工具”-->“扩展和更新”-->“联机”和搜索 + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + 有关要用于 F# 的其他模板,请参见 Visual Studio 中的“联机模板”, + + + + 'New Project' --> 'Online Templates' + “新建项目”-->“联机模板” + + + + F# supports three kinds of comments: + F# 支持三种注释: + + + + 1. Double-slash comments. These are used in most situations. + 1. 双斜线注释。 此类注释用于大多数情况。 + + + + 2. ML-style Block comments. These aren't used that often. + 2. ML 样式块注释。此类注释不经常使用。 + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. 三斜线注释。此类注释用于记录功能和类型等。 + + + + They will appear as text when you hover over something which is decorated with these comments. + 光标悬停在附带有注释的位置时,这些注释会以文本形式显示。 + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + 它们还支持 .NET 样式的 XML 注释,这些注释可生成参考文档, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + 还可允许编辑器(例如 Visual Studio)从其中提取信息。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + 使用 "open" 关键字打开命名空间。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + 模块是值、类型和函数值等 F# 代码的分组。 + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + 用模块分组代码有助于汇集相关代码和避免程序中出现名称冲突。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + 此为示例整数。 + + + + This is a sample floating point number. + 此为示例浮点数。 + + + + This computed a new number by some arithmetic. Numeric types are converted using + 这按照某种运算方法计算新的数字。数字类型通过 + + + + functions 'int', 'double' and so on. + "int"、"double" 等函数进行转换。 + + + + This is a list of the numbers from 0 to 99. + 这是从 0 到 99 的数字列表 + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + 这是包含从 0 到 99 的所有数字及其平方的所有元组的列表. + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + 下一行打印包含元组的列表,使用 "%A" 来进行一般打印。 + + + + This is a sample integer with a type annotation + 这是一个具有类型注释的示例整数 + + + + Values in F# are immutable by default. They cannot be changed + F# 中的值默认为不可变。程序执行过程中 + + + + in the course of a program's execution unless explicitly marked as mutable. + 这些值无法更改,除非被显式标记为可变。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + 通过 "let" 将值绑定到名称可使其不可变。 + + + + The second line of code fails to compile because 'number' is immutable and bound. + 未能编译第二行代码,因为 "number" 不可变且已绑定。 + + + + Re-defining 'number' to be a different value is not allowed in F#. + F# 中不允许将 "number" 重定义为其他值。 + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + 一个可变绑定。必须提供这种绑定才能改变 "otherNumber" 的值。 + + + + When mutating a value, use '<-' to assign a new value. + 若要改变值,请使用 "<-" 分配新值。 + + + + You could not use '=' here for this purpose since it is used for equality + 在这里不能将 "=" 用作此目的,因为该符号用于表示等式 + + + + or other contexts such as 'let' or 'module' + 或者 "let" 或 "module" 等其他上下文 + + + + Much of F# programming consists of defining functions that transform input data to produce + 大部分 F# 编程包括定义函数,该函数转换输入数据以生成 + + + + useful results. + 有用的结果。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + 可使用 "let" 定义函数。它将接受整数参数,然后返回整数。 + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + 括号对函数参数是可选的,但使用显示类型注释时除外。 + + + + Apply the function, naming the function return result using 'let'. + 应用函数,并使用“let”命名函数返回结果。 + + + + The variable type is inferred from the function return type. + 变量类型是从函数返回类型推导出来的。 + + + + This line uses '%d' to print the result as an integer. This is type-safe. + 该行用 "%d" 将结果作为整数进行打印。这属于类型安全。 + + + + If 'result1' were not of type 'int', then the line would fail to compile. + 如果 "result1" 不是类型 "int",则将无法编译该行。 + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + 如有需要,可使用 "(argument:type)" 批注参数名称类型。括号是必需的。 + + + + Conditionals use if/then/elid/elif/else. + 条件语句使用 if/then/elid/elif/else。 + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + 注意,F# 使用可识别空格缩进的语法,与 Python 等语言类似。 + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + 此行使用 "%f" 将结果作为浮点打印。与上述 "%d" 情况一样,属于类型安全。 + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + 布尔是 F# 中的基本数据类型。下面是一些布尔值和条件逻辑示例。 + + + + To learn more, see: + 有关详细信息,请参阅: + + + + and + + + + + Booleans values are 'true' and 'false'. + 布尔值为 "true" 和 "false"。 + + + + Operators on booleans are 'not', '&&' and '||'. + 布尔运算符为 "not"、"&&" 和 "||"。 + + + + This line uses '%b'to print a boolean value. This is type-safe. + 本行用 "%b" 打印布尔值。这属于类型安全。 + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + 字符串是 F# 中的基本数据类型。下面是一些字符串和基本的字符串操作示例。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + 字符串使用双引号。 + + + + Strings can also use @ to create a verbatim string literal. + 字符串也可使用 @ 创建逐字的字符串。 + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + 这将忽略转义字符,如 "\", "\n", "\t" 等。 + + + + String literals can also use triple-quotes. + 字符串文本也可使用三重引号。 + + + + String concatenation is normally done with the '+' operator. + 字符串串联通常是用 "+" 运算符完成的。 + + + + This line uses '%s' to print a string value. This is type-safe. + 本行用 "%s" 打印字符串值。这属于类型安全。 + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + 子字符串使用索引表示法。此行提取前 7 个字符作为子字符串。 + + + + Note that like many languages, Strings are zero-indexed in F#. + 注意,与许多语言相同,字符串在 F# 中从零开始编制索引。 + + + + Tuples are simple combinations of data values into a combined value. + 元组是组合成组合值的简单数据值组合。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + 一个包含整数的简单元组。 + + + + A function that swaps the order of two values in a tuple. + 一个用于交换两个值在元组中的顺序的函数。 + + + + F# Type Inference will automatically generalize the function to have a generic type, + F# 类型推理可自动泛化函数,使其具有泛型类型, + + + + meaning that it will work with any type. + 意味着它可与任何类型兼容。 + + + + A tuple consisting of an integer, a string, + 一个整数,一个字符串以及 + + + + and a double-precision floating point number. + 一个双精度浮点数字组成的元组。 + + + + A simple tuple of integers with a type annotation. + 一个具有类型批注的简单的整数元组。 + + + + Type annotations for tuples use the * symbol to separate elements + 元组的类型批注使用 * 号来分隔元素 + + + + Tuples are normally objects, but they can also be represented as structs. + 元组通常为对象,但也可表示为结构。 + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + 这些可在 C# 和 Visual Basic.NET 中与结构完全进行交互操作;然而, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + 结构元组不隐式转换为对象元组(通常称为引用元组)。 + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + 下面的第二行将因此无法编译。取消注释观察将发生什么。 + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + 尽管不能在结构元组和引用元组之间进行隐式转换, + + + + you can explicitly convert via pattern matching, as demonstrated below. + 可通过模式匹配进行显式转换,如下所示。 + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + F# 管道运算符("|>"、"<|" 等 )和 F# 组合运算符(">>"、"<<") + + + + are used extensively when processing data. These operators are themselves functions + 广泛用于数据处理。这些运算符本身就是函数, + + + + which make use of Partial Application. + 它使用偏函数应用。 + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + 若要深入了解这些运算符,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + 若要深入了解偏函数应用,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + 计算值的平方。 + + + + Adds 1 to a value. + 将值加 1。 + + + + Tests if an integer value is odd via modulo. + 通过取模测试整数是否为奇数。 + + + + A list of 5 numbers. More on lists later. + 包含 5 个数字的列表。稍后列表上会有更多数字。 + + + + Given a list of integers, it filters out the even numbers, + 如果是整数列表,它会筛选出偶数, + + + + squares the resulting odds, and adds 1 to the squared odds. + 将产生的奇数平方,然后将奇数平方值加 1。 + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + 编写 "squareOddValuesAndAddOne" 的简便方法是将每个 + + + + sub-result into the function calls themselves. + 子结果嵌入函数调用本身。 + + + + This makes the function much shorter, but it's difficult to see the + 这将使函数短得多,但难以查看 + + + + order in which the data is processed. + 处理数据的顺序。 + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + 编写 "squareOddValuesAndAddOne" 的首选方法是使用 F# 管道运算符。 + + + + This allows you to avoid creating intermediate results, but is much more readable + 这可使你避免产生中间结果,而且可读性更好 + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + 嵌入式函数调用(如 "squareOddValuesAndAddOneNested")更具可读性 + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + 使用 Lambda 函数,通过将第二个 "List.map" 调用移动到第一个, + + + + into the first, using a Lambda Function. + 可以缩短 "squareOddValuesAndAddOnePipeline"。 + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + 注意,管道也在 lambda 函数内使用。F# 管道运算符 + + + + can be used for single values as well. This makes them very powerful for processing data. + 还可用于单个值。这使它们处理数据的功能很强大。 + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + 最后,无需再将 "value" 显式作为参数,你可使用 ">>" + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + 以合成两个核心运算: 筛选出偶数,然后平方并加 1。 + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + 同样,lambda 表达式的 "fun x -> ..." 也不需要了,因为 "x" 只是 + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + 在该范围内定义,以便可传递到功能管道。因此,也可将 ">>" + + + + there as well. + 用在该处。 + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + "squareOddValuesAndAddOneComposition" 的结果本身就是另一个函数,它 + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + 将整数列表作为其输入值。如果使用整数列表执行 "squareOddValuesAndAddOneComposition", + + + + of integers, you'll notice that it produces the same results as previous functions. + 你将发现它与上述函数产生的结果相同。 + + + + This is using what is known as function composition. This is possible because functions in F# + 这使用的就是所谓的函数组合。这是可能的,因为 F# 中的函数 + + + + use Partial Application and the input and output types of each data processing operation match + 使用偏函数应用,并且每个数据处理操作的输入和输出类型与 + + + + the signatures of the functions we're using. + 我们使用的函数签名。 + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + 列表属于有序、不可变、单向链接的列表。它们都采用主动求值方式。 + + + + This module shows various ways to generate lists and process lists with some functions + 本模块介绍使用某些函数生成列表和处理列表的各种方法 + + + + in the 'List' module in the F# Core Library. + 在 F# 核心库的 "List" 模块中。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + 使用 [ ... ] 定义列表。这是空列表。 + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + 这是一个包含 3 个元素的列表。";" 用于分隔同一行的元素。 + + + + You can also separate elements by placing them on their own lines. + 也可通过将各元素放在其自身行来分隔。 + + + + This is a list of integers from 1 to 1000 + 这是从 1 到 1000 的整数列表 + + + + Lists can also be generated by computations. This is a list containing + 也可通过计算来生成列表。此列表包含 + + + + all the days of the year. + 一年的所有天。 + + + + Print the first 5 elements of 'daysList' using 'List.take'. + 使用 "List.take" 打印 "daysList" 的前 5 个元素。 + + + + Computations can include conditionals. This is a list containing the tuples + 计算可以包括条件。这是包含元组的列表 + + + + which are the coordinates of the black squares on a chess board. + 这是棋盘上黑色方格的坐标。 + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + 列表可使用 "List.map" 和其他函数编程连结符进行转换。 + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + 此定义通过使用管道将 numberList 中的数字进行平方运算来生成新列表 + + + + operator to pass an argument to List.map. + 将参数传递给 List.map 的运算符。 + + + + There are many other list combinations. The following computes the sum of the squares of the + 还有许多其他列表组合。下面计算以下内容的平方和: + + + + numbers divisible by 3. + 数字可被 3 整除。 + + + + Arrays are fixed-size, mutable collections of elements of the same type. + 数组是固定大小,同类型元素的可变集合。 + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + 尽管它们与列表相同(支持枚举,且具有用于数据处理的类似连接符), + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + 它们通常速度更快,且支持快速随机访问。代价是因为可变而不太安全。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + 这是空数组。注意,语法与列表类似,但改用 `[| ... |]`。 + + + + Arrays are specified using the same range of constructs as lists. + 使用与列表相同的构造范围来指定数组。 + + + + This is an array of numbers from 1 to 1000. + 这是从 1 到 1000 的数字数组。 + + + + This is an array containing only the words "hello" and "world". + 这是只包含单词 "hello" 和 "world" 的数组。 + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + 这是由索引初始化的数组,包含从 0 到 2000 之间的偶数。 + + + + Sub-arrays are extracted using slicing notation. + 使用切片表示法提取子数组。 + + + + You can loop over arrays and lists using 'for' loops. + 可使用 "for" 循环循环数组和列表。 + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + 可使用左箭头赋值运算符来修改数组元素的内容。 + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + 若要深入了解此运算符,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + 可使用 "Array.map" 和其他功能性编程运算来转换数组。 + + + + The following calculates the sum of the lengths of the words that start with 'h'. + 下面的函数计算以 "h" 开头的单词的总长度。 + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + 序列是类型相同的所有元素的逻辑系列。序列是比列表和数组更常规的类型。 + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + 将根据需要计算序列,并在每次循环访问它们时重新进行计算。 + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + F# 序列是 .NET System.Collections.Generic.IEnumerable<'T> 的别名。 + + + + Sequence processing functions can be applied to Lists and Arrays as well. + 序列处理函数也可以应用于列表和数组。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + 这是空序列。 + + + + This a sequence of values. + 这是一个值的序列。 + + + + This is an on-demand sequence from 1 to 1000. + 这是从 1 到 1000 的按需序列。 + + + + This is a sequence producing the words "hello" and "world" + 这是生成单词 "hello" 和 "world" 的序列 + + + + This sequence producing the even numbers up to 2000. + 此序列生成最大为 2000 的偶数。 + + + + This is an infinite sequence which is a random walk. + 这是可随机访问的无限序列。 + + + + This example uses yield! to return each element of a subsequence. + 此示例使用 yield! 返回子序列的每个元素。 + + + + This example shows the first 100 elements of the random walk. + 此示例演示随机访问的前 100 个元素。 + + + + Recursive functions can call themselves. In F#, functions are only recursive + 递归函数可调用其自身。在 F# 中,函数只递归 + + + + when declared using 'let rec'. + 使用 "let rec" 声明时。 + + + + Recursion is the preferred way to process sequences or collections in F#. + 递归是 F# 中处理序列或集合的首选方式。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + 此示例演示递归函数,计算以下内容的阶乘: + + + + integer. It uses 'let rec' to define a recursive function. + 整数。它使用 "let rec" 来定义递归函数。 + + + + Computes the greatest common factor of two integers. + 计算两个整数的最大公因数。 + + + + Since all of the recursive calls are tail calls, + 由于所有递归调用都是尾调用, + + + + the compiler will turn the function into a loop, + 因此编译器会将该函数转变成一个循环, + + + + which improves performance and reduces memory consumption. + 这可提高性能并减少内存消耗。 + + + + This example computes the sum of a list of integers using recursion. + 本示例使用递归计算整数列表的总和。 + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + 通过将 Helper 函数与结果累加器一起使用,使 "sumList" 成为尾递归函数。 + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + 假如 "0" 作为种子累加器,这将调用尾递归 helper 函数。 + + + + An approach like this is common in F#. + 此类方法在 F# 中很常见。 + + + + Records are an aggregate of named values, with optional members (such as methods). + 记录是已命名值的聚合,同时具有可选成员(例如,方法)。 + + + + They are immutable and have structural equality semantics. + 它们不可变且具有结构相等性语义。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + 此示例演示如何定义新记录类型。 + + + + This example shows how to instantiate a record type. + 本示例演示如何实例化记录类型。 + + + + You can also do this on the same line with ';' separators. + 也可使用 ";" 分隔符在同一行上执行此操作。 + + + + This example shows how to use "copy-and-update" on record values. It creates + 此示例演示如何对记录值使用 "copy-and-update"。它创建了 + + + + a new record value that is a copy of contact1, but has different values for + 新的记录值,该值是 contact1 的副本,但对以下内容具有不同的值: + + + + the 'Phone' and 'Verified' fields. + “电话”和“已验证”字段。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + 此示例演示如何编写处理记录值的函数。 + + + + It converts a 'ContactCard' object to a string. + 它将 "ContactCard" 对象转换为字符串。 + + + + This is an example of a Record with a member. + 这是一个具有成员的记录示例。 + + + + Members can implement object-oriented members. + 成员可实现面向对象的成员。 + + + + Members are accessed via the '.' operator on an instantiated type. + 可通过实例化类型上的 "." 运算符访问成员。 + + + + Records can also be represented as structs via the 'Struct' attribute. + 记录也可通过 "Struct" 属性表示为结构。 + + + + This is helpful in situations where the performance of structs outweighs + 这在结构性能更重要的情况下很有用 + + + + the flexibility of reference types. + 引用类型的灵活性。 + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + 可区分联合(简称 DU)的值可以是一系列已命名窗体或用例。 + + + + Data stored in DUs can be one of several distinct values. + DU 中存储的数据可以为多个不同值之一。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + 下面代表一套扑克牌。 + + + + A Disciminated Union can also be used to represent the rank of a playing card. + 可区分联合还可用来表示纸牌的设置级别。 + + + + Represents the rank of cards 2 .. 10 + 表示扑克牌点数 2 .. 10 + + + + Discriminated Unions can also implement object-oriented members. + 可区分联合还可实现面向对象的成员。 + + + + This is a record type that combines a Suit and a Rank. + 这是结合花色和牌面大小的记录类型。 + + + + It's common to use both Records and Disciminated Unions when representing data. + 表示数据时同时使用记录和可区分联合是很常见的。 + + + + This computes a list representing all the cards in the deck. + 它将计算代表牌组中所有扑克牌的列表。 + + + + This example converts a 'Card' object to a string. + 此示例将“纸牌”对象转换为字符串。 + + + + This example prints all the cards in a playing deck. + 此示例打印扑克牌中的所有牌。 + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + 单用例 DU 常用于域建模。这可确保额外类型的安全 + + + + over primitive types such as strings and ints. + 字符串和整数等基元类型。 + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + 单用例 DU 无法隐式转换为其包装的类型或从其包装的类型进行转换。 + + + + For example, a function which takes in an Address cannot accept a string as that input, + 例如,地址中采用的函数无法接受字符串作为输入, + + + + or vive/versa. + 反之亦然。 + + + + You can easily instantiate a single-case DU as follows. + 可轻松实例化单用例 DU,如下所示。 + + + + When you need the value, you can unwrap the underlying value with a simple function. + 需要值时,可使用单个函数解包基础值。 + + + + Printing single-case DUs is simple with unwrapping functions. + 打印单用例 DU 与解包函数一样简单。 + + + + Disciminated Unions also support recursive definitions. + 可区分联合还支持递归定义。 + + + + This represents a Binary Search Tree, with one case being the Empty tree, + 这代表一个二进制文件搜索树,且有一个用例为空树, + + + + and the other being a Node with a value and two subtrees. + 而另一个用例为具有一个值和两个子树的节点。 + + + + Check if an item exists in the binary search tree. + 检查项是否存在于二进制文件搜索树中。 + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + 使用模式匹配进行递归搜索。如果存在,则返回 true,否则返回 false。 + + + + Check the left subtree. + 检查左子树。 + + + + Check the right subtree. + 检查右子树。 + + + + Inserts an item in the Binary Search Tree. + 在二进制文件搜索树中插入项。 + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + 查找使用模式匹配递归插入的位置,然后插入新节点。 + + + + If the item is already present, it does not insert anything. + 如果项已存在,则不会插入任何内容。 + + + + No need to insert, it already exists; return the node. + 无需插入,该项已存在;返回节点。 + + + + Call into left subtree. + 调入左子树。 + + + + Call into right subtree. + 调入右子树。 + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + 可区分联合也可通过 "Struct" 属性表示为结构。 + + + + This is helpful in situations where the performance of structs outweighs + 这在结构性能更重要的情况下很有用 + + + + the flexibility of reference types. + 引用类型的灵活性。 + + + + However, there are two important things to know when doing this: + 然而,执行此操作时需了解两个重要事项: + + + + 1. A struct DU cannot be recursively-defined. + 1. 无法以递归方式定义结构 DU。 + + + + 2. A struct DU must have unique names for each of its cases. + 2. 结构 DU 必须对其每个用例均有唯一名称。 + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + 模式匹配是 F# 的一个功能,使你能够利用模式, + + + + which are a way to compare data with a logical structure or structures, + 它们是将数据与逻辑结构或结构进行比较的方法, + + + + decompose data into constituent parts, or extract information from data in various ways. + 将数据分解为各个构成部分,或通过各种方式从数据中提取信息。 + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + 然后,你便可以在模式的“形状”上通过模式匹配进行派遣。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + 人员的姓氏和名字的记录 + + + + A Discriminated Union of 3 different kinds of employees + 具有 3 种不同员工的可区分联合 + + + + Count everyone underneath the employee in the management hierarchy, + 在管理层次结构下对员工进行计数, + + + + including the employee. + 其中包括员工。 + + + + Find all managers/executives named "Dave" who do not have any reports. + 查找所有名为 "Dave" 且没有任何下属的经理/主管。 + + + + This uses the 'function' shorthand to as a lambda expression. + 这使用 "function" 简写为 lambda 表达式。 + + + + [] matches an empty list. + [] 匹配空列表。 + + + + '_' is a wildcard pattern that matches anything. + "_" 是与任何对象均匹配的通配符模式。 + + + + This handles the "or else" case. + 它处理 "or else" 情况。 + + + + You can also use the shorthand function construct for pattern matching, + 你也可将简写函数构造用于模式匹配, + + + + which is useful when you're writing functions which make use of Partial Application. + 这在编写使用偏函数应用的函数时很有用。 + + + + Define some more functions which parse with the helper function. + 定义更多使用 helper 函数分析的函数。 + + + + Active Patterns are another powerful construct to use with pattern matching. + 活动模式是另一个与模式匹配配合使用的强大构造。 + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + 它们使你能够将输入数据分区到自定义窗体,然后在模式匹配调用站点分解它们。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + 通过 "function" 关键字的匹配模式和活动模式通常如下所示。 + + + + Call the printer with some different values to parse. + 使用一些其他值调用打印机进行分析。 + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + 选项值是用“Some”或“None”标记的任何类型的值。 + + + + They are used extensively in F# code to represent the cases where many other + 它们在 F# 代码中广泛用于表示许多其他 + + + + languages would use null references. + 语言使用 null 引用的用例。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + 首先,定义通过单用例可区分联合定义的邮政编码。 + + + + Next, define a type where the ZipCode is optional. + 接下来,定义一个类型,其中 ZipCode 是可选项。 + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + 接下来,定义表示对象的接口类型,用于计算客户邮政编码的送货区域, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + 假定提供了“getState”和“getShippingZone”抽象方法的实现。 + + + + Next, calculate a shipping zone for a customer using a calculator instance. + 接下来,使用计算器实例计算客户的发货区域。 + + + + This uses combinators in the Option module to allow a functional pipeline for + 它在选项模块中使用连接符以允许功能管道 + + + + transforming data with Optionals. + 用于使用可选项转换数据。 + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + 度量单位是一种以类型安全方式批注基元数值类型的方式。 + + + + You can then perform type-safe arithmetic on these values. + 然后,你便可以对这些值执行类型安全算术。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + 首先,打开常用单位名称集合 + + + + Define a unitized constant + 定义单元化常量 + + + + Next, define a new unit type + 接下来,定义新的单位类型 + + + + Conversion factor mile to meter. + 英里到米的换算系数。 + + + + Define a unitized constant + 定义单元化常量 + + + + Compute metric-system constant + 计算公制常量 + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + 使用度量单位的值可像基元数值类型用于打印等操作一样直接使用。 + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + 类是 F# 中定义新对象类型的一种方式,且支持标准的面向对象的构造。 + + + + They can have a variety of members (methods, properties, events, etc.) + 它们可以有各种成员(如,方法、属性、事件等) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + 若要了解关于类的详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + 若要深入了解成员,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + 简单的二维矢量类。 + + + + The class's constructor is on the first line, + 该类的构造函数位于第一行, + + + + and takes two arguments: dx and dy, both of type 'double'. + 并且采用两个参数: dx 和 dy,二者均属于类型 "double"。 + + + + This internal field stores the length of the vector, computed when the + 此内部字段存储矢量的长度,当发生以下情况时进行计算: + + + + object is constructed + 对象已构造 + + + + 'this' specifies a name for the object's self identifier. + “this”用于指定对象的自我标识符的名称。 + + + + In instance methods, it must appear before the member name. + 在实例方法中,它必须出现在成员名称之前。 + + + + This member is a method. The previous members were properties. + 该成员属于方法。以前的成员属于属性。 + + + + This is how you instantiate the Vector2D class. + 这就是你实例化 Vector2D 类的方式。 + + + + Get a new scaled vector object, without modifying the original object. + 获取新的缩放矢量对象而不修改原始对象。 + + + + Generic classes allow types to be defined with respect to a set of type parameters. + 通用类允许考虑使用一组类型参数来定义类型。 + + + + In the following, 'T is the type parameter for the class. + 以下示例中,"T" 表示类的类型参数。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + 此内部字段将状态存储在列表中。 + + + + Add a new element to the list of states. + 将新元素添加到状态列表中。 + + + + use the '<-' operator to mutate the value. + 使用 "<-" 运算符改变值。 + + + + Get the entire list of historical states. + 获取历史状态的完整列表。 + + + + Get the latest state. + 获取最新状态。 + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + 状态跟踪程序类的一个“int”实例。请注意,已推断类型参数。 + + + + Add a state + 添加状态 + + + + Interfaces are object types with only 'abstract' members. + 接口是只有“抽象”成员的对象类型。 + + + + Object types and object expressions can implement interfaces. + 对象类型和对象表达式可以实现接口。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + 它是实现 IDisposable 的类型。 + + + + This is the implementation of IDisposable members. + 它是 IDisposable 成员的实现。 + + + + This is an object that implements IDisposable via an Object Expression + 该对象可通过对象表达式实现 IDisposable + + + + Unlike other languages such as C# or Java, a new type definition is not needed + 与 C# 或 Java 等其他语言不同,无需新的类型定义 + + + + to implement an interface. + 以实现接口。 + + + + The FSharp.Core library defines a range of parallel processing functions. Here + FSharp.Core 库定义了一系列并行处理函数。此处 + + + + you use some functions for parallel processing over arrays. + 可使用某些函数对数组进行并行处理。 + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + 有关详细信息,请参阅: https://msdn.microsoft.com/zh-cn/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + 首先,输入一个数组。 + + + + Next, define a functions that does some CPU intensive computation. + 接下来,定义执行某些 CPU 密集型计算的函数。 + + + + Next, do a parallel map over a large input array. + 接下来,对大型输入数组执行并行映射。 + + + + Next, print the results. + 接下来,打印结果。 + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + 事件是 .NET 编程的常见习惯用语,尤其是使用 WinForms 或 WPF 应用程序编程时。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + 有关详细信息,请参阅: https://docs.microsoft.com/zh-cn/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + 首先,创建包含订阅点(event.Publish)和事件触发器(event.Trigger)的事件对象实例。 + + + + Next, add handler to the event. + 接下来,将处理程序添加到事件。 + + + + Next, trigger the event. + 接下来,触发该事件。 + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + 接下来,创建遵循标准 .NET 约定的事件的实例: (sender, EventArgs)。 + + + + Next, add a handler for this new event. + 接下来,为此新事件添加处理程序。 + + + + Next, trigger this event (note that sender argument should be set). + 接下来,触发此事件(请注意,应设置 sender 参数)。 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hant.xlf b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hant.xlf new file mode 100644 index 0000000000..fd33d17fa3 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/Template/xlf/Tutorial.fsx.zh-Hant.xlf @@ -0,0 +1,1637 @@ + + + + + + This sample will guide you through elements of the F# language. + 此範例將引導您了解 F# 語言的項目。 + + + + To execute the code in F# Interactive, highlight a section of code and press Alt-Enter or right-click + 若要執行 F# 互動中的程式碼,請反白顯示某個程式碼區段並按下 Alt-Enter,或者以滑鼠右鍵按一下 + + + + and select "Execute in Interactive". You can open the F# Interactive Window from the "View" menu. + 並選取 [以互動方式執行]。您可以從 [檢視] 功能表開啟 F# 互動式視窗。 + + + + For more about F#, see: + 如需有關 F# 的詳細資訊,請參閱: + + + + To see this tutorial in documentation form, see: + 若要參閱文件表單中的此教學課程,請參閱: + + + + To learn more about applied F# programming, use + 如需深入了解套用的 F# 程式設計,請使用 + + + + To install the Visual F# Power Tools, use + 若要安裝 Visual F# Power Tools,請使用 + + + + 'Tools' --> 'Extensions and Updates' --> `Online` and search + [工具]5D; --> [延伸模組和更新]5D; --> [連線]5D; 並搜尋 + + + + For additional templates to use with F#, see the 'Online Templates' in Visual Studio, + 如需有關搭配 F# 一起使用的其他範本,請參閱 Visual Studio 中的 [線上範本]5D;, + + + + 'New Project' --> 'Online Templates' + [新增專案]5D; --> [線上範本]5D; + + + + F# supports three kinds of comments: + F# 支援三種註解: + + + + 1. Double-slash comments. These are used in most situations. + 1. 將註解加上雙斜線。適用於大部分的情況。 + + + + 2. ML-style Block comments. These aren't used that often. + 2. 將註解加上 ML 樣式區塊。較不常使用。 + + + + 3. Triple-slash comments. These are used for documenting functions, types, and so on. + 3. 將註解加上三斜線。適用於記錄函式、類型等。 + + + + They will appear as text when you hover over something which is decorated with these comments. + 當您暫留在以這些註解為裝飾的項目上時,這些註解會顯示為文字。 + + + + They also support .NET-style XML comments, which allow you to generate reference documentation, + 這些註解也支援 .NET 樣式的 XML 註解,讓您可以產生參考文件, + + + + and they also allow editors (such as Visual Studio) to extract information from them. + 也讓編輯者 (像是 Visual Studio) 可以從註解中擷取資訊。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation + 若要深入了解,請參閱: https://docs.microsoft.com/zh-tw/dotnet/articles/fsharp/language-reference/xml-documentation + + + + Open namespaces using the 'open' keyword. + 使用 'open' 關鍵字開啟命名空間。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + 若要深入了解,請參閱: https://docs.microsoft.com/zh-tw/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword + + + + A module is a grouping of F# code, such as values, types, and function values. + 模組是 F# 程式碼的分組,例如值、類型及函式值。 + + + + Grouping code in modules helps keep related code together and helps avoid name conflicts in your program. + 將程式碼分組為模組有助於將相關的程式碼整合在一塊,且能避免程式發生名稱衝突。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/modules + 若要深入了解,請參閱: https://docs.microsoft.com/zh-tw/dotnet/articles/fsharp/language-reference/modules + + + + This is a sample integer. + 此為範例整數。 + + + + This is a sample floating point number. + 此為範例浮點數。 + + + + This computed a new number by some arithmetic. Numeric types are converted using + 這使用了一些算數來計算新數字。使用函式 'int'、'double' 等 + + + + functions 'int', 'double' and so on. + 來轉換數字類型。 + + + + This is a list of the numbers from 0 to 99. + 此為從 0 到 99 的數字清單。 + + + + This is a list of all tuples containing all the numbers from 0 to 99 and their squares. + 此為所有 Tuple 的清單,內含從 0 到 99 的所有數字及其平方。 + + + + The next line prints a list that includes tuples, using '%A' for generic printing. + 下一行會使用 '%A' 執行一般列印,來列印包含 Tuple 的清單。 + + + + This is a sample integer with a type annotation + 此為具有型別註解的範例整數 + + + + Values in F# are immutable by default. They cannot be changed + 根據預設,F# 中的值是不可變的。於程式執行過程中,除非明確標示為可變的 + + + + in the course of a program's execution unless explicitly marked as mutable. + 否則無法對其進行變更。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable + + + + Binding a value to a name via 'let' makes it immutable. + 透過 'let' 將值繫結到名稱,即可將它設為不可變動。 + + + + The second line of code fails to compile because 'number' is immutable and bound. + 因為 'number' 無法變動並已繫結,所以無法編譯第二行程式碼。 + + + + Re-defining 'number' to be a different value is not allowed in F#. + 在 F# 中,不得將 'number' 重新定義為不同的值。 + + + + A mutable binding. This is required to be able to mutate the value of 'otherNumber'. + 可變動的繫結。需要此項目才可變更 'otherNumber' 的值。 + + + + When mutating a value, use '<-' to assign a new value. + 變動值時,請使用 '<-' 指派新的值。 + + + + You could not use '=' here for this purpose since it is used for equality + '=' 在此表示等於,所以無法用於此用途 + + + + or other contexts such as 'let' or 'module' + 或其他內容,例如 'let' 或 'module' + + + + Much of F# programming consists of defining functions that transform input data to produce + F# 程式設計時常需要定義函式來轉換輸入資料,從而產生 + + + + useful results. + 實用的結果。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/ + + + + You use 'let' to define a function. This one accepts an integer argument and returns an integer. + 您可以使用 'let' 來定義函式。此接受整數引數,並會傳回整數。 + + + + Parentheses are optional for function arguments, except for when you use an explicit type annotation. + 對函式引數來說不一定要使用括號,但使用明確的型別註解時例外。 + + + + Apply the function, naming the function return result using 'let'. + 套用函式,使用 'let' 命名函數會傳回結果。 + + + + The variable type is inferred from the function return type. + 變數型別是從函式傳回型別推斷出來。 + + + + This line uses '%d' to print the result as an integer. This is type-safe. + 此行使用 '%d' 以整數形式列印結果。這是型別安全。 + + + + If 'result1' were not of type 'int', then the line would fail to compile. + 如果 'result1' 的類型不是 'int',則無法編譯該行。 + + + + When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required. + 需要時,請使用 '(argument:type)' 為參數名稱的類型加上標註。需要使用括號。 + + + + Conditionals use if/then/elid/elif/else. + 條件使用 if/then/elid/elif/else。 + + + + Note that F# uses whitespace indentation-aware syntax, similar to languages like Python. + 請注意,F# 使用空白縮排感知語法,其與 Python 這類語言類似。 + + + + This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe. + 此行使用 '%f' 以浮點形式列印結果。與上述 '%d' 相同,這是型別安全。 + + + + Booleans are fundamental data types in F#. Here are some examples of Booleans and conditional logic. + 布林值是 F# 中的基本資料類型。以下是一些布林值與條件式邏輯的範例。 + + + + To learn more, see: + 若要深入了解,請參閱: + + + + and + + + + + Booleans values are 'true' and 'false'. + 布林值為 'true' 和 'false'。 + + + + Operators on booleans are 'not', '&&' and '||'. + 布林值上的運算子為 'not'、'&&' 和 '||'。 + + + + This line uses '%b'to print a boolean value. This is type-safe. + 此行使用 '%b' 列印布林值。這是型別安全。 + + + + Strings are fundamental data types in F#. Here are some examples of Strings and basic String manipulation. + 字串在 F# 中是基本的資料類型。以下是一些字串與基本字串操作的範例。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/strings + + + + Strings use double quotes. + 字串使用雙引號。 + + + + Strings can also use @ to create a verbatim string literal. + 字串也可使用 @ 來建立逐字字串常值。 + + + + This will ignore escape characters such as '\', '\n', '\t', etc. + 這將會忽略逸出字元,例如 '\'、'\n'、'\t' 等等。 + + + + String literals can also use triple-quotes. + 字串常值也可使用三引號。 + + + + String concatenation is normally done with the '+' operator. + 串連字串通常使用 '+' 運算子進行。 + + + + This line uses '%s' to print a string value. This is type-safe. + 此行使用 '%s' 列印字串值。這是型別安全。 + + + + Substrings use the indexer notation. This line extracts the first 7 characters as a substring. + 子字串使用索引子標記法。此行會擷取前 7 個字元作為子字串。 + + + + Note that like many languages, Strings are zero-indexed in F#. + 請注意,就像許多語言一樣,字串在 F# 中會以零為基底編製索引。 + + + + Tuples are simple combinations of data values into a combined value. + 元組是簡單的資料值合併為合併值。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/tuples + + + + A simple tuple of integers. + 簡式整數元組。 + + + + A function that swaps the order of two values in a tuple. + 將元組中兩個值的順序互換的函式。 + + + + F# Type Inference will automatically generalize the function to have a generic type, + F# 型別推斷會自動將函式一般化成泛型類型, + + + + meaning that it will work with any type. + 表示其可與任何類型搭配運作。 + + + + A tuple consisting of an integer, a string, + 元組,包含整數、字串、 + + + + and a double-precision floating point number. + 和雙精確度浮點數。 + + + + A simple tuple of integers with a type annotation. + 具有類型註釋之整數的簡單元組。 + + + + Type annotations for tuples use the * symbol to separate elements + 元組的類型註釋會使用 * 符號分隔項目 + + + + Tuples are normally objects, but they can also be represented as structs. + 元組一般是物件,但也可以用結構形式呈現。 + + + + These interoperate completely with structs in C# and Visual Basic.NET; however, + 這些會與 C# 和 Visual Basic .NET 中的結構完全相互操作; 不過, + + + + struct tuples are not implicitly convertable with object tuples (often called reference tuples). + 結構元組無法利用物件元組 (通常稱為參考元組) 進行隱含轉換。 + + + + The second line below will fail to compile because of this. Uncomment it to see what happens. + 因此,將無法編譯以下的第二行。請取消它的註解,看看會如何。 + + + + Although you cannot implicitly convert between struct tuples and reference tuples, + 雖然您不能隱含地在結構元組及參考元組間進行轉換, + + + + you can explicitly convert via pattern matching, as demonstrated below. + 但您可透過模式比對明確地轉換,如下所示。 + + + + The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<') + F# 管道運算子 ('|>'、'<|' 等) 與 F# 組合運算子 ('>>'、'<<') + + + + are used extensively when processing data. These operators are themselves functions + 廣泛用於處理資料時。這些運算子本身就是函式 + + + + which make use of Partial Application. + 其會利用局部應用程式。 + + + + To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + 若要深入了解這些運算子,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining + + + + To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + 若要深入了解局部應用程式,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments + + + + Squares a value. + 產生值的平方。 + + + + Adds 1 to a value. + 將值加 1。 + + + + Tests if an integer value is odd via modulo. + 測試整數值是否為經過模數的奇數。 + + + + A list of 5 numbers. More on lists later. + 5 個數字的清單。清單上稍後會有更多項目。 + + + + Given a list of integers, it filters out the even numbers, + 提供整數清單,它會篩選出偶數, + + + + squares the resulting odds, and adds 1 to the squared odds. + 取結果奇數的平方值,並對平方後的奇數加 1。 + + + + A shorter way to write 'squareOddValuesAndAddOne' is to nest each + 撰寫 'squareOddValuesAndAddOne' 較簡短的方式是巢狀每個項目 + + + + sub-result into the function calls themselves. + 子結果進入函式呼叫本身。 + + + + This makes the function much shorter, but it's difficult to see the + 這會將函式設成更短,但較難查看 + + + + order in which the data is processed. + 資料的處理順序。 + + + + A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators. + 撰寫 'squareOddValuesAndAddOne' 的慣用方式是使用 F# 管道運算子。 + + + + This allows you to avoid creating intermediate results, but is much more readable + 這可讓您避免建立中繼結果,但比較容易閱讀 + + + + than nesting function calls like 'squareOddValuesAndAddOneNested' + ,相較於 'squareOddValuesAndAddOneNested' 這類的巢狀函式呼叫 + + + + You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call + 您可以移動第二個 'List.map' 呼叫來縮短 'squareOddValuesAndAddOnePipeline' + + + + into the first, using a Lambda Function. + 到第一個項目,使用 Lambda 函式。 + + + + Note that pipelines are also being used inside the lambda function. F# pipe operators + 請注意,管線也會用於 lambda 函式內。F# 管道運算子 + + + + can be used for single values as well. This makes them very powerful for processing data. + 也可以用於單一值。如此可讓它們在處理資料時功能極為強大。 + + + + Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>' + 最後,您不需要使用 '>>' 來明確接受 'values' 作為參數 + + + + to compose the two core operations: filtering out even numbers, then squaring and adding one. + 以撰寫兩個核心作業: 篩選出偶數,然後取其平方值再加一。 + + + + Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply + 同樣地,也不需要 lambda 運算式的 'fun x -> ...' 位元,因為 'x' 只是 + + + + being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used + 定義於該範圍內,以將它傳遞至功能管線。因此,可以使用 '>>' + + + + there as well. + 也會在該處。 + + + + The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a + 'squareOddValuesAndAddOneComposition' 的結果本身是另一個函式,且該函式接受 + + + + list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list + 作為輸入的整數清單。如果您執行 'squareOddValuesAndAddOneComposition' 時搭配清單 + + + + of integers, you'll notice that it produces the same results as previous functions. + (整數),您將注意到它會產生與先前函式相同的結果。 + + + + This is using what is known as function composition. This is possible because functions in F# + 這將使用所謂的函式組合。原因可能是 F# 中的函式 + + + + use Partial Application and the input and output types of each data processing operation match + 使用局部應用程式,以及每個資料處理作業相符的輸入與輸出類型 + + + + the signatures of the functions we're using. + 所使用之函式的簽章。 + + + + Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation. + 清單是已排序且不可變動的單向連結清單。它們於評估時會即刻進行運算。 + + + + This module shows various ways to generate lists and process lists with some functions + 此模組示範產生清單及利用某些函式處理清單的各種方法 + + + + in the 'List' module in the F# Core Library. + 在 F# 核心程式庫的 'List' 模組中。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/lists + + + + Lists are defined using [ ... ]. This is an empty list. + 清單使用 [ ... ] 定義。這是空白清單。 + + + + This is a list with 3 elements. ';' is used to separate elements on the same line. + 這是內含 3 個項目的清單。使用 ';' 分隔同一行的項目。 + + + + You can also separate elements by placing them on their own lines. + 您也可以將項目放在各自的行上加以分隔。 + + + + This is a list of integers from 1 to 1000 + 此為從 1 到 1000 的整數清單 + + + + Lists can also be generated by computations. This is a list containing + 計算也可產生清單。此清單內含 + + + + all the days of the year. + 當年每一天。 + + + + Print the first 5 elements of 'daysList' using 'List.take'. + 使用 'List.take' 列印 'daysList' 的前 5 個項目。 + + + + Computations can include conditionals. This is a list containing the tuples + 計算可包含條件。此為內含元組的清單 + + + + which are the coordinates of the black squares on a chess board. + 其為棋盤上黑方格的座標。 + + + + Lists can be transformed using 'List.map' and other functional programming combinators. + 可以使用 'List.map' 及其他函式程式設計結合器轉換清單。 + + + + This definition produces a new list by squaring the numbers in numberList, using the pipeline + 此定義會產生新的清單,方法是使用管線使 numberList 中的數字成平方 + + + + operator to pass an argument to List.map. + 運算子以將引數傳遞到 List.map。 + + + + There are many other list combinations. The following computes the sum of the squares of the + 還有許多其他清單組合。以下會計算下項的平方總和: + + + + numbers divisible by 3. + 可由 3 整除的數字。 + + + + Arrays are fixed-size, mutable collections of elements of the same type. + 陣列是固定大小且類型相同的可變動項目集合。 + + + + Although they are similar to Lists (they support enumeration and have similar combinators for data processing), + 陣列雖與清單 (支援列舉,並具有類似的結合器可用於資料處理) 相似,但 + + + + they are generally faster and support fast random access. This comes at the cost of being less safe by being mutable. + 陣列通常比較快,而且支援快速隨機存取。但可變動的代價是安全性變低。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/arrays + + + + This is The empty array. Note that the syntax is similar to that of Lists, but uses `[| ... |]` instead. + 此為空白的陣列。請注意與清單前置詞相似的前置詞,請改用 `[| ... |]`。 + + + + Arrays are specified using the same range of constructs as lists. + 使用與所列相同的建構範圍指定陣列。 + + + + This is an array of numbers from 1 to 1000. + 這是從 1 到 1000 的數字陣列。 + + + + This is an array containing only the words "hello" and "world". + 這是僅包含 "hello" 與 "world" 字詞的陣列。 + + + + This is an array initialized by index and containing the even numbers from 0 to 2000. + 這是由索引初始化的陣列,內含從 0 到 2000 之間的偶數。 + + + + Sub-arrays are extracted using slicing notation. + 使用了切割標記法來擷取子陣列。 + + + + You can loop over arrays and lists using 'for' loops. + 您可以使用 'for' 迴圈逐一反覆執行陣列與清單。 + + + + You can modify the contents of an an array element by using the left arrow assignment operator. + 您可以使用向左鍵指派運算子來修改陣列元素的內容。 + + + + To learn more about this operator, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + 若要深入了解此運算子,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#mutable-variables + + + + You can transform arrays using 'Array.map' and other functional programming operations. + 您可以使用 'Array.map' 及其他功能程式設計作業來轉換陣列。 + + + + The following calculates the sum of the lengths of the words that start with 'h'. + 以下會計算 'h' 開頭的字組之長度總和。 + + + + Sequences are a logical series of elements, all of the same type. These are a more general type than Lists and Arrays. + 序列是一系列的邏輯項目,全部皆為相同的類型。它是比清單及陣列更常見的類型。 + + + + Sequences are evaluated on-demand and are re-evaluated each time they are iterated. + 序列是視需要評估,並在每次反覆執行時重新評估。 + + + + An F# sequence is an alias for a .NET System.Collections.Generic.IEnumerable<'T>. + F# 序列是 .NET System.Collections.Generic.IEnumerable<'T> 的別名。 + + + + Sequence processing functions can be applied to Lists and Arrays as well. + 序列處理函式也可以套用到清單和陣列。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/sequences + + + + This is the empty sequence. + 此為空白序列。 + + + + This a sequence of values. + 這是值的序列。 + + + + This is an on-demand sequence from 1 to 1000. + 此為從 1 到 1000 的隨選序列。 + + + + This is a sequence producing the words "hello" and "world" + 此為產生 "hello" 及 "world" 的序列 + + + + This sequence producing the even numbers up to 2000. + 此序列產生 2000 以下的偶數。 + + + + This is an infinite sequence which is a random walk. + 這是屬於隨機漫步的無限序列。 + + + + This example uses yield! to return each element of a subsequence. + 此範例使用 yield! 傳回序列的每個元素。 + + + + This example shows the first 100 elements of the random walk. + 此範例顯示了隨機漫步的前 100 個項目。 + + + + Recursive functions can call themselves. In F#, functions are only recursive + 遞迴函式可以呼叫其本身。在 F# 中,函式均為遞迴 + + + + when declared using 'let rec'. + (於使用 'let rec' 宣告時)。 + + + + Recursion is the preferred way to process sequences or collections in F#. + 遞迴是處理 F# 中序列或集合的慣用方法。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/index#recursive-functions + + + + This example shows a recursive function that computes the factorial of an + 此範例顯示遞迴函式,其可計算下項的階乘: + + + + integer. It uses 'let rec' to define a recursive function. + 整數。其使用 'let rec' 來定義遞迴函式。 + + + + Computes the greatest common factor of two integers. + 計算兩個整數的最大公因數。 + + + + Since all of the recursive calls are tail calls, + 因為所有遞迴呼叫都是先計算細項的呼叫 (tail call),所以 + + + + the compiler will turn the function into a loop, + 編譯器會將函式轉換為迴圈, + + + + which improves performance and reduces memory consumption. + 以改善效能並降低記憶體耗用。 + + + + This example computes the sum of a list of integers using recursion. + 此範例會計算使用遞迴之整數清單的總和。 + + + + This makes 'sumList' tail recursive, using a helper function with a result accumulator. + 這會將 'sumList' 設成尾遞迴,使用內含結果累加器的 Helper 函式。 + + + + This invokes the tail recursive helper function, providing '0' as a seed accumulator. + 這會叫用尾遞迴 helper 函式,提供 '0' 作為種子累加器。 + + + + An approach like this is common in F#. + 在 F# 中,這類方式十分常見。 + + + + Records are an aggregate of named values, with optional members (such as methods). + 記錄是具有選擇性成員 (例如方法) 之具名值的彙總。 + + + + They are immutable and have structural equality semantics. + 它們不可變動,且具有結構相等的語意。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/records + + + + This example shows how to define a new record type. + 此範例示範如何定義新記錄類型。 + + + + This example shows how to instantiate a record type. + 此範例示範如何具現化記錄類型。 + + + + You can also do this on the same line with ';' separators. + 您也可以使用 ';' 分隔符號,在同一行執行此作業。 + + + + This example shows how to use "copy-and-update" on record values. It creates + 此範例顯示如何在記錄值上使用 "copy-and-update"。其會建立 + + + + a new record value that is a copy of contact1, but has different values for + 新記錄值,其為 contact1 的複本,但對於下項有不同的值: + + + + the 'Phone' and 'Verified' fields. + [Phone]5D; 與 [Verified]5D; 欄位。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/copy-and-update-record-expressions + + + + This example shows how to write a function that processes a record value. + 此範例示範如何寫入會處理記錄值的函式。 + + + + It converts a 'ContactCard' object to a string. + 其會將 'ContactCard' 物件轉換為字串。 + + + + This is an example of a Record with a member. + 這是內含成員之記錄的範例。 + + + + Members can implement object-oriented members. + 成員可以實作物件導向成員。 + + + + Members are accessed via the '.' operator on an instantiated type. + 成員透過在具現化類型上的 '.' 運算子加以存取。 + + + + Records can also be represented as structs via the 'Struct' attribute. + 記錄也可透過 'Struct' 屬性以結構形式呈現。 + + + + This is helpful in situations where the performance of structs outweighs + 它在結構效能較優的情況下很有用 + + + + the flexibility of reference types. + 參考類型的彈性。 + + + + Discriminated Unions (DU for short) are values which could be a number of named forms or cases. + 差異聯集 (簡寫為 DU) 是可能為數個具名表單或案例的值。 + + + + Data stored in DUs can be one of several distinct values. + DU 中所儲存的資料可以是數個相異值中的一個。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions + + + + The following represents the suit of a playing card. + 以下代表一副撲克牌。 + + + + A Disciminated Union can also be used to represent the rank of a playing card. + 差異聯集也可用以代表一張撲克牌的順位。 + + + + Represents the rank of cards 2 .. 10 + 代表 2 .. 10 這幾張牌的順位 + + + + Discriminated Unions can also implement object-oriented members. + 差異聯集也可以實作物件導向成員。 + + + + This is a record type that combines a Suit and a Rank. + 這是合併了 Suit 和 Rank 的記錄類型。 + + + + It's common to use both Records and Disciminated Unions when representing data. + 代表資料時,通常會使用記錄與差異聯集。 + + + + This computes a list representing all the cards in the deck. + 這會計算代表一疊牌中所有牌的清單。 + + + + This example converts a 'Card' object to a string. + 此範例將 'Card' 物件轉換為字串。 + + + + This example prints all the cards in a playing deck. + 此範例會列印牌局的所有紙牌。 + + + + Single-case DUs are often used for domain modeling. This can buy you extra type safety + 單一案例 DU 通常用於網域模型。這讓使用類型變得更加安全 + + + + over primitive types such as strings and ints. + 針對基本類型,例如 strings 和 ints。 + + + + Single-case DUs cannot be implicitly converted to or from the type they wrap. + 單一案例 DU 無法隱含地轉換成它們所包裝的類型,反之亦然。 + + + + For example, a function which takes in an Address cannot accept a string as that input, + 例如,接受位址的函式無法接受字串作為輸入, + + + + or vive/versa. + 反之亦然。 + + + + You can easily instantiate a single-case DU as follows. + 您可以輕鬆地具現化單一案例 DU,如下所示。 + + + + When you need the value, you can unwrap the underlying value with a simple function. + 當您需要值時,可以使用簡單的函式來展開基礎值。 + + + + Printing single-case DUs is simple with unwrapping functions. + 使用展開 (unwrap) 函式來列印單一案例的 DU 十分簡單。 + + + + Disciminated Unions also support recursive definitions. + 差異聯集也支援遞迴定義。 + + + + This represents a Binary Search Tree, with one case being the Empty tree, + 這代表二進位搜尋樹狀結構,其中有一個案例是空的樹狀結構, + + + + and the other being a Node with a value and two subtrees. + 而另一個是具有一個值和兩個子樹狀結構的節點。 + + + + Check if an item exists in the binary search tree. + 請確認二進位搜尋樹狀結構中是否已有項目存在。 + + + + Searches recursively using Pattern Matching. Returns true if it exists; otherwise, false. + 使用模式比對進行遞迴搜尋。若存在即傳回 true; 否則傳回 false。 + + + + Check the left subtree. + 請檢查左樹狀子結構。 + + + + Check the right subtree. + 請檢查右樹狀子結構。 + + + + Inserts an item in the Binary Search Tree. + 在二進位搜尋樹狀結構中插入項目。 + + + + Finds the place to insert recursively using Pattern Matching, then inserts a new node. + 尋找要使用模式比對遞迴插入的位置,然後插入新節點。 + + + + If the item is already present, it does not insert anything. + 如果該項目已經存在,就不會插入任何內容。 + + + + No need to insert, it already exists; return the node. + 其已存在,所以無須插入; 傳回該節點。 + + + + Call into left subtree. + 呼叫左樹狀子結構。 + + + + Call into right subtree. + 呼叫右樹狀子結構。 + + + + Discriminated Unions can also be represented as structs via the 'Struct' attribute. + 差異聯集也可透過 'Struct' 屬性以結構形式呈現。 + + + + This is helpful in situations where the performance of structs outweighs + 它在結構效能較優的情況下很有用 + + + + the flexibility of reference types. + 參考類型的彈性。 + + + + However, there are two important things to know when doing this: + 但執行這項作業時,需要知道兩件重要的事情: + + + + 1. A struct DU cannot be recursively-defined. + 1. 不可遞迴定義結構 DU。 + + + + 2. A struct DU must have unique names for each of its cases. + 2. 結構 DU 的每個案例都必須要有唯一的名稱。 + + + + Pattern Matching is a feature of F# that allows you to utilize Patterns, + 模式比對是讓您能利用模式的一項 F# 功能, + + + + which are a way to compare data with a logical structure or structures, + 這是使用一或多個邏輯結構來比對資料的方式, + + + + decompose data into constituent parts, or extract information from data in various ways. + 將資料分解為構成組件,或透過各種方式來擷取資料中的資訊。 + + + + You can then dispatch on the "shape" of a pattern via Pattern Matching. + 接著可根據透過比對模式之模式的「形狀」加以分派。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching + + + + A record for a person's first and last name + 人員姓名的記錄 + + + + A Discriminated Union of 3 different kinds of employees + 3 種不同種類員工的差異聯集 + + + + Count everyone underneath the employee in the management hierarchy, + 計算管理階層中該員工下的每位人員, + + + + including the employee. + 包括員工。 + + + + Find all managers/executives named "Dave" who do not have any reports. + 尋找沒有任何報表且名為 "Dave" 的所有經理/主管。 + + + + This uses the 'function' shorthand to as a lambda expression. + 這會使用 'function' 速記作為 lambda 運算式。 + + + + [] matches an empty list. + [] 代表空的清單。 + + + + '_' is a wildcard pattern that matches anything. + '_' 是符合所有項目的萬用字元模式。 + + + + This handles the "or else" case. + 這會處理 "or else" 案例。 + + + + You can also use the shorthand function construct for pattern matching, + 您也可以使用速記函式建構來進行模式比對, + + + + which is useful when you're writing functions which make use of Partial Application. + 適用於撰寫可利用局部應用程式的函式時。 + + + + Define some more functions which parse with the helper function. + 再額外定義一些使用 Helper 函式進行剖析的函式。 + + + + Active Patterns are another powerful construct to use with pattern matching. + 現用模式是另一項功能強大之建構,可與模式比對搭配使用。 + + + + They allow you to partition input data into custom forms, decomposing them at the pattern match call site. + 它們可讓您將輸入資料分割到多個自訂表單,於模式比對呼叫網站進行分解。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns + + + + Pattern Matching via 'function' keyword and Active Patterns often looks like this. + 透過 'function' 關鍵字與現用模式進行模式比對,通常看來如下。 + + + + Call the printer with some different values to parse. + 透過解析一些不同的值來呼叫印表機。 + + + + Option values are any kind of value tagged with either 'Some' or 'None'. + 選項值是以 'Some' 或 'None' 標記的任何一種值。 + + + + They are used extensively in F# code to represent the cases where many other + 它們廣泛用於 F# 程式碼中,來代表許多其他語言會 + + + + languages would use null references. + 使用 null 參考的狀況。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/options + + + + First, define a zipcode defined via Single-case Discriminated Union. + 首先,定義透過單一案例差異聯集所定義的郵遞區號。 + + + + Next, define a type where the ZipCode is optional. + 接著,定義不一定需要 ZipCode 的類型。 + + + + Next, define an interface type that represents an object to compute the shipping zone for the customer's zip code, + 然後,定義代表物件的介面類型,以計算客戶郵遞區號的郵寄區域, + + + + given implementations for the 'getState' and 'getShippingZone' abstract methods. + 'getState' 和 'getShippingZone' 抽象方法的指定實作。 + + + + Next, calculate a shipping zone for a customer using a calculator instance. + 接下來,為使用計算機執行個體的客戶計算出貨區。 + + + + This uses combinators in the Option module to allow a functional pipeline for + 這會在 Option 模組中使用結合器,以允許在執行下列功能時使用功能管線: + + + + transforming data with Optionals. + 使用選用項目來轉換資料。 + + + + Units of measure are a way to annotate primitive numeric types in a type-safe way. + 測量單位是以型別安全方式為基本數值類型加上註釋的方法。 + + + + You can then perform type-safe arithmetic on these values. + 接著可以在這些值上執行型別安全算術。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/units-of-measure + + + + First, open a collection of common unit names + 首先,開啟常用單位名稱的集合 + + + + Define a unitized constant + 定義 unitized 常數 + + + + Next, define a new unit type + 接著,定義新單位類型 + + + + Conversion factor mile to meter. + 英哩到公尺的轉換因數。 + + + + Define a unitized constant + 定義 unitized 常數 + + + + Compute metric-system constant + 計算計量系統常數 + + + + Values using Units of Measure can be used just like the primitive numeric type for things like printing. + 使用測量單位之值的用法,就像是列印這類作業的基本數字類型一樣。 + + + + Classes are a way of defining new object types in F#, and support standard Object-oriented constructs. + 類別是在 F# 中定義新物件類型的一種方式,且支援標準物件導向建構。 + + + + They can have a variety of members (methods, properties, events, etc.) + 它們可以有各式不同的成員 (方法、屬性、事件等等) + + + + To learn more about Classes, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + 若要深入了解類別,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes + + + + To learn more about Members, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + 若要深入了解成員,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members + + + + A simple two-dimensional Vector class. + 簡式二維向量類別。 + + + + The class's constructor is on the first line, + 類別的建構函式位於第一行, + + + + and takes two arguments: dx and dy, both of type 'double'. + 並接受兩種引數: dx 與 dy,兩者的類型都是 'double'。 + + + + This internal field stores the length of the vector, computed when the + 這個內部欄位會儲存向量長度,計算時機為 + + + + object is constructed + 物件已建構 + + + + 'this' specifies a name for the object's self identifier. + 'this' 會為物件的自我識別碼指定名稱。 + + + + In instance methods, it must appear before the member name. + 在執行個體方法中,它必須出現在成員名稱前面。 + + + + This member is a method. The previous members were properties. + 此成員是方法。先前的成員是屬性。 + + + + This is how you instantiate the Vector2D class. + 這是 Vector2D 類別的具現化方式。 + + + + Get a new scaled vector object, without modifying the original object. + 取得全新且可調整大小的向量物件,但不修改原始物件。 + + + + Generic classes allow types to be defined with respect to a set of type parameters. + 泛型類別可定義關乎一組類型參數的類型。 + + + + In the following, 'T is the type parameter for the class. + 在下列範例中,'T 是類別的型別參數。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/ + + + + This internal field store the states in a list. + 此內部欄位會以清單形式儲存狀態。 + + + + Add a new element to the list of states. + 新增項目至狀態清單。 + + + + use the '<-' operator to mutate the value. + 使用 '<-' 運算子可變動值。 + + + + Get the entire list of historical states. + 取得完整的歷程狀態清單。 + + + + Get the latest state. + 取得最新狀態。 + + + + An 'int' instance of the state tracker class. Note that the type parameter is inferred. + 狀態追蹤器類別的 'int' 執行個體。請注意,型別參數是推斷出來的。 + + + + Add a state + 加入狀態 + + + + Interfaces are object types with only 'abstract' members. + 介面為只有 'abstract' 成員的物件類型。 + + + + Object types and object expressions can implement interfaces. + 物件類型與物件運算式可以實作介面。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/interfaces + + + + This is a type that implements IDisposable. + 這是實作 IDisposable 的類型。 + + + + This is the implementation of IDisposable members. + 這是 IDisposable 成員的實作。 + + + + This is an object that implements IDisposable via an Object Expression + 這是透過物件運算式實作 IDisposable 的物件 + + + + Unlike other languages such as C# or Java, a new type definition is not needed + 與 C# 或 Java 等其他這類語言不同,不需要新的類型定義 + + + + to implement an interface. + 以實作介面。 + + + + The FSharp.Core library defines a range of parallel processing functions. Here + FSharp.Core 程式庫定義一個範圍內的平行處理函式。這裡 + + + + you use some functions for parallel processing over arrays. + 您可以使用一些函式對陣列進行平行處理。 + + + + To learn more, see: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + 若要深入了解,請參閱: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.parallel-module-%5Bfsharp%5D + + + + First, an array of inputs. + 首先,輸入的陣列。 + + + + Next, define a functions that does some CPU intensive computation. + 接下來,定義執行某些 CPU 密集型計算的函式。 + + + + Next, do a parallel map over a large input array. + 接下來,對大型輸入陣列執行平行對應。 + + + + Next, print the results. + 接下來,列印結果。 + + + + Events are a common idiom for .NET programming, especially with WinForms or WPF applications. + 事件是 .NET 程式設計的常見慣用語,特別是使用 WinForms 或 WPF 應用程式時。 + + + + To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + 若要深入了解,請參閱: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/events + + + + First, create instance of Event object that consists of subscription point (event.Publish) and event trigger (event.Trigger). + 首先,建立由訂閱點 (event.Publish) 與事件觸發程序 (event.Trigger) 所組成之事件物件的執行個體。 + + + + Next, add handler to the event. + 接下來,將處理常式新增到事件。 + + + + Next, trigger the event. + 接下來,觸發該事件。 + + + + Next, create an instance of Event that follows standard .NET convention: (sender, EventArgs). + 接下來,為遵循標準 .NET 慣例的事件建立執行個體: (sender, EventArgs)。 + + + + Next, add a handler for this new event. + 接下來,為此新事件新增處理常式。 + + + + Next, trigger this event (note that sender argument should be set). + 接下來,觸發此事件 (請注意,應該設定 sender 引數)。 + + + + + \ No newline at end of file diff --git a/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj b/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj new file mode 100644 index 0000000000..72afa7b760 --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj @@ -0,0 +1,17 @@ + + + + + + TutorialProject + + + + + + Template\Tutorial.fsx + + + + + diff --git a/vsintegration/ProjectTemplates/TutorialProject/source.extension.vsixmanifest b/vsintegration/ProjectTemplates/TutorialProject/source.extension.vsixmanifest new file mode 100644 index 0000000000..39bac985bc --- /dev/null +++ b/vsintegration/ProjectTemplates/TutorialProject/source.extension.vsixmanifest @@ -0,0 +1,25 @@ + + + + + F# .NETCore Project Templates + F# project templates for .NETCore. + + + + + + + + + + + + + + + + + + + diff --git a/vsintegration/Vsix/VisualFSharpTemplates/Source.extension.vsixmanifest b/vsintegration/Vsix/VisualFSharpTemplates/Source.extension.vsixmanifest new file mode 100644 index 0000000000..4b0a45a6e9 --- /dev/null +++ b/vsintegration/Vsix/VisualFSharpTemplates/Source.extension.vsixmanifest @@ -0,0 +1,28 @@ + + + + + + + Visual F# Templates + Deploy Visual F# Tools Desktop Project Templates to Visual Studio + Microsoft.FSharp.VSIX.Templates + https://docs.microsoft.com/en-us/dotnet/articles/fsharp/ + + + + + + + + + + + + + + + + + + diff --git a/vsintegration/Vsix/VisualFSharpTemplates/VisualFSharpTemplates.csproj b/vsintegration/Vsix/VisualFSharpTemplates/VisualFSharpTemplates.csproj new file mode 100644 index 0000000000..cfab3f5dfa --- /dev/null +++ b/vsintegration/Vsix/VisualFSharpTemplates/VisualFSharpTemplates.csproj @@ -0,0 +1,60 @@ + + + + + + Library + Microsoft\FSharpTemplates + net472 + true + + + + + PreserveNewest + packages\System.ValueTuple.4.4.0.nupkg + true + + + PreserveNewest + packages\FSharp.Core.$(FSharpCoreShippedPackageVersion).nupkg + true + + + Designer + + + + + + + + + + + {604f0daa-2d33-48dd-b162-edf0b672803d} + ConsoleProject + ProjectTemplates + TemplateProjectOutputGroup%3b + false + True + + + {01678cda-a11f-4dee-9344-2edf91cf1ae7} + LibraryProject + ProjectTemplates + TemplateProjectOutputGroup%3b + false + True + + + {2facee44-48bd-40b5-a2ee-b54a0c9bb7c4} + TutorialProject + ProjectTemplates + TemplateProjectOutputGroup%3b + false + True + + + + diff --git a/vsintegration/readme.md b/vsintegration/readme.md index ae582cbdf9..4f929238bd 100644 --- a/vsintegration/readme.md +++ b/vsintegration/readme.md @@ -51,3 +51,7 @@ A skeleton command line tool which exercises the F# Compiler Service. # ItemTemplates Visual Studio item templates for F# projects. + +# ProjectTemplates + +Visual Studio project templates for .NET Framework projects. From 0962ff147d280a594c5c0413225c9784d1ad0a45 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 14 Jan 2020 20:19:47 -0800 Subject: [PATCH 026/101] Remove ILGlobals dependency on ILMetadataReader (#8041) * First step to get rid of ilglobals * Added ILScopeRef.PrimaryAssembly * almost * Fixed * Fixing build * Revert ilwrite changes from last commit * some cleanup * Trying to fix build * Trying to fix build * Adjusting a few cases that use QualifiedName * Refactor a bit on normalize * Some cleanup * Put ctok in local function * Minor touch up for ILScopeRef matching * Do not need this function anymore * Remove ILGlobals dep on getNameOfScopeRef * Added possiblePrimaryAssemblyRefs * Fixed build * Hopefully this fixes the build * Added EqualsIgnoringVersion to ILAssemblyRef * Added RemapAssemblyRef * Use EqualsIgnoringVersion on primaryAssemblyRef check in remap * Cleanup * nit style feedback changes * Removed RemapAssemblyRef. Added stamp that ignores version. * Fixed build * Minor format change * minor name refactoring * minimizing diff --- src/absil/il.fs | 170 ++++++++++++++++-------------- src/absil/il.fsi | 61 +++++++---- src/absil/ilprint.fs | 8 +- src/absil/ilread.fs | 73 +++++++------ src/absil/ilread.fsi | 2 - src/absil/ilreflect.fs | 31 +++--- src/absil/ilwrite.fs | 41 +++---- src/fsharp/CompileOps.fs | 62 ++++++++--- src/fsharp/CompileOptions.fs | 13 ++- src/fsharp/CompileOptions.fsi | 3 +- src/fsharp/QuotationTranslator.fs | 1 + src/fsharp/TastPickle.fs | 8 +- src/fsharp/fsc.fs | 9 +- src/fsharp/fsi/fsi.fs | 2 +- src/fsharp/import.fs | 30 +++--- src/fsharp/symbols/Symbols.fs | 18 ++-- src/fsharp/tast.fs | 1 + 17 files changed, 304 insertions(+), 229 deletions(-) diff --git a/src/absil/il.fs b/src/absil/il.fs index a55c8be248..7e27e71da2 100644 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -66,10 +66,6 @@ type PrimaryAssembly = | Mscorlib -> "mscorlib" | System_Runtime -> "System.Runtime" | NetStandard -> "netstandard" - static member IsSomePrimaryAssembly n = - n = PrimaryAssembly.Mscorlib.Name - || n = PrimaryAssembly.System_Runtime.Name - || n = PrimaryAssembly.NetStandard.Name // -------------------------------------------------------------------- // Utilities: type names @@ -373,6 +369,7 @@ let isMscorlib data = [] type ILAssemblyRef(data) = let uniqueStamp = AssemblyRefUniqueStampGenerator.Encode data + let uniqueIgnoringVersionStamp = AssemblyRefUniqueStampGenerator.Encode { data with assemRefVersion = None } member x.Name=data.assemRefName @@ -388,6 +385,11 @@ type ILAssemblyRef(data) = member x.UniqueStamp=uniqueStamp + member x.UniqueIgnoringVersionStamp=uniqueIgnoringVersionStamp + + member x.EqualsIgnoringVersion (aref: ILAssemblyRef) = + aref.UniqueIgnoringVersionStamp = uniqueIgnoringVersionStamp + override x.GetHashCode() = uniqueStamp override x.Equals yobj = ((yobj :?> ILAssemblyRef).UniqueStamp = uniqueStamp) @@ -490,6 +492,7 @@ type ILScopeRef = | Local | Module of ILModuleRef | Assembly of ILAssemblyRef + | PrimaryAssembly member x.IsLocalRef = match x with ILScopeRef.Local -> true | _ -> false @@ -498,6 +501,7 @@ type ILScopeRef = | ILScopeRef.Local -> "" | ILScopeRef.Module mref -> "module "+mref.Name | ILScopeRef.Assembly aref -> aref.QualifiedName + | ILScopeRef.PrimaryAssembly -> "" type ILArrayBound = int32 option @@ -2193,6 +2197,11 @@ and ILExportedTypesAndForwarders = member x.AsList = let (ILExportedTypesAndForwarders ltab) = x in Map.foldBack (fun _x y r -> y :: r) (ltab.Force()) [] + member x.TryFindByName nm = + match x with + | ILExportedTypesAndForwarders ltab -> + ltab.Value.TryFind nm + [] type ILResourceAccess = | Public @@ -2593,54 +2602,47 @@ let tname_IntPtr = "System.IntPtr" [] let tname_UIntPtr = "System.UIntPtr" +[] +let tname_TypedReference = "System.TypedReference" + [] -// This data structure needs an entirely delayed implementation -type ILGlobals(primaryScopeRef) = - - let m_mkSysILTypeRef nm = mkILTyRef (primaryScopeRef, nm) - - let m_typ_Object = mkILBoxedType (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Object)) - let m_typ_String = mkILBoxedType (mkILNonGenericTySpec (m_mkSysILTypeRef tname_String)) - let m_typ_Array = mkILBoxedType (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Array)) - let m_typ_Type = mkILBoxedType (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Type)) - let m_typ_SByte = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_SByte)) - let m_typ_Int16 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Int16)) - let m_typ_Int32 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Int32)) - let m_typ_Int64 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Int64)) - let m_typ_Byte = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Byte)) - let m_typ_UInt16 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_UInt16)) - let m_typ_UInt32 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_UInt32)) - let m_typ_UInt64 = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_UInt64)) - let m_typ_Single = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Single)) - let m_typ_Double = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Double)) - let m_typ_Bool = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Bool)) - let m_typ_Char = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_Char)) - let m_typ_IntPtr = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_IntPtr)) - let m_typ_UIntPtr = ILType.Value (mkILNonGenericTySpec (m_mkSysILTypeRef tname_UIntPtr)) - - member x.primaryAssemblyScopeRef = m_typ_Object.TypeRef.Scope - member x.primaryAssemblyName = - match m_typ_Object.TypeRef.Scope with - | ILScopeRef.Assembly aref -> aref.Name +type ILGlobals(primaryScopeRef: ILScopeRef, assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list) = + + let assembliesThatForwardToPrimaryAssembly = Array.ofList assembliesThatForwardToPrimaryAssembly + + let mkSysILTypeRef nm = mkILTyRef (primaryScopeRef, nm) + + member _.primaryAssemblyScopeRef = primaryScopeRef + member x.primaryAssemblyRef = + match primaryScopeRef with + | ILScopeRef.Assembly aref -> aref | _ -> failwith "Invalid primary assembly" - member x.typ_Object = m_typ_Object - member x.typ_String = m_typ_String - member x.typ_Array = m_typ_Array - member x.typ_Type = m_typ_Type - member x.typ_IntPtr = m_typ_IntPtr - member x.typ_UIntPtr = m_typ_UIntPtr - member x.typ_Byte = m_typ_Byte - member x.typ_Int16 = m_typ_Int16 - member x.typ_Int32 = m_typ_Int32 - member x.typ_Int64 = m_typ_Int64 - member x.typ_SByte = m_typ_SByte - member x.typ_UInt16 = m_typ_UInt16 - member x.typ_UInt32 = m_typ_UInt32 - member x.typ_UInt64 = m_typ_UInt64 - member x.typ_Single = m_typ_Single - member x.typ_Double = m_typ_Double - member x.typ_Bool = m_typ_Bool - member x.typ_Char = m_typ_Char + member x.primaryAssemblyName = x.primaryAssemblyRef.Name + + member val typ_Object = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_Object)) + member val typ_String = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_String)) + member val typ_Array = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_Array)) + member val typ_Type = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_Type)) + member val typ_SByte = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_SByte)) + member val typ_Int16 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Int16)) + member val typ_Int32 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Int32)) + member val typ_Int64 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Int64)) + member val typ_Byte = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Byte)) + member val typ_UInt16 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_UInt16)) + member val typ_UInt32 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_UInt32)) + member val typ_UInt64 = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_UInt64)) + member val typ_Single = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Single)) + member val typ_Double = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Double)) + member val typ_Bool = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Bool)) + member val typ_Char = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_Char)) + member val typ_IntPtr = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_IntPtr)) + member val typ_UIntPtr = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_UIntPtr)) + member val typ_TypedReference = ILType.Value (mkILNonGenericTySpec (mkSysILTypeRef tname_TypedReference)) + + member x.IsPossiblePrimaryAssemblyRef(aref: ILAssemblyRef) = + aref.EqualsIgnoringVersion x.primaryAssemblyRef || + assembliesThatForwardToPrimaryAssembly + |> Array.exists aref.EqualsIgnoringVersion /// For debugging [] @@ -2648,7 +2650,7 @@ type ILGlobals(primaryScopeRef) = override x.ToString() = "" -let mkILGlobals primaryScopeRef = ILGlobals primaryScopeRef +let mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) = ILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) let mkNormalCall mspec = I_call (Normalcall, mspec, None) @@ -2693,54 +2695,55 @@ let isILBoxedTy = function ILType.Boxed _ -> true | _ -> false let isILValueTy = function ILType.Value _ -> true | _ -> false -let isPrimaryAssemblyTySpec (tspec: ILTypeSpec) n = +let isBuiltInTySpec (ilg: ILGlobals) (tspec: ILTypeSpec) n = let tref = tspec.TypeRef let scoref = tref.Scope - (tref.Name = n) && - match scoref with - | ILScopeRef.Assembly n -> PrimaryAssembly.IsSomePrimaryAssembly n.Name - | ILScopeRef.Module _ -> false - | ILScopeRef.Local -> true + tref.Name = n && + (match scoref with + | ILScopeRef.Local + | ILScopeRef.Module _ -> false + | ILScopeRef.Assembly aref -> ilg.IsPossiblePrimaryAssemblyRef aref + | ILScopeRef.PrimaryAssembly -> true) -let isILBoxedPrimaryAssemblyTy (ty: ILType) n = - isILBoxedTy ty && isPrimaryAssemblyTySpec ty.TypeSpec n +let isILBoxedBuiltInTy ilg (ty: ILType) n = + isILBoxedTy ty && isBuiltInTySpec ilg ty.TypeSpec n -let isILValuePrimaryAssemblyTy (ty: ILType) n = - isILValueTy ty && isPrimaryAssemblyTySpec ty.TypeSpec n +let isILValueBuiltInTy ilg (ty: ILType) n = + isILValueTy ty && isBuiltInTySpec ilg ty.TypeSpec n -let isILObjectTy ty = isILBoxedPrimaryAssemblyTy ty tname_Object +let isILObjectTy ilg ty = isILBoxedBuiltInTy ilg ty tname_Object -let isILStringTy ty = isILBoxedPrimaryAssemblyTy ty tname_String +let isILStringTy ilg ty = isILBoxedBuiltInTy ilg ty tname_String -let isILTypedReferenceTy ty = isILValuePrimaryAssemblyTy ty "System.TypedReference" +let isILTypedReferenceTy ilg ty = isILValueBuiltInTy ilg ty tname_TypedReference -let isILSByteTy ty = isILValuePrimaryAssemblyTy ty tname_SByte +let isILSByteTy ilg ty = isILValueBuiltInTy ilg ty tname_SByte -let isILByteTy ty = isILValuePrimaryAssemblyTy ty tname_Byte +let isILByteTy ilg ty = isILValueBuiltInTy ilg ty tname_Byte -let isILInt16Ty ty = isILValuePrimaryAssemblyTy ty tname_Int16 +let isILInt16Ty ilg ty = isILValueBuiltInTy ilg ty tname_Int16 -let isILUInt16Ty ty = isILValuePrimaryAssemblyTy ty tname_UInt16 +let isILUInt16Ty ilg ty = isILValueBuiltInTy ilg ty tname_UInt16 -let isILInt32Ty ty = isILValuePrimaryAssemblyTy ty tname_Int32 +let isILInt32Ty ilg ty = isILValueBuiltInTy ilg ty tname_Int32 -let isILUInt32Ty ty = isILValuePrimaryAssemblyTy ty tname_UInt32 +let isILUInt32Ty ilg ty = isILValueBuiltInTy ilg ty tname_UInt32 -let isILInt64Ty ty = isILValuePrimaryAssemblyTy ty tname_Int64 +let isILInt64Ty ilg ty = isILValueBuiltInTy ilg ty tname_Int64 -let isILUInt64Ty ty = isILValuePrimaryAssemblyTy ty tname_UInt64 +let isILUInt64Ty ilg ty = isILValueBuiltInTy ilg ty tname_UInt64 -let isILIntPtrTy ty = isILValuePrimaryAssemblyTy ty tname_IntPtr +let isILIntPtrTy ilg ty = isILValueBuiltInTy ilg ty tname_IntPtr -let isILUIntPtrTy ty = isILValuePrimaryAssemblyTy ty tname_UIntPtr +let isILUIntPtrTy ilg ty = isILValueBuiltInTy ilg ty tname_UIntPtr -let isILBoolTy ty = isILValuePrimaryAssemblyTy ty tname_Bool +let isILBoolTy ilg ty = isILValueBuiltInTy ilg ty tname_Bool -let isILCharTy ty = isILValuePrimaryAssemblyTy ty tname_Char +let isILCharTy ilg ty = isILValueBuiltInTy ilg ty tname_Char -let isILSingleTy ty = isILValuePrimaryAssemblyTy ty tname_Single +let isILSingleTy ilg ty = isILValueBuiltInTy ilg ty tname_Single -let isILDoubleTy ty = isILValuePrimaryAssemblyTy ty tname_Double +let isILDoubleTy ilg ty = isILValueBuiltInTy ilg ty tname_Double // -------------------------------------------------------------------- // Rescoping @@ -3710,7 +3713,7 @@ let getCustomAttrData (ilg: ILGlobals) cattr = let MscorlibScopeRef = ILScopeRef.Assembly (ILAssemblyRef.Create ("mscorlib", None, Some ecmaPublicKey, true, None, None)) -let EcmaMscorlibILGlobals = mkILGlobals MscorlibScopeRef +let EcmaMscorlibILGlobals = mkILGlobals (MscorlibScopeRef, []) // ILSecurityDecl is a 'blob' having the following format: // - A byte containing a period (.). @@ -4006,7 +4009,8 @@ type ILReferences = ModuleReferences: ILModuleRef list } type ILReferencesAccumulator = - { refsA: HashSet + { ilg: ILGlobals + refsA: HashSet refsM: HashSet } let emptyILRefs = @@ -4023,6 +4027,7 @@ let refs_of_scoref s x = | ILScopeRef.Local -> () | ILScopeRef.Assembly assemblyRef -> refs_of_assemblyRef s assemblyRef | ILScopeRef.Module modref -> refs_of_modref s modref + | ILScopeRef.PrimaryAssembly -> refs_of_assemblyRef s s.ilg.primaryAssemblyRef let refs_of_tref s (x: ILTypeRef) = refs_of_scoref s x.Scope @@ -4219,9 +4224,10 @@ and refs_of_manifest s (m: ILAssemblyManifest) = refs_of_custom_attrs s m.CustomAttrs refs_of_exported_types s m.ExportedTypes -let computeILRefs modul = +let computeILRefs ilg modul = let s = - { refsA = HashSet<_>(HashIdentity.Structural) + { ilg = ilg + refsA = HashSet<_>(HashIdentity.Structural) refsM = HashSet<_>(HashIdentity.Structural) } refs_of_modul s modul diff --git a/src/absil/il.fsi b/src/absil/il.fsi index a0b818259d..506878e1d6 100644 --- a/src/absil/il.fsi +++ b/src/absil/il.fsi @@ -79,6 +79,9 @@ type ILAssemblyRef = member Retargetable: bool member Version: ILVersionInfo option member Locale: string option + + member EqualsIgnoringVersion: ILAssemblyRef -> bool + interface System.IComparable [] @@ -97,7 +100,9 @@ type ILScopeRef = /// A reference to a type in a module in the same assembly | Module of ILModuleRef /// A reference to a type in another assembly - | Assembly of ILAssemblyRef + | Assembly of ILAssemblyRef + /// A reference to a type in the primary assembly + | PrimaryAssembly member IsLocalRef: bool member QualifiedName: string @@ -1393,7 +1398,8 @@ type ILExportedTypeOrForwarder = [] [] type ILExportedTypesAndForwarders = - member AsList: ILExportedTypeOrForwarder list + member AsList: ILExportedTypeOrForwarder list + member TryFindByName: string -> ILExportedTypeOrForwarder option [] type ILResourceAccess = @@ -1571,6 +1577,7 @@ val isTypeNameForGlobalFunctions: string -> bool [] type ILGlobals = member primaryAssemblyScopeRef: ILScopeRef + member primaryAssemblyRef: ILAssemblyRef member primaryAssemblyName: string member typ_Object: ILType member typ_String: ILType @@ -1590,10 +1597,20 @@ type ILGlobals = member typ_Double: ILType member typ_Bool: ILType member typ_Char: ILType - + member typ_TypedReference: ILType + + /// Is the given assembly possibly a primary assembly? + /// In practice, a primary assembly is an assembly that contains the System.Object type definition + /// and has no referenced assemblies. + /// However, we must consider assemblies that forward the System.Object type definition + /// to be possible primary assemblies. + /// Therefore, this will return true if the given assembly is the real primary assembly or an assembly that forwards + /// the System.Object type definition. + /// Assembly equivalency ignores the version here. + member IsPossiblePrimaryAssemblyRef: ILAssemblyRef -> bool /// Build the table of commonly used references given functions to find types in system assemblies -val mkILGlobals: ILScopeRef -> ILGlobals +val mkILGlobals: primaryScopeRef: ILScopeRef * assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list -> ILGlobals val EcmaMscorlibILGlobals: ILGlobals @@ -1944,23 +1961,23 @@ val instILType: ILGenericArgs -> ILType -> ILType val ecmaPublicKey: PublicKey /// Discriminating different important built-in types. -val isILObjectTy: ILType -> bool -val isILStringTy: ILType -> bool -val isILSByteTy: ILType -> bool -val isILByteTy: ILType -> bool -val isILInt16Ty: ILType -> bool -val isILUInt16Ty: ILType -> bool -val isILInt32Ty: ILType -> bool -val isILUInt32Ty: ILType -> bool -val isILInt64Ty: ILType -> bool -val isILUInt64Ty: ILType -> bool -val isILIntPtrTy: ILType -> bool -val isILUIntPtrTy: ILType -> bool -val isILBoolTy: ILType -> bool -val isILCharTy: ILType -> bool -val isILTypedReferenceTy: ILType -> bool -val isILDoubleTy: ILType -> bool -val isILSingleTy: ILType -> bool +val isILObjectTy: ILGlobals -> ILType -> bool +val isILStringTy: ILGlobals -> ILType -> bool +val isILSByteTy: ILGlobals -> ILType -> bool +val isILByteTy: ILGlobals -> ILType -> bool +val isILInt16Ty: ILGlobals -> ILType -> bool +val isILUInt16Ty: ILGlobals -> ILType -> bool +val isILInt32Ty: ILGlobals -> ILType -> bool +val isILUInt32Ty: ILGlobals -> ILType -> bool +val isILInt64Ty: ILGlobals -> ILType -> bool +val isILUInt64Ty: ILGlobals -> ILType -> bool +val isILIntPtrTy: ILGlobals -> ILType -> bool +val isILUIntPtrTy: ILGlobals -> ILType -> bool +val isILBoolTy: ILGlobals -> ILType -> bool +val isILCharTy: ILGlobals -> ILType -> bool +val isILTypedReferenceTy: ILGlobals -> ILType -> bool +val isILDoubleTy: ILGlobals -> ILType -> bool +val isILSingleTy: ILGlobals -> ILType -> bool val sha1HashInt64 : byte[] -> int64 /// Get a public key token from a public key. @@ -2002,6 +2019,6 @@ type ILReferences = ModuleReferences: ILModuleRef list } /// Find the full set of assemblies referenced by a module. -val computeILRefs: ILModuleDef -> ILReferences +val computeILRefs: ILGlobals -> ILModuleDef -> ILReferences val emptyILRefs: ILReferences diff --git a/src/absil/ilprint.fs b/src/absil/ilprint.fs index 2515634395..42c0dcddd6 100644 --- a/src/absil/ilprint.fs +++ b/src/absil/ilprint.fs @@ -157,12 +157,14 @@ let output_ieee32 os (x:float32) = output_string os "float32 ("; output_string o let output_ieee64 os (x:float) = output_string os "float64 ("; output_string os (string (bits_of_float x)); output_string os ")" -let rec goutput_scoref _env os = function +let rec goutput_scoref env os = function | ILScopeRef.Local -> () | ILScopeRef.Assembly aref -> output_string os "["; output_sqstring os aref.Name; output_string os "]" | ILScopeRef.Module mref -> output_string os "[.module "; output_sqstring os mref.Name; output_string os "]" + | ILScopeRef.PrimaryAssembly -> + output_string os "["; output_sqstring os env.ilGlobals.primaryAssemblyName; output_string os "]" and goutput_type_name_ref env os (scoref, enc, n) = goutput_scoref env os scoref @@ -1065,7 +1067,7 @@ let output_module_fragment_aux _refs os (ilg: ILGlobals) modul = reraise() let output_module_fragment os (ilg: ILGlobals) modul = - let refs = computeILRefs modul + let refs = computeILRefs ilg modul output_module_fragment_aux refs os ilg modul refs @@ -1086,7 +1088,7 @@ let goutput_module_manifest env os modul = let output_module os (ilg: ILGlobals) modul = try - let refs = computeILRefs modul + let refs = computeILRefs ilg modul let env = mk_ppenv ilg let env = ppenv_enter_modul env output_module_refs os refs diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index fed858c4d5..aa4438cedf 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -32,6 +32,8 @@ open System.Reflection #nowarn "9" +let primaryAssemblyILGlobals = mkILGlobals (ILScopeRef.PrimaryAssembly, []) + let checking = false let logging = false let _ = if checking then dprintn "warning: ILBinaryReader.checking is on" @@ -859,8 +861,7 @@ type PEReader = [] type ILMetadataReader = - { ilg: ILGlobals - sorted: int64 + { sorted: int64 mdfile: BinaryFile pectxtCaptured: PEReader option // only set when reading full PE including code etc. for static linking entryPointToken: TableName * int @@ -1713,7 +1714,7 @@ and seekReadTypeDefOrRefAsTypeRef (ctxt: ILMetadataReader) (TaggedIndex(tag, idx | tag when tag = tdor_TypeRef -> seekReadTypeRef ctxt idx | tag when tag = tdor_TypeSpec -> dprintn ("type spec used where a type ref or def is required") - ctxt.ilg.typ_Object.TypeRef + primaryAssemblyILGlobals.typ_Object.TypeRef | _ -> failwith "seekReadTypeDefOrRefAsTypeRef_readTypeDefOrRefOrSpec" and seekReadMethodRefParent (ctxt: ILMetadataReader) mdv numtypars (TaggedIndex(tag, idx)) = @@ -1831,22 +1832,22 @@ and sigptrGetTypeDefOrRefOrSpecIdx bytes sigptr = and sigptrGetTy (ctxt: ILMetadataReader) numtypars bytes sigptr = let b0, sigptr = sigptrGetByte bytes sigptr - if b0 = et_OBJECT then ctxt.ilg.typ_Object, sigptr - elif b0 = et_STRING then ctxt.ilg.typ_String, sigptr - elif b0 = et_I1 then ctxt.ilg.typ_SByte, sigptr - elif b0 = et_I2 then ctxt.ilg.typ_Int16, sigptr - elif b0 = et_I4 then ctxt.ilg.typ_Int32, sigptr - elif b0 = et_I8 then ctxt.ilg.typ_Int64, sigptr - elif b0 = et_I then ctxt.ilg.typ_IntPtr, sigptr - elif b0 = et_U1 then ctxt.ilg.typ_Byte, sigptr - elif b0 = et_U2 then ctxt.ilg.typ_UInt16, sigptr - elif b0 = et_U4 then ctxt.ilg.typ_UInt32, sigptr - elif b0 = et_U8 then ctxt.ilg.typ_UInt64, sigptr - elif b0 = et_U then ctxt.ilg.typ_UIntPtr, sigptr - elif b0 = et_R4 then ctxt.ilg.typ_Single, sigptr - elif b0 = et_R8 then ctxt.ilg.typ_Double, sigptr - elif b0 = et_CHAR then ctxt.ilg.typ_Char, sigptr - elif b0 = et_BOOLEAN then ctxt.ilg.typ_Bool, sigptr + if b0 = et_OBJECT then primaryAssemblyILGlobals.typ_Object, sigptr + elif b0 = et_STRING then primaryAssemblyILGlobals.typ_String, sigptr + elif b0 = et_I1 then primaryAssemblyILGlobals.typ_SByte, sigptr + elif b0 = et_I2 then primaryAssemblyILGlobals.typ_Int16, sigptr + elif b0 = et_I4 then primaryAssemblyILGlobals.typ_Int32, sigptr + elif b0 = et_I8 then primaryAssemblyILGlobals.typ_Int64, sigptr + elif b0 = et_I then primaryAssemblyILGlobals.typ_IntPtr, sigptr + elif b0 = et_U1 then primaryAssemblyILGlobals.typ_Byte, sigptr + elif b0 = et_U2 then primaryAssemblyILGlobals.typ_UInt16, sigptr + elif b0 = et_U4 then primaryAssemblyILGlobals.typ_UInt32, sigptr + elif b0 = et_U8 then primaryAssemblyILGlobals.typ_UInt64, sigptr + elif b0 = et_U then primaryAssemblyILGlobals.typ_UIntPtr, sigptr + elif b0 = et_R4 then primaryAssemblyILGlobals.typ_Single, sigptr + elif b0 = et_R8 then primaryAssemblyILGlobals.typ_Double, sigptr + elif b0 = et_CHAR then primaryAssemblyILGlobals.typ_Char, sigptr + elif b0 = et_BOOLEAN then primaryAssemblyILGlobals.typ_Bool, sigptr elif b0 = et_WITH then let b0, sigptr = sigptrGetByte bytes sigptr let tdorIdx, sigptr = sigptrGetTypeDefOrRefOrSpecIdx bytes sigptr @@ -1892,8 +1893,7 @@ and sigptrGetTy (ctxt: ILMetadataReader) numtypars bytes sigptr = elif b0 = et_VOID then ILType.Void, sigptr elif b0 = et_TYPEDBYREF then - let t = mkILNonGenericValueTy(mkILTyRef(ctxt.ilg.primaryAssemblyScopeRef, "System.TypedReference")) - t, sigptr + primaryAssemblyILGlobals.typ_TypedReference, sigptr elif b0 = et_CMOD_REQD || b0 = et_CMOD_OPT then let tdorIdx, sigptr = sigptrGetTypeDefOrRefOrSpecIdx bytes sigptr let ty, sigptr = sigptrGetTy ctxt numtypars bytes sigptr @@ -3037,6 +3037,7 @@ and seekReadManifestResources (ctxt: ILMetadataReader) canReduceMemory (mdv: Bin | ILScopeRef.Module mref -> ILResourceLocation.File (mref, offset) | ILScopeRef.Assembly aref -> ILResourceLocation.Assembly aref + | _ -> failwith "seekReadManifestResources: Invalid ILScopeRef" let r = { Name= readStringHeap ctxt nameIdx @@ -3120,7 +3121,7 @@ let getPdbReader pdbDirPath fileName = #endif // Note, pectxtEager and pevEager must not be captured by the results of this function -let openMetadataReader (fileName, mdfile: BinaryFile, metadataPhysLoc, peinfo, pectxtEager: PEReader, pevEager, pectxtCaptured, reduceMemoryUsage, ilGlobals) = +let openMetadataReader (fileName, mdfile: BinaryFile, metadataPhysLoc, peinfo, pectxtEager: PEReader, pevEager, pectxtCaptured, reduceMemoryUsage) = let mdv = mdfile.GetView() let magic = seekReadUInt16AsInt32 mdv metadataPhysLoc if magic <> 0x5342 then failwith (fileName + ": bad metadata magic number: " + string magic) @@ -3426,8 +3427,7 @@ let openMetadataReader (fileName, mdfile: BinaryFile, metadataPhysLoc, peinfo, p // Use an initialization hole let ctxtH = ref None let ctxt: ILMetadataReader = - { ilg=ilGlobals - sorted=sorted + { sorted=sorted getNumRows=getNumRows mdfile=mdfile dataEndPoints = match pectxtCaptured with None -> notlazy [] | Some pectxt -> getDataEndPointsDelayed pectxt ctxtH @@ -3705,13 +3705,13 @@ let openPEFileReader (fileName, pefile: BinaryFile, pdbDirPath, noFileOnDisk) = let peinfo = (subsys, (subsysMajor, subsysMinor), useHighEnthropyVA, ilOnly, only32, is32bitpreferred, only64, platform, isDll, alignVirt, alignPhys, imageBaseReal) (metadataPhysLoc, metadataSize, peinfo, pectxt, pev, pdb) -let openPE (fileName, pefile, pdbDirPath, reduceMemoryUsage, ilGlobals, noFileOnDisk) = +let openPE (fileName, pefile, pdbDirPath, reduceMemoryUsage, noFileOnDisk) = let (metadataPhysLoc, _metadataSize, peinfo, pectxt, pev, pdb) = openPEFileReader (fileName, pefile, pdbDirPath, noFileOnDisk) - let ilModule, ilAssemblyRefs = openMetadataReader (fileName, pefile, metadataPhysLoc, peinfo, pectxt, pev, Some pectxt, reduceMemoryUsage, ilGlobals) + let ilModule, ilAssemblyRefs = openMetadataReader (fileName, pefile, metadataPhysLoc, peinfo, pectxt, pev, Some pectxt, reduceMemoryUsage) ilModule, ilAssemblyRefs, pdb -let openPEMetadataOnly (fileName, peinfo, pectxtEager, pevEager, mdfile: BinaryFile, reduceMemoryUsage, ilGlobals) = - openMetadataReader (fileName, mdfile, 0, peinfo, pectxtEager, pevEager, None, reduceMemoryUsage, ilGlobals) +let openPEMetadataOnly (fileName, peinfo, pectxtEager, pevEager, mdfile: BinaryFile, reduceMemoryUsage) = + openMetadataReader (fileName, mdfile, 0, peinfo, pectxtEager, pevEager, None, reduceMemoryUsage) let ClosePdbReader pdb = #if FX_NO_PDB_READER @@ -3734,7 +3734,6 @@ type ReduceMemoryFlag = Yes | No type ILReaderOptions = { pdbDirPath: string option - ilGlobals: ILGlobals reduceMemoryUsage: ReduceMemoryFlag metadataOnly: MetadataOnlyFlag tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot } @@ -3756,7 +3755,7 @@ type ILModuleReaderImpl(ilModule: ILModuleDef, ilAssemblyRefs: Lazy BinaryFile - let ilModule, ilAssemblyRefs, pdb = openPE (fileName, pefile, opts.pdbDirPath, (opts.reduceMemoryUsage = ReduceMemoryFlag.Yes), opts.ilGlobals, true) + let ilModule, ilAssemblyRefs, pdb = openPE (fileName, pefile, opts.pdbDirPath, (opts.reduceMemoryUsage = ReduceMemoryFlag.Yes), true) new ILModuleReaderImpl(ilModule, ilAssemblyRefs, (fun () -> ClosePdbReader pdb)) :> ILModuleReader let ClearAllILModuleReaderCache() = @@ -3815,15 +3814,15 @@ let ClearAllILModuleReaderCache() = let OpenILModuleReader fileName opts = // Pseudo-normalize the paths. - let (ILModuleReaderCacheKey (fullPath,writeStamp,_,_,_,_) as key), keyOk = + let (ILModuleReaderCacheKey (fullPath,writeStamp,_,_,_) as key), keyOk = try let fullPath = FileSystem.GetFullPathShim fileName let writeTime = FileSystem.GetLastWriteTimeShim fileName - let key = ILModuleReaderCacheKey (fullPath, writeTime, opts.ilGlobals.primaryAssemblyScopeRef, opts.pdbDirPath.IsSome, opts.reduceMemoryUsage, opts.metadataOnly) + let key = ILModuleReaderCacheKey (fullPath, writeTime, opts.pdbDirPath.IsSome, opts.reduceMemoryUsage, opts.metadataOnly) key, true with exn -> System.Diagnostics.Debug.Assert(false, sprintf "Failed to compute key in OpenILModuleReader cache for '%s'. Falling back to uncached. Error = %s" fileName (exn.ToString())) - let fakeKey = ILModuleReaderCacheKey(fileName, System.DateTime.UtcNow, ILScopeRef.Local, false, ReduceMemoryFlag.Yes, MetadataOnlyFlag.Yes) + let fakeKey = ILModuleReaderCacheKey(fileName, System.DateTime.UtcNow, false, ReduceMemoryFlag.Yes, MetadataOnlyFlag.Yes) fakeKey, false let cacheResult1 = @@ -3878,13 +3877,13 @@ let OpenILModuleReader fileName opts = // If tryGetMetadata doesn't give anything, then just read the metadata chunk out of the binary createByteFileChunk opts fullPath (Some (metadataPhysLoc, metadataSize)) - let ilModule, ilAssemblyRefs = openPEMetadataOnly (fullPath, peinfo, pectxtEager, pevEager, mdfile, reduceMemoryUsage, opts.ilGlobals) + let ilModule, ilAssemblyRefs = openPEMetadataOnly (fullPath, peinfo, pectxtEager, pevEager, mdfile, reduceMemoryUsage) new ILModuleReaderImpl(ilModule, ilAssemblyRefs, ignore) else // If we are not doing metadata-only, then just go ahead and read all the bytes and hold them either strongly or weakly // depending on the heuristic let pefile = createByteFileChunk opts fullPath None - let ilModule, ilAssemblyRefs, _pdb = openPE (fullPath, pefile, None, reduceMemoryUsage, opts.ilGlobals, false) + let ilModule, ilAssemblyRefs, _pdb = openPE (fullPath, pefile, None, reduceMemoryUsage, false) new ILModuleReaderImpl(ilModule, ilAssemblyRefs, ignore) let ilModuleReader = ilModuleReader :> ILModuleReader @@ -3912,7 +3911,7 @@ let OpenILModuleReader fileName opts = else createByteFileChunk opts fullPath None - let ilModule, ilAssemblyRefs, pdb = openPE (fullPath, pefile, opts.pdbDirPath, reduceMemoryUsage, opts.ilGlobals, false) + let ilModule, ilAssemblyRefs, pdb = openPE (fullPath, pefile, opts.pdbDirPath, reduceMemoryUsage, false) let ilModuleReader = new ILModuleReaderImpl(ilModule, ilAssemblyRefs, (fun () -> ClosePdbReader pdb)) let ilModuleReader = ilModuleReader :> ILModuleReader diff --git a/src/absil/ilread.fsi b/src/absil/ilread.fsi index 000b9cc34f..aaa2b0b6e8 100644 --- a/src/absil/ilread.fsi +++ b/src/absil/ilread.fsi @@ -46,8 +46,6 @@ type ReduceMemoryFlag = Yes | No type ILReaderOptions = { pdbDirPath: string option - ilGlobals: ILGlobals - // fsc.exe does not use reduceMemoryUsage (hence keeps MORE caches in AbstractIL and MORE memory mapping and MORE memory hogging but FASTER and SIMPLER file access) // fsi.exe does uses reduceMemoryUsage (hence keeps FEWER caches in AbstractIL and LESS memory mapping and LESS memory hogging but slightly SLOWER file access), because its long running // FCS uses reduceMemoryUsage (hence keeps FEWER caches in AbstractIL and LESS memory mapping and LESS memory hogging), because it is typically long running diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index c6a79dd5b8..9657cf1794 100644 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -322,6 +322,21 @@ type cenv = override x.ToString() = "" +let convResolveAssemblyRef (cenv: cenv) (asmref: ILAssemblyRef) qualifiedName = + let assembly = + match cenv.resolveAssemblyRef asmref with + | Some (Choice1Of2 path) -> + FileSystem.AssemblyLoadFrom path + | Some (Choice2Of2 assembly) -> + assembly + | None -> + let asmName = convAssemblyRef asmref + FileSystem.AssemblyLoad asmName + let typT = assembly.GetType qualifiedName + match typT with + | null -> error(Error(FSComp.SR.itemNotFoundDuringDynamicCodeGen ("type", qualifiedName, asmref.QualifiedName), range0)) + | res -> res + /// 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. @@ -333,25 +348,15 @@ let convTypeRefAux (cenv: cenv) (tref: ILTypeRef) = let qualifiedName = (String.concat "+" (tref.Enclosing @ [ tref.Name ])).Replace(",", @"\,") match tref.Scope with | ILScopeRef.Assembly asmref -> - let assembly = - match cenv.resolveAssemblyRef asmref with - | Some (Choice1Of2 path) -> - FileSystem.AssemblyLoadFrom path - | Some (Choice2Of2 assembly) -> - assembly - | None -> - let asmName = convAssemblyRef asmref - FileSystem.AssemblyLoad asmName - let typT = assembly.GetType qualifiedName - match typT with - | null -> error(Error(FSComp.SR.itemNotFoundDuringDynamicCodeGen ("type", qualifiedName, asmref.QualifiedName), range0)) - | res -> res + convResolveAssemblyRef cenv asmref qualifiedName | ILScopeRef.Module _ | ILScopeRef.Local _ -> let typT = Type.GetType qualifiedName match typT with | null -> error(Error(FSComp.SR.itemNotFoundDuringDynamicCodeGen ("type", qualifiedName, ""), range0)) | res -> res + | ILScopeRef.PrimaryAssembly -> + convResolveAssemblyRef cenv cenv.ilg.primaryAssemblyRef qualifiedName diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 802ad3d3a0..1464e29923 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -754,6 +754,7 @@ let GetScopeRefAsImplementationElem cenv scoref = | ILScopeRef.Local -> (i_AssemblyRef, 0) | ILScopeRef.Assembly aref -> (i_AssemblyRef, GetAssemblyRefAsIdx cenv aref) | ILScopeRef.Module mref -> (i_File, GetModuleRefAsFileIdx cenv mref) + | ILScopeRef.PrimaryAssembly -> (i_AssemblyRef, GetAssemblyRefAsIdx cenv cenv.ilg.primaryAssemblyRef) // -------------------------------------------------------------------- // Type references, types etc. @@ -781,6 +782,7 @@ and GetResolutionScopeAsElem cenv (scoref, enc) = | ILScopeRef.Local -> (rs_Module, 1) | ILScopeRef.Assembly aref -> (rs_AssemblyRef, GetAssemblyRefAsIdx cenv aref) | ILScopeRef.Module mref -> (rs_ModuleRef, GetModuleRefAsIdx cenv mref) + | ILScopeRef.PrimaryAssembly -> (rs_AssemblyRef, GetAssemblyRefAsIdx cenv cenv.ilg.primaryAssemblyRef) else let enc2, n2 = List.frontAndBack enc (rs_TypeRef, GetTypeDescAsTypeRefIdx cenv (scoref, enc2, n2)) @@ -866,27 +868,25 @@ and GetTypeAsTypeSpecIdx cenv env ty = FindOrAddSharedRow cenv TableNames.TypeSpec (GetTypeAsTypeSpecRow cenv env ty) and EmitType cenv env bb ty = + let ilg = cenv.ilg match ty with - // REVIEW: what are these doing here? - | ILType.Value tspec when tspec.Name = "System.String" -> bb.EmitByte et_STRING - | ILType.Value tspec when tspec.Name = "System.Object" -> bb.EmitByte et_OBJECT - | ty when isILSByteTy ty -> bb.EmitByte et_I1 - | ty when isILInt16Ty ty -> bb.EmitByte et_I2 - | ty when isILInt32Ty ty -> bb.EmitByte et_I4 - | ty when isILInt64Ty ty -> bb.EmitByte et_I8 - | ty when isILByteTy ty -> bb.EmitByte et_U1 - | ty when isILUInt16Ty ty -> bb.EmitByte et_U2 - | ty when isILUInt32Ty ty -> bb.EmitByte et_U4 - | ty when isILUInt64Ty ty -> bb.EmitByte et_U8 - | ty when isILDoubleTy ty -> bb.EmitByte et_R8 - | ty when isILSingleTy ty -> bb.EmitByte et_R4 - | ty when isILBoolTy ty -> bb.EmitByte et_BOOLEAN - | ty when isILCharTy ty -> bb.EmitByte et_CHAR - | ty when isILStringTy ty -> bb.EmitByte et_STRING - | ty when isILObjectTy ty -> bb.EmitByte et_OBJECT - | ty when isILIntPtrTy ty -> bb.EmitByte et_I - | ty when isILUIntPtrTy ty -> bb.EmitByte et_U - | ty when isILTypedReferenceTy ty -> bb.EmitByte et_TYPEDBYREF + | ty when isILSByteTy ilg ty -> bb.EmitByte et_I1 + | ty when isILInt16Ty ilg ty -> bb.EmitByte et_I2 + | ty when isILInt32Ty ilg ty -> bb.EmitByte et_I4 + | ty when isILInt64Ty ilg ty -> bb.EmitByte et_I8 + | ty when isILByteTy ilg ty -> bb.EmitByte et_U1 + | ty when isILUInt16Ty ilg ty -> bb.EmitByte et_U2 + | ty when isILUInt32Ty ilg ty -> bb.EmitByte et_U4 + | ty when isILUInt64Ty ilg ty -> bb.EmitByte et_U8 + | ty when isILDoubleTy ilg ty -> bb.EmitByte et_R8 + | ty when isILSingleTy ilg ty -> bb.EmitByte et_R4 + | ty when isILBoolTy ilg ty -> bb.EmitByte et_BOOLEAN + | ty when isILCharTy ilg ty -> bb.EmitByte et_CHAR + | ty when isILStringTy ilg ty -> bb.EmitByte et_STRING + | ty when isILObjectTy ilg ty -> bb.EmitByte et_OBJECT + | ty when isILIntPtrTy ilg ty -> bb.EmitByte et_I + | ty when isILUIntPtrTy ilg ty -> bb.EmitByte et_U + | ty when isILTypedReferenceTy ilg ty -> bb.EmitByte et_TYPEDBYREF | ILType.Boxed tspec -> EmitTypeSpec cenv env bb (et_CLASS, tspec) | ILType.Value tspec -> EmitTypeSpec cenv env bb (et_VALUETYPE, tspec) @@ -3621,6 +3621,7 @@ let writeBinaryAndReportMappings (outfile, match ilg.primaryAssemblyScopeRef with | ILScopeRef.Local -> failwith "Expected mscorlib to be ILScopeRef.Assembly was ILScopeRef.Local" | ILScopeRef.Module(_) -> failwith "Expected mscorlib to be ILScopeRef.Assembly was ILScopeRef.Module" + | ILScopeRef.PrimaryAssembly -> failwith "Expected mscorlib to be ILScopeRef.Assembly was ILScopeRef.PrimaryAssembly" | ILScopeRef.Assembly aref -> match aref.Version with | Some version when version.Major = 2us -> parseILVersion "2.0.50727.0" diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 676ea72f16..2217184054 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2474,10 +2474,9 @@ type TcConfigBuilder = ri, fileNameOfPath ri, ILResourceAccess.Public -let OpenILBinary(filename, reduceMemoryUsage, ilGlobals, pdbDirPath, shadowCopyReferences, tryGetMetadataSnapshot) = +let OpenILBinary(filename, reduceMemoryUsage, pdbDirPath, shadowCopyReferences, tryGetMetadataSnapshot) = let opts: ILReaderOptions = - { ilGlobals = ilGlobals - metadataOnly = MetadataOnlyFlag.Yes + { metadataOnly = MetadataOnlyFlag.Yes reduceMemoryUsage = reduceMemoryUsage pdbDirPath = pdbDirPath tryGetMetadataSnapshot = tryGetMetadataSnapshot } @@ -2542,7 +2541,6 @@ type AssemblyResolution = | None -> let readerSettings: ILReaderOptions = { pdbDirPath=None - ilGlobals = EcmaMscorlibILGlobals reduceMemoryUsage = reduceMemoryUsage metadataOnly = MetadataOnlyFlag.Yes tryGetMetadataSnapshot = tryGetMetadataSnapshot } @@ -3981,8 +3979,7 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let tcConfig = tcConfigP.Get ctok let ilModule, ilAssemblyRefs = let opts: ILReaderOptions = - { ilGlobals = g.ilg - reduceMemoryUsage = tcConfig.reduceMemoryUsage + { reduceMemoryUsage = tcConfig.reduceMemoryUsage pdbDirPath = None metadataOnly = MetadataOnlyFlag.Yes tryGetMetadataSnapshot = tcConfig.tryGetMetadataSnapshot } @@ -4075,15 +4072,8 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse else None - let ilGlobals = - // ILScopeRef.Local can be used only for primary assembly (mscorlib or System.Runtime) itself - // Remaining assemblies should be opened using existing ilGlobals (so they can properly locate fundamental types) - match ilGlobalsOpt with - | None -> mkILGlobals ILScopeRef.Local - | Some g -> g - let ilILBinaryReader = - OpenILBinary (filename, tcConfig.reduceMemoryUsage, ilGlobals, pdbDirPath, tcConfig.shadowCopyReferences, tcConfig.tryGetMetadataSnapshot) + OpenILBinary (filename, tcConfig.reduceMemoryUsage, pdbDirPath, tcConfig.shadowCopyReferences, tcConfig.tryGetMetadataSnapshot) tcImports.AttachDisposeAction(fun _ -> (ilILBinaryReader :> IDisposable).Dispose()) ilILBinaryReader.ILModuleDef, ilILBinaryReader.ILAssemblyRefs @@ -4678,11 +4668,48 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse | (_, [ResolvedImportedAssembly ccu]) -> ccu.FSharpViewOfMetadata.ILScopeRef | _ -> failwith "unexpected" - let ilGlobals = mkILGlobals primaryScopeRef + let primaryAssemblyResolvedPath = + match primaryAssemblyResolution with + | [primaryAssemblyResolution] -> primaryAssemblyResolution.resolvedPath + | _ -> failwith "unexpected" + + let resolvedAssemblies = tcResolutions.GetAssemblyResolutions() + + let readerSettings: ILReaderOptions = + { pdbDirPath=None + reduceMemoryUsage = tcConfig.reduceMemoryUsage + metadataOnly = MetadataOnlyFlag.Yes + tryGetMetadataSnapshot = tcConfig.tryGetMetadataSnapshot } + + let tryFindAssemblyByExportedType manifest (exportedType: ILExportedTypeOrForwarder) = + match exportedType.ScopeRef, primaryScopeRef with + | ILScopeRef.Assembly aref1, ILScopeRef.Assembly aref2 when aref1.EqualsIgnoringVersion aref2 -> + mkRefToILAssembly manifest + |> Some + | _ -> + None + + let tryFindAssemblyThatForwardsToPrimaryAssembly manifest = + manifest.ExportedTypes.TryFindByName "System.Object" + |> Option.bind (tryFindAssemblyByExportedType manifest) + + // Determine what other assemblies could have been the primary assembly + // by checking to see if "System.Object" is an exported type. + let assembliesThatForwardToPrimaryAssembly = + resolvedAssemblies + |> List.choose (fun resolvedAssembly -> + if primaryAssemblyResolvedPath <> resolvedAssembly.resolvedPath then + let reader = OpenILModuleReader resolvedAssembly.resolvedPath readerSettings + reader.ILModuleDef.Manifest + |> Option.bind tryFindAssemblyThatForwardsToPrimaryAssembly + else + None) + + let ilGlobals = mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly) frameworkTcImports.SetILGlobals ilGlobals // Load the rest of the framework DLLs all at once (they may be mutually recursive) - let! _assemblies = frameworkTcImports.RegisterAndImportReferencedAssemblies (ctok, tcResolutions.GetAssemblyResolutions()) + let! _assemblies = frameworkTcImports.RegisterAndImportReferencedAssemblies (ctok, resolvedAssemblies) // These are the DLLs we can search for well-known types let sysCcus = @@ -4725,7 +4752,8 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse (let scoref = fslibCcuInfo.ILScopeRef match scoref with | ILScopeRef.Assembly aref -> Some aref - | ILScopeRef.Local | ILScopeRef.Module _ -> error(InternalError("not ILScopeRef.Assembly", rangeStartup))) + | ILScopeRef.Local | ILScopeRef.Module _ | ILScopeRef.PrimaryAssembly -> + error(InternalError("not ILScopeRef.Assembly", rangeStartup))) fslibCcuInfo.FSharpViewOfMetadata // OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index e5febe9d65..6510790668 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -1833,14 +1833,17 @@ let GenerateIlxCode // by the same references. Only used for static linking. //---------------------------------------------------------------------------- -let NormalizeAssemblyRefs (ctok, tcImports:TcImports) scoref = +let NormalizeAssemblyRefs (ctok, ilGlobals: ILGlobals, tcImports:TcImports) scoref = + let normalizeAssemblyRefByName nm = + match tcImports.TryFindDllInfo (ctok, Range.rangeStartup, nm, lookupOnly=false) with + | Some dllInfo -> dllInfo.ILScopeRef + | None -> scoref + match scoref with | ILScopeRef.Local | ILScopeRef.Module _ -> scoref - | ILScopeRef.Assembly aref -> - match tcImports.TryFindDllInfo (ctok, Range.rangeStartup, aref.Name, lookupOnly=false) with - | Some dllInfo -> dllInfo.ILScopeRef - | None -> scoref + | ILScopeRef.PrimaryAssembly -> normalizeAssemblyRefByName ilGlobals.primaryAssemblyName + | ILScopeRef.Assembly aref -> normalizeAssemblyRefByName aref.Name let GetGeneratedILModuleName (t:CompilerTarget) (s:string) = // return the name of the file as a module name diff --git a/src/fsharp/CompileOptions.fsi b/src/fsharp/CompileOptions.fsi index c9fe8de35d..da86aa4200 100644 --- a/src/fsharp/CompileOptions.fsi +++ b/src/fsharp/CompileOptions.fsi @@ -4,6 +4,7 @@ module internal FSharp.Compiler.CompileOptions open System open FSharp.Compiler +open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.CompileOps open FSharp.Compiler.Tast @@ -85,7 +86,7 @@ val CreateIlxAssemblyGenerator : TcConfig * TcImports * TcGlobals * ConstraintSo val GenerateIlxCode : IlxGen.IlxGenBackend * isInteractiveItExpr:bool * isInteractiveOnMono:bool * TcConfig * TypeChecker.TopAttribs * TypedAssemblyAfterOptimization * fragName:string * IlxGen.IlxAssemblyGenerator -> IlxGen.IlxGenResults // Used during static linking -val NormalizeAssemblyRefs : CompilationThreadToken * TcImports -> (AbstractIL.IL.ILScopeRef -> AbstractIL.IL.ILScopeRef) +val NormalizeAssemblyRefs : CompilationThreadToken * ILGlobals * TcImports -> (AbstractIL.IL.ILScopeRef -> AbstractIL.IL.ILScopeRef) // Miscellany val ignoreFailureOnMono1_1_16 : (unit -> unit) -> unit diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index cf4e4e1745..879130ab74 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -988,6 +988,7 @@ and ConvILTypeRef cenv (tr: ILTypeRef) = let assemblyRef = match tr.Scope with | ILScopeRef.Local -> "." + | ILScopeRef.PrimaryAssembly -> cenv.g.ilg.primaryAssemblyScopeRef.QualifiedName | _ -> tr.Scope.QualifiedName QP.Named(tr.BasicQualifiedName, assemblyRef) diff --git a/src/fsharp/TastPickle.fs b/src/fsharp/TastPickle.fs index 5b0acbc517..ffdf31efbd 100644 --- a/src/fsharp/TastPickle.fs +++ b/src/fsharp/TastPickle.fs @@ -919,9 +919,11 @@ let p_ILAssemblyRef (x: ILAssemblyRef) st = let p_ILScopeRef x st = match x with - | ILScopeRef.Local -> p_byte 0 st - | ILScopeRef.Module mref -> p_byte 1 st; p_ILModuleRef mref st - | ILScopeRef.Assembly aref -> p_byte 2 st; p_ILAssemblyRef aref st + | ILScopeRef.Local -> p_byte 0 st + | ILScopeRef.Module mref -> p_byte 1 st; p_ILModuleRef mref st + | ILScopeRef.Assembly aref -> p_byte 2 st; p_ILAssemblyRef aref st + // Encode primary assembly as a normal assembly ref + | ILScopeRef.PrimaryAssembly -> p_byte 2 st; p_ILAssemblyRef st.oglobals.ilg.primaryAssemblyRef st let u_ILPublicKey st = let tag = u_byte st diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 17c8a21931..839d7b4d63 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -1282,7 +1282,7 @@ module StaticLinker = mutable visited: bool } // Find all IL modules that are to be statically linked given the static linking roots. - let FindDependentILModulesForStaticLinking (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals, ilxMainModule) = + let FindDependentILModulesForStaticLinking (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlobals, ilxMainModule) = if not tcConfig.standalone && tcConfig.extraStaticLinkRoots.IsEmpty then [] else @@ -1298,7 +1298,7 @@ module StaticLinker = let assumedIndependentSet = set [ "mscorlib"; "System"; "System.Core"; "System.Xml"; "Microsoft.Build.Framework"; "Microsoft.Build.Utilities" ] begin - let mutable remaining = (computeILRefs ilxMainModule).AssemblyReferences + let mutable remaining = (computeILRefs ilGlobals ilxMainModule).AssemblyReferences while not (isNil remaining) do let ilAssemRef = List.head remaining remaining <- List.tail remaining @@ -1330,8 +1330,7 @@ module StaticLinker = None let opts : ILReaderOptions = - { ilGlobals = ilGlobals - metadataOnly = MetadataOnlyFlag.No // turn this off here as we need the actual IL code + { metadataOnly = MetadataOnlyFlag.No // turn this off here as we need the actual IL code reduceMemoryUsage = tcConfig.reduceMemoryUsage pdbDirPath = pdbDirPathOption tryGetMetadataSnapshot = (fun _ -> None) } @@ -1591,7 +1590,7 @@ module StaticLinker = if (not isMscorlib && name = PrimaryAssembly.Mscorlib.Name) then error (Error(FSComp.SR.fscStaticLinkingNoProfileMismatches(), rangeCmdArgs)) scopeRef - let rewriteAssemblyRefsToMatchLibraries = NormalizeAssemblyRefs (ctok, tcImports) + let rewriteAssemblyRefsToMatchLibraries = NormalizeAssemblyRefs (ctok, ilGlobals, tcImports) Morphs.morphILTypeRefsInILModuleMemoized ilGlobals (Morphs.morphILScopeRefsInILTypeRef (validateTargetPlatform >> rewriteExternalRefsToLocalRefs >> rewriteAssemblyRefsToMatchLibraries)) ilxMainModule ilxMainModule) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 1c7f4b6759..cd43753ab5 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1037,7 +1037,7 @@ type internal FsiDynamicCompiler errorLogger.AbortOnError(fsiConsoleOutput); ReportTime tcConfig "Assembly refs Normalised"; - let mainmod3 = Morphs.morphILScopeRefsInILModuleMemoized ilGlobals (NormalizeAssemblyRefs (ctok, tcImports)) ilxMainModule + let mainmod3 = Morphs.morphILScopeRefsInILModuleMemoized ilGlobals (NormalizeAssemblyRefs (ctok, ilGlobals, tcImports)) ilxMainModule errorLogger.AbortOnError(fsiConsoleOutput); #if DEBUG diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs index 29943461bd..849d7fff70 100644 --- a/src/fsharp/import.fs +++ b/src/fsharp/import.fs @@ -56,32 +56,38 @@ type ImportMap(g: TcGlobals, assemblyLoader: AssemblyLoader) = member this.ILTypeRefToTyconRefCache = typeRefToTyconRefCache let CanImportILScopeRef (env: ImportMap) m scoref = - match scoref with - | ILScopeRef.Local -> true - | ILScopeRef.Module _ -> true - | ILScopeRef.Assembly assemblyRef -> + let isResolved assemblyRef = // Explanation: This represents an unchecked invariant in the hosted compiler: that any operations // which import types (and resolve assemblies from the tcImports tables) happen on the compilation thread. let ctok = AssumeCompilationThreadWithoutEvidence() - + match env.assemblyLoader.FindCcuFromAssemblyRef (ctok, m, assemblyRef) with - | UnresolvedCcu _ -> false + | UnresolvedCcu _ -> false | ResolvedCcu _ -> true + match scoref with + | ILScopeRef.Local + | ILScopeRef.Module _ -> true + | ILScopeRef.Assembly assemblyRef -> isResolved assemblyRef + | ILScopeRef.PrimaryAssembly -> isResolved env.g.ilg.primaryAssemblyRef /// Import a reference to a type definition, given the AbstractIL data for the type reference let ImportTypeRefData (env: ImportMap) m (scoref, path, typeName) = - - // Explanation: This represents an unchecked invariant in the hosted compiler: that any operations - // which import types (and resolve assemblies from the tcImports tables) happen on the compilation thread. - let ctok = AssumeCompilationThreadWithoutEvidence() - let ccu = + let findCcu assemblyRef = + // Explanation: This represents an unchecked invariant in the hosted compiler: that any operations + // which import types (and resolve assemblies from the tcImports tables) happen on the compilation thread. + let ctok = AssumeCompilationThreadWithoutEvidence() + + env.assemblyLoader.FindCcuFromAssemblyRef (ctok, m, assemblyRef) + + let ccu = match scoref with | ILScopeRef.Local -> error(InternalError("ImportILTypeRef: unexpected local scope", m)) | ILScopeRef.Module _ -> error(InternalError("ImportILTypeRef: reference found to a type in an auxiliary module", m)) - | ILScopeRef.Assembly assemblyRef -> env.assemblyLoader.FindCcuFromAssemblyRef (ctok, m, assemblyRef) // NOTE: only assemblyLoader callsite + | ILScopeRef.Assembly assemblyRef -> findCcu assemblyRef + | ILScopeRef.PrimaryAssembly -> findCcu env.g.ilg.primaryAssemblyRef // Do a dereference of a fake tcref for the type just to check it exists in the target assembly and to find // the corresponding Tycon. diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index d46313cb37..295e42b02c 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -99,7 +99,7 @@ module Impl = invalidOp (sprintf "The entity '%s' does not exist or is in an unresolved assembly." poorQualifiedName) /// Checking accessibility that arise from different compilations needs more care - this is a duplicate of the F# compiler code for this case - let checkForCrossProjectAccessibility (thisCcu2:CcuThunk, ad2) (thisCcu1, taccess1) = + let checkForCrossProjectAccessibility (ilg: ILGlobals) (thisCcu2:CcuThunk, ad2) (thisCcu1, taccess1) = match ad2 with | AccessibleFrom(cpaths2, _) -> let nameOfScoRef (thisCcu:CcuThunk) scoref = @@ -107,6 +107,7 @@ module Impl = | ILScopeRef.Local -> thisCcu.AssemblyName | ILScopeRef.Assembly aref -> aref.Name | ILScopeRef.Module mref -> mref.Name + | ILScopeRef.PrimaryAssembly -> ilg.primaryAssemblyName let canAccessCompPathFromCrossProject (CompPath(scoref1, cpath1)) (CompPath(scoref2, cpath2)) = let rec loop p1 p2 = match p1, p2 with @@ -328,7 +329,7 @@ and FSharpEntity(cenv: SymbolEnv, entity:EntityRef) = if entity.IsModuleOrNamespace then Item.ModuleOrNamespaces [entity] else Item.UnqualifiedType [entity]), (fun _this thisCcu2 ad -> - checkForCrossProjectAccessibility (thisCcu2, ad) (cenv.thisCcu, getApproxFSharpAccessibilityOfEntity entity)) + checkForCrossProjectAccessibility cenv.g.ilg (thisCcu2, ad) (cenv.thisCcu, getApproxFSharpAccessibilityOfEntity entity)) // && AccessibilityLogic.IsEntityAccessible cenv.amap range0 ad entity) ) @@ -757,7 +758,7 @@ and FSharpUnionCase(cenv, v: UnionCaseRef) = checkEntityIsResolved v.TyconRef Item.UnionCase(UnionCaseInfo(generalizeTypars v.TyconRef.TyparsNoRange, v), false)), (fun _this thisCcu2 ad -> - checkForCrossProjectAccessibility (thisCcu2, ad) (cenv.thisCcu, v.UnionCase.Accessibility)) + checkForCrossProjectAccessibility cenv.g.ilg (thisCcu2, ad) (cenv.thisCcu, v.UnionCase.Accessibility)) //&& AccessibilityLogic.IsUnionCaseAccessible cenv.amap range0 ad v) ) @@ -874,7 +875,7 @@ and FSharpField(cenv: SymbolEnv, d: FSharpFieldData) = | ILField f -> Item.ILField f), (fun this thisCcu2 ad -> - checkForCrossProjectAccessibility (thisCcu2, ad) (cenv.thisCcu, (this :?> FSharpField).Accessibility.Contents)) + checkForCrossProjectAccessibility cenv.g.ilg (thisCcu2, ad) (cenv.thisCcu, (this :?> FSharpField).Accessibility.Contents)) //&& //match d with //| Recd v -> AccessibilityLogic.IsRecdFieldAccessible cenv.amap range0 ad v @@ -1366,7 +1367,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = (fun () -> item), (fun this thisCcu2 ad -> let this = this :?> FSharpMemberOrFunctionOrValue - checkForCrossProjectAccessibility (thisCcu2, ad) (cenv.thisCcu, this.Accessibility.Contents)) + checkForCrossProjectAccessibility cenv.g.ilg (thisCcu2, ad) (cenv.thisCcu, this.Accessibility.Contents)) //&& //match d with //| E e -> @@ -2462,7 +2463,12 @@ and FSharpAssembly internal (cenv, ccu: CcuThunk) = member __.Contents : FSharpAssemblySignature = FSharpAssemblySignature(cenv, ccu) - override x.ToString() = ccu.ILScopeRef.QualifiedName + override x.ToString() = + match ccu.ILScopeRef with + | ILScopeRef.PrimaryAssembly -> + cenv.g.ilg.primaryAssemblyRef.QualifiedName + | scoref -> + scoref.QualifiedName /// Represents open declaration in F# code. [] diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 7dc9e0a11d..a6d5ae499a 100644 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -515,6 +515,7 @@ let getNameOfScopeRef sref = | ILScopeRef.Local -> "" | ILScopeRef.Module mref -> mref.Name | ILScopeRef.Assembly aref -> aref.Name + | ILScopeRef.PrimaryAssembly -> "" #if !NO_EXTENSIONTYPING let ComputeDefinitionLocationOfProvidedItem (p: Tainted<#IProvidedCustomAttributeProvider>) = From 6cec616b0db3a01715163f9959d98c0173cfab5b Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 15 Jan 2020 23:06:58 +0200 Subject: [PATCH 027/101] Add Expr.NewStructTuple constructor and active pattern (#8193) * add Expr.NewStructTuple constructor and active pattern * update surface areas --- src/fsharp/FSharp.Core/quotations.fs | 10 +++++ src/fsharp/FSharp.Core/quotations.fsi | 12 +++++ src/fsharp/FSharp.Core/reflect.fsi | 2 + .../FSharpQuotations.fs | 45 ++++++++++++++++++- .../SurfaceArea.coreclr.fs | 2 + .../SurfaceArea.net40.fs | 2 + 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index 974e32c767..f1d2dea11e 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -391,6 +391,9 @@ module Patterns = [] let (|NewTuple|_|) input = match input with E(CombTerm(NewTupleOp(_), es)) -> Some es | _ -> None + [] + let (|NewStructTuple|_|) input = match input with E(CombTerm(NewTupleOp(ty), es)) when ty.IsValueType -> Some es | _ -> None + [] let (|DefaultValue|_|) input = match input with E(CombTerm(DefaultValueOp ty, [])) -> Some ty | _ -> None @@ -747,6 +750,10 @@ module Patterns = let ty = FSharpType.MakeTupleType(Array.map typeOf (Array.ofList args)) mkFEN (NewTupleOp ty) args + let mkNewStructTuple (asm, args) = + let ty = FSharpType.MakeStructTupleType(asm, Array.map typeOf (Array.ofList args)) + mkFEN (NewTupleOp ty) args + let mkTupleGet (ty, n, x) = checkTypesSR ty (typeOf x) "tupleGet" (SR.GetString(SR.QtmmExprNotMatchTuple)) let mems = FSharpType.GetTupleElements ty @@ -1820,6 +1827,9 @@ type Expr with static member NewTuple elements = mkNewTuple elements + static member NewStructTuple (asm:Assembly, elements) = + mkNewStructTuple (asm, elements) + static member NewRecord (recordType:Type, elements) = checkNonNull "recordType" recordType mkNewRecord (recordType, elements) diff --git a/src/fsharp/FSharp.Core/quotations.fsi b/src/fsharp/FSharp.Core/quotations.fsi index f9ab5d7089..a782140fe4 100644 --- a/src/fsharp/FSharp.Core/quotations.fsi +++ b/src/fsharp/FSharp.Core/quotations.fsi @@ -181,6 +181,12 @@ type Expr = /// The resulting expression. static member NewTuple: elements:Expr list -> Expr + /// Builds an expression that represents the creation of an F# tuple value + /// Runtime assembly containing System.ValueTuple definitions. + /// The list of elements of the tuple. + /// The resulting expression. + static member NewStructTuple: asm:Assembly * elements:Expr list -> Expr + /// Builds record-construction expressions /// The type of record. /// The list of elements of the record. @@ -545,6 +551,12 @@ module Patterns = [] val (|NewTuple|_|) : input:Expr -> (Expr list) option + /// An active pattern to recognize expressions that represent construction of struct tuple values + /// The input expression to match against. + /// (Expr list) option + [] + val (|NewStructTuple|_|) : input:Expr -> (Expr list) option + /// An active pattern to recognize expressions that represent the read of a static or instance property, or a non-function value declared in a module /// The input expression to match against. /// (Expr option * PropertyInfo * Expr list) option diff --git a/src/fsharp/FSharp.Core/reflect.fsi b/src/fsharp/FSharp.Core/reflect.fsi index 359f36af77..465529677a 100644 --- a/src/fsharp/FSharp.Core/reflect.fsi +++ b/src/fsharp/FSharp.Core/reflect.fsi @@ -314,11 +314,13 @@ type FSharpType = static member MakeTupleType: types:Type[] -> Type /// Returns a System.Type representing an F# tuple type with the given element types + /// Runtime assembly containing System.Tuple definitions. /// An array of types for the tuple elements. /// The type representing the tuple containing the input elements. static member MakeTupleType: asm:Assembly * types:Type[] -> Type /// Returns a System.Type representing an F# struct tuple type with the given element types + /// Runtime assembly containing System.ValueTuple definitions. /// An array of types for the tuple elements. /// The type representing the struct tuple containing the input elements. static member MakeStructTupleType: asm:Assembly * types:Type[] -> Type diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs index ab5e8f9bd2..41c0cc19fb 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs @@ -7,7 +7,8 @@ namespace FSharp.Core.UnitTests.FSharp_Core.Microsoft_FSharp_Quotations open System open FSharp.Core.UnitTests.LibraryTestFx open NUnit.Framework -open Microsoft.FSharp.Quotations +open FSharp.Quotations +open FSharp.Quotations.Patterns type E = Microsoft.FSharp.Quotations.Expr;; @@ -84,4 +85,44 @@ type FSharpQuotationsTests() = [] member x.GetConstructorFiltersOutStaticConstructor() = - ignore <@ System.Exception() @> \ No newline at end of file + ignore <@ System.Exception() @> + + [] + member x.``NewStructTuple literal should be recognized by NewStructTuple active pattern`` () = + match <@ struct(1, "") @> with + | NewStructTuple [ Value(:? int as i, _) ; Value(:? string as s, _) ] when i = 1 && s = "" -> () + | _ -> Assert.Fail() + + + [] + member x.``NewStructTuple literal should be recognized by NewTuple active pattern`` () = + match <@ struct(1, "") @> with + | NewTuple [ Value(:? int as i, _) ; Value(:? string as s, _) ] when i = 1 && s = "" -> () + | _ -> Assert.Fail() + + [] + member x.``NewTuple literal should not be recognized by NewStructTuple active pattern`` () = + match <@ (1, "") @> with + | NewStructTuple _ -> Assert.Fail() + | _ -> () + + [] + member x.``NewStructTuple should be recognized by NewStructTuple active pattern`` () = + let expr = Expr.NewStructTuple(typeof.Assembly, [ <@@ 1 @@>; <@@ "" @@> ]) + match expr with + | NewStructTuple [ Value(:? int as i, _) ; Value(:? string as s, _) ] when i = 1 && s = "" -> () + | _ -> Assert.Fail() + + [] + member x.``NewStructTuple should be recognized by NewTuple active pattern`` () = + let expr = Expr.NewStructTuple(typeof.Assembly, [ <@@ 1 @@>; <@@ "" @@> ]) + match expr with + | NewTuple [ Value(:? int as i, _) ; Value(:? string as s, _) ] when i = 1 && s = "" -> () + | _ -> Assert.Fail() + + [] + member x.``NewTuple should not be recognized by NewStructTuple active pattern`` () = + let expr = Expr.NewTuple [ <@@ 1 @@>; <@@ "" @@> ] + match expr with + | NewStructTuple _ -> Assert.Fail() + | _ -> () \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs index 75461964f2..5e17904137 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs @@ -2584,6 +2584,7 @@ Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr N Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewDelegate(System.Type, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpVar], Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewObject(System.Reflection.ConstructorInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewRecord(System.Type, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) +Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewStructTuple(System.Reflection.Assembly, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewTuple(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewUnionCase(Microsoft.FSharp.Reflection.UnionCaseInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr PropertyGet(Microsoft.FSharp.Quotations.FSharpExpr, System.Reflection.PropertyInfo, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]) @@ -2641,6 +2642,7 @@ Microsoft.FSharp.Quotations.FSharpVar: System.String get_Name() Microsoft.FSharp.Quotations.FSharpVar: System.Type Type Microsoft.FSharp.Quotations.FSharpVar: System.Type get_Type() Microsoft.FSharp.Quotations.FSharpVar: Void .ctor(System.String, System.Type, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]] NewStructTuplePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]] NewTuplePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr] AddressOfPattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr] QuotePattern(Microsoft.FSharp.Quotations.FSharpExpr) diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs index 5b9b5f4388..42984aa831 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs @@ -2584,6 +2584,7 @@ Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr N Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewDelegate(System.Type, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpVar], Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewObject(System.Reflection.ConstructorInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewRecord(System.Type, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) +Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewStructTuple(System.Reflection.Assembly, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewTuple(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr NewUnionCase(Microsoft.FSharp.Reflection.UnionCaseInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr PropertyGet(Microsoft.FSharp.Quotations.FSharpExpr, System.Reflection.PropertyInfo, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]) @@ -2641,6 +2642,7 @@ Microsoft.FSharp.Quotations.FSharpVar: System.String get_Name() Microsoft.FSharp.Quotations.FSharpVar: System.Type Type Microsoft.FSharp.Quotations.FSharpVar: System.Type get_Type() Microsoft.FSharp.Quotations.FSharpVar: Void .ctor(System.String, System.Type, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]] NewStructTuplePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]] NewTuplePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr] AddressOfPattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr] QuotePattern(Microsoft.FSharp.Quotations.FSharpExpr) From c627f27c8b119715e423acd265ed0788b42c9db1 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 15 Jan 2020 14:41:23 -0800 Subject: [PATCH 028/101] Inline List.iter/List.iteri for performance (#8176) --- src/fsharp/FSharp.Core/list.fs | 6 ++++-- src/fsharp/FSharp.Core/list.fsi | 4 ++-- src/fsharp/FSharp.Core/local.fs | 11 ----------- src/fsharp/FSharp.Core/local.fsi | 2 -- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index 87035fb3c6..bf37ab08a1 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -100,7 +100,7 @@ namespace Microsoft.FSharp.Collections loop ([], state) (rev list) [] - let iter action list = Microsoft.FSharp.Primitives.Basics.List.iter action list + let inline iter action (list:'T list) = for x in list do action x [] let distinct (list:'T list) = Microsoft.FSharp.Primitives.Basics.List.distinctWithComparer HashIdentity.Structural<'T> list @@ -164,7 +164,9 @@ namespace Microsoft.FSharp.Collections let takeWhile predicate (list: 'T list) = Microsoft.FSharp.Primitives.Basics.List.takeWhile predicate list [] - let iteri action list = Microsoft.FSharp.Primitives.Basics.List.iteri action list + let inline iteri action (list: 'T list) = + let mutable n = 0 + for x in list do action n x; n <- n + 1 [] let init length initializer = Microsoft.FSharp.Primitives.Basics.List.init length initializer diff --git a/src/fsharp/FSharp.Core/list.fsi b/src/fsharp/FSharp.Core/list.fsi index aba9b3505b..26c5dad94e 100644 --- a/src/fsharp/FSharp.Core/list.fsi +++ b/src/fsharp/FSharp.Core/list.fsi @@ -380,7 +380,7 @@ namespace Microsoft.FSharp.Collections /// The function to apply to elements from the input list. /// The input list. [] - val iter: action:('T -> unit) -> list:'T list -> unit + val inline iter: action:('T -> unit) -> list:'T list -> unit /// Applies the given function to two collections simultaneously. The /// collections must have identical size. @@ -395,7 +395,7 @@ namespace Microsoft.FSharp.Collections /// The function to apply to the elements of the list along with their index. /// The input list. [] - val iteri: action:(int -> 'T -> unit) -> list:'T list -> unit + val inline iteri: action:(int -> 'T -> unit) -> list:'T list -> unit /// Applies the given function to two collections simultaneously. The /// collections must have identical size. The integer passed to the diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 89db09ecda..8e1b17ea91 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -88,8 +88,6 @@ module internal List = [] let nonempty x = match x with [] -> false | _ -> true - let rec iter f x = match x with [] -> () | h :: t -> f h; iter f t - // optimized mutation-based implementation. This code is only valid in fslib, where mutation of private // tail cons cells is permitted in carefully written library code. let inline setFreshConsTail cons t = cons.( :: ).1 <- t @@ -499,15 +497,6 @@ module internal List = else filter predicate t - let iteri action x = - let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(action) - let rec loop n x = - match x with - | [] -> () - | h :: t -> f.Invoke(n, h); loop (n+1) t - - loop 0 x - // optimized mutation-based implementation. This code is only valid in fslib, where mutation of private // tail cons cells is permitted in carefully written library code. let rec concatToFreshConsTail cons h1 l = diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index b5bcec9e95..2c9996d4f1 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -32,7 +32,6 @@ module internal List = val distinctWithComparer : System.Collections.Generic.IEqualityComparer<'T> -> 'T list -> 'T list val distinctByWithComparer : System.Collections.Generic.IEqualityComparer<'Key> -> ('T -> 'Key) -> list:'T list -> 'T list when 'Key : equality val init : int -> (int -> 'T) -> 'T list - val iter : ('T -> unit) -> 'T list -> unit val filter : predicate:('T -> bool) -> 'T list -> 'T list val collect : ('T -> 'U list) -> 'T list -> 'U list val partition : predicate:('T -> bool) -> 'T list -> 'T list * 'T list @@ -48,7 +47,6 @@ module internal List = val exists : predicate:('T -> bool) -> 'T list -> bool val rev: 'T list -> 'T list val concat : seq<'T list> -> 'T list - val iteri : action:(int -> 'T -> unit) -> 'T list -> unit val unfold : ('State -> ('T * 'State) option) -> 'State -> 'T list val unzip : ('T1 * 'T2) list -> 'T1 list * 'T2 list val unzip3 : ('T1 * 'T2 * 'T3) list -> 'T1 list * 'T2 list * 'T3 list From 68ea1f9b2bc8d224d1e884688cf121f44e026887 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Thu, 16 Jan 2020 20:36:55 +0100 Subject: [PATCH 029/101] Fix the .bsl spurious whitespace (#8219) * Rename `buff` to `writeViaBuffer` and remove `writeViaBufferWithEnvironmentNewLines` `writeViaBufferWithEnvironmentNewLines` is causing borked output when error message ends with "\n". This is probably dating from far back in the history of the codebase, and it doesn't show in windows console, probably because the console itself has some silly work around line termination... * a bunch of .bsl updated with accurate output * fix one bsl * non change for CI * non change for CI --- src/fsharp/fsc.fs | 4 ++-- src/fsharp/fsi/fsi.fs | 8 ++++---- src/fsharp/lib.fs | 11 ++--------- tests/fsharp/core/load-script/out.stderr.bsl | 1 - tests/fsharp/typecheck/sigs/neg04.bsl | 1 - tests/fsharp/typecheck/sigs/neg06.bsl | 1 - tests/fsharp/typecheck/sigs/neg07.bsl | 4 ---- tests/fsharp/typecheck/sigs/neg10.bsl | 2 -- tests/fsharp/typecheck/sigs/neg111.bsl | 3 --- tests/fsharp/typecheck/sigs/neg15.bsl | 6 ------ tests/fsharp/typecheck/sigs/neg17.bsl | 6 ------ tests/fsharp/typecheck/sigs/neg25.bsl | 3 --- tests/fsharp/typecheck/sigs/neg26.bsl | 2 -- tests/fsharp/typecheck/sigs/neg99.bsl | 2 +- tests/fsharp/typecheck/sigs/version46/neg24.bsl | 2 +- 15 files changed, 10 insertions(+), 46 deletions(-) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 839d7b4d63..e140b3351f 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -102,7 +102,7 @@ let ConsoleErrorLoggerUpToMaxErrors (tcConfigB: TcConfigBuilder, exiter : Exiter member __.HandleIssue(tcConfigB, err, isError) = DoWithErrorColor isError (fun () -> let diag = OutputDiagnostic (tcConfigB.implicitIncludeDir, tcConfigB.showFullPaths, tcConfigB.flatErrors, tcConfigB.errorStyle, isError) - writeViaBufferWithEnvironmentNewLines stderr diag err + writeViaBuffer stderr diag err stderr.WriteLine()) } :> ErrorLogger @@ -316,7 +316,7 @@ module InterfaceFileWriter = for (TImplFile (_, _, mexpr, _, _, _)) in declaredImpls do let denv = BuildInitialDisplayEnvForSigFileGeneration tcGlobals - writeViaBufferWithEnvironmentNewLines os (fun os s -> Printf.bprintf os "%s\n\n" s) + writeViaBuffer os (fun os s -> Printf.bprintf os "%s\n\n" s) (NicePrint.layoutInferredSigOfModuleExpr true denv infoReader AccessibleFromSomewhere range0 mexpr |> Layout.squashTo 80 |> Layout.showL) if tcConfig.printSignatureFile <> "" then os.Dispose() diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index cd43753ab5..9f6df3f16a 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -502,8 +502,8 @@ type internal FsiStdinSyphon(errorWriter: TextWriter) = let isError = true DoWithErrorColor isError (fun () -> errorWriter.WriteLine(); - writeViaBufferWithEnvironmentNewLines errorWriter (OutputDiagnosticContext " " syphon.GetLine) err; - writeViaBufferWithEnvironmentNewLines errorWriter (OutputDiagnostic (tcConfig.implicitIncludeDir,tcConfig.showFullPaths,tcConfig.flatErrors,tcConfig.errorStyle,isError)) err; + writeViaBuffer errorWriter (OutputDiagnosticContext " " syphon.GetLine) err; + writeViaBuffer errorWriter (OutputDiagnostic (tcConfig.implicitIncludeDir,tcConfig.showFullPaths,tcConfig.flatErrors,tcConfig.errorStyle,isError)) err; errorWriter.WriteLine() errorWriter.WriteLine() errorWriter.Flush())) @@ -548,8 +548,8 @@ type internal ErrorLoggerThatStopsOnFirstError(tcConfigB:TcConfigBuilder, fsiStd DoWithErrorColor isError (fun () -> if ReportWarning tcConfigB.errorSeverityOptions err then fsiConsoleOutput.Error.WriteLine() - writeViaBufferWithEnvironmentNewLines fsiConsoleOutput.Error (OutputDiagnosticContext " " fsiStdinSyphon.GetLine) err - writeViaBufferWithEnvironmentNewLines fsiConsoleOutput.Error (OutputDiagnostic (tcConfigB.implicitIncludeDir,tcConfigB.showFullPaths,tcConfigB.flatErrors,tcConfigB.errorStyle,isError)) err + writeViaBuffer fsiConsoleOutput.Error (OutputDiagnosticContext " " fsiStdinSyphon.GetLine) err + writeViaBuffer fsiConsoleOutput.Error (OutputDiagnostic (tcConfigB.implicitIncludeDir,tcConfigB.showFullPaths,tcConfigB.flatErrors,tcConfigB.errorStyle,isError)) err fsiConsoleOutput.Error.WriteLine() fsiConsoleOutput.Error.WriteLine() fsiConsoleOutput.Error.Flush()) diff --git a/src/fsharp/lib.fs b/src/fsharp/lib.fs index b9653f35c7..2b9d584bdc 100755 --- a/src/fsharp/lib.fs +++ b/src/fsharp/lib.fs @@ -313,19 +313,12 @@ let bufs f = f buf buf.ToString() -let buff (os: TextWriter) f x = +// writing to output stream via a string buffer. +let writeViaBuffer (os: TextWriter) f x = let buf = System.Text.StringBuilder 100 f buf x os.Write(buf.ToString()) -// Converts "\n" into System.Environment.NewLine before writing to os. See lib.fs:buff -let writeViaBufferWithEnvironmentNewLines (os: TextWriter) f x = - let buf = System.Text.StringBuilder 100 - f buf x - let text = buf.ToString() - let text = text.Replace("\n", System.Environment.NewLine) - os.Write text - //--------------------------------------------------------------------------- // Imperative Graphs //--------------------------------------------------------------------------- diff --git a/tests/fsharp/core/load-script/out.stderr.bsl b/tests/fsharp/core/load-script/out.stderr.bsl index 0c48e3a944..3090d5e2f8 100644 --- a/tests/fsharp/core/load-script/out.stderr.bsl +++ b/tests/fsharp/core/load-script/out.stderr.bsl @@ -1,4 +1,3 @@ usesfsi.fsx(2,1): error FS0039: The value, namespace, type or module 'fsi' is not defined. Maybe you want one of the following: - fst diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl index 058e3226a0..77df1028d2 100644 --- a/tests/fsharp/typecheck/sigs/neg04.bsl +++ b/tests/fsharp/typecheck/sigs/neg04.bsl @@ -12,7 +12,6 @@ neg04.fs(22,8,22,17): typecheck error FS0912: This declaration element is not pe neg04.fs(26,8,26,17): typecheck error FS0912: This declaration element is not permitted in an augmentation neg04.fs(32,8,32,11): typecheck error FS0039: The field, constructor or member 'Nan' is not defined. Maybe you want one of the following: - IsNaN neg04.fs(46,69,46,94): typecheck error FS0001: Type mismatch. Expecting a diff --git a/tests/fsharp/typecheck/sigs/neg06.bsl b/tests/fsharp/typecheck/sigs/neg06.bsl index bd3a528947..f7fe3615e4 100644 --- a/tests/fsharp/typecheck/sigs/neg06.bsl +++ b/tests/fsharp/typecheck/sigs/neg06.bsl @@ -1,6 +1,5 @@ neg06.fs(3,40,3,45): typecheck error FS0039: The field, constructor or member 'Ascii' is not defined. Maybe you want one of the following: - ASCII neg06.fs(12,6,12,31): typecheck error FS0942: Struct types are always sealed diff --git a/tests/fsharp/typecheck/sigs/neg07.bsl b/tests/fsharp/typecheck/sigs/neg07.bsl index af0466dd3f..614d9b222a 100644 --- a/tests/fsharp/typecheck/sigs/neg07.bsl +++ b/tests/fsharp/typecheck/sigs/neg07.bsl @@ -4,7 +4,6 @@ neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers shou neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers should not generally be used in patterns, and may indicate a misspelt pattern name. neg07.fs(24,13,24,23): typecheck error FS0039: The value or constructor 'UnionCase1' is not defined. Maybe you want one of the following: - X.UnionCase1 neg07.fs(27,11,27,21): typecheck error FS0049: Uppercase variable identifiers should not generally be used in patterns, and may indicate a misspelt pattern name. @@ -14,7 +13,6 @@ neg07.fs(28,11,28,21): typecheck error FS0049: Uppercase variable identifiers sh neg07.fs(28,11,28,21): typecheck error FS0026: This rule will never be matched neg07.fs(31,18,31,28): typecheck error FS0039: The value or constructor 'UnionCase1' is not defined. Maybe you want one of the following: - X.UnionCase1 neg07.fs(35,11,35,21): typecheck error FS0049: Uppercase variable identifiers should not generally be used in patterns, and may indicate a misspelt pattern name. @@ -24,11 +22,9 @@ neg07.fs(36,11,36,21): typecheck error FS0049: Uppercase variable identifiers sh neg07.fs(36,11,36,21): typecheck error FS0026: This rule will never be matched neg07.fs(46,15,46,27): typecheck error FS0039: The record label 'RecordLabel1' is not defined. Maybe you want one of the following: - R.RecordLabel1 neg07.fs(47,19,47,31): typecheck error FS0039: The record label 'RecordLabel1' is not defined. Maybe you want one of the following: - R.RecordLabel1 neg07.fs(57,10,57,17): typecheck error FS1196: The 'UseNullAsTrueValue' attribute flag may only be used with union types that have one nullary case and at least one non-nullary case diff --git a/tests/fsharp/typecheck/sigs/neg10.bsl b/tests/fsharp/typecheck/sigs/neg10.bsl index c31220273d..2e94ef5bd9 100644 --- a/tests/fsharp/typecheck/sigs/neg10.bsl +++ b/tests/fsharp/typecheck/sigs/neg10.bsl @@ -63,9 +63,7 @@ neg10.fs(169,32,169,35): typecheck error FS0035: This construct is deprecated: T neg10.fs(169,32,169,33): typecheck error FS3213: The member 'X : unit -> 'a' matches multiple overloads of the same method. Please restrict it to one of the following: - X : unit -> 'a - X : unit -> 'a. neg10.fs(169,19,169,26): typecheck error FS0783: At least one override did not correctly implement its corresponding abstract member diff --git a/tests/fsharp/typecheck/sigs/neg111.bsl b/tests/fsharp/typecheck/sigs/neg111.bsl index afe770b8fd..c5048f7c29 100644 --- a/tests/fsharp/typecheck/sigs/neg111.bsl +++ b/tests/fsharp/typecheck/sigs/neg111.bsl @@ -4,11 +4,8 @@ neg111.fs(2,552,2,557): typecheck error FS0039: The type 'fail1' is not defined. neg111.fs(2,552,2,557): typecheck error FS0039: The type 'fail1' is not defined. neg111.fs(3,624,3,629): typecheck error FS0039: The value or constructor 'fail2' is not defined. Maybe you want one of the following: - Failure - failwith - failwithf neg111.fs(5,538,5,540): typecheck error FS0003: This value is not a function and cannot be applied. diff --git a/tests/fsharp/typecheck/sigs/neg15.bsl b/tests/fsharp/typecheck/sigs/neg15.bsl index c8c59c1dc2..92d49dd44a 100644 --- a/tests/fsharp/typecheck/sigs/neg15.bsl +++ b/tests/fsharp/typecheck/sigs/neg15.bsl @@ -30,21 +30,15 @@ neg15.fs(115,19,115,48): typecheck error FS0072: Lookup on object of indetermina neg15.fs(116,20,116,73): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. neg15.fs(122,32,122,57): typecheck error FS0039: The value, constructor, namespace or type 'InternalTagOfInternalType' is not defined. Maybe you want one of the following: - InternalUnionType - InternalRecordType - DefaultTagOfInternalType neg15.fs(128,31,128,61): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. neg15.fs(135,31,135,56): typecheck error FS0039: The value, constructor, namespace or type 'InternalTagOfInternalType' is not defined. Maybe you want one of the following: - InternalUnionType - InternalRecordType - DefaultTagOfInternalType neg15.fs(141,30,141,60): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. diff --git a/tests/fsharp/typecheck/sigs/neg17.bsl b/tests/fsharp/typecheck/sigs/neg17.bsl index 499430cdaa..4fa0cd39c5 100644 --- a/tests/fsharp/typecheck/sigs/neg17.bsl +++ b/tests/fsharp/typecheck/sigs/neg17.bsl @@ -8,13 +8,11 @@ neg17b.fs(8,18,8,43): typecheck error FS1092: The type 'PrivateUnionType' is not neg17b.fs(11,26,11,41): typecheck error FS0039: The field, constructor or member 'PrivateProperty' is not defined. neg17b.fs(12,24,12,45): typecheck error FS0039: The field, constructor or member 'PrivateStaticProperty' is not defined. Maybe you want one of the following: - InternalStaticProperty neg17b.fs(13,26,13,39): typecheck error FS0039: The field, constructor or member 'PrivateMethod' is not defined. neg17b.fs(14,24,14,43): typecheck error FS0039: The field, constructor or member 'PrivateStaticMethod' is not defined. Maybe you want one of the following: - InternalStaticMethod neg17b.fs(15,17,15,52): typecheck error FS1092: The type 'PrivateRecordType' is not accessible from this code location @@ -26,9 +24,7 @@ neg17b.fs(16,19,16,48): typecheck error FS0072: Lookup on object of indeterminat neg17b.fs(17,19,17,47): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. neg17b.fs(21,31,21,77): typecheck error FS0039: The value, constructor, namespace or type 'DefaultTagOfUnionTypeWithPrivateRepresentation' is not defined. Maybe you want one of the following: - DefaultTagOfInternalType - UnionTypeWithPrivateRepresentation neg17b.fs(29,31,29,61): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. @@ -36,13 +32,11 @@ neg17b.fs(29,31,29,61): typecheck error FS0072: Lookup on object of indeterminat neg17b.fs(30,31,30,84): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. neg17b.fs(32,24,32,50): typecheck error FS0039: The type 'RecordTypeWithPrivateField' is not defined in 'Neg17.M'. Maybe you want one of the following: - RecordTypeWithPrivateRepresentation neg17b.fs(43,30,43,60): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. neg17b.fs(45,23,45,49): typecheck error FS0039: The type 'RecordTypeWithPrivateField' is not defined in 'Neg17.M'. Maybe you want one of the following: - RecordTypeWithPrivateRepresentation neg17b.fs(54,20,54,50): typecheck error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. diff --git a/tests/fsharp/typecheck/sigs/neg25.bsl b/tests/fsharp/typecheck/sigs/neg25.bsl index 6a9653c42d..ebbf45ae77 100644 --- a/tests/fsharp/typecheck/sigs/neg25.bsl +++ b/tests/fsharp/typecheck/sigs/neg25.bsl @@ -10,11 +10,8 @@ neg25.fs(87,19,87,25): typecheck error FS0366: No implementation was given for ' neg25.fs(104,19,104,27): typecheck error FS0366: No implementation was given for 'abstract member AnotherNegativeTest.ITestSub.Meth1 : int -> int'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'. neg25.fs(126,27,126,35): typecheck error FS0366: No implementation was given for those members: - 'abstract member MissingInterfaceMemberTests.Test0.ITestSub.Meth2 : int -> int' - 'abstract member MissingInterfaceMemberTests.Test0.ITest.Meth1 : string -> string' - Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'. neg25.fs(147,27,147,35): typecheck error FS0366: No implementation was given for 'abstract member MissingInterfaceMemberTests.Test1.ITest.Meth1 : string -> string'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'. diff --git a/tests/fsharp/typecheck/sigs/neg26.bsl b/tests/fsharp/typecheck/sigs/neg26.bsl index d17ba9ed7e..74a0337d92 100644 --- a/tests/fsharp/typecheck/sigs/neg26.bsl +++ b/tests/fsharp/typecheck/sigs/neg26.bsl @@ -7,9 +7,7 @@ neg26.fs(40,27,40,32): typecheck error FS0361: The override 'Meth1 : int -> int' neg26.fs(53,27,53,32): typecheck error FS3213: The member 'Meth1 : 'a -> 'a' matches multiple overloads of the same method. Please restrict it to one of the following: - Meth1 : int -> int - Meth1 : int -> int. neg26.fs(52,15,52,23): typecheck error FS0783: At least one override did not correctly implement its corresponding abstract member diff --git a/tests/fsharp/typecheck/sigs/neg99.bsl b/tests/fsharp/typecheck/sigs/neg99.bsl index 6482281b89..9f6010f249 100644 --- a/tests/fsharp/typecheck/sigs/neg99.bsl +++ b/tests/fsharp/typecheck/sigs/neg99.bsl @@ -3,4 +3,4 @@ neg99.fs(19,16,19,64): typecheck error FS0077: Member constraints with the name neg99.fs(22,18,22,64): typecheck error FS0077: Member constraints with the name 'op_Explicit' are given special status by the F# compiler as certain .NET types are implicitly augmented with this member. This may result in runtime failures if you attempt to invoke the member constraint from your own code. -neg99.fs(25,39,25,43): typecheck error FS0043: The type 'CrashFSC.OhOh.MyByte' does not support a conversion to the type 'CrashFSC.OhOh.MyByte' \ No newline at end of file +neg99.fs(25,39,25,43): typecheck error FS0043: The type 'CrashFSC.OhOh.MyByte' does not support a conversion to the type 'CrashFSC.OhOh.MyByte' diff --git a/tests/fsharp/typecheck/sigs/version46/neg24.bsl b/tests/fsharp/typecheck/sigs/version46/neg24.bsl index 96a64e8c88..b782269bb5 100644 --- a/tests/fsharp/typecheck/sigs/version46/neg24.bsl +++ b/tests/fsharp/typecheck/sigs/version46/neg24.bsl @@ -27,4 +27,4 @@ neg24.fs(62,31,62,41): typecheck error FS0816: One or more of the overloads of t neg24.fs(64,44,64,48): typecheck error FS0816: One or more of the overloads of this method has curried arguments. Consider redesigning these members to take arguments in tupled form. -neg24.fs(70,15,70,18): typecheck error FS0495: The member or object constructor 'M' has no argument or settable return property 'qez'. The required signature is member C.M : abc:int * def:string -> int. \ No newline at end of file +neg24.fs(70,15,70,18): typecheck error FS0495: The member or object constructor 'M' has no argument or settable return property 'qez'. The required signature is member C.M : abc:int * def:string -> int. From 51f40837607a9b96f9d0ed3840b8f28f7e5de988 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 16 Jan 2020 18:19:33 -0800 Subject: [PATCH 030/101] Fixed exception that prevented creating a memory mapped file that shadow copies a file on-disk (#8238) * Fixed exception that prevented creating a memory mapped file that is shadow copied * Update bytes.fs --- src/absil/bytes.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 9ec1757793..754b9d49dd 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -306,10 +306,11 @@ type ByteMemory with leaveOpen=false) mmf, mmf.CreateViewAccessor(0L, length, memoryMappedFileAccess), length + // Validate MMF with the access that was intended. match access with - | FileAccess.Read when not accessor.CanRead -> failwith "Cannot read file" - | FileAccess.Write when not accessor.CanWrite -> failwith "Cannot write file" - | _ when not accessor.CanRead || not accessor.CanWrite -> failwith "Cannot read or write file" + | FileAccess.Read when not accessor.CanRead -> invalidOp "Cannot read file" + | FileAccess.Write when not accessor.CanWrite -> invalidOp "Cannot write file" + | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" | _ -> () let safeHolder = From 88c7a2b0d9ec4656f7d20891903f84dfb7e22739 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 16 Jan 2020 19:59:54 -0800 Subject: [PATCH 031/101] Using ArrayPool for AssocTable (#8234) * Using ArrayPool * Remove open * Changed some style nits * Clear arrays --- eng/Versions.props | 1 + .../FSharp.Compiler.Service.fsproj | 1 + .../FSharp.Compiler.Private.fsproj | 1 + src/utils/prim-parsing.fs | 24 +++++++++++++------ 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index f7611980e0..64a7ddd713 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -95,6 +95,7 @@ 4.3.0 4.3.0 4.5.0 + 4.5.0 $(RoslynVersion) $(RoslynVersion) diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index f99d7aac7a..4ba9a9b2c3 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -680,6 +680,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 8710d929be..c919f3056b 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -743,6 +743,7 @@ + diff --git a/src/utils/prim-parsing.fs b/src/utils/prim-parsing.fs index b58e592278..996cdc67d5 100644 --- a/src/utils/prim-parsing.fs +++ b/src/utils/prim-parsing.fs @@ -7,6 +7,7 @@ namespace Internal.Utilities.Text.Parsing open Internal.Utilities.Text.Lexing open System +open System.Buffers exception RecoverableParseError exception Accept of obj @@ -131,11 +132,7 @@ module internal Implementation = //------------------------------------------------------------------------- // Read the tables written by FSYACC. - type AssocTable(elemTab:uint16[], offsetTab:uint16[]) = - let cacheSize = 7919 // the 1000'th prime - // Use a simpler hash table with faster lookup, but only one - // hash bucket per key. - let cache = Array.zeroCreate (cacheSize * 2) + type AssocTable(elemTab: uint16[], offsetTab: uint16[], cache: int[], cacheSize: int) = member t.ReadAssoc (minElemNum,maxElemNum,defaultValueOfAssoc,keyToFind) = // do a binary chop on the table @@ -234,8 +231,21 @@ module internal Implementation = let ruleValues = (Array.zeroCreate 100 : obj[]) let lhsPos = (Array.zeroCreate 2 : Position[]) let reductions = tables.reductions - let actionTable = new AssocTable(tables.actionTableElements, tables.actionTableRowOffsets) - let gotoTable = new AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets) + let cacheSize = 7919 // the 1000'th prime + // Use a simpler hash table with faster lookup, but only one + // hash bucket per key. + let actionTableCache = ArrayPool.Shared.Rent(cacheSize * 2) + let gotoTableCache = ArrayPool.Shared.Rent(cacheSize * 2) + // Clear the arrays since ArrayPool does not + Array.Clear(actionTableCache, 0, actionTableCache.Length) + Array.Clear(gotoTableCache, 0, gotoTableCache.Length) + use _cacheDisposal = + { new IDisposable with + member _.Dispose() = + ArrayPool.Shared.Return actionTableCache + ArrayPool.Shared.Return gotoTableCache } + let actionTable = AssocTable(tables.actionTableElements, tables.actionTableRowOffsets, actionTableCache, cacheSize) + let gotoTable = AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets, gotoTableCache, cacheSize) let stateToProdIdxsTable = new IdxToIdxListTable(tables.stateToProdIdxsTableElements, tables.stateToProdIdxsTableRowOffsets) let parseState = From 4d1e14094ddee8aca9f017735363361b78d7dced Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Thu, 16 Jan 2020 21:44:10 -0800 Subject: [PATCH 032/101] Cleanup additional merge issue from fsharp5 to master (#8249) --- .../Microsoft.FSharp.NetSdk.targets | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets index a6923d4c17..de13273e2a 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -66,17 +66,6 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - - Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) - $(%(EnhancedResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx - - - - fsharp41 @@ -115,15 +104,4 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - - Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) - $(%(FsxResolvedFile.PackageRootProperty)) - $(%(FsxResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx - - - From 04119ce879561774e598fded0f05b4f36b4d852f Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Fri, 17 Jan 2020 03:44:36 -0800 Subject: [PATCH 033/101] improve build telemetry (#8239) * add windows build telemetry * fix linux build telemetry --- eng/Build.ps1 | 10 ++++++++++ eng/build.sh | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index b1bac65054..cf7ce0413c 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -61,6 +61,8 @@ param ( Set-StrictMode -version 2.0 $ErrorActionPreference = "Stop" +$BuildCategory = "" +$BuildMessage = "" function Print-Usage() { Write-Host "Common settings:" @@ -303,6 +305,9 @@ function EnablePreviewSdks() { } try { + $script:BuildCategory = "Build" + $script:BuildMessage = "Failure preparing build" + Process-Arguments . (Join-Path $PSScriptRoot "build-utils.ps1") @@ -317,9 +322,11 @@ try { } if ($bootstrap) { + $script:BuildMessage = "Failure building bootstrap compiler" $bootstrapDir = Make-BootstrapBuild } + $script:BuildMessage = "Failure building product" if ($restore -or $build -or $rebuild -or $pack -or $sign -or $publish) { if ($noVisualStudio) { BuildCompiler @@ -332,6 +339,8 @@ try { VerifyAssemblyVersionsAndSymbols } + $script:BuildCategory = "Test" + $script:BuildMessage = "Failure running tests" $desktopTargetFramework = "net472" $coreclrTargetFramework = "netcoreapp3.0" @@ -421,6 +430,7 @@ catch { Write-Host $_ Write-Host $_.Exception Write-Host $_.ScriptStackTrace + Write-PipelineTelemetryError -Category $script:BuildCategory -Message $script:BuildMessage ExitWithExitCode 1 } finally { diff --git a/eng/build.sh b/eng/build.sh index a53fce7914..6340d55746 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -66,6 +66,9 @@ properties="" docker=false args="" +BuildCategory="" +BuildMessage="" + if [[ $# = 0 ]] then usage @@ -150,6 +153,8 @@ done . "$scriptroot/common/tools.sh" function TestUsingNUnit() { + BuildCategory="Test" + BuildMessage="Error running tests" testproject="" targetframework="" while [[ $# > 0 ]]; do @@ -180,14 +185,12 @@ function TestUsingNUnit() { projectname="${projectname%.*}" testlogpath="$artifacts_dir/TestResults/$configuration/${projectname}_$targetframework.xml" args="test \"$testproject\" --no-restore --no-build -c $configuration -f $targetframework --test-adapter-path . --logger \"nunit;LogFilePath=$testlogpath\"" - "$DOTNET_INSTALL_DIR/dotnet" $args || { - local exit_code=$? - Write-PipelineTelemetryError -category 'Test' "dotnet test failed for $testproject:$targetframework (exit code $exit_code)." - ExitWithExitCode $exit_code - } + "$DOTNET_INSTALL_DIR/dotnet" $args || exit $? } function BuildSolution { + BuildCategory="Build" + BuildMessage="Error preparing build" local solution="FSharp.sln" echo "$solution:" @@ -229,33 +232,28 @@ function BuildSolution { rm -fr $bootstrap_dir fi if [ ! -f "$bootstrap_dir/fslex.dll" ]; then + BuildMessage="Error building tools" MSBuild "$repo_root/src/buildtools/buildtools.proj" \ /restore \ /p:Configuration=$bootstrap_config \ - /t:Publish || { - local exit_code=$? - Write-PipelineTelemetryError -category 'Build' "Error building buildtools (exit code '$exit_code')." - ExitWithExitCode $exit_code - } + /t:Publish mkdir -p "$bootstrap_dir" cp -pr $artifacts_dir/bin/fslex/$bootstrap_config/netcoreapp3.0/publish $bootstrap_dir/fslex cp -pr $artifacts_dir/bin/fsyacc/$bootstrap_config/netcoreapp3.0/publish $bootstrap_dir/fsyacc fi if [ ! -f "$bootstrap_dir/fsc.exe" ]; then + BuildMessage="Error building bootstrap" MSBuild "$repo_root/proto.proj" \ /restore \ /p:Configuration=$bootstrap_config \ - /t:Publish || { - local exit_code=$? - Write-PipelineTelemetryError -category 'Build' "Error building bootstrap compiler (exit code '$exit_code')." - ExitWithExitCode $exit_code - } + /t:Publish cp -pr $artifacts_dir/bin/fsc/$bootstrap_config/netcoreapp3.0/publish $bootstrap_dir/fsc fi # do real build + BuildMessage="Error building solution" MSBuild $toolset_build_proj \ $bl \ /v:$verbosity \ @@ -271,13 +269,20 @@ function BuildSolution { /p:ContinuousIntegrationBuild=$ci \ /p:QuietRestore=$quiet_restore \ /p:QuietRestoreBinaryLog="$binary_log" \ - $properties || { - local exit_code=$? - Write-PipelineTelemetryError -category 'Build' "Error building solution (exit code '$exit_code')." - ExitWithExitCode $exit_code - } + $properties +} + +function TrapAndReportError { + local exit_code=$? + if [[ ! $exit_code == 0 ]]; then + Write-PipelineTelemetryError -category $BuildCategory "$BuildMessage (exit code '$exit_code')." + ExitWithExitCode $exit_code + fi } +# allow early termination to report the appropriate build failure reason +trap TrapAndReportError EXIT + InitializeDotNetCli $restore BuildSolution @@ -293,4 +298,3 @@ if [[ "$test_core_clr" == true ]]; then fi ExitWithExitCode 0 - From 0a37c384dbabe08f5f96486e31448f5d9833405e Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 17 Jan 2020 18:59:52 +0000 Subject: [PATCH 034/101] cleanup and whitespace --- src/fsharp/ConstraintSolver.fsi | 73 +++++---- src/fsharp/IlxGen.fs | 10 +- src/fsharp/InfoReader.fs | 2 +- src/fsharp/MethodCalls.fs | 7 + src/fsharp/NameResolution.fs | 37 +++-- src/fsharp/NameResolution.fsi | 76 +++++++-- src/fsharp/PostInferenceChecks.fs | 6 +- src/fsharp/TastOps.fs | 44 +++--- src/fsharp/TastOps.fsi | 8 +- src/fsharp/TypeChecker.fs | 146 +++++++++--------- src/fsharp/TypeRelations.fs | 2 +- src/fsharp/fsc.fs | 4 +- src/fsharp/infos.fs | 7 +- src/fsharp/tast.fs | 7 +- ...osoft.VisualStudio.Editors.Designer.cs.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.de.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.es.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.fr.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.it.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ja.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ko.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.pl.xlf | 3 +- ...ft.VisualStudio.Editors.Designer.pt-BR.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ru.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.tr.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hans.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hant.xlf | 3 +- 27 files changed, 278 insertions(+), 190 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 1fce009f61..6aa40c6ea9 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -47,34 +47,48 @@ val FreshenMethInfo : range -> MethInfo -> TType list [] /// 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 + + /// 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 @@ -116,7 +130,10 @@ type OptionalTrace = val SimplifyMeasuresInTypeScheme : TcGlobals -> bool -> Typars -> TType -> TyparConstraint list -> Typars val SolveTyparEqualsType : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult val SolveTypeEqualsTypeKeepAbbrevs : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult + +/// Canonicalize constraints prior to generalization val CanonicalizeRelevantMemberConstraints : ConstraintSolverEnv -> int -> OptionalTrace -> Typars -> OperationResult + val ResolveOverloading : ConstraintSolverEnv -> OptionalTrace -> string -> ndeep: int -> TraitConstraintInfo option -> int * int -> AccessorDomain -> CalledMeth list -> bool -> TType option -> CalledMeth option * OperationResult val UnifyUniqueOverloading : ConstraintSolverEnv -> int * int -> string -> AccessorDomain -> CalledMeth list -> TType -> OperationResult val EliminateConstraintsForGeneralizedTypars : ConstraintSolverEnv -> OptionalTrace -> Typars -> unit diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 9534358624..c39fad857f 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5273,7 +5273,7 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) s // Workaround for .NET and Visual Studio restriction w.r.t debugger type proxys // Mark internal constructors in internal classes as public. let access = - if access = ILMemberAccess.Assembly && vspec.IsConstructor && IsHiddenTycon g eenv.sigToImplRemapInfo vspec.MemberApparentEntity.Deref then + if access = ILMemberAccess.Assembly && vspec.IsConstructor && IsHiddenTycon eenv.sigToImplRemapInfo vspec.MemberApparentEntity.Deref then ILMemberAccess.Public else access @@ -6488,7 +6488,7 @@ and GenModuleBinding cenv (cgbuf: CodeGenBuffer) (qname: QualifiedNameOfFile) la GenLetRecBindings cenv cgbuf eenv ([bind], m) | ModuleOrNamespaceBinding.Module (mspec, mdef) -> - let hidden = IsHiddenTycon cenv.g eenv.sigToImplRemapInfo mspec + let hidden = IsHiddenTycon eenv.sigToImplRemapInfo mspec let eenvinner = if mspec.IsNamespace then eenv else @@ -6827,8 +6827,8 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = let ilIntfTys = tycon.ImmediateInterfaceTypesOfFSharpTycon |> List.map (GenType cenv.amap m eenvinner.tyenv) let ilTypeName = tref.Name - let hidden = IsHiddenTycon g eenv.sigToImplRemapInfo tycon - let hiddenRepr = hidden || IsHiddenTyconRepr g eenv.sigToImplRemapInfo tycon + let hidden = IsHiddenTycon eenv.sigToImplRemapInfo tycon + let hiddenRepr = hidden || IsHiddenTyconRepr eenv.sigToImplRemapInfo tycon let access = ComputeTypeAccess tref hidden // The implicit augmentation doesn't actually create CompareTo(object) or Object.Equals @@ -7411,7 +7411,7 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) = | TExnFresh _ -> let ilThisTy = GenExnType cenv.amap m eenv.tyenv exncref let tref = ilThisTy.TypeRef - let isHidden = IsHiddenTycon g eenv.sigToImplRemapInfo exnc + let isHidden = IsHiddenTycon eenv.sigToImplRemapInfo exnc let access = ComputeTypeAccess tref isHidden let reprAccess = ComputeMemberAccess isHidden let fspecs = exnc.TrueInstanceFieldsAsList diff --git a/src/fsharp/InfoReader.fs b/src/fsharp/InfoReader.fs index 5e655ed0e7..1fac7a0f6e 100644 --- a/src/fsharp/InfoReader.fs +++ b/src/fsharp/InfoReader.fs @@ -19,7 +19,7 @@ open FSharp.Compiler.Tastops open FSharp.Compiler.TcGlobals /// Use the given function to select some of the member values from the members of an F# type -let private SelectImmediateMemberVals g optFilter f (tcref: TyconRef) = +let SelectImmediateMemberVals g optFilter f (tcref: TyconRef) = let chooser (vref: ValRef) = match vref.MemberInfo with // The 'when' condition is a workaround for the fact that values providing diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 37f031e782..9b657f6f8b 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -498,6 +498,8 @@ type CalledMeth<'T> member x.TotalNumAssignedNamedArgs = x.ArgSets |> List.sumBy (fun x -> x.NumAssignedNamedArgs) + override x.ToString() = "call to " + minfo.ToString() + let NamesOfCalledArgs (calledArgs: CalledArg list) = calledArgs |> List.choose (fun x -> x.NameOpt) @@ -1050,15 +1052,20 @@ let BuildFSharpMethodCall g m (ty, vref: ValRef) valUseFlags minst args = /// calls to the type-directed solutions to member constraints. let MakeMethInfoCall amap m minfo minst args = let valUseFlags = NormalValUse // correct unless if we allow wild trait constraints like "T has a ctor and can be used as a parent class" + match minfo with + | ILMeth(g, ilminfo, _) -> let direct = not minfo.IsVirtual let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant BuildILMethInfoCall g amap m isProp ilminfo valUseFlags minst direct args |> fst + | FSMeth(g, ty, vref, _) -> BuildFSharpMethodCall g m (ty, vref) valUseFlags minst args |> fst + | DefaultStructCtor(_, ty) -> mkDefault (m, ty) + #if !NO_EXTENSIONTYPING | ProvidedMeth(amap, mi, _, m) -> let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 30f456fd86..acf1a318df 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -550,15 +550,30 @@ let AllPropInfosOfTypeInScope collectionSettings infoReader nenv optFilter ad fi @ ExtensionPropInfosOfTypeInScope collectionSettings infoReader nenv optFilter ad m ty /// Get the available methods of a type (both declared and inherited) -let IntrinsicMethInfosOfType (infoReader:InfoReader) optFilter ad allowMultiIntfInst findFlag m ty = +let IntrinsicMethInfosOfType (infoReader: InfoReader) optFilter ad allowMultiIntfInst findFlag m ty = let g = infoReader.g let amap = infoReader.amap let minfos = GetIntrinsicMethInfoSetsOfType infoReader optFilter ad allowMultiIntfInst findFlag m ty let minfos = minfos |> ExcludeHiddenOfMethInfos g amap m minfos +let TrySelectExtensionMethInfoOfILExtMem m amap apparentTy (actualParent, minfo, pri) = + match minfo with + | ILMeth(_,ilminfo,_) -> + MethInfo.CreateILExtensionMeth (amap, m, apparentTy, actualParent, Some pri, ilminfo.RawMetadata) |> Some + // F#-defined IL-style extension methods are not seen as extension methods in F# code + | FSMeth(g,_,vref,_) -> + FSMeth(g, apparentTy, vref, Some pri) |> Some +#if !NO_EXTENSIONTYPING + // // Provided extension methods are not yet supported + | ProvidedMeth(amap,providedMeth,_,m) -> + ProvidedMeth(amap, providedMeth, Some pri,m) |> Some +#endif + | DefaultStructCtor _ -> + None + /// Select from a list of extension methods -let SelectMethInfosFromExtMembers (infoReader:InfoReader) optFilter apparentTy m extMemInfos = +let SelectMethInfosFromExtMembers (infoReader: InfoReader) optFilter apparentTy m extMemInfos = let g = infoReader.g // NOTE: multiple "open"'s push multiple duplicate values into eIndexedExtensionMembers let seen = HashSet(ExtensionMember.Comparer g) @@ -575,24 +590,14 @@ let SelectMethInfosFromExtMembers (infoReader:InfoReader) optFilter apparentTy m | _ -> () | ILExtMem (actualParent, minfo, pri) when (match optFilter with None -> true | Some nm -> nm = minfo.LogicalName) -> // Make a reference to the type containing the extension members - match minfo with - | ILMeth(_, ilminfo, _) -> - yield (MethInfo.CreateILExtensionMeth (infoReader.amap, m, apparentTy, actualParent, Some pri, ilminfo.RawMetadata)) - // F#-defined IL-style extension methods are not seen as extension methods in F# code - | FSMeth(g, _, vref, _) -> - yield (FSMeth(g, apparentTy, vref, Some pri)) -#if !NO_EXTENSIONTYPING - // // Provided extension methods are not yet supported - | ProvidedMeth(amap, providedMeth, _, m) -> - yield (ProvidedMeth(amap, providedMeth, Some pri, m)) -#endif - | DefaultStructCtor _ -> - () + match TrySelectExtensionMethInfoOfILExtMem m infoReader.amap apparentTy (actualParent, minfo, pri) with + | Some minfo -> yield minfo + | None -> () | _ -> () ] /// Query the available extension properties of a methods (including extension methods for inherited types) -let ExtensionMethInfosOfTypeInScope (collectionSettings:ResultCollectionSettings) (infoReader:InfoReader) (nenv: NameResolutionEnv) optFilter m ty = +let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSettings) (infoReader: InfoReader) (nenv: NameResolutionEnv) optFilter m ty = let extMemsDangling = SelectMethInfosFromExtMembers infoReader optFilter ty m nenv.eUnindexedExtensionMembers if collectionSettings = ResultCollectionSettings.AtMostOneResult && not (isNil extMemsDangling) then extMemsDangling diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index ea3bbd8aea..e5d8ca00ae 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -141,25 +141,68 @@ val ItemWithNoInst : Item -> ItemWithInst type FieldResolution = FieldResolution of RecdFieldRef * bool /// Information about an extension member held in the name resolution environment -[] -type ExtensionMember +type ExtensionMember = + /// F#-style Extrinsic extension member, defined in F# code + | FSExtMem of ValRef * ExtensionMethodPriority + + /// ILExtMem(declaringTyconRef, ilMetadata, pri) + /// + /// IL-style extension member, backed by some kind of method with an [] attribute + | ILExtMem of TyconRef * MethInfo * ExtensionMethodPriority + + /// Describes the sequence order of the introduction of an extension method. Extension methods that are introduced + /// later through 'open' get priority in overload resolution. + member Priority : ExtensionMethodPriority /// The environment of information used to resolve names [] type NameResolutionEnv = - {eDisplayEnv: DisplayEnv - eUnqualifiedItems: LayeredMap - ePatItems: NameMap - eModulesAndNamespaces: NameMultiMap - eFullyQualifiedModulesAndNamespaces: NameMultiMap - eFieldLabels: NameMultiMap - eTyconsByAccessNames: LayeredMultiMap - eFullyQualifiedTyconsByAccessNames: LayeredMultiMap - eTyconsByDemangledNameAndArity: LayeredMap - eFullyQualifiedTyconsByDemangledNameAndArity: LayeredMap - eIndexedExtensionMembers: TyconRefMultiMap - eUnindexedExtensionMembers: ExtensionMember list - eTypars: NameMap } + { /// Display environment information for output + eDisplayEnv: DisplayEnv + + /// Values and Data Tags available by unqualified name + eUnqualifiedItems: LayeredMap + + /// Data Tags and Active Pattern Tags available by unqualified name + ePatItems: NameMap + + /// Modules accessible via "." notation. Note this is a multi-map. + /// Adding a module abbreviation adds it a local entry to this List.map. + /// Likewise adding a ccu or opening a path adds entries to this List.map. + eModulesAndNamespaces: NameMultiMap + + /// Fully qualified modules and namespaces. 'open' does not change this. + eFullyQualifiedModulesAndNamespaces: NameMultiMap + + /// RecdField labels in scope. RecdField labels are those where type are inferred + /// by label rather than by known type annotation. + /// Bools indicate if from a record, where no warning is given on indeterminate lookup + eFieldLabels: NameMultiMap + + /// Tycons indexed by the various names that may be used to access them, e.g. + /// "List" --> multiple TyconRef's for the various tycons accessible by this name. + /// "List`1" --> TyconRef + eTyconsByAccessNames: LayeredMultiMap + + eFullyQualifiedTyconsByAccessNames: LayeredMultiMap + + /// Tycons available by unqualified, demangled names (i.e. (List,1) --> TyconRef) + eTyconsByDemangledNameAndArity: LayeredMap + + /// Tycons available by unqualified, demangled names (i.e. (List,1) --> TyconRef) + eFullyQualifiedTyconsByDemangledNameAndArity: LayeredMap + + /// Extension members by type and name + eIndexedExtensionMembers: TyconRefMultiMap + + /// Other extension members unindexed by type + eUnindexedExtensionMembers: ExtensionMember list + + /// Typars (always available by unqualified names). Further typars can be + /// in the tpenv, a structure folded through each top-level definition. + eTypars: NameMap + + } static member Empty : g:TcGlobals -> NameResolutionEnv member DisplayEnv : DisplayEnv member FindUnqualifiedItem : string -> Item @@ -542,3 +585,6 @@ val ResolveCompletionsInType : NameResolver -> NameResolutionEnv -> Resolv val GetVisibleNamespacesAndModulesAtPoint : NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> ModuleOrNamespaceRef list val IsItemResolvable : NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> Item -> bool + +val TrySelectExtensionMethInfoOfILExtMem : range -> ImportMap -> TType -> TyconRef * MethInfo * ExtensionMethodPriority -> MethInfo option + \ No newline at end of file diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 2420e636d2..aedf7252d9 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1926,8 +1926,8 @@ let CheckRecdField isUnion cenv env (tycon: Tycon) (rfield: RecdField) = let m = rfield.Range let fieldTy = stripTyEqns cenv.g rfield.FormalType let isHidden = - IsHiddenTycon cenv.g env.sigToImplRemapInfo tycon || - IsHiddenTyconRepr cenv.g env.sigToImplRemapInfo tycon || + IsHiddenTycon env.sigToImplRemapInfo tycon || + IsHiddenTyconRepr env.sigToImplRemapInfo tycon || (not isUnion && IsHiddenRecdField env.sigToImplRemapInfo (tcref.MakeNestedRecdFieldRef rfield)) let access = AdjustAccess isHidden (fun () -> tycon.CompilationPath) rfield.Accessibility CheckTypeForAccess cenv env (fun () -> rfield.Name) access m fieldTy @@ -2189,7 +2189,7 @@ let CheckEntityDefn cenv env (tycon: Entity) = uc.RecdFieldsArray |> Array.iter (CheckRecdField true cenv env tycon)) // Access checks - let access = AdjustAccess (IsHiddenTycon g env.sigToImplRemapInfo tycon) (fun () -> tycon.CompilationPath) tycon.Accessibility + let access = AdjustAccess (IsHiddenTycon env.sigToImplRemapInfo tycon) (fun () -> tycon.CompilationPath) tycon.Accessibility let visitType ty = CheckTypeForAccess cenv env (fun () -> tycon.DisplayNameWithStaticParametersAndUnderscoreTypars) access tycon.Range ty abstractSlotValsOfTycons [tycon] |> List.iter (typeOfVal >> visitType) diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index fe30b314d1..3d474dadbc 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -95,8 +95,14 @@ let emptyTyparInst = ([]: TyparInst) [] type Remap = { tpinst: TyparInst + + /// Values to remap valRemap: ValRemap + + /// TyconRefs to remap tyconRefRemap: TyconRefRemap + + /// Remove existing trait solutions? removeTraitSolutions: bool } let emptyRemap = @@ -889,7 +895,9 @@ type TypeEquivEnv with static member FromEquivTypars tps1 tps2 = TypeEquivEnv.Empty.BindEquivTypars tps1 tps2 -let rec traitsAEquivAux erasureFlag g aenv (TTrait(tys1, nm, mf1, argtys, rty, _)) (TTrait(tys2, nm2, mf2, argtys2, rty2, _)) = +let rec traitsAEquivAux erasureFlag g aenv traitInfo1 traitInfo2 = + let (TTrait(tys1, nm, mf1, argtys, rty, _)) = traitInfo1 + let (TTrait(tys2, nm2, mf2, argtys2, rty2, _)) = traitInfo2 mf1 = mf2 && nm = nm2 && ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 && @@ -909,7 +917,7 @@ and typarConstraintsAEquivAux erasureFlag g aenv tpc1 tpc2 = TyparConstraint.CoercesTo(fcty, _) -> typeAEquivAux erasureFlag g aenv acty fcty - | TyparConstraint.MayResolveMember(trait1, _), + | TyparConstraint.MayResolveMember(trait1, _), TyparConstraint.MayResolveMember(trait2, _) -> traitsAEquivAux erasureFlag g aenv trait1 trait2 @@ -2479,8 +2487,6 @@ module PrettyTypes = computeKeep keep (tp :: change) rest let keep, change = computeKeep [] [] ftps - // change |> List.iter (fun tp -> dprintf "change typar: %s %s %d\n" tp.Name (tp.DisplayName) (stamp_of_typar tp)) - // keep |> List.iter (fun tp -> dprintf "keep typar: %s %s %d\n" tp.Name (tp.DisplayName) (stamp_of_typar tp)) let alreadyInUse = keep |> List.map (fun x -> x.Name) let names = PrettyTyparNames (fun x -> List.memq x change) alreadyInUse ftps @@ -2494,7 +2500,6 @@ module PrettyTypes = let tauThings = mapTys getTauStayTau things let prettyThings = mapTys (instType renaming) tauThings - // niceTypars |> List.iter (fun tp -> dprintf "nice typar: %d\n" (stamp_of_typar tp)); * let tpconstraints = niceTypars |> List.collect (fun tpnice -> List.map (fun tpc -> tpnice, tpc) tpnice.Constraints) prettyThings, tpconstraints @@ -4081,7 +4086,6 @@ let accValRemap g aenv (msigty: ModuleOrNamespaceType) (implVal: Val) (mrpi, mhi let vref = mkLocalValRef implVal match sigValOpt with | None -> - if verbose then dprintf "accValRemap, hide = %s#%d\n" implVal.LogicalName implVal.Stamp let mhi = { mhi with HiddenVals = Zset.add implVal mhi.HiddenVals } (mrpi, mhi) | Some (sigVal: Val) -> @@ -4105,7 +4109,6 @@ let rec accValRemapFromModuleOrNamespaceType g aenv (mty: ModuleOrNamespaceType) acc let ComputeRemappingFromInferredSignatureToExplicitSignature g mty msigty = - // dprintf "ComputeRemappingFromInferredSignatureToExplicitSignature, \nmty = %s\nmmsigty=%s\n" (showL(entityTypeL mty)) (showL(entityTypeL msigty)) let ((mrpi, _) as entityRemap) = accEntityRemapFromModuleOrNamespaceType mty msigty (SignatureRepackageInfo.Empty, SignatureHidingInfo.Empty) let aenv = mrpi.ImplToSigMapping let valAndEntityRemap = accValRemapFromModuleOrNamespaceType g aenv mty msigty entityRemap @@ -4166,7 +4169,6 @@ and accValRemapFromModuleOrNamespaceBind g aenv msigty x acc = and accValRemapFromModuleOrNamespaceDefs g aenv msigty mdefs acc = List.foldBack (accValRemapFromModuleOrNamespace g aenv msigty) mdefs acc let ComputeRemappingFromImplementationToSignature g mdef msigty = - //if verbose then dprintf "ComputeRemappingFromImplementationToSignature, \nmdefs = %s\nmsigty=%s\n" (showL(DebugPrint.mdefL mdef)) (showL(DebugPrint.entityTypeL msigty)) let ((mrpi, _) as entityRemap) = accEntityRemapFromModuleOrNamespace msigty mdef (SignatureRepackageInfo.Empty, SignatureHidingInfo.Empty) let aenv = mrpi.ImplToSigMapping @@ -4222,16 +4224,14 @@ let rec accModuleOrNamespaceHidingInfoAtAssemblyBoundary mty acc = acc let ComputeHidingInfoAtAssemblyBoundary mty acc = -// dprintf "ComputeRemappingFromInferredSignatureToExplicitSignature, \nmty = %s\nmmsigty=%s\n" (showL(entityTypeL mty)) (showL(entityTypeL msigty)) accModuleOrNamespaceHidingInfoAtAssemblyBoundary mty acc //-------------------------------------------------------------------------- // Compute instances of the above for mexpr -> mty //-------------------------------------------------------------------------- -let IsHidden setF accessF remapF debugF = +let IsHidden setF accessF remapF = let rec check mrmi x = - if verbose then dprintf "IsHidden %s ??\n" (showL (debugF x)) // Internal/private? not (canAccessFromEverywhere (accessF x)) || (match mrmi with @@ -4242,18 +4242,15 @@ let IsHidden setF accessF remapF debugF = // Recurse... check rest (remapF rpi x)) fun mrmi x -> - let res = check mrmi x - if verbose then dprintf "IsHidden, #mrmi = %d, %s = %b\n" mrmi.Length (showL (debugF x)) res - res + check mrmi x + +let IsHiddenTycon mrmi x = IsHidden (fun mhi -> mhi.HiddenTycons) (fun tc -> tc.Accessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) mrmi x + +let IsHiddenTyconRepr mrmi x = IsHidden (fun mhi -> mhi.HiddenTyconReprs) (fun v -> v.TypeReprAccessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) mrmi x + +let IsHiddenVal mrmi x = IsHidden (fun mhi -> mhi.HiddenVals) (fun v -> v.Accessibility) (fun rpi x -> (remapValRef rpi (mkLocalValRef x)).Deref) mrmi x -let IsHiddenTycon g mrmi x = - let debugPrint x = DebugPrint.tyconL g x - IsHidden (fun mhi -> mhi.HiddenTycons) (fun tc -> tc.Accessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) debugPrint mrmi x -let IsHiddenTyconRepr g mrmi x = - let debugPrint x = DebugPrint.tyconL g x - IsHidden (fun mhi -> mhi.HiddenTyconReprs) (fun v -> v.TypeReprAccessibility) (fun rpi x -> (remapTyconRef rpi.tyconRefRemap (mkLocalTyconRef x)).Deref) debugPrint mrmi x -let IsHiddenVal mrmi x = IsHidden (fun mhi -> mhi.HiddenVals) (fun v -> v.Accessibility) (fun rpi x -> (remapValRef rpi (mkLocalValRef x)).Deref) DebugPrint.valL mrmi x -let IsHiddenRecdField mrmi x = IsHidden (fun mhi -> mhi.HiddenRecdFields) (fun rfref -> rfref.RecdField.Accessibility) (fun rpi x -> remapRecdFieldRef rpi.tyconRefRemap x) DebugPrint.recdFieldRefL mrmi x +let IsHiddenRecdField mrmi x = IsHidden (fun mhi -> mhi.HiddenRecdFields) (fun rfref -> rfref.RecdField.Accessibility) (fun rpi x -> remapRecdFieldRef rpi.tyconRefRemap x) mrmi x //-------------------------------------------------------------------------- // Generic operations on module types @@ -5725,7 +5722,7 @@ let rec tyOfExpr g e = | TOp.LValueOp (LByrefGet, v) -> destByrefTy g v.Type | TOp.LValueOp (LAddrOf readonly, v) -> mkByrefTyWithFlag g readonly v.Type | TOp.RefAddrGet readonly -> (match tinst with [ty] -> mkByrefTyWithFlag g readonly ty | _ -> failwith "bad TOp.RefAddrGet node") - | TOp.TraitCall (TTrait(_, _, _, _, ty, _)) -> GetFSharpViewOfReturnType g ty + | TOp.TraitCall traitInfo -> GetFSharpViewOfReturnType g traitInfo.ReturnType | TOp.Reraise -> (match tinst with [rtn_ty] -> rtn_ty | _ -> failwith "bad TOp.Reraise node") | TOp.Goto _ | TOp.Label _ | TOp.Return -> //assert false @@ -7782,7 +7779,6 @@ let typarEnc _g (gtpsType, gtpsMethod) typar = "``0" let rec typeEnc g (gtpsType, gtpsMethod) ty = - if verbose then dprintf "--> typeEnc" let stripped = stripTyEqnsAndMeasureEqns g ty match stripped with | TType_forall _ -> diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 5179b85239..176f64df72 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1208,16 +1208,16 @@ val MakeExportRemapping : CcuThunk -> ModuleOrNamespace -> Remap val ApplyExportRemappingToEntity : TcGlobals -> Remap -> ModuleOrNamespace -> ModuleOrNamespace /// Determine if a type definition is hidden by a signature -val IsHiddenTycon : TcGlobals -> (Remap * SignatureHidingInfo) list -> Tycon -> bool +val IsHiddenTycon: (Remap * SignatureHidingInfo) list -> Tycon -> bool /// Determine if the representation of a type definition is hidden by a signature -val IsHiddenTyconRepr : TcGlobals -> (Remap * SignatureHidingInfo) list -> Tycon -> bool +val IsHiddenTyconRepr: (Remap * SignatureHidingInfo) list -> Tycon -> bool /// Determine if a member, function or value is hidden by a signature -val IsHiddenVal : (Remap * SignatureHidingInfo) list -> Val -> bool +val IsHiddenVal: (Remap * SignatureHidingInfo) list -> Val -> bool /// Determine if a record field is hidden by a signature -val IsHiddenRecdField : (Remap * SignatureHidingInfo) list -> RecdFieldRef -> bool +val IsHiddenRecdField: (Remap * SignatureHidingInfo) list -> RecdFieldRef -> bool /// Adjust marks in expressions, replacing all marks by the given mark. /// Used when inlining. diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 5d7a170c2c..539f67d844 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -223,7 +223,7 @@ type TcEnv = /// Compute the value of this computed, cached field let computeAccessRights eAccessPath eInternalsVisibleCompPaths eFamilyType = - AccessibleFrom (eAccessPath :: eInternalsVisibleCompPaths, eFamilyType) // env.eAccessRights + AccessibleFrom (eAccessPath :: eInternalsVisibleCompPaths, eFamilyType) // env.AccessRights let emptyTcEnv g = let cpath = compPathInternal // allow internal access initially @@ -324,7 +324,7 @@ let AddLocalValMap tcSink scopem (vals: Val NameMap) env = { env with eNameResEnv = AddValMapToNameEnv vals env.eNameResEnv eUngeneralizableItems = NameMap.foldBackRange (typeOfVal >> addFreeItemOfTy) vals env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env /// Add a list of local values to TcEnv and report them to the sink @@ -336,7 +336,7 @@ let AddLocalVals tcSink scopem (vals: Val list) env = { env with eNameResEnv = AddValListToNameEnv vals env.eNameResEnv eUngeneralizableItems = List.foldBack (typeOfVal >> addFreeItemOfTy) vals env.eUngeneralizableItems } - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env /// Add a local value to TcEnv and report it to the sink @@ -351,8 +351,8 @@ let AddLocalVal tcSink scopem v env = let AddLocalExnDefnAndReport tcSink scopem env (exnc: Tycon) = let env = { env with eNameResEnv = AddExceptionDeclsToNameEnv BulkAdd.No env.eNameResEnv (mkLocalEntityRef exnc) } // Also make VisualStudio think there is an identifier in scope at the range of the identifier text of its binding location - CallEnvSink tcSink (exnc.Range, env.NameEnv, env.eAccessRights) - CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) + CallEnvSink tcSink (exnc.Range, env.NameEnv, env.AccessRights) + CallEnvSink tcSink (scopem, env.NameEnv, env.AccessRights) env /// Add a list of type definitions to TcEnv @@ -431,7 +431,7 @@ let AddModuleAbbreviationAndReport tcSink scopem id modrefs env = CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights) let item = Item.ModuleOrNamespaces modrefs - CallNameResolutionSink tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) env /// Add a "module X = ..." definition to the TcEnv @@ -558,7 +558,7 @@ let MakeInnerEnvWithAcc env nm mtypeAcc modKind = eCompPath = cpath eAccessPath = cpath eAccessRights = computeAccessRights cpath env.eInternalsVisibleCompPaths env.eFamilyType // update this computed field - eNameResEnv = { env.eNameResEnv with eDisplayEnv = env.DisplayEnv.AddOpenPath (pathOfLid path) } + eNameResEnv = { env.NameEnv with eDisplayEnv = env.DisplayEnv.AddOpenPath (pathOfLid path) } eModuleOrNamespaceTypeAccumulator = mtypeAcc } /// Make an environment suitable for a module or namespace, creating a new accumulator. @@ -863,7 +863,7 @@ module AttributeTargets = let ForNewConstructors tcSink (env: TcEnv) mObjTy methodName meths = let origItem = Item.CtorGroup(methodName, meths) - let callSink (item, minst) = CallNameResolutionSink tcSink (mObjTy, env.NameEnv, item, origItem, minst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + let callSink (item, minst) = CallNameResolutionSink tcSink (mObjTy, env.NameEnv, item, origItem, minst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) let sendToSink minst refinedMeths = callSink (Item.CtorGroup(methodName, refinedMeths), minst) match meths with | [] -> @@ -1301,7 +1301,7 @@ let PublishModuleDefn cenv env mspec = if intoFslibCcu then mty else mty.AddEntity mspec) let item = Item.ModuleOrNamespaces([mkLocalModRef mspec]) - CallNameResolutionSink cenv.tcSink (mspec.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (mspec.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) let PublishTypeDefn cenv env tycon = UpdateAccModuleOrNamespaceType cenv env (fun _ mty -> @@ -1531,7 +1531,7 @@ let MakeAndPublishVal cenv env (altActualParent, inSig, declKind, vrec, vscheme, baseOrThisInfo = ValBaseOrThisInfo.MemberThisVal && vspec.LogicalName = "__" -> false | _ -> true - match cenv.tcSink.CurrentSink with + match cenv.tcSink.CurrentSink with | Some _ when not vspec.IsCompilerGenerated && shouldNotifySink vspec -> let nenv = AddFakeNamedValRefToNameEnv vspec.DisplayName env.NameEnv (mkLocalValRef vspec) CallEnvSink cenv.tcSink (vspec.Range, nenv, env.eAccessRights) @@ -1931,7 +1931,7 @@ let FreshenPossibleForallTy g m rigid ty = let tps, renaming, tinst = CopyAndFixupTypars m rigid tpsorig tpsorig, tps, tinst, instType renaming tau -let infoOfTyconRef m (tcref: TyconRef) = +let FreshenTyconRef2 m (tcref: TyconRef) = let tps, renaming, tinst = FreshenTypeInst m (tcref.Typars m) tps, renaming, tinst, TType_app (tcref, tinst) @@ -2119,24 +2119,24 @@ module GeneralizationHelpers = let ComputeUnabstractableTycons env = - let acc_in_free_item acc (item: UngeneralizableItem) = + let accInFreeItem acc (item: UngeneralizableItem) = let ftycs = if item.WillNeverHaveFreeTypars then item.CachedFreeLocalTycons else let ftyvs = item.GetFreeTyvars() ftyvs.FreeTycons if ftycs.IsEmpty then acc else unionFreeTycons ftycs acc - List.fold acc_in_free_item emptyFreeTycons env.eUngeneralizableItems + List.fold accInFreeItem emptyFreeTycons env.eUngeneralizableItems let ComputeUnabstractableTraitSolutions env = - let acc_in_free_item acc (item: UngeneralizableItem) = + let accInFreeItem acc (item: UngeneralizableItem) = let ftycs = if item.WillNeverHaveFreeTypars then item.CachedFreeTraitSolutions else let ftyvs = item.GetFreeTyvars() ftyvs.FreeTraitSolutions if ftycs.IsEmpty then acc else unionFreeLocals ftycs acc - List.fold acc_in_free_item emptyFreeLocals env.eUngeneralizableItems + List.fold accInFreeItem emptyFreeLocals env.eUngeneralizableItems let rec IsGeneralizableValue g t = match t with @@ -2291,17 +2291,17 @@ module GeneralizationHelpers = (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult - let ComputeAndGeneralizeGenericTypars (cenv, - denv: DisplayEnv, - m, - freeInEnv: FreeTypars, - canInferTypars, - genConstrainedTyparFlag, - inlineFlag, - exprOpt, - allDeclaredTypars: Typars, - maxInferredTypars: Typars, - tauTy, + let ComputeAndGeneralizeGenericTypars (cenv, + denv: DisplayEnv, + m, + freeInEnv: FreeTypars, + canInferTypars, + genConstrainedTyparFlag, + inlineFlag, + exprOpt, + allDeclaredTypars: Typars, + maxInferredTypars: Typars, + tauTy, resultFirst) = let allDeclaredTypars = NormalizeDeclaredTyparsForEquiRecursiveInference cenv.g allDeclaredTypars @@ -2534,7 +2534,7 @@ module BindingNormalization = | _ -> MakeNormalizedInstanceMemberBinding cenv thisId memberId toolId vis m typars args rhsExpr valSynData let private NormalizeBindingPattern cenv nameResolver isObjExprBinding (env: TcEnv) valSynData pat rhsExpr = - let ad = env.eAccessRights + let ad = env.AccessRights let (SynValData(memberFlagsOpt, _, _)) = valSynData let rec normPattern pat = // One major problem with versions of F# prior to 1.9.x was that data constructors easily 'pollute' the namespace @@ -2545,7 +2545,7 @@ module BindingNormalization = let typars = match tyargs with None -> inferredTyparDecls | Some typars -> typars match memberFlagsOpt with | None -> - match ResolvePatternLongIdent cenv.tcSink nameResolver AllIdsOK true m ad env.eNameResEnv TypeNameResolutionInfo.Default longId with + match ResolvePatternLongIdent cenv.tcSink nameResolver AllIdsOK true m ad env.NameEnv TypeNameResolutionInfo.Default longId with | Item.NewDef id -> if id.idText = opNameCons then NormalizedBindingPat(pat, rhsExpr, valSynData, typars) @@ -3278,7 +3278,7 @@ let CompilePatternForMatchClauses cenv env mExpr matchm warnOnUnused actionOnFai // localAlloc is relevant if the enumerator is a mutable struct and indicates // if the enumerator can be allocated as a mutable local variable let AnalyzeArbitraryExprAsEnumerable cenv (env: TcEnv) localAlloc m exprty expr = - let ad = env.eAccessRights + let ad = env.AccessRights let err k ty = let txt = NicePrint.minimalStringOfType env.DisplayEnv ty @@ -4419,7 +4419,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv memSpfn m = let logicalCompiledName = ComputeLogicalName id memberFlags let item = Item.ArgName (id, memberConstraintTy, None) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None), tpenv | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) @@ -4580,7 +4580,7 @@ and TcTyparOrMeasurePar optKind cenv (env: TcEnv) newOk tpenv (Typar(id, _, _) a | Some TyparKind.Type, TyparKind.Measure -> error (Error(FSComp.SR.tcExpectedTypeParameter(), id.idRange)); res, tpenv | _, _ -> let item = Item.TypeVar(id.idText, res) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) // record the ' as well for tokenization // CallNameResolutionSink cenv.tcSink (tp.Range.StartRange, env.NameEnv, item, item, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) res, tpenv @@ -4608,7 +4608,7 @@ and TcTyparOrMeasurePar optKind cenv (env: TcEnv) newOk tpenv (Typar(id, _, _) a // The kind defaults to Type let tp' = NewTypar ((match optKind with None -> TyparKind.Type | Some kind -> kind), TyparRigidity.WarnIfNotRigid, tp, false, TyparDynamicReq.Yes, [], false, false) let item = Item.TypeVar(id.idText, tp') - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.UseInType, env.DisplayEnv, env.AccessRights) tp', AddUnscopedTypar key tp' tpenv and TcTypar cenv env newOk tpenv tp = @@ -4648,7 +4648,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: SyntacticUnscope | SynType.LongIdent(LongIdentWithDots(tc, _) as lidwd) -> let m = lidwd.Range let ad = env.eAccessRights - let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) + let tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.NameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) match optKind, tcref.TypeOrMeasureKind with | Some TyparKind.Type, TyparKind.Measure -> error(Error(FSComp.SR.tcExpectedTypeNotUnitOfMeasure(), m)) @@ -4880,7 +4880,7 @@ and TcStaticConstantParameter cenv (env: TcEnv) tpenv kind (v: SynType) idOpt co match idOpt with | Some id -> let item = Item.ArgName (id, ttype, Some container) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) | _ -> () match v with @@ -5060,7 +5060,7 @@ and TcProvidedTypeApp cenv env tpenv tcref args m = /// the prefix of type arguments. and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (synArgTys: SynType list) = let g = cenv.g - CheckTyconAccessible cenv.amap m env.eAccessRights tcref |> ignore + CheckTyconAccessible cenv.amap m env.AccessRights tcref |> ignore CheckEntityAttributes g tcref m |> CommitOperationResult #if !NO_EXTENSIONTYPING @@ -5069,7 +5069,7 @@ and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (synArgTys: if tcref.Deref.IsProvided then TcProvidedTypeApp cenv env tpenv tcref synArgTys m else #endif - let tps, _, tinst, _ = infoOfTyconRef m tcref + let tps, _, tinst, _ = FreshenTyconRef2 m tcref // If we're not checking constraints, i.e. when we first assert the super/interfaces of a type definition, then just // clear the constraint lists of the freshly generated type variables. A little ugly but fairly localized. @@ -5250,7 +5250,7 @@ and TcPatBindingName cenv env id ty isMemberThis vis1 topValData (inlineFlag, de // For non-left-most paths, we register the name resolutions here if not isLeftMost && not vspec.IsCompilerGenerated && not (vspec.LogicalName.StartsWithOrdinal("_")) then let item = Item.Value(mkLocalValRef vspec) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) PBind(vspec, typeScheme)), names, takenNames @@ -5275,7 +5275,7 @@ and TcPatAndRecover warnOnUpper cenv (env: TcEnv) topValInfo vFlags (tpenv, name /// the second-phase function in terms of a List.map from names to actual /// value specifications. and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty pat = - let ad = env.eAccessRights + let ad = env.AccessRights match pat with | SynPat.Const (c, m) -> match c with @@ -5354,7 +5354,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynConstructorArgs.NamePatPairs (pairs, _) -> pairs.Length if numArgs <> 0 then error(Error(FSComp.SR.tcLiteralDoesNotTakeArguments(), m)) - match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver warnOnUpperForId false m ad env.eNameResEnv TypeNameResolutionInfo.Default longId with + match ResolvePatternLongIdent cenv.tcSink cenv.nameResolver warnOnUpperForId false m ad env.NameEnv TypeNameResolutionInfo.Default longId with | Item.NewDef id -> match args with | SynConstructorArgs.Pats [] @@ -5425,7 +5425,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p let activePatIdentity = if isNil activePatArgsAsSynExprs then Some (vref, tinst) else None (fun values -> // Report information about the 'active recognizer' occurrence to IDE - CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.AccessRights) TPat_query((activePatExpr, activePatResTys, activePatIdentity, idx, apinfo), arg' values, m)), (tpenv, names, takenNames) @@ -5492,12 +5492,12 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p let args', acc = TcPatterns warnOnUpper cenv env vFlags (tpenv, names, takenNames) argTys args (fun values -> // Report information about the case occurrence to IDE - CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (rangeOfLid longId, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Pattern, env.DisplayEnv, env.AccessRights) mkf m (List.map (fun f -> f values) args')), acc | Item.ILField finfo -> // LITERAL .NET FIELDS - CheckILFieldInfoAccessible cenv.g cenv.amap m env.eAccessRights finfo + CheckILFieldInfoAccessible cenv.g cenv.amap m env.AccessRights finfo if not finfo.IsStatic then errorR (Error (FSComp.SR.tcFieldIsNotStatic(finfo.FieldName), m)) CheckILFieldAttributes cenv.g finfo m match finfo.LiteralValue with @@ -5512,7 +5512,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | Item.RecdField rfinfo -> // LITERAL F# FIELDS - CheckRecdFieldInfoAccessible cenv.amap m env.eAccessRights rfinfo + CheckRecdFieldInfoAccessible cenv.amap m env.AccessRights rfinfo if not rfinfo.IsStatic then errorR (Error (FSComp.SR.tcFieldIsNotStatic(rfinfo.Name), m)) CheckRecdFieldInfoAttributes cenv.g rfinfo m |> CommitOperationResult match rfinfo.LiteralValue with @@ -5531,7 +5531,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | None -> error (Error(FSComp.SR.tcNonLiteralCannotBeUsedInPattern(), m)) | Some lit -> let _, _, _, vexpty, _, _ = TcVal true cenv env tpenv vref None None m - CheckValAccessible m env.eAccessRights vref + CheckValAccessible m env.AccessRights vref CheckFSharpAttributes cenv.g vref.Attribs m |> CommitOperationResult checkNoArgsForLiteral() UnifyTypes cenv env m ty vexpty @@ -5563,7 +5563,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynPat.Record (flds, m) -> let tcref, fldsmap, _fldsList = BuildFieldMap cenv env true ty flds m // REVIEW: use _fldsList to type check pattern in code order not field defn order - let _, inst, tinst, gtyp = infoOfTyconRef m tcref + let _, inst, tinst, gtyp = FreshenTyconRef2 m tcref UnifyTypes cenv env m ty gtyp let fields = tcref.TrueInstanceFieldsAsList let ftys = fields |> List.map (fun fsp -> actualTyOfRecdField inst fsp, fsp) @@ -5587,6 +5587,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | SynPat.InstanceMember (_, _, _, _, m) -> errorR(Error(FSComp.SR.tcIllegalPattern(), pat.Range)) (fun _ -> TPat_wild m), (tpenv, names, takenNames) + | SynPat.FromParseError (pat, _) -> suppressErrorReporting (fun () -> TcPatAndRecover warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) (NewErrorType()) pat) @@ -5813,7 +5814,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.Paren (expr2, _, _, mWholeExprIncludingParentheses) -> // We invoke CallExprHasTypeSink for every construct which is atomic in the syntax, i.e. where a '.' immediately following the // construct is a dot-lookup for the result of the construct. - CallExprHasTypeSink cenv.tcSink (mWholeExprIncludingParentheses, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mWholeExprIncludingParentheses, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) let env = ShrinkContext env mWholeExprIncludingParentheses expr2.Range TcExpr cenv overallTy env tpenv expr2 @@ -5821,11 +5822,11 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.TypeApp _ | SynExpr.Ident _ | SynExpr.LongIdent _ | SynExpr.App _ | SynExpr.DotGet _ -> error(Error(FSComp.SR.tcExprUndelayed(), synExpr.Range)) | SynExpr.Const (SynConst.String (s, m), _) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcConstStringExpr cenv overallTy env m tpenv s | SynExpr.Const (synConst, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcConstExpr cenv overallTy env m tpenv synConst | SynExpr.Lambda _ -> @@ -5941,7 +5942,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = TcAnonRecdExpr cenv overallTy env tpenv (isStruct, optOrigExpr, unsortedFieldExprs, mWholeExpr) | SynExpr.ArrayOrList (isArray, args, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) let argty = NewInferenceType () UnifyTypes cenv env m overallTy (if isArray then mkArrayType cenv.g argty else Tastops.mkListTy cenv.g argty) @@ -5973,7 +5974,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = TcObjectExpr cenv overallTy env tpenv (objTy, argopt, binds, extraImpls, mNewExpr, m) | SynExpr.Record (inherits, optOrigExpr, flds, mWholeExpr) -> - CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr) | SynExpr.While (spWhile, synGuardExpr, synBodyExpr, m) -> @@ -5991,7 +5992,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = // notify name resolution sink about loop variable let item = Item.Value(mkLocalValRef idv) - CallNameResolutionSink cenv.tcSink (idv.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (idv.Range, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights) let bodyExpr, tpenv = TcStmt cenv envinner tpenv body mkFastForLoop cenv.g (spBind, m, idv, startExpr, dir, finishExpr, bodyExpr), tpenv @@ -6192,11 +6193,12 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.TraitCall (tps, memSpfn, arg, m) -> let synTypes = tps |> List.map (fun tp -> SynType.Var(tp, m)) - let (TTrait(_, logicalCompiledName, _, argTys, returnTy, _) as traitInfo), tpenv = TcPseudoMemberSpec cenv NewTyparsOK env synTypes tpenv memSpfn m - if BakedInTraitConstraintNames.Contains logicalCompiledName then - warning(BakedInMemberConstraintName(logicalCompiledName, m)) + let traitInfo, tpenv = TcPseudoMemberSpec cenv NewTyparsOK env synTypes tpenv memSpfn m + if BakedInTraitConstraintNames.Contains traitInfo.MemberName then + warning(BakedInMemberConstraintName(traitInfo.MemberName, m)) - let returnTy = GetFSharpViewOfReturnType cenv.g returnTy + let argTys = traitInfo.ArgumentTypes + let returnTy = GetFSharpViewOfReturnType cenv.g traitInfo.ReturnType let args, namedCallerArgs = GetMethodArgs arg if not (isNil namedCallerArgs) then errorR(Error(FSComp.SR.tcNamedArgumentsCannotBeUsedInMemberTraits(), m)) // Subsumption at trait calls if arguments have nominal type prior to unification of any arguments or return type @@ -6243,7 +6245,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = mkAsmExpr (Array.toList s, tyargs', args', rtys', m), tpenv | SynExpr.Quote (oper, raw, ast, isFromQueryExpression, m) -> - CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights) + CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.AccessRights) TcQuotationExpr cenv overallTy env tpenv (oper, raw, ast, isFromQueryExpression, m) | SynExpr.YieldOrReturn ((isTrueYield, _), _, m) @@ -6293,7 +6295,7 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = // .NET metadata. This means we manually typecheck 'e1' and look to see if it has a nominal type. We then // do the right thing in each case. and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArgs delayed = - let ad = env.eAccessRights + let ad = env.AccessRights let e1', e1ty, tpenv = TcExprOfUnknownType cenv env tpenv e1 // Find the first type in the effective hierarchy that either has a DefaultMember attribute OR @@ -6495,7 +6497,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg /// For 'inherit Type(args)', mWholeExprOrObjTy is the whole expression /// For an implicit inherit from System.Object or a default constructor, mWholeExprOrObjTy is the type name of the type being defined and TcNewExpr cenv env tpenv objTy mObjTyOpt superInit arg mWholeExprOrObjTy = - let ad = env.eAccessRights + let ad = env.AccessRights // Handle the case 'new 'a()' if (isTyparTy cenv.g objTy) then if superInit then error(Error(FSComp.SR.tcCannotInheritFromVariableType(), mWholeExprOrObjTy)) @@ -6514,7 +6516,7 @@ and TcNewExpr cenv env tpenv objTy mObjTyOpt superInit arg mWholeExprOrObjTy = /// Check an 'inheritedTys declaration in an implicit or explicit class and TcCtorCall isNaked cenv env tpenv overallTy objTy mObjTyOpt item superInit args mWholeCall delayed afterTcOverloadResolutionOpt = - let ad = env.eAccessRights + let ad = env.AccessRights let isSuperInit = (if superInit then CtorValUsedAsSuperInit else NormalValUse) let mItem = match mObjTyOpt with Some m -> m | None -> mWholeCall @@ -6543,7 +6545,7 @@ and TcCtorCall isNaked cenv env tpenv overallTy objTy mObjTyOpt item superInit a | Item.DelegateCtor ty, [arg] -> // Re-record the name resolution since we now know it's a constructor call match mObjTyOpt with - | Some mObjTy -> CallNameResolutionSink cenv.tcSink (mObjTy, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + | Some mObjTy -> CallNameResolutionSink cenv.tcSink (mObjTy, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) | None -> () TcNewDelegateThen cenv objTy env tpenv mItem mWholeCall ty arg ExprAtomicFlag.NonAtomic delayed @@ -6884,7 +6886,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, // Object expression members can access protected members of the implemented type let env = EnterFamilyRegion tcref env - let ad = env.eAccessRights + let ad = env.AccessRights if // record construction ? isRecordTy || @@ -6926,7 +6928,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, | Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) -> let meths = minfos |> List.map (fun minfo -> minfo, None) let afterResolution = ForNewConstructors cenv.tcSink env synObjTy.Range methodName minfos - let ad = env.eAccessRights + let ad = env.AccessRights let expr, tpenv = TcMethodApplicationThen cenv env objTy None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic [] // The 'base' value is always bound @@ -7132,7 +7134,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr | [] -> [] | _ -> let tcref, _, fldsList = BuildFieldMap cenv env hasOrigExpr overallTy flds mWholeExpr - let _, _, _, gtyp = infoOfTyconRef mWholeExpr tcref + let _, _, _, gtyp = FreshenTyconRef2 mWholeExpr tcref UnifyTypes cenv env mWholeExpr overallTy gtyp [ for n, v in fldsList do @@ -7723,7 +7725,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder match e with | SynExpr.App (_, _, SynExpr.App (_, _, e1, SingleIdent opName, _), e2, _) when opName.idText = customOperationJoinConditionWord nm -> let item = Item.CustomOperation (opName.idText, (fun () -> None), None) - CallNameResolutionSink cenv.tcSink (opName.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights) + CallNameResolutionSink cenv.tcSink (opName.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.AccessRights) Some (e1, e2) | _ -> None @@ -9046,8 +9048,8 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del mkConstrApp, [ucaseAppTy], [ for (s, m) in apinfo.ActiveTagsWithRanges -> mkSynId m s ] | _ -> let ucref = mkChoiceCaseRef g mItem aparity n - let _, _, tinst, _ = infoOfTyconRef mItem ucref.TyconRef - let ucinfo = UnionCaseInfo(tinst, ucref) + let _, _, tinst, _ = FreshenTyconRef2 mItem ucref.TyconRef + let ucinfo = UnionCaseInfo (tinst, ucref) ApplyUnionCaseOrExnTypes mItem cenv env ucaseAppTy (Item.UnionCase(ucinfo, false)) | _ -> ApplyUnionCaseOrExnTypes mItem cenv env ucaseAppTy item @@ -9301,6 +9303,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del | Item.FakeInterfaceCtor _ -> error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem)) + | Item.ImplicitOp(id, sln) -> let isPrefix = PrettyNaming.IsPrefixOperator id.idText @@ -9441,8 +9444,8 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del | DelayedSet(e2, mStmt) :: otherDelayed -> if not (isNil otherDelayed) then error(Error(FSComp.SR.tcInvalidAssignment(), mStmt)) UnifyTypes cenv env mStmt overallTy g.unit_ty - vref.Deref.SetHasBeenReferenced() - CheckValAccessible mItem env.eAccessRights vref + vref.Deref.SetHasBeenReferenced() + CheckValAccessible mItem env.AccessRights vref CheckValAttributes g vref mItem |> CommitOperationResult let vty = vref.Type let vty2 = @@ -9637,7 +9640,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela if isTyparTy cenv.g objExprTy then GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, env.DisplayEnv, mExprAndLongId) (freeInTypeLeftToRight cenv.g false objExprTy) - let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.eNameResEnv objExprTy longId findFlag false + let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId findFlag false let mExprAndItem = unionRanges mObjExpr mItem let delayed = delayRest rest mExprAndItem delayed @@ -10085,7 +10088,7 @@ and TcMethodApplication if meth.UsesParamArrayConversion then yield makeOneCalledMeth (minfo, pinfoOpt, false) ] - let uniquelyResolved = + let uniquelyResolved = let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css mMethExpr denv UnifyUniqueOverloading csenv callerArgCounts methodName ad preArgumentTypeCheckingCalledMethGroup returnTy @@ -10842,7 +10845,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt apinfo.ActiveTagsWithRanges |> List.iteri (fun i (_tag, tagRange) -> let item = Item.ActivePatternResult(apinfo, cenv.g.unit_ty, i, tagRange) - CallNameResolutionSink cenv.tcSink (tagRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights)) + CallNameResolutionSink cenv.tcSink (tagRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.AccessRights)) { envinner with eNameResEnv = AddActivePatternResultTagsToNameEnv apinfo envinner.eNameResEnv ty m } | None -> @@ -11750,7 +11753,6 @@ and AnalyzeAndMakeAndPublishRecursiveValue overridesOK isGeneratedEventVal cenv let item = Item.Value (mkLocalValRef vspec) CallNameResolutionSink cenv.tcSink (tid.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.RelatedText, env.DisplayEnv, env.eAccessRights) | _ -> () - let mangledId = ident(vspec.LogicalName, vspec.Range) // Reconstitute the binding with the unique name diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index dd32a6ee00..9878880972 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -133,7 +133,7 @@ let ChooseTyparSolutionAndRange (g: TcGlobals) amap (tp:Typar) = match tpc with | TyparConstraint.CoercesTo(x, m) -> join m x, m - | TyparConstraint.MayResolveMember(TTrait(_, _, _, _, _, _), m) -> + | TyparConstraint.MayResolveMember(_traitInfo, m) -> maxSoFar, m | TyparConstraint.SimpleChoice(_, m) -> errorR(Error(FSComp.SR.typrelCannotResolveAmbiguityInPrintf(), m)) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index e140b3351f..c717d9b6e3 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -1978,7 +1978,7 @@ let main1OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, use unwindParsePhase = PushThreadBuildPhaseUntilUnwind (BuildPhase.TypeCheck) let tcEnv0 = GetInitialTcEnv (assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals) - let tcState,topAttrs,typedAssembly,_tcEnvAtEnd = + let tcState, topAttrs, typedAssembly, _tcEnvAtEnd = TypeCheck(ctok, tcConfig, tcImports, tcGlobals, errorLogger, assemblyName, NiceNameGenerator(), tcEnv0, inputs,exiter) let generatedCcu = tcState.Ccu @@ -2024,7 +2024,7 @@ let main2a(Args (ctok, tcConfig, tcImports, frameworkTcImports: TcImports, tcGlo use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Optimize let optEnv0 = GetInitialOptimizationEnv (tcImports, tcGlobals) - + let importMap = tcImports.GetImportMap() let metadataVersion = match tcConfig.metadataVersion with diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 83d7ab4c35..1db4e36b35 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -870,9 +870,7 @@ type ILMethInfo = // MethInfo -#if DEBUG [] -#endif /// Describes an F# use of a method [] type MethInfo = @@ -955,7 +953,6 @@ type MethInfo = /// over extension members. member x.ExtensionMemberPriority = defaultArg x.ExtensionMemberPriorityOption System.UInt64.MaxValue -#if DEBUG /// Get the method name in DebuggerDisplayForm member x.DebuggerDisplayName = match x with @@ -965,7 +962,6 @@ type MethInfo = | ProvidedMeth(_, mi, _, m) -> "ProvidedMeth: " + mi.PUntaint((fun mi -> mi.Name), m) #endif | DefaultStructCtor _ -> ".ctor" -#endif /// Get the method name in LogicalName form, i.e. the name as it would be stored in .NET metadata member x.LogicalName = @@ -2247,6 +2243,8 @@ type PropInfo = | ProvidedProp(_, pi, _) -> ProvidedPropertyInfo.TaintedGetHashCode pi #endif + override x.ToString() = "property " + x.PropertyName + //------------------------------------------------------------------------- // ILEventInfo @@ -2494,6 +2492,7 @@ type EventInfo = #if !NO_EXTENSIONTYPING | ProvidedEvent (_, ei, _) -> ProvidedEventInfo.TaintedGetHashCode ei #endif + override x.ToString() = "event " + x.EventName //------------------------------------------------------------------------- // Helpers associated with getting and comparing method signatures diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index a6d5ae499a..27caa7b600 100644 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -2357,7 +2357,7 @@ and | SupportsNull of range /// Indicates a constraint that a type has a member with the given signature - | MayResolveMember of TraitConstraintInfo * range + | MayResolveMember of TraitConstraintInfo * range /// Indicates a constraint that a type is a non-Nullable value type /// These are part of .NET's model of generic constraints, and in order to @@ -2408,6 +2408,9 @@ and /// Get the member name associated with the member constraint. member x.MemberName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) + /// Get the argument types required of a member in order to solve the constraint + member x.ArgumentTypes = (let (TTrait(_, _, _, argtys, _, _)) = x in argtys) + /// Get the return type recorded in the member constraint. member x.ReturnType = (let (TTrait(_, _, _, _, ty, _)) = x in ty) @@ -4880,7 +4883,7 @@ and | Label of ILCodeLabel /// Pseudo method calls. This is used for overloaded operations like op_Addition. - | TraitCall of TraitConstraintInfo + | TraitCall of TraitConstraintInfo /// Operation nodes representing C-style operations on byrefs and mutable vals (l-values) | LValueOp of LValueOperation * ValRef diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index b071e0c5f7..5340031907 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 4184f3edc5..2ca4bd450e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 4b1a5e0d90..394481ad69 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 99d3469919..821545638e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index 8902030751..dd58cb9a11 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index de4d65e71f..c0221174d9 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index e7191ac3c4..6f540b5425 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index 6936b8e97f..f912b6b4c7 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index fefd197867..5a2b75dce0 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 355d363084..2b5303d91d 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 86ac32f4b3..73a72b806a 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 0537632d5f..474f99a3dc 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 17c64ffefb..16b7339b2a 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" From 45d9b1a4f3f2484f33c2ffc584c917cf6e5f849f Mon Sep 17 00:00:00 2001 From: Will Smith Date: Fri, 17 Jan 2020 15:52:29 -0800 Subject: [PATCH 035/101] Move Finalize from TcImports to another object (#8251) * Move Finalize from TcImports to another object responsible for disposing of TcImports resources * Use ResizeArray --- src/fsharp/CompileOps.fs | 60 ++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 2217184054..c90e75a3ae 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -3756,6 +3756,38 @@ type TcConfigProvider = // TcImports //-------------------------------------------------------------------------- +[] +type TcImportsSafeDisposal + (disposeActions: ResizeArray unit>, +#if !NO_EXTENSIONTYPING + disposeTypeProviderActions: ResizeArray unit>, +#endif + compilationThread: ICompilationThread) = + + let mutable isDisposed = false + + let dispose () = + // disposing deliberately only closes this tcImports, not the ones up the chain + isDisposed <- true + if verbose then + dprintf "disposing of TcImports, %d binaries\n" disposeActions.Count +#if !NO_EXTENSIONTYPING + let actions = disposeTypeProviderActions + if actions.Count > 0 then + compilationThread.EnqueueWork (fun _ -> for action in actions do action()) +#endif + for action in disposeActions do action() + + override _.Finalize() = + dispose () + + interface IDisposable with + + member this.Dispose() = + if not isDisposed then + GC.SuppressFinalize this + dispose () + #if !NO_EXTENSIONTYPING // These are hacks in order to allow TcImports to be held as a weak reference inside a type provider. // The reason is due to older type providers compiled using an older TypeProviderSDK, that SDK used reflection on fields and properties to determine the contract. @@ -3800,34 +3832,24 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let mutable dllTable: NameMap = NameMap.empty let mutable ccuInfos: ImportedAssembly list = [] let mutable ccuTable: NameMap = NameMap.empty - let mutable disposeActions = [] + let disposeActions = ResizeArray() let mutable disposed = false let mutable ilGlobalsOpt = ilGlobalsOpt let mutable tcGlobals = None #if !NO_EXTENSIONTYPING - let mutable disposeTypeProviderActions = [] + let disposeTypeProviderActions = ResizeArray() let mutable generatedTypeRoots = new System.Collections.Generic.Dictionary() let mutable tcImportsWeak = TcImportsWeakHack (WeakReference<_> this) #endif + + let disposal = new TcImportsSafeDisposal(disposeActions, disposeTypeProviderActions, compilationThread) let CheckDisposed() = if disposed then assert false let dispose () = CheckDisposed() - // disposing deliberately only closes this tcImports, not the ones up the chain - disposed <- true - if verbose then - dprintf "disposing of TcImports, %d binaries\n" disposeActions.Length -#if !NO_EXTENSIONTYPING - let actions = disposeTypeProviderActions - disposeTypeProviderActions <- [] - if actions.Length > 0 then - compilationThread.EnqueueWork (fun _ -> for action in actions do action()) -#endif - let actions = disposeActions - disposeActions <- [] - for action in actions do action() + (disposal :> IDisposable).Dispose() static let ccuHasType (ccu: CcuThunk) (nsname: string list) (tname: string) = let matchNameSpace (entityOpt: Entity option) n = @@ -4043,12 +4065,12 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse member private tcImports.AttachDisposeAction action = CheckDisposed() - disposeActions <- action :: disposeActions + disposeActions.Add action #if !NO_EXTENSIONTYPING member private tcImports.AttachDisposeTypeProviderAction action = CheckDisposed() - disposeTypeProviderActions <- action :: disposeTypeProviderActions + disposeTypeProviderActions.Add action #endif // Note: the returned binary reader is associated with the tcImports, i.e. when the tcImports are closed @@ -4781,9 +4803,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse knownUnresolved |> List.map (function UnresolvedAssemblyReference(file, originalReferences) -> file, originalReferences) |> List.iter reportAssemblyNotResolved - - override tcImports.Finalize () = - dispose () static member BuildNonFrameworkTcImports (ctok, tcConfigP: TcConfigProvider, tcGlobals: TcGlobals, baseTcImports, nonFrameworkReferences, knownUnresolved) = cancellable { @@ -4809,7 +4828,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse interface System.IDisposable with member tcImports.Dispose() = dispose () - GC.SuppressFinalize tcImports override tcImports.ToString() = "TcImports(...)" From 0595fecc4c20e453892a715f346516dd5f71751a Mon Sep 17 00:00:00 2001 From: Will Smith Date: Fri, 17 Jan 2020 16:06:37 -0800 Subject: [PATCH 036/101] Added keepAllBackgroundSymbolUses to FSharpChecker (#8256) --- src/fsharp/NameResolution.fs | 2 ++ src/fsharp/NameResolution.fsi | 3 +++ src/fsharp/service/IncrementalBuild.fs | 9 +++++---- src/fsharp/service/IncrementalBuild.fsi | 2 +- src/fsharp/service/service.fs | 14 ++++++++------ src/fsharp/service/service.fsi | 2 +- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 30f456fd86..7173baa3f6 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1702,6 +1702,8 @@ type TcSymbolUses(g, capturedNameResolutions: ResizeArray, ResizeArray(), Array.empty) + /// An accumulator for the results being emitted into the tcSink. type TcResultsSinkImpl(g, ?sourceText: ISourceText) = let capturedEnvs = ResizeArray<_>() diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index ea3bbd8aea..3bb04f3737 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -326,6 +326,9 @@ type internal TcSymbolUses = /// Get the locations of all the printf format specifiers in the file member GetFormatSpecifierLocationsAndArity : unit -> (range * int)[] + /// Empty collection of symbol uses + static member Empty : TcSymbolUses + /// Represents open declaration statement. type internal OpenDeclaration = { /// Long identifier as it's presented in source code. diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index de773fd3aa..5e36f94b55 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1208,7 +1208,7 @@ type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, tcState: type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInputs, nonFrameworkResolutions, unresolvedReferences, tcConfig: TcConfig, projectDirectory, outfile, assemblyName, niceNameGen: NiceNameGenerator, lexResourceManager, sourceFiles, loadClosureOpt: LoadClosure option, - keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds) = + keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds, keepAllBackgroundSymbolUses) = let tcConfigP = TcConfigProvider.Constant tcConfig let fileParsed = new Event() @@ -1386,7 +1386,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let implFile = if keepAssemblyContents then implFile else None let tcResolutions = if keepAllBackgroundResolutions then sink.GetResolutions() else TcResolutions.Empty let tcEnvAtEndOfFile = (if keepAllBackgroundResolutions then tcEnvAtEndOfFile else tcState.TcEnvFromImpls) - let tcSymbolUses = sink.GetSymbolUses() + let tcSymbolUses = if keepAllBackgroundSymbolUses then sink.GetSymbolUses() else TcSymbolUses.Empty RequireCompilationThread ctok // Note: events get raised on the CompilationThread @@ -1700,7 +1700,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput projectReferences, projectDirectory, useScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds, - tryGetMetadataSnapshot, suggestNamesForErrors) = + tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses) = let useSimpleResolutionSwitch = "--simpleresolution" cancellable { @@ -1820,7 +1820,8 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput resourceManager, sourceFilesNew, loadClosureOpt, keepAssemblyContents=keepAssemblyContents, keepAllBackgroundResolutions=keepAllBackgroundResolutions, - maxTimeShareMilliseconds=maxTimeShareMilliseconds) + maxTimeShareMilliseconds=maxTimeShareMilliseconds, + keepAllBackgroundSymbolUses=keepAllBackgroundSymbolUses) return Some builder with e -> errorRecoveryNoRange e diff --git a/src/fsharp/service/IncrementalBuild.fsi b/src/fsharp/service/IncrementalBuild.fsi index fb60dbff69..d775c92fcc 100755 --- a/src/fsharp/service/IncrementalBuild.fsi +++ b/src/fsharp/service/IncrementalBuild.fsi @@ -161,7 +161,7 @@ type internal IncrementalBuilder = /// This may be a marginally long-running operation (parses are relatively quick, only one file needs to be parsed) member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable - static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * suggestNamesForErrors: bool -> Cancellable + static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * suggestNamesForErrors: bool * keepAllBackgroundSymbolUses: bool -> Cancellable /// Generalized Incremental Builder. This is exposed only for unit testing purposes. module internal IncrementalBuild = diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 7030262aab..978d6cd087 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -249,7 +249,7 @@ type ScriptClosureCacheToken() = interface LockToken // There is only one instance of this type, held in FSharpChecker -type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors) as self = +type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses) as self = // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.reactor: The one and only Reactor let reactor = Reactor.Singleton let beforeFileChecked = Event() @@ -306,7 +306,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC (ctok, legacyReferenceResolver, FSharpCheckerResultsSettings.defaultFSharpBinariesDir, frameworkTcImportsCache, loadClosure, Array.toList options.SourceFiles, Array.toList options.OtherOptions, projectReferences, options.ProjectDirectory, options.UseScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, FSharpCheckerResultsSettings.maxTimeShareMilliseconds, - tryGetMetadataSnapshot, suggestNamesForErrors) + tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses) match builderOpt with | None -> () @@ -905,9 +905,10 @@ type FSharpChecker(legacyReferenceResolver, keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, - suggestNamesForErrors) = + suggestNamesForErrors, + keepAllBackgroundSymbolUses) = - let backgroundCompiler = BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors) + let backgroundCompiler = BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses) static let globalInstance = lazy FSharpChecker.Create() @@ -924,7 +925,7 @@ type FSharpChecker(legacyReferenceResolver, let maxMemEvent = new Event() /// Instantiate an interactive checker. - static member Create(?projectCacheSize, ?keepAssemblyContents, ?keepAllBackgroundResolutions, ?legacyReferenceResolver, ?tryGetMetadataSnapshot, ?suggestNamesForErrors) = + static member Create(?projectCacheSize, ?keepAssemblyContents, ?keepAllBackgroundResolutions, ?legacyReferenceResolver, ?tryGetMetadataSnapshot, ?suggestNamesForErrors, ?keepAllBackgroundSymbolUses) = let legacyReferenceResolver = match legacyReferenceResolver with @@ -936,7 +937,8 @@ type FSharpChecker(legacyReferenceResolver, let projectCacheSizeReal = defaultArg projectCacheSize projectCacheSizeDefault let tryGetMetadataSnapshot = defaultArg tryGetMetadataSnapshot (fun _ -> None) let suggestNamesForErrors = defaultArg suggestNamesForErrors false - new FSharpChecker(legacyReferenceResolver, projectCacheSizeReal,keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors) + let keepAllBackgroundSymbolUses = defaultArg keepAllBackgroundSymbolUses true + new FSharpChecker(legacyReferenceResolver, projectCacheSizeReal,keepAssemblyContents, keepAllBackgroundResolutions, tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses) member __.ReferenceResolver = legacyReferenceResolver diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index 182714e8d6..c463f2a2ee 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -77,7 +77,7 @@ type public FSharpChecker = /// If false, do not keep full intermediate checking results from background checking suitable for returning from GetBackgroundCheckResultsForFileInProject. This reduces memory usage. /// An optional resolver for non-file references, for legacy purposes /// An optional resolver to access the contents of .NET binaries in a memory-efficient way - static member Create : ?projectCacheSize: int * ?keepAssemblyContents: bool * ?keepAllBackgroundResolutions: bool * ?legacyReferenceResolver: ReferenceResolver.Resolver * ?tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * ?suggestNamesForErrors: bool -> FSharpChecker + static member Create : ?projectCacheSize: int * ?keepAssemblyContents: bool * ?keepAllBackgroundResolutions: bool * ?legacyReferenceResolver: ReferenceResolver.Resolver * ?tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * ?suggestNamesForErrors: bool * ?keepAllBackgroundSymbolUses: bool -> FSharpChecker /// /// Parse a source code file, returning information about brace matching in the file. From c0cc02453a234c1d7d070550d622ccf0b5eff4a2 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Fri, 17 Jan 2020 16:52:25 -0800 Subject: [PATCH 037/101] revert xlf --- .../xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf | 3 +-- 13 files changed, 13 insertions(+), 26 deletions(-) diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index 5340031907..b071e0c5f7 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 2ca4bd450e..4184f3edc5 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 394481ad69..4b1a5e0d90 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 821545638e..99d3469919 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index dd58cb9a11..8902030751 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index c0221174d9..de4d65e71f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index 6f540b5425..e7191ac3c4 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index f912b6b4c7..6936b8e97f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index 5a2b75dce0..fefd197867 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 2b5303d91d..355d363084 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 73a72b806a..86ac32f4b3 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 474f99a3dc..0537632d5f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 16b7339b2a..17c64ffefb 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" From e690e922d3ed6991e26e712fea76129bec0eb399 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Sun, 19 Jan 2020 06:11:19 +0100 Subject: [PATCH 038/101] Do not convert back and forth from list (#8262) * Do not convert back and forth from list * Use a simple for loop in replicate * Put wildcard back --- src/fsharp/FSharp.Core/list.fs | 8 ++++---- src/fsharp/FSharp.Core/local.fs | 2 +- src/fsharp/TypeChecker.fs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index bf37ab08a1..920f0f0d9f 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -171,13 +171,13 @@ namespace Microsoft.FSharp.Collections [] let init length initializer = Microsoft.FSharp.Primitives.Basics.List.init length initializer - let rec initConstAcc n x acc = - if n <= 0 then acc else initConstAcc (n-1) x (x :: acc) - [] let replicate count initial = if count < 0 then invalidArg "count" (SR.GetString(SR.inputMustBeNonNegative)) - initConstAcc count initial [] + let mutable result = [] + for i in 0..count-1 do + result <- initial :: result + result [] let iter2 action list1 list2 = diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 8e1b17ea91..3d812fc72c 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -83,7 +83,7 @@ open System.Collections.Generic module internal List = - let arrayZeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T array #) + let inline arrayZeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T array #) [] let nonempty x = match x with [] -> false | _ -> true diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 539f67d844..c7e69f71be 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -5482,7 +5482,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p | [SynPatErrorSkip(SynPat.Tuple (false, args, _)) | SynPatErrorSkip(SynPat.Paren(SynPatErrorSkip(SynPat.Tuple (false, args, _)), _))] when numArgTys > 1 -> args // note: we allow both 'C _' and 'C (_)' regardless of number of argument of the pattern - | [SynPatErrorSkip(SynPat.Wild _ as e) | SynPatErrorSkip(SynPat.Paren(SynPatErrorSkip(SynPat.Wild _ as e), _))] -> Array.toList (Array.create numArgTys e) + | [SynPatErrorSkip(SynPat.Wild _ as e) | SynPatErrorSkip(SynPat.Paren(SynPatErrorSkip(SynPat.Wild _ as e), _))] -> List.replicate numArgTys e | [arg] -> [arg] | _ when numArgTys = 0 -> error(Error(FSComp.SR.tcUnionCaseDoesNotTakeArguments(), m)) | _ when numArgTys = 1 -> error(Error(FSComp.SR.tcUnionCaseRequiresOneArgument(), m)) From 7b3c2afc2b3c1e1d78f2f086c6b4a964b4e8a6d2 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sat, 18 Jan 2020 22:25:07 -0800 Subject: [PATCH 039/101] Allow length of zero for ByteMemory (#8273) --- src/absil/bytes.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 754b9d49dd..89556fc968 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -67,7 +67,7 @@ type ByteArrayMemory(bytes: byte[], offset, length) = inherit ByteMemory() do - if length <= 0 || length > bytes.Length then + if length < 0 || length > bytes.Length then raise (ArgumentOutOfRangeException("length")) if offset < 0 || (offset + length) > bytes.Length then @@ -155,7 +155,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = raise (ArgumentOutOfRangeException("i")) do - if length <= 0 then + if length < 0 then raise (ArgumentOutOfRangeException("length")) override _.Item From e07132b09f3c9aec2624ed07dc356fff875a979e Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Sun, 19 Jan 2020 07:46:48 +0100 Subject: [PATCH 040/101] Inline isRecdTy (#8274) --- src/fsharp/NameResolution.fs | 7 ++++--- src/fsharp/TypeChecker.fs | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 941de1c35e..10e330f207 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -3214,11 +3214,12 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) |> List.map (fun x -> ResolutionInfo.Empty, FieldResolution(x, false)) - if isAppTy g ty then + match tryDestAppTy g ty with + | ValueSome tcref -> match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText, m, ty) with | ValueSome (RecdFieldInfo(_, rfref)) -> [ResolutionInfo.Empty, FieldResolution(rfref, false)] | _ -> - if isRecdTy g ty then + if tcref.IsRecordTycon then // record label doesn't belong to record type -> suggest other labels of same record let suggestLabels (addToBuffer: string -> unit) = for label in SuggestOtherLabelsOfSameRecordType g nenv ty id allFields do @@ -3229,7 +3230,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi error(ErrorWithSuggestions(errorText, m, id.idText, suggestLabels)) else lookup() - else + | _ -> lookup() | _ -> let lid = (mp@[id]) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index c7e69f71be..6609d5ad95 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -6876,7 +6876,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, match tryDestAppTy cenv.g objTy with | ValueNone -> error(Error(FSComp.SR.tcNewMustBeUsedWithNamedType(), mNewExpr)) | ValueSome tcref -> - let isRecordTy = isRecdTy cenv.g objTy + let isRecordTy = tcref.IsRecordTycon if not isRecordTy && not (isInterfaceTy cenv.g objTy) && isSealedTy cenv.g objTy then errorR(Error(FSComp.SR.tcCannotCreateExtensionOfSealedType(), mNewExpr)) CheckSuperType cenv objTy synObjTy.Range @@ -7265,12 +7265,12 @@ and TcAnonRecdExpr cenv overallTy env tpenv (isStruct, optOrigSynExpr, unsortedF for (i, id) in Array.indexed anonInfo.SortedIds do yield id, Choice2Of2 (mkAnonRecdFieldGetViaExprAddr (anonInfo, oldveaddr, tinst, i, mOrigExpr)) | ValueNone -> - if isRecdTy cenv.g origExprTy then - let tcref, tinst = destAppTy cenv.g origExprTy + match tryAppTy cenv.g origExprTy with + | ValueSome(tcref, tinst) when tcref.IsRecordTycon -> let fspecs = tcref.Deref.TrueInstanceFieldsAsList for fspec in fspecs do yield fspec.Id, Choice2Of2 (mkRecdFieldGetViaExprAddr (oldveaddr, tcref.MakeNestedRecdFieldRef fspec, tinst, mOrigExpr)) - else + | _ -> error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr)) |] |> Array.distinctBy (fst >> textOfId) From b7a3bf87971ef3d4aacdd94f269f0ab5c5b78e0f Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 20 Jan 2020 06:45:10 -0800 Subject: [PATCH 041/101] Remove Finalize on obj holder for RawByteMemory (#8237) * Remove Finalize on obj holder for RawByteMemory as memory mapped files use a safe handler. * Removed Finalize from SafeUnamanagedMemoryStream as it is an impl detail for viewing RawByteMemory as a stream * Remove new * Update bytes.fs --- src/absil/bytes.fs | 58 +++++++++++++-------------------------------- src/absil/bytes.fsi | 2 +- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 89556fc968..24159a728c 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -120,34 +120,29 @@ type ByteArrayMemory(bytes: byte[], offset, length) = type SafeUnmanagedMemoryStream = inherit UnmanagedMemoryStream - val mutable private hold: obj + val mutable private holder: obj val mutable private isDisposed: bool - new (addr, length, hold) = + new (addr, length, holder) = { inherit UnmanagedMemoryStream(addr, length) - hold = hold + holder = holder isDisposed = false } - new (addr: nativeptr, length: int64, capacity: int64, access: FileAccess, hold) = + new (addr: nativeptr, length: int64, capacity: int64, access: FileAccess, holder) = { inherit UnmanagedMemoryStream(addr, length, capacity, access) - hold = hold + holder = holder isDisposed = false } - override x.Finalize() = - x.Dispose false - override x.Dispose disposing = base.Dispose disposing - if not x.isDisposed then - x.hold <- null // Null out so it can be collected. - x.isDisposed <- true + x.holder <- null // Null out so it can be collected. [] -type RawByteMemory(addr: nativeptr, length: int, hold: obj) = +type RawByteMemory(addr: nativeptr, length: int, holder: obj) = inherit ByteMemory () let check i = @@ -159,7 +154,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = raise (ArgumentOutOfRangeException("length")) override _.Item - with get i = + with get i = check i NativePtr.add addr i |> NativePtr.read @@ -174,7 +169,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = check (pos + count - 1) System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) - override _.ReadBytes(pos, count) = + override _.ReadBytes(pos, count) = check pos check (pos + count - 1) let res = Bytes.zeroCreate count @@ -194,7 +189,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = override _.Slice(pos, count) = check pos check (pos + count - 1) - RawByteMemory(NativePtr.add addr pos, count, hold) :> ByteMemory + RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory override x.CopyTo stream = use stream2 = x.AsStream() @@ -210,10 +205,10 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = res override _.AsStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, hold) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream override _.AsReadOnlyStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, hold) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream [] type ReadOnlyByteMemory(bytes: ByteMemory) = @@ -259,17 +254,7 @@ type ByteMemory with mmf let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) - - let safeHolder = - { new obj() with - override x.Finalize() = - (x :?> IDisposable).Dispose() - interface IDisposable with - member x.Dispose() = - GC.SuppressFinalize x - accessor.Dispose() - mmf.Dispose() } - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, safeHolder) + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromFile(path, access, ?canShadowCopy: bool) = let canShadowCopy = defaultArg canShadowCopy false @@ -313,19 +298,10 @@ type ByteMemory with | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" | _ -> () - let safeHolder = - { new obj() with - override x.Finalize() = - (x :?> IDisposable).Dispose() - interface IDisposable with - member x.Dispose() = - GC.SuppressFinalize x - accessor.Dispose() - mmf.Dispose() } - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, safeHolder) - - static member FromUnsafePointer(addr, length, hold: obj) = - RawByteMemory(NativePtr.ofNativeInt addr, length, hold) :> ByteMemory + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + + static member FromUnsafePointer(addr, length, holder: obj) = + RawByteMemory(NativePtr.ofNativeInt addr, length, holder) :> ByteMemory static member FromArray(bytes, offset, length) = ByteArrayMemory(bytes, offset, length) :> ByteMemory diff --git a/src/absil/bytes.fsi b/src/absil/bytes.fsi index 11e7c9f58c..46b30b6c5a 100644 --- a/src/absil/bytes.fsi +++ b/src/absil/bytes.fsi @@ -95,7 +95,7 @@ type ByteMemory with /// Creates a ByteMemory object that is backed by a raw pointer. /// Use with care. - static member FromUnsafePointer: addr: nativeint * length: int * hold: obj -> ByteMemory + static member FromUnsafePointer: addr: nativeint * length: int * holder: obj -> ByteMemory /// Creates a ByteMemory object that is backed by a byte array with the specified offset and length. static member FromArray: bytes: byte[] * offset: int * length: int -> ByteMemory From e20fc26d0b68a540fd91286e2d8881c73164e991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Cie=C5=9Blak?= Date: Mon, 20 Jan 2020 15:53:43 +0100 Subject: [PATCH 042/101] Remove project cracker (#8288) * Remove ProjectCracker project * Remove Project Cracker tests * Remove ProjectCracker docs --- ...arp.Compiler.Service.ProjectCracker.fsproj | 33 - .../ProjectCracker.fs | 127 ---- .../App.config | 22 - ...rp.Compiler.Service.ProjectCracker.targets | 7 - ...Compiler.Service.ProjectCrackerTool.fsproj | 25 - .../Program.fs | 46 -- .../ProjectCrackerOptions.fs | 11 - .../ProjectCrackerTool.fs | 471 -------------- .../FSharp.Compiler.Service.Tests.fsproj | 7 - fcs/FSharp.Compiler.Service.sln | 38 +- fcs/README.md | 10 +- fcs/docsrc/content/devnotes.md | 2 +- fcs/docsrc/content/project.fsx | 56 -- tests/service/ExprTests.fs | 312 ---------- tests/service/MultiProjectAnalysisTests.fs | 2 - tests/service/ProjectOptionsTests.fs | 578 ------------------ .../LanguageServiceProfiling.fsproj | 1 - .../ProjectCracker.fs | 2 - .../UnitTests/VisualFSharp.UnitTests.fsproj | 4 - 19 files changed, 15 insertions(+), 1739 deletions(-) delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs delete mode 100644 tests/service/ProjectOptionsTests.fs delete mode 100644 vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj deleted file mode 100644 index b12fa10ee5..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - $(FcsTargetNetFxFramework) - true - - - Legacy project file cracker for the F# compiler service. - Legacy project file cracker for the F# compiler service. - false - Microsoft Corporation; F# community contributors - https://github.com/fsharp/FSharp.Compiler.Service/blob/master/LICENSE - https://github.com/fsharp/FSharp.Compiler.Service - logo.png - F#, compiler, msbuild - - - - - ProjectCrackerOptions.fs - - - - - - - - - - - - - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs b/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs deleted file mode 100644 index 3a096cb566..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs +++ /dev/null @@ -1,127 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices - -#if !NETSTANDARD -open System.Runtime.Serialization.Json -#endif -open System.Text -open System.IO -open System - -module Utils = - - let Convert loadedTimeStamp (originalOpts: ProjectCrackerTool.ProjectOptions) = - let logMap = ref Map.empty - - let rec convertProject (opts: ProjectCrackerTool.ProjectOptions) = - if not (isNull opts.Error) then failwith opts.Error - - let referencedProjects() = Array.map (fun (a, b) -> a,convertProject b) opts.ReferencedProjectOptions - - let sourceFiles, otherOptions = - opts.Options - |> Array.partition (fun x -> - let extension = Path.GetExtension(x).ToLower() - x.IndexOfAny(Path.GetInvalidPathChars()) = -1 - && (extension = ".fs" || extension = ".fsi")) - - let sepChar = Path.DirectorySeparatorChar - - let sourceFiles = sourceFiles |> Array.map (fun x -> - match sepChar with - | '\\' -> x.Replace('/', '\\') - | '/' -> x.Replace('\\', '/') - | _ -> x - ) - - logMap := Map.add opts.ProjectFile opts.LogOutput !logMap - { ProjectFileName = opts.ProjectFile - ProjectId = None - SourceFiles = sourceFiles - OtherOptions = otherOptions - ReferencedProjects = referencedProjects() - IsIncompleteTypeCheckEnvironment = false - UseScriptResolutionRules = false - LoadTime = loadedTimeStamp - UnresolvedReferences = None - OriginalLoadReferences = [] - ExtraProjectInfo = None - Stamp = None } - - convertProject originalOpts, !logMap - -type ProjectCracker = - - static member GetProjectOptionsFromProjectFileLogged(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp, ?enableLogging) = - let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading - let properties = defaultArg properties [] - let enableLogging = defaultArg enableLogging true - - -#if NETSTANDARD - let arguments = [| - yield projectFileName - yield enableLogging.ToString() - for k, v in properties do - yield k - yield v - |] - - let ret, opts = FSharp.Compiler.SourceCodeServices.ProjectCrackerTool.ProjectCrackerTool.crackOpen arguments - ignore ret -#else - let arguments = new StringBuilder() - arguments.Append('"').Append(projectFileName).Append('"') |> ignore - arguments.Append(' ').Append(enableLogging.ToString()) |> ignore - for k, v in properties do - arguments.Append(' ').Append(k).Append(' ').Append(v) |> ignore - let codebase = Path.GetDirectoryName(Uri(typeof.Assembly.CodeBase).LocalPath) - - let crackerFilename = Path.Combine(codebase,"FSharp.Compiler.Service.ProjectCrackerTool.exe") - if not (File.Exists crackerFilename) then - failwithf "ProjectCracker exe not found at: %s it must be next to the ProjectCracker dll." crackerFilename - - let p = new System.Diagnostics.Process() - - p.StartInfo.FileName <- crackerFilename - p.StartInfo.Arguments <- arguments.ToString() - p.StartInfo.UseShellExecute <- false - p.StartInfo.CreateNoWindow <- true - p.StartInfo.RedirectStandardOutput <- true - p.StartInfo.RedirectStandardError <- true - - let sbOut = StringBuilder() - let sbErr = StringBuilder() - - p.ErrorDataReceived.AddHandler(fun _ a -> sbErr.AppendLine a.Data |> ignore) - p.OutputDataReceived.AddHandler(fun _ a -> sbOut.AppendLine a.Data |> ignore) - - ignore <| p.Start() - - p.EnableRaisingEvents <- true - p.BeginOutputReadLine() - p.BeginErrorReadLine() - - p.WaitForExit() - - let crackerOut = sbOut.ToString() - let crackerErr = sbErr.ToString() - - let opts = - try - let ser = new DataContractJsonSerializer(typeof) - let stringBytes = Encoding.Unicode.GetBytes crackerOut - use ms = new MemoryStream(stringBytes) - ser.ReadObject(ms) :?> ProjectCrackerTool.ProjectOptions - with - exn -> - raise (Exception(sprintf "error parsing ProjectCrackerTool output, stdoutput was:\n%s\n\nstderr was:\n%s" crackerOut crackerErr, exn)) -#endif - - Utils.Convert loadedTimeStamp opts - - static member GetProjectOptionsFromProjectFile(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp) = - fst (ProjectCracker.GetProjectOptionsFromProjectFileLogged( - projectFileName, - ?properties=properties, - ?loadedTimeStamp=loadedTimeStamp, - enableLogging=false)) diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config deleted file mode 100644 index fdab151af2..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets deleted file mode 100644 index ed01293ada..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj deleted file mode 100644 index 19789a9629..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - Exe - $(FcsTargetNetFxFramework) - true - $(DefineConstants);CROSS_PLATFORM_COMPILER - $(DefineConstants);ENABLE_MONO_SUPPORT - $(OtherFlags) --staticlink:FSharp.Core - true - false - - - - - - - - - - - - - - diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs deleted file mode 100644 index 5cc3fc8b1e..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs +++ /dev/null @@ -1,46 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -open System -open System.Reflection -open System.Runtime.Serialization.Json - -module Program = - -#if !NETCOREAPP - let addMSBuildv14BackupResolution () = - let onResolveEvent = new ResolveEventHandler(fun sender evArgs -> - let requestedAssembly = AssemblyName(evArgs.Name) - if requestedAssembly.Name.StartsWith("Microsoft.Build", StringComparison.Ordinal) && - not (requestedAssembly.Name.EndsWith(".resources", StringComparison.Ordinal)) && - not (requestedAssembly.Version.ToString().Contains("12.0.0.0")) - then - // If the version of MSBuild that we're using wasn't present on the machine, then - // just revert back to 12.0.0.0 since that's normally installed as part of the .NET - // Framework. - requestedAssembly.Version <- Version("12.0.0.0") - Assembly.Load requestedAssembly - else - null) - AppDomain.CurrentDomain.add_AssemblyResolve(onResolveEvent) -#endif - - let crackAndSendOutput asText argv = - let ret, opts = ProjectCrackerTool.crackOpen argv - - if asText then - printfn "%A" opts - else - let ser = new DataContractJsonSerializer(typeof) - ser.WriteObject(Console.OpenStandardOutput(), opts) - ret - - - [][] - let main argv = - let asText = Array.exists (fun (s: string) -> s = "--text") argv - let argv = Array.filter (fun (s: string) -> s <> "--text") argv - -#if !NETCOREAPP - addMSBuildv14BackupResolution () -#endif - crackAndSendOutput asText argv diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs deleted file mode 100644 index a48bdc25aa..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs +++ /dev/null @@ -1,11 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -[] -type ProjectOptions = - { - ProjectFile: string - Options: string[] - ReferencedProjectOptions: (string * ProjectOptions)[] - LogOutput: string - Error: string - } diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs deleted file mode 100644 index 0f2d4ad056..0000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs +++ /dev/null @@ -1,471 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -open System -open System.IO -open System.Text -open Microsoft.Build.Framework -open Microsoft.Build.Utilities - -module internal ProjectCrackerTool = - open System.Collections.Generic - - let runningOnMono = -#if NETCOREAPP - false -#else - try match System.Type.GetType("Mono.Runtime") with null -> false | _ -> true - with e -> false -#endif - - type internal BasicStringLogger() = - inherit Logger() - - let sb = new StringBuilder() - - let log (e: BuildEventArgs) = - sb.Append(e.Message) |> ignore - sb.AppendLine() |> ignore - - override x.Initialize(eventSource:IEventSource) = - sb.Clear() |> ignore - eventSource.AnyEventRaised.Add(log) - - member x.Log = sb.ToString() - - type internal HostCompile() = - member th.Compile(_:obj, _:obj, _:obj) = 0 - interface ITaskHost - - let vs = - let programFiles = - let getEnv v = - let result = System.Environment.GetEnvironmentVariable(v) - match result with - | null -> None - | _ -> Some result - - match List.tryPick getEnv [ "ProgramFiles(x86)"; "ProgramFiles" ] with - | Some r -> r - | None -> "C:\\Program Files (x86)" - - let vsVersions = ["14.0"; "12.0"] - let msbuildBin v = IO.Path.Combine(programFiles, "MSBuild", v, "Bin", "MSBuild.exe") - List.tryFind (fun v -> IO.File.Exists(msbuildBin v)) vsVersions - - let mkAbsolute dir v = - if Path.IsPathRooted v then v - else Path.Combine(dir, v) - - let mkAbsoluteOpt dir v = Option.map (mkAbsolute dir) v - - let CrackProjectUsingNewBuildAPI fsprojFile properties logOpt = - let fsprojFullPath = try Path.GetFullPath(fsprojFile) with _ -> fsprojFile - let fsprojAbsDirectory = Path.GetDirectoryName fsprojFullPath - - use _pwd = - let dir = Directory.GetCurrentDirectory() - Directory.SetCurrentDirectory(fsprojAbsDirectory) - { new System.IDisposable with - member x.Dispose() = Directory.SetCurrentDirectory(dir) } - use engine = new Microsoft.Build.Evaluation.ProjectCollection() - let host = new HostCompile() - - engine.HostServices.RegisterHostObject(fsprojFullPath, "CoreCompile", "Fsc", host) - - let projectInstanceFromFullPath (fsprojFullPath: string) = - use file = new FileStream(fsprojFullPath, FileMode.Open, FileAccess.Read, FileShare.Read) - use stream = new StreamReader(file) - use xmlReader = System.Xml.XmlReader.Create(stream) - - let project = - try - engine.LoadProject(xmlReader, FullPath=fsprojFullPath) - with - | exn -> - let tools = engine.Toolsets |> Seq.map (fun x -> x.ToolsPath) |> Seq.toList - raise (new Exception(sprintf "Could not load project %s in ProjectCollection. Available tools: %A. Message: %s" fsprojFullPath tools exn.Message)) - - project.SetGlobalProperty("BuildingInsideVisualStudio", "true") |> ignore - if not (List.exists (fun (p,_) -> p = "VisualStudioVersion") properties) then - match vs with - | Some version -> project.SetGlobalProperty("VisualStudioVersion", version) |> ignore - | None -> () - project.SetGlobalProperty("ShouldUnsetParentConfigurationAndPlatform", "false") |> ignore - for (prop, value) in properties do - project.SetGlobalProperty(prop, value) |> ignore - - project.CreateProjectInstance() - - let project = projectInstanceFromFullPath fsprojFullPath - let directory = project.Directory - - let getprop (p: Microsoft.Build.Execution.ProjectInstance) s = - let v = p.GetPropertyValue s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = getprop project "TargetPath" - - let log = match logOpt with - | None -> [] - | Some l -> [l :> ILogger] - - project.Build([| "Build" |], log) |> ignore - - let getItems s = [ for f in project.GetItems(s) -> mkAbsolute directory f.EvaluatedInclude ] - - let projectReferences = - [ for cp in project.GetItems("ProjectReference") do - yield cp.GetMetadataValue("FullPath") - ] - - let references = - [ for i in project.GetItems("ReferencePath") do - yield i.EvaluatedInclude - for i in project.GetItems("ChildProjectReferences") do - yield i.EvaluatedInclude ] - - outFileOpt, directory, getItems, references, projectReferences, getprop project, project.FullPath - -#if !NETCOREAPP - let CrackProjectUsingOldBuildAPI (fsprojFile:string) properties logOpt = - let engine = new Microsoft.Build.BuildEngine.Engine() - Option.iter (fun l -> engine.RegisterLogger(l)) logOpt - - let bpg = Microsoft.Build.BuildEngine.BuildPropertyGroup() - - bpg.SetProperty("BuildingInsideVisualStudio", "true") - for (prop, value) in properties do - bpg.SetProperty(prop, value) - - engine.GlobalProperties <- bpg - - let projectFromFile (fsprojFile:string) = - // We seem to need to pass 12.0/4.0 in here for some unknown reason - let project = new Microsoft.Build.BuildEngine.Project(engine, engine.DefaultToolsVersion) - do project.Load(fsprojFile) - project - - let project = projectFromFile fsprojFile - project.Build([| "ResolveReferences" |]) |> ignore - let directory = Path.GetDirectoryName project.FullFileName - - let getProp (p: Microsoft.Build.BuildEngine.Project) s = - let v = p.GetEvaluatedProperty s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = - match mkAbsoluteOpt directory (getProp project "OutDir") with - | None -> None - | Some d -> mkAbsoluteOpt d (getProp project "TargetFileName") - - let getItems s = - let fs = project.GetEvaluatedItemsByName(s) - [ for f in fs -> mkAbsolute directory f.FinalItemSpec ] - - let projectReferences = - [ for i in project.GetEvaluatedItemsByName("ProjectReference") do - yield mkAbsolute directory i.FinalItemSpec - ] - - let references = - [ for i in project.GetEvaluatedItemsByName("ReferencePath") do - yield i.FinalItemSpec - for i in project.GetEvaluatedItemsByName("ChildProjectReferences") do - yield i.FinalItemSpec ] - // Duplicate slashes sometimes appear in the output here, which prevents - // them from matching keys used in FSharpProjectOptions.ReferencedProjects - |> List.map (fun (s: string) -> s.Replace("//","/")) - - outFileOpt, directory, getItems, references, projectReferences, getProp project, project.FullFileName - -#endif - - //---------------------------------------------------------------------------- - // FSharpProjectFileInfo - // - [] - type FSharpProjectFileInfo (fsprojFileName:string, ?properties, ?enableLogging) = - let properties = defaultArg properties [] - let enableLogging = defaultArg enableLogging false - - let logOpt = - if enableLogging then - let log = new BasicStringLogger() - do log.Verbosity <- Microsoft.Build.Framework.LoggerVerbosity.Diagnostic - Some log - else - None - - let outFileOpt, directory, getItems, references, projectReferences, getProp, fsprojFullPath = - try -#if NETCOREAPP - CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt - with -#else - if runningOnMono then - CrackProjectUsingOldBuildAPI fsprojFileName properties logOpt - else - CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt - with - | :? Microsoft.Build.BuildEngine.InvalidProjectFileException as e -> - raise (Microsoft.Build.Exceptions.InvalidProjectFileException( - e.ProjectFile, - e.LineNumber, - e.ColumnNumber, - e.EndLineNumber, - e.EndColumnNumber, - e.Message, - e.ErrorSubcategory, - e.ErrorCode, - e.HelpKeyword)) -#endif - | :? ArgumentException as e -> raise (IO.FileNotFoundException(e.Message)) - - let logOutput = match logOpt with None -> "" | Some l -> l.Log - let pages = getItems "Page" - let embeddedResources = getItems "EmbeddedResource" - let files = getItems "Compile" - let resources = getItems "Resource" - let noaction = getItems "None" - let content = getItems "Content" - - let split (s : string option) (cs : char []) = - match s with - | None -> [||] - | Some s -> - if String.IsNullOrWhiteSpace s then [||] - else s.Split(cs, StringSplitOptions.RemoveEmptyEntries) - - let getbool (s : string option) = - match s with - | None -> false - | Some s -> - match (Boolean.TryParse s) with - | (true, result) -> result - | (false, _) -> false - - let fxVer = getProp "TargetFrameworkVersion" - let optimize = getProp "Optimize" |> getbool - let assemblyNameOpt = getProp "AssemblyName" - let tailcalls = getProp "Tailcalls" |> getbool - let outputPathOpt = getProp "OutputPath" - let docFileOpt = getProp "DocumentationFile" - let outputTypeOpt = getProp "OutputType" - let debugTypeOpt = getProp "DebugType" - let baseAddressOpt = getProp "BaseAddress" - let sigFileOpt = getProp "GenerateSignatureFile" - let keyFileOpt = getProp "KeyFile" - let pdbFileOpt = getProp "PdbFile" - let platformOpt = getProp "Platform" - let targetTypeOpt = getProp "TargetType" - let versionFileOpt = getProp "VersionFile" - let targetProfileOpt = getProp "TargetProfile" - let warnLevelOpt = getProp "Warn" - let subsystemVersionOpt = getProp "SubsystemVersion" - let win32ResOpt = getProp "Win32ResourceFile" - let heOpt = getProp "HighEntropyVA" |> getbool - let win32ManifestOpt = getProp "Win32ManifestFile" - let debugSymbols = getProp "DebugSymbols" |> getbool - let prefer32bit = getProp "Prefer32Bit" |> getbool - let warnAsError = getProp "TreatWarningsAsErrors" |> getbool - let defines = split (getProp "DefineConstants") [| ';'; ','; ' ' |] - let nowarn = split (getProp "NoWarn") [| ';'; ','; ' ' |] - let warningsAsError = split (getProp "WarningsAsErrors") [| ';'; ','; ' ' |] - let libPaths = split (getProp "ReferencePath") [| ';'; ',' |] - let otherFlags = split (getProp "OtherFlags") [| ' ' |] - let isLib = (outputTypeOpt = Some "Library") - - let docFileOpt = - match docFileOpt with - | None -> None - | Some docFile -> Some(mkAbsolute directory docFile) - - - let options = - [ yield "--simpleresolution" - yield "--noframework" - match outFileOpt with - | None -> () - | Some outFile -> yield "--out:" + outFile - match docFileOpt with - | None -> () - | Some docFile -> yield "--doc:" + docFile - match baseAddressOpt with - | None -> () - | Some baseAddress -> yield "--baseaddress:" + baseAddress - match keyFileOpt with - | None -> () - | Some keyFile -> yield "--keyfile:" + keyFile - match sigFileOpt with - | None -> () - | Some sigFile -> yield "--sig:" + sigFile - match pdbFileOpt with - | None -> () - | Some pdbFile -> yield "--pdb:" + pdbFile - match versionFileOpt with - | None -> () - | Some versionFile -> yield "--versionfile:" + versionFile - match warnLevelOpt with - | None -> () - | Some warnLevel -> yield "--warn:" + warnLevel - match subsystemVersionOpt with - | None -> () - | Some s -> yield "--subsystemversion:" + s - if heOpt then yield "--highentropyva+" - match win32ResOpt with - | None -> () - | Some win32Res -> yield "--win32res:" + win32Res - match win32ManifestOpt with - | None -> () - | Some win32Manifest -> yield "--win32manifest:" + win32Manifest - match targetProfileOpt with - | None -> () - | Some targetProfile -> yield "--targetprofile:" + targetProfile - yield "--fullpaths" - yield "--flaterrors" - if warnAsError then yield "--warnaserror" - yield - if isLib then "--target:library" - else "--target:exe" - for symbol in defines do - if not (String.IsNullOrWhiteSpace symbol) then yield "--define:" + symbol - for nw in nowarn do - if not (String.IsNullOrWhiteSpace nw) then yield "--nowarn:" + nw - for nw in warningsAsError do - if not (String.IsNullOrWhiteSpace nw) then yield "--warnaserror:" + nw - yield if debugSymbols then "--debug+" - else "--debug-" - yield if optimize then "--optimize+" - else "--optimize-" - yield if tailcalls then "--tailcalls+" - else "--tailcalls-" - match debugTypeOpt with - | None -> () - | Some debugType -> - match debugType.ToUpperInvariant() with - | "NONE" -> () - | "PDBONLY" -> yield "--debug:pdbonly" - | "FULL" -> yield "--debug:full" - | _ -> () - match platformOpt |> Option.map (fun o -> o.ToUpperInvariant()), prefer32bit, - targetTypeOpt |> Option.map (fun o -> o.ToUpperInvariant()) with - | Some "ANYCPU", true, Some "EXE" | Some "ANYCPU", true, Some "WINEXE" -> yield "--platform:anycpu32bitpreferred" - | Some "ANYCPU", _, _ -> yield "--platform:anycpu" - | Some "X86", _, _ -> yield "--platform:x86" - | Some "X64", _, _ -> yield "--platform:x64" - | Some "ITANIUM", _, _ -> yield "--platform:Itanium" - | _ -> () - match targetTypeOpt |> Option.map (fun o -> o.ToUpperInvariant()) with - | Some "LIBRARY" -> yield "--target:library" - | Some "EXE" -> yield "--target:exe" - | Some "WINEXE" -> yield "--target:winexe" - | Some "MODULE" -> yield "--target:module" - | _ -> () - yield! otherFlags - for f in resources do - yield "--resource:" + f - for i in libPaths do - yield "--lib:" + mkAbsolute directory i - for r in references do - yield "-r:" + r - yield! files ] - - member x.Options = options - member x.FrameworkVersion = fxVer - member x.ProjectReferences = projectReferences - member x.References = references - member x.CompileFiles = files - member x.ResourceFiles = resources - member x.EmbeddedResourceFiles = embeddedResources - member x.ContentFiles = content - member x.OtherFiles = noaction - member x.PageFiles = pages - member x.OutputFile = outFileOpt - member x.Directory = directory - member x.AssemblyName = assemblyNameOpt - member x.OutputPath = outputPathOpt - member x.FullPath = fsprojFullPath - member x.LogOutput = logOutput - static member Parse(fsprojFileName:string, ?properties, ?enableLogging) = new FSharpProjectFileInfo(fsprojFileName, ?properties=properties, ?enableLogging=enableLogging) - - let getOptions file enableLogging properties = - let cache = new Dictionary<_,_>() - let rec getOptions file : Option * ProjectOptions = - match cache.TryGetValue file with - | true, option -> option - | _ -> - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=enableLogging) - - let referencedProjectOptions = - [| for file in parsedProject.ProjectReferences do - if Path.GetExtension(file) = ".fsproj" then - match getOptions file with - | Some outFile, opts -> yield outFile, opts - | None, _ -> () |] - - // Workaround for Mono 4.2, which doesn't populate the subproject - // details anymore outside of a solution context. See https://github.com/mono/mono/commit/76c6a08e730393927b6851709cdae1d397cbcc3a#diff-59afd196a55d61d5d1eaaef7bd49d1e5 - // and some explanation from the author at https://github.com/fsharp/FSharp.Compiler.Service/pull/455#issuecomment-154103963 - // - // In particular we want the output path, which we can get from - // fully parsing that project itself. We also have to specially parse - // C# referenced projects, as we don't look at them otherwise. - let referencedProjectOutputs = - if runningOnMono then - [ yield! Array.map (fun (s,_) -> "-r:" + s) referencedProjectOptions - for file in parsedProject.ProjectReferences do - let ext = Path.GetExtension(file) - if ext = ".csproj" || ext = ".vbproj" then - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=false) - match parsedProject.OutputFile with - | None -> () - | Some f -> yield "-r:" + f ] - else - [] - - // On some versions of Mono the referenced projects are already - // correctly included, so we make sure not to introduce duplicates - |> List.filter (fun r -> not (Set.contains r (set parsedProject.Options))) - - let options = { ProjectFile = file - Options = Array.ofSeq (parsedProject.Options @ referencedProjectOutputs) - ReferencedProjectOptions = referencedProjectOptions - LogOutput = parsedProject.LogOutput - Error = null } - - let result = parsedProject.OutputFile, options - cache.Add(file,result) - result - - snd (getOptions file) - - - let rec pairs l = - match l with - | [] | [_] -> [] - | x::y::rest -> (x,y) :: pairs rest - - let crackOpen (argv: string[])= - if argv.Length >= 2 then - let projectFile = argv.[0] - let enableLogging = match Boolean.TryParse(argv.[1]) with - | true, true -> true - | _ -> false - try - let props = pairs (List.ofArray argv.[2..]) - let opts = getOptions argv.[0] enableLogging props - 0, opts - with e -> - 2, { ProjectFile = projectFile; - Options = [||]; - ReferencedProjectOptions = [||]; - LogOutput = e.ToString() + " StackTrace: " + e.StackTrace - Error = e.Message + " StackTrace: " + e.StackTrace } - else - 1, { ProjectFile = ""; - Options = [||]; - ReferencedProjectOptions = [||]; - LogOutput = "At least two arguments required." - Error = null } diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 0c32c068af..072e2e0a58 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -11,9 +11,6 @@ true true - - $(DefineConstants);NO_PROJECTCRACKER - FsUnit.fs @@ -51,9 +48,6 @@ CSharpProjectAnalysis.fs - - ProjectOptionsTests.fs - StructureTests.fs @@ -100,6 +94,5 @@ - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.sln b/fcs/FSharp.Compiler.Service.sln index 192f8bd624..af0ed390cb 100644 --- a/fcs/FSharp.Compiler.Service.sln +++ b/fcs/FSharp.Compiler.Service.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.16 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29418.71 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{B6B68AE6-E7A4-4D43-9B34-FFA74BFE192B}" ProjectSection(SolutionItems) = preProject @@ -9,7 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{B6B6 build.sh = build.sh nuget\FSharp.Compiler.Service.MSBuild.v12.nuspec = nuget\FSharp.Compiler.Service.MSBuild.v12.nuspec nuget\FSharp.Compiler.Service.nuspec = nuget\FSharp.Compiler.Service.nuspec - nuget\FSharp.Compiler.Service.ProjectCracker.nuspec = nuget\FSharp.Compiler.Service.ProjectCracker.nuspec paket.dependencies = paket.dependencies README.md = README.md RELEASE_NOTES.md = RELEASE_NOTES.md @@ -41,23 +40,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0554567F EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E396742E-B4E5-4584-A9E4-CC1A491F5BC1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "EditorService", "samples\EditorService\EditorService.fsproj", "{A40507D6-FA48-43D3-B18A-AE3DAACE4020}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "EditorService", "samples\EditorService\EditorService.fsproj", "{A40507D6-FA48-43D3-B18A-AE3DAACE4020}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "InteractiveService", "samples\InteractiveService\InteractiveService.fsproj", "{067E95E5-E3DC-4CA7-813A-4D1E277D2D52}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "InteractiveService", "samples\InteractiveService\InteractiveService.fsproj", "{067E95E5-E3DC-4CA7-813A-4D1E277D2D52}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tokenizer", "samples\Tokenizer\Tokenizer.fsproj", "{92793069-816F-4F69-84AC-0966F8275E65}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Tokenizer", "samples\Tokenizer\Tokenizer.fsproj", "{92793069-816F-4F69-84AC-0966F8275E65}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "UntypedTree", "samples\UntypedTree\UntypedTree.fsproj", "{C816728D-BBEA-472D-9F6C-E8913957A673}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "UntypedTree", "samples\UntypedTree\UntypedTree.fsproj", "{C816728D-BBEA-472D-9F6C-E8913957A673}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FscExe", "samples\FscExe\FscExe.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FscExe", "samples\FscExe\FscExe.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharp_Analysis", "FSharp.Compiler.Service.Tests\CSharp_Analysis\CSharp_Analysis.csproj", "{887630A3-4B1D-40EA-B8B3-2D842E9C40DB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharp_Analysis", "FSharp.Compiler.Service.Tests\CSharp_Analysis\CSharp_Analysis.csproj", "{887630A3-4B1D-40EA-B8B3-2D842E9C40DB}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsiExe", "samples\FsiExe\FsiExe.fsproj", "{F9540CA8-1CE0-4546-A23A-A461E416E95B}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.ProjectCrackerTool", "FSharp.Compiler.Service.ProjectCrackerTool\FSharp.Compiler.Service.ProjectCrackerTool.fsproj", "{B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.ProjectCracker", "FSharp.Compiler.Service.ProjectCracker\FSharp.Compiler.Service.ProjectCracker.fsproj", "{893C3CD9-5AF8-4027-A667-21E62FC2C703}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsiExe", "samples\FsiExe\FsiExe.fsproj", "{F9540CA8-1CE0-4546-A23A-A461E416E95B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{098D1C35-D0FB-4720-83DD-8002293EA237}" ProjectSection(SolutionItems) = preProject @@ -71,14 +66,13 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "package", "package", "{9020E136-794A-473F-9B1B-9623C97B7161}" ProjectSection(SolutionItems) = preProject nuget\FSharp.Compiler.Service.template = nuget\FSharp.Compiler.Service.template - nuget\projectcracker.template = nuget\projectcracker.template EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.MSBuild.v12", "FSharp.Compiler.Service.MSBuild.v12\FSharp.Compiler.Service.MSBuild.v12.fsproj", "{8157B50E-397D-4232-A4E0-1977AFC7076D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service.MSBuild.v12", "FSharp.Compiler.Service.MSBuild.v12\FSharp.Compiler.Service.MSBuild.v12.fsproj", "{8157B50E-397D-4232-A4E0-1977AFC7076D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service", "FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service", "FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.Tests", "FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj", "{EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service.Tests", "FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj", "{EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -114,14 +108,6 @@ Global {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Release|Any CPU.Build.0 = Release|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Release|Any CPU.Build.0 = Release|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Debug|Any CPU.Build.0 = Debug|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Release|Any CPU.ActiveCfg = Release|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Release|Any CPU.Build.0 = Release|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/fcs/README.md b/fcs/README.md index 8a518f6219..54681c43e1 100644 --- a/fcs/README.md +++ b/fcs/README.md @@ -17,8 +17,6 @@ There are subtle differences between FSharp.Compiler.Service and FSharp.Compiler - FCS has a .NET Standard 2.0 version in the nuget package -- FCS testing also tests the "Project Cracker" (see below) - - FCS doesn't add the System.ValueTuple.dll reference by default, see ``#if COMPILER_SERVICE_AS_DLL`` in compiler codebase ## Version Numbers @@ -29,7 +27,6 @@ To update the version number a global replace through fcs\... is currently neede Directory.Build.props nuget/FSharp.Compiler.Service.nuspec nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec - nuget/FSharp.Compiler.Service.ProjectCracker.nuspec RELEASE_NOTES.md ## Building, Testing, Packaging, Releases @@ -64,7 +61,6 @@ You can push the packages if you have permissions, either automatically using `` set APIKEY=... ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.22.0.3.nupkg %APIKEY% -Source https://nuget.org ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.MSBuild.v12.22.0.3.nupkg %APIKEY% -Source https://nuget.org - ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.ProjectCracker.22.0.3.nupkg %APIKEY% -Source https://nuget.org ### Use of Paket and FAKE @@ -82,15 +78,13 @@ Testing reuses the test files from ..\tests\service which were are also FCS test Output is in ``docs``. In the ``FSharp.Compiler.Service`` repo this is checked in and hosted as . -## The two other NuGet packages +## Other NuGet packages It also contains both the source, build, packaging and test logic for - ``FSharp.Compiler.Service.MSBuild.v12`` adds legacy MSBuild v12 support to an instance of FSharp.Compiler.Service, if exact compatibility for scripting references such as ``#r "Foo, Version=1.3.4"`` is required. -- ``FSharp.Compiler.Service.ProjectCracker`` is part of ``FsAutoComplete`` and Ionide and is used to crack old-style project formats using MSBuild. It used to be part of the FCS API. - -Both of these components are gradually becoming obsolete +These components are gradually becoming obsolete ## Engineering road map diff --git a/fcs/docsrc/content/devnotes.md b/fcs/docsrc/content/devnotes.md index 7f80660f36..98684f9f35 100644 --- a/fcs/docsrc/content/devnotes.md +++ b/fcs/docsrc/content/devnotes.md @@ -54,4 +54,4 @@ Release checklist to publish a new version on nuget.org 1. Update `RELEASE_NOTES.md` 2. Check the version numbers are correct across the source (some files duplicate them) 3. Commit and add the necessary tag to the repo -4. Publish the nupkgs for `FSharp.Compiler.Service` and `FSharp.Compiler.Service.ProjectCracker` once they appear in AppVeyor artifacts +4. Publish the nupkgs for `FSharp.Compiler.Service` once it appears in AppVeyor artifacts diff --git a/fcs/docsrc/content/project.fsx b/fcs/docsrc/content/project.fsx index a537000435..7573b7f9ba 100644 --- a/fcs/docsrc/content/project.fsx +++ b/fcs/docsrc/content/project.fsx @@ -23,7 +23,6 @@ of `InteractiveChecker`: *) // Reference F# compiler API #r "FSharp.Compiler.Service.dll" -#r "FSharp.Compiler.Service.ProjectCracker.dll" open System open System.Collections.Generic @@ -306,61 +305,6 @@ correctly and then analyze each project in turn. *) -(** -Cracking a legacy project file ------------------------------ - -F# projects normally use the '.fsproj' project file format. -A project cracking facility for legacy old-style .fsproj is provided as a separate NuGet package: -FSharp.Compiler.Service.ProjectCracker. - -Project cracking for modern project files should be done using a library such as DotNetProjInfo. -See FsAutoComplete for example code. - -The legacy NuGet package `FSharp.Compiler.Service.ProjectCracker` contains a -library `FSharp.Compiler.Service.ProjectCracker.dll`, which should be -referenced by your application directly, and an executable -`FSharp.Compiler.Service.ProjectCrackerTool.exe`, which should be copied -into the output folder of your application by the build process. If -you install using Paket or NuGet, then this will be configured for you -automatically. If not, you should reference the provided `.targets` -file manually in your application. This can be found in the NuGet -package at `build/net461/FSharp.Compiler.Service.ProjectCrackerTool.targets`. - -The reason for this split was so the analysis of an F# project -file is performed out of process, in order that the necessary assembly -binding redirects can be applied without requiring the caller to -arrange this. In this way MSBuild versions from 4 up to 14 can be -accommodated transparently. - -In this example we get the project options for one of the -project files in the F# Compiler Service project itself - you should also be able to use this technique -for any project that builds cleanly using the command line tools 'xbuild' or 'msbuild'. - - -*) - -let projectFile = __SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj" - -ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - -(** - -You can also request RELEASE mode and set other build configuration parameters: - -*) - -ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Release")]) - -(** - -For debugging purposes it is also possible to obtain a detailed log from the assembly resolution process. - -*) - -let options, logs = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFile, [("Configuration", "Release")]) - (** Summary ------- diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index 284bc72e48..b039632af0 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -1,7 +1,6 @@  #if INTERACTIVE #r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.ProjectCracker.dll" #r "../../artifacts/bin/fcs/net461/nunit.framework.dll" #load "FsUnit.fs" #load "Common.fs" @@ -2956,315 +2955,4 @@ let ``Test expressions of optimized declarations stress big expressions`` () = printDeclarations None (List.ofSeq file1.Declarations) |> Seq.toList |> ignore -#if NOT_YET_ENABLED - -#if !NO_PROJECTCRACKER && !NETCOREAPP - -[] -let ``Check use of type provider that provides calls to F# code`` () = - let config = -#if DEBUG - ["Configuration", "Debug"] -#else - ["Configuration", "Release"] -#endif - let options = - ProjectCracker.GetProjectOptionsFromProjectFile (Path.Combine(Path.Combine(Path.Combine(__SOURCE_DIRECTORY__, "data"),"TestProject"),"TestProject.fsproj"), config) - - let res = - options - |> exprChecker.ParseAndCheckProject - |> Async.RunSynchronously - - Assert.AreEqual ([||], res.Errors, sprintf "Should not be errors, but: %A" res.Errors) - - let results = - [ for f in res.AssemblyContents.ImplementationFiles do - for d in f.Declarations do - for line in d |> printDeclaration None do - yield line ] - - results |> List.iter (printfn "%s") - - results |> shouldEqual - ["type TestProject"; "type AssemblyInfo"; "type TestProject"; "type T"; - """type Class1"""; - """member .ctor(unitVar0) = (new Object(); ()) @ (5,5--5,11)"""; - """member get_X1(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothing () @ (6,21--6,36)""" - """member get_X2(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGeneric (3) @ (7,21--7,43)""" - """member get_X3(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingOneArg (3) @ (8,21--8,42)""" - """member get_X4(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothing () @ (9,21--9,41)""" - """member get_X5(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingGeneric (3) @ (10,21--10,48)""" - """member get_X6(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingOneArg (3) @ (11,21--11,47)""" - """member get_X7(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingTwoArg (new C(),3) @ (12,21--12,47)""" - """member get_X8(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothing() @ (13,21--13,49)""" - """member get_X9(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingGeneric(3) @ (14,21--14,56)""" - """member get_X10(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingOneArg(3) @ (15,22--15,56)""" - """member get_X11(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingTwoArg(new C(),3) @ (16,22--16,56)""" - """member get_X12(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothing () @ (17,22--17,49)""" - """member get_X13(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothingOneArg (3) @ (18,22--18,55)""" - """member get_X14(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothingTwoArg (new C(),3) @ (19,22--19,55)""" - """member get_X15(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let matchValue: Microsoft.FSharp.Core.Option = FSharpOption`1.Some (1) in (if Operators.op_Equality (matchValue.Tag,1) then let x: Microsoft.FSharp.Core.int = matchValue.get_Value() in x else 0) @ (20,22--20,54)""" - """member get_X16(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let matchValue: Microsoft.FSharp.Core.Choice = Choice1Of2(1) in (if Operators.op_Equality (matchValue.Tag,0) then 1 else 0) @ (21,22--21,54)""" - """member get_X17(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let r: TestTP.Helper.R = {A = 1; B = 0} in (r.B <- 1; r.A) @ (22,22--22,60)""" - """member get_X18(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingTwoArg (3,4) @ (23,22--23,43)""" - """member get_X19(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingTwoArgCurried (3,4) @ (24,22--24,50)""" - """member get_X21(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (fun arg00 -> fun arg10 -> C.DoNothingTwoArgCurried (arg00,arg10) new C()) 3 @ (25,22--25,55)""" - """member get_X23(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (let objectArg: TestTP.Helper.C = new C() in fun arg00 -> fun arg10 -> objectArg.InstanceDoNothingTwoArgCurried(arg00,arg10) new C()) 3 @ (26,22--26,63)""" - """member get_X24(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithConstraint (3) @ (27,22--27,58)""" - """member get_X25(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithTypeConstraint,Microsoft.FSharp.Core.int> (FSharpList`1.Cons (3,FSharpList`1.get_Empty ())) @ (28,22--28,62)""" - """member get_X26(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithTypeConstraint,Microsoft.FSharp.Core.int> (FSharpList`1.Cons (3,FSharpList`1.get_Empty ())) @ (29,22--29,62)""" - """member get_X27(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.DoNothingReally () @ (30,22--30,53)""" - """member get_X28(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).Method("x") :> Microsoft.FSharp.Core.Unit @ (31,22--31,40)""" - """member get_X29(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Operators.op_Addition (new CSharpClass(0).Method2("x"),new CSharpClass(0).Method2("empty")) :> Microsoft.FSharp.Core.Unit @ (32,22--32,53)""" - """member get_X30(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).Method3([|"x"; "y"|]) :> Microsoft.FSharp.Core.Unit @ (33,22--33,50)""" - """member get_X31(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod(2) @ (34,22--34,47)""" - """member get_X32(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod2(new Object()) @ (35,22--35,61)""" - """member get_X33(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod3(3) @ (36,22--36,65)""" - """member get_X34(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingReally () @ (37,22--37,58)""" - """member get_X35(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().DoNothingReallyInst() @ (38,22--38,66)""" - """member get_X36(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (new CSharpClass(0) :> FSharp.Compiler.Service.Tests.ICSharpExplicitInterface).ExplicitMethod("x") :> Microsoft.FSharp.Core.Unit @ (39,22--39,62)""" - """member get_X37(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (new C() :> TestTP.Helper.I).DoNothing() @ (40,22--40,46)""" - """member get_X38(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().VirtualDoNothing() @ (41,22--41,45)""" - """member get_X39(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let t: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int = (1,2,3) in let i: Microsoft.FSharp.Core.int = t.Item1 in i @ (42,22--42,51)""" - """member get_X40(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (moduleValue <- 1; moduleValue) @ (43,22--43,39)""" - """member get_X41(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let x: TestTP.Helper.C = new C() in (x.set_Property(1); x.get_Property()) @ (44,22--44,41)""" - """member get_X42(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let x: TestTP.Helper.C = new C() in (x.set_AutoProperty(1); x.get_AutoProperty()) @ (45,22--45,45)""" - """member get_X43(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (C.set_StaticAutoProperty (1); C.get_StaticAutoProperty ()) @ (46,22--46,51)""" - ] - - let members = - [ for f in res.AssemblyContents.ImplementationFiles do yield! printMembersOfDeclatations f.Declarations ] - - members |> List.iter (printfn "%s") - - members |> shouldEqual - [ - ".ctor: Microsoft.FSharp.Core.unit -> TestProject.Class1" - ".ctor: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X1: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X2: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X3: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X4: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X5: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X6: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X7: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X8: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X9: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X10: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X11: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X12: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X13: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X14: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X15: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "Some: 'T -> 'T Microsoft.FSharp.Core.option" - "op_Equality<'T when 'T : equality>: 'T -> 'T -> Microsoft.FSharp.Core.bool" - "matchValue: Microsoft.FSharp.Core.Option" - "matchValue: Microsoft.FSharp.Core.Option" - "get_Value: Microsoft.FSharp.Core.unit -> 'T" - "x: Microsoft.FSharp.Core.int" - "get_X16: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "op_Equality<'T when 'T : equality>: 'T -> 'T -> Microsoft.FSharp.Core.bool" - "matchValue: Microsoft.FSharp.Core.Choice" - "get_X17: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "r: TestTP.Helper.R" - "r: TestTP.Helper.R" - "get_X18: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingTwoArg: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X19: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingTwoArgCurried: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X21: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArgCurried: TestTP.Helper.C -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "arg00: TestTP.Helper.C" - "arg10: Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X23: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "objectArg: TestTP.Helper.C" - "InstanceDoNothingTwoArgCurried: TestTP.Helper.C -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "arg00: TestTP.Helper.C" - "arg10: Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X24: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithConstraint<'T when 'T : equality>: 'T -> Microsoft.FSharp.Core.unit" - "get_X25: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithTypeConstraint<'T, _ when 'T :> Microsoft.FSharp.Collections.seq<'a>>: 'T -> Microsoft.FSharp.Core.unit" - "Cons: 'T * 'T Microsoft.FSharp.Collections.list -> 'T Microsoft.FSharp.Collections.list" - "get_Empty: Microsoft.FSharp.Core.unit -> 'T Microsoft.FSharp.Collections.list" - "get_X26: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithTypeConstraint<'T, _ when 'T :> Microsoft.FSharp.Collections.seq<'a>>: 'T -> Microsoft.FSharp.Core.unit" - "Cons: 'T * 'T Microsoft.FSharp.Collections.list -> 'T Microsoft.FSharp.Collections.list" - "get_Empty: Microsoft.FSharp.Core.unit -> 'T Microsoft.FSharp.Collections.list" - "get_X27: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingReally: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X28: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X29: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "op_Addition<^T1, ^T2, ^T3>: ^T1 -> ^T2 -> ^T3" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method2: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method2: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X30: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method3: Microsoft.FSharp.Core.string Microsoft.FSharp.Core.[] -> Microsoft.FSharp.Core.int" - "get_X31: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X32: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod2<'T when 'T : class>: 'T -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X33: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod3<'T when 'T :> System.IComparable<'T>>: 'T -> Microsoft.FSharp.Core.unit" - "get_X34: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingReally: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X35: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "DoNothingReallyInst: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X36: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "ExplicitMethod: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X37: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X38: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "VirtualDoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X39: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "t: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int" - "i: Microsoft.FSharp.Core.int" - "get_X40: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "moduleValue: Microsoft.FSharp.Core.int" - "moduleValue: Microsoft.FSharp.Core.int" - "get_X41: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "x: TestTP.Helper.C" - "set_Property: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "x: TestTP.Helper.C" - "get_Property: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "get_X42: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "x: TestTP.Helper.C" - "set_AutoProperty: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "x: TestTP.Helper.C" - "get_AutoProperty: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "get_X43: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "set_StaticAutoProperty: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_StaticAutoProperty: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ] - -#endif -#endif - - -#if SELF_HOST_STRESS - - -[] -let ``Test Declarations selfhost`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - // Check with Configuration = Release - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - wholeProjectResults.Errors.Length |> shouldEqual 0 - - wholeProjectResults.AssemblyContents.ImplementationFiles.Length |> shouldEqual 13 - - let textOfAll = [ for file in wholeProjectResults.AssemblyContents.ImplementationFiles -> Array.ofSeq (printDeclarations None (List.ofSeq file.Declarations)) ] - - () - - -[] -let ``Test Declarations selfhost whole compiler`` () = - - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service") - let projectFile = __SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj" - - //let v = FSharpProjectFileInfo.Parse(projectFile, [("Configuration", "Debug"); ("NoFsSrGenTask", "true")],enableLogging=true) - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug"); ("NoFsSrGenTask", "true")]) - - // For subsets of the compiler: - //let options = { options with OtherOptions = options.OtherOptions.[0..51] } - - //for x in options.OtherOptions do printfn "%s" x - - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - (wholeProjectResults.Errors |> Array.filter (fun x -> x.Severity = FSharpErrorSeverity.Error)).Length |> shouldEqual 0 - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in printDeclaration None d do - () //printfn "%s" s - - // Very Quick (1 sec - expressions are computed on demand) - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in exprsOfDecl d do - () - - // Quickish (~4.5 seconds for all of FSharp.Compiler.Service.dll) - #time "on" - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for (e,m) in exprsOfDecl d do - // This forces the computation of the expression - match e with - | BasicPatterns.Const _ -> () //printfn "%s" s - | _ -> () //printfn "%s" s - -[] -let ``Test Declarations selfhost FSharp.Core`` () = - - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../../../fsharp/src/fsharp/FSharp.Core") - let projectFile = __SOURCE_DIRECTORY__ + @"/../../../fsharp/src/fsharp/FSharp.Core/FSharp.Core.fsproj" - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) - - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - //(wholeProjectResults.Errors |> Array.filter (fun x -> x.Severity = FSharpErrorSeverity.Error)).Length |> shouldEqual 0 - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in printDeclaration (Some (HashSet [])) d do - printfn "%s" s - - #time "on" - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for (e,m) in exprsOfDecl d do - // This forces the computation of the expression - match e with - | BasicPatterns.Const _ -> () - | _ -> () - -#endif diff --git a/tests/service/MultiProjectAnalysisTests.fs b/tests/service/MultiProjectAnalysisTests.fs index a4ba694cfa..ac5df3f1c7 100644 --- a/tests/service/MultiProjectAnalysisTests.fs +++ b/tests/service/MultiProjectAnalysisTests.fs @@ -823,7 +823,6 @@ let ``Test max memory gets triggered`` () = [] #endif let ``Type provider project references should not throw exceptions`` () = - //let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) let options = {ProjectFileName = __SOURCE_DIRECTORY__ + @"/data/TypeProviderConsole/TypeProviderConsole.fsproj"; ProjectId = None @@ -915,7 +914,6 @@ let ``Type provider project references should not throw exceptions`` () = [] #endif let ``Projects creating generated types should not utilize cross-project-references but should still analyze oK once project is built`` () = - //let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) let options = {ProjectFileName = __SOURCE_DIRECTORY__ + @"/data/TypeProvidersBug/TestConsole/TestConsole.fsproj"; diff --git a/tests/service/ProjectOptionsTests.fs b/tests/service/ProjectOptionsTests.fs deleted file mode 100644 index ed30de97dc..0000000000 --- a/tests/service/ProjectOptionsTests.fs +++ /dev/null @@ -1,578 +0,0 @@ -#if INTERACTIVE -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.ProjectCracker.dll" -#r "../../artifacts/bin/fcs/net461/nunit.framework.dll" -#load "FsUnit.fs" -#load "Common.fs" -#else -module FSharp.Compiler.Service.Tests.ProjectOptionsTests -#endif - -let runningOnMono = try System.Type.GetType("Mono.Runtime") <> null with e -> false - -open System.IO -open NUnit.Framework -open FsUnit -open FSharp.Compiler.Ast -open FSharp.Compiler.SourceCodeServices - -open FSharp.Compiler.Service.Tests.Common - -#if !NO_PROJECTCRACKER && DISABLED // Disabled tests because of MSBuild API dependencies. The ProjectCracker is basically deprecated in any case - -let hasMSBuild14 = - use engine = new Microsoft.Build.Evaluation.ProjectCollection() - engine.Toolsets |> Seq.exists (fun x -> x.ToolsPath.Contains "v14.0") - -let normalizePath s = (new Uri(s)).LocalPath - -let checkOption (opts:string[]) s = - let found = "Found '"+s+"'" - (if opts |> Array.exists (fun o -> o.EndsWith(s)) then found else "Failed to find '"+s+"'") - |> shouldEqual found - -let checkOptionNotPresent (opts:string[]) s = - let found = "Found '"+s+"'" - let notFound = "Did not expect to find '"+s+"'" - (if opts |> Array.exists (fun o -> o.EndsWith(s)) then found else notFound) - |> shouldEqual notFound - -let getReferencedFilenames = Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> (Path.GetFileName >> Some) else None) -let getReferencedFilenamesAndContainingFolders = Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> (fun r -> ((r |> Path.GetFileName), (r |> Path.GetDirectoryName |> Path.GetFileName)) |> Some) else None) -let getOutputFile = Array.pick (fun (o:string) -> if o.StartsWith("--out:") then o.[6..] |> Some else None) - -let getCompiledFilenames = - Array.choose (fun (opt: string) -> - if opt.EndsWith ".fs" then - opt |> Path.GetFileName |> Some - else None) - >> Array.distinct - -(* -[] - let ``Project file parsing example 1 Default Configuration`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOption options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--flaterrors" - checkOption options.OtherOptions "--simpleresolution" - checkOption options.OtherOptions "--noframework" - -[] -let ``Project file parsing example 1 Release Configuration`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - // Check with Configuration = Release - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Release")]) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOptionNotPresent options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--debug:pdbonly" - -[] -let ``Project file parsing example 1 Default configuration relative path`` () = - let projectFile = "FSharp.Compiler.Service.Tests.fsproj" - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__) - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOption options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--flaterrors" - checkOption options.OtherOptions "--simpleresolution" - checkOption options.OtherOptions "--noframework" -*) - -[] -let ``Project file parsing VS2013_FSharp_Portable_Library_net45``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj" - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, []) - - checkOption options.OtherOptions "--targetprofile:netcore" - checkOption options.OtherOptions "--tailcalls-" - - checkOption options.OtherOptions "FSharp.Core.dll" - checkOption options.OtherOptions "Microsoft.CSharp.dll" - checkOption options.OtherOptions "System.Runtime.dll" - checkOption options.OtherOptions "System.Net.Requests.dll" - checkOption options.OtherOptions "System.Xml.XmlSerializer.dll" - -[] -let ``Project file parsing Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj" - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/") - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, []) - - checkOption options.OtherOptions "--targetprofile:netcore" - checkOption options.OtherOptions "--tailcalls-" - - checkOption options.OtherOptions "FSharp.Core.dll" - checkOption options.OtherOptions "Microsoft.CSharp.dll" - checkOption options.OtherOptions "System.Runtime.dll" - checkOption options.OtherOptions "System.Net.Requests.dll" - checkOption options.OtherOptions "System.Xml.XmlSerializer.dll" - -[] -let ``Project file parsing -- compile files 1``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - CollectionAssert.AreEqual (["Test1File2.fs"; "Test1File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- compile files 2``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - - CollectionAssert.AreEqual (["Test2File2.fs"; "Test2File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- bad project file``() = - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Malformed.fsproj") - try - ProjectCracker.GetProjectOptionsFromProjectFileLogged(f) |> ignore - failwith "Expected exception" - with e -> - Assert.That(e.Message, Contains.Substring "Could not load project") - Assert.That(e.Message, Contains.Substring "Malformed.fsproj") - -[] -let ``Project file parsing -- non-existent project file``() = - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/DoesNotExist.fsproj") - try - ProjectCracker.GetProjectOptionsFromProjectFileLogged(f, enableLogging=true) |> ignore - with e -> - Assert.That(e.Message, Contains.Substring "DoesNotExist.fsproj") - -[] -let ``Project file parsing -- output file``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - - let expectedOutputPath = - normalizePath (__SOURCE_DIRECTORY__ + "/data/bin/Debug/Test1.dll") - - p.OtherOptions - |> getOutputFile - |> should equal expectedOutputPath - -[] -let ``Project file parsing -- references``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - printfn "Project file parsing -- references: references = %A" references - references |> should haveLength 4 - p.ReferencedProjects |> should be Empty - -[] -let ``Project file parsing -- no project references``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test3.fsproj") - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - p.ReferencedProjects |> should haveLength 0 - -[] -let ``Project file parsing -- 2nd level references``() = - let p,_ = ProjectCracker.GetProjectOptionsFromProjectFileLogged(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj", enableLogging=true) - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - checkOption references "Test1.dll" - printfn "Project file parsing -- references: references = %A" references - references |> should haveLength 5 - p.ReferencedProjects |> should haveLength 1 - (snd p.ReferencedProjects.[0]).ProjectFileName |> should contain (normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj")) - - -[] -let ``Project file parsing -- reference project output file``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/DifferingOutputDir/Dir2/Test2.fsproj") - - let expectedOutputPath = - normalizePath (__SOURCE_DIRECTORY__ + "/data/DifferingOutputDir/Dir2/OutputDir2/Test2.exe") - - p.OtherOptions - |> getOutputFile - |> should equal expectedOutputPath - - p.OtherOptions - |> Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> Some else None) - |> should contain (normalizePath (__SOURCE_DIRECTORY__ + @"/data/DifferingOutputDir/Dir1/OutputDir1/Test1.dll")) - -[] -let ``Project file parsing -- Tools Version 12``() = - if not hasMSBuild14 then () else - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - checkOption (getReferencedFilenames opts.OtherOptions) "System.Core.dll" - -[] -let ``Project file parsing -- Logging``() = - if not hasMSBuild14 then () else - let projectFileName = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - let _, logMap = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFileName, enableLogging=true) - let log = logMap.[projectFileName] - - Assert.That(log, Does.Contain("ResolveAssemblyReference")) - if runningOnMono then - Assert.That(log, Does.Contain("System.Core")) - Assert.That(log, Does.Contain("Microsoft.Build.Tasks.ResolveAssemblyReference")) - else - Assert.That(log, Does.Contain("Microsoft.Build.Tasks.Core")) - -[] -let ``Project file parsing -- FSharpProjectOptions.SourceFiles contains both fs and fsi files``() = - let projectFileName = normalizePath (__SOURCE_DIRECTORY__ + @"/data/FsAndFsiFiles.fsproj") - let options, log = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFileName, enableLogging=true) - printfn "%A" log - let expectedSourceFiles = - [| "Test1File2.fsi" - "Test1File2.fs" - "Test1File1.fs" - "Test1File0.fsi" - "Test1File0.fs" |] - Assert.That(options.SourceFiles |> Array.map Path.GetFileName, Is.EqualTo expectedSourceFiles, "source files") - -[] -let ``Project file parsing -- Full path``() = - if not hasMSBuild14 then () else - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - let p = ProjectCracker.GetProjectOptionsFromProjectFile(f) - p.ProjectFileName |> should equal f - -[] -let ``Project file parsing -- project references``() = - let f1 = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - let f2 = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f2) - - options.ReferencedProjects |> should haveLength 1 - fst options.ReferencedProjects.[0] |> should endWith "Test1.dll" - snd options.ReferencedProjects.[0] |> should equal (ProjectCracker.GetProjectOptionsFromProjectFile(f1)) - -[] -let ``Project file parsing -- multi language project``() = - if not hasMSBuild14 then () else - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/MultiLanguageProject/ConsoleApplication1.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - - options.ReferencedProjects |> should haveLength 1 - options.ReferencedProjects.[0] |> fst |> should endWith "ConsoleApplication2.exe" - - checkOption options.OtherOptions "ConsoleApplication2.exe" - checkOption options.OtherOptions "ConsoleApplication3.exe" - -[] -let ``Project file parsing -- PCL profile7 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "Microsoft.VisualBasic.dll"; - "System.Collections.Concurrent.dll"; "System.Collections.dll"; - "System.ComponentModel.Annotations.dll"; - "System.ComponentModel.DataAnnotations.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Diagnostics.Tracing.dll"; "System.Dynamic.Runtime.dll"; - "System.Globalization.dll"; "System.IO.Compression.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Parallel.dll"; - "System.Linq.Queryable.dll"; "System.Linq.dll"; "System.Net.Http.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.Numerics.dll"; - "System.ObjectModel.dll"; "System.Reflection.Context.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.InteropServices.dll"; "System.Runtime.Numerics.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Duplex.dll"; "System.ServiceModel.Http.dll"; - "System.ServiceModel.NetTcp.dll"; "System.ServiceModel.Primitives.dll"; - "System.ServiceModel.Security.dll"; "System.ServiceModel.Web.dll"; - "System.ServiceModel.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.Parallel.dll"; "System.Threading.Tasks.dll"; - "System.Threading.dll"; "System.Windows.dll"; "System.Xml.Linq.dll"; - "System.Xml.ReaderWriter.dll"; "System.Xml.Serialization.dll"; - "System.Xml.XDocument.dll"; "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; - "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -[] -let ``Project file parsing -- PCL profile78 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "System.Collections.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Dynamic.Runtime.dll"; "System.Globalization.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Queryable.dll"; "System.Linq.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.ObjectModel.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Http.dll"; "System.ServiceModel.Primitives.dll"; - "System.ServiceModel.Security.dll"; "System.ServiceModel.Web.dll"; - "System.ServiceModel.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.dll"; "System.Threading.dll"; "System.Windows.dll"; - "System.Xml.Linq.dll"; "System.Xml.ReaderWriter.dll"; - "System.Xml.Serialization.dll"; "System.Xml.XDocument.dll"; - "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -[] -let ``Project file parsing -- PCL profile259 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile259/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "System.Collections.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Dynamic.Runtime.dll"; "System.Globalization.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Queryable.dll"; "System.Linq.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.ObjectModel.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Web.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.dll"; "System.Threading.dll"; "System.Windows.dll"; - "System.Xml.Linq.dll"; "System.Xml.ReaderWriter.dll"; - "System.Xml.Serialization.dll"; "System.Xml.XDocument.dll"; - "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -(* -[] -let ``Project file parsing -- Exe with a PCL reference``() = - - let f = normalizePath(__SOURCE_DIRECTORY__ + @"/data/sqlite-net-spike/sqlite-net-spike.fsproj") - - let p = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = getReferencedFilenames p.OtherOptions |> set - references |> should contain "FSharp.Core.dll" - references |> should contain "SQLite.Net.Platform.Generic.dll" - references |> should contain "SQLite.Net.Platform.Win32.dll" - references |> should contain "SQLite.Net.dll" - references |> should contain "System.Collections.Concurrent.dll" - references |> should contain "System.Linq.Queryable.dll" - references |> should contain "System.Resources.ResourceManager.dll" - references |> should contain "System.Threading.dll" - references |> should contain "System.dll" - references |> should contain "mscorlib.dll" - references |> should contain "System.Reflection.dll" - references |> should contain "System.Reflection.Emit.Lightweight.dll" -*) - -[] -let ``Project file parsing -- project file contains project reference to out-of-solution project and is used in release mode``() = - let projectFileName = normalizePath(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(projectFileName,[("Configuration","Release")]) - let references = getReferencedFilenamesAndContainingFolders opts.OtherOptions |> set - // Check the reference is to a release DLL - references |> should contain ("Test1.dll", "Release") - -[] -let ``Project file parsing -- project file contains project reference to out-of-solution project and is used in debug mode``() = - - let projectFileName = normalizePath(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(projectFileName,[("Configuration","Debug")]) - let references = getReferencedFilenamesAndContainingFolders opts.OtherOptions |> set - // Check the reference is to a debug DLL - references |> should contain ("Test1.dll", "Debug") - -[] -let ``Project file parsing -- space in file name``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Space in name.fsproj") - CollectionAssert.AreEqual (["Test2File2.fs"; "Test2File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- report files``() = - let programFilesx86Folder = System.Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") - if not runningOnMono then - - let dirRefs = programFilesx86Folder + @"\Reference Assemblies\Microsoft\FSharp\" - printfn "Enumerating %s" dirRefs - if Directory.Exists(dirRefs) then - for f in Directory.EnumerateFiles(dirRefs,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - - let dir40 = programFilesx86Folder + @"\Microsoft SDKs\F#\4.0\" - printfn "Enumerating %s" dir40 - if Directory.Exists(dir40) then - for f in Directory.EnumerateFiles(dir40,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - - let dir41 = programFilesx86Folder + @"\Microsoft SDKs\F#\4.1\" - printfn "Enumerating %s" dir41 - if Directory.Exists(dir41) then - for f in Directory.EnumerateFiles(dir41,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - -[] -let ``Test OtherOptions order for GetProjectOptionsFromScript`` () = - let test scriptName expected2 = - let scriptPath = __SOURCE_DIRECTORY__ + @"/data/ScriptProject/" + scriptName + ".fsx" - let scriptSource = File.ReadAllText scriptPath - let projOpts, _diagnostics = checker.GetProjectOptionsFromScript(scriptPath, scriptSource) |> Async.RunSynchronously - projOpts.OtherOptions - |> Array.map (fun s -> if s.StartsWith "--" then s else Path.GetFileNameWithoutExtension s) - |> Array.forall (fun s -> Set.contains s expected2) - |> shouldEqual true - - let otherArgs = [|"--noframework"; "--warn:3"; "System.Numerics"; "System.ValueTuple"; "mscorlib"; "FSharp.Core"; "System"; "System.Xml"; "System.Runtime.Remoting"; "System.Runtime.Serialization.Formatters.Soap"; "System.Data"; "System.Drawing"; "System.Core"; "System.Runtime"; "System.Linq"; "System.Reflection"; "System.Linq.Expressions"; "System.Threading.Tasks"; "System.IO"; "System.Net.Requests"; "System.Collections"; "System.Runtime.Numerics"; "System.Threading"; "System.Web"; "System.Web.Services"; "System.Windows.Forms"; "FSharp.Compiler.Interactive.Settings"|] |> Set.ofArray - - test "Main1" otherArgs - test "Main2" otherArgs - test "Main3" otherArgs - test "Main4" otherArgs - test "MainBad" otherArgs - - -#endif - -[] -let ``Test SourceFiles order for GetProjectOptionsFromScript`` () = // See #594 - let test scriptName expected = - let scriptPath = __SOURCE_DIRECTORY__ + @"/data/ScriptProject/" + scriptName + ".fsx" - let scriptSource = File.ReadAllText scriptPath - let projOpts, _diagnostics = - checker.GetProjectOptionsFromScript(scriptPath, FSharp.Compiler.Text.SourceText.ofString scriptSource) - |> Async.RunSynchronously - projOpts.SourceFiles - |> Array.map Path.GetFileNameWithoutExtension - |> shouldEqual expected - test "Main1" [|"BaseLib1"; "Lib1"; "Lib2"; "Main1"|] - test "Main2" [|"BaseLib1"; "Lib1"; "Lib2"; "Lib3"; "Main2"|] - test "Main3" [|"Lib3"; "Lib4"; "Main3"|] - test "Main4" [|"BaseLib2"; "Lib5"; "BaseLib1"; "Lib1"; "Lib2"; "Main4"|] - test "MainBad" [|"MainBad"|] - -[] -#if NETCOREAPP -[] -#endif -let ``Script load closure project`` () = - let fileName1 = Path.GetTempPath() + Path.DirectorySeparatorChar.ToString() + "Impl.fs" - let fileName2 = Path.ChangeExtension(Path.GetTempFileName(), ".fsx") - - let fileSource1Text = """ -module ImplFile - -#if INTERACTIVE -let x = 42 -#endif -""" - let fileSource1 = FSharp.Compiler.Text.SourceText.ofString fileSource1Text - let fileSource2Text = """ -#load "Impl.fs" -ImplFile.x -""" - let fileSource2 = FSharp.Compiler.Text.SourceText.ofString fileSource2Text - File.WriteAllText(fileName1, fileSource1Text) - File.WriteAllText(fileName2, fileSource2Text) - - printfn "------Starting Script load closure project----" - printfn "Getting project options..." - let projectOptions, diagnostics = - checker.GetProjectOptionsFromScript(fileName2, fileSource2, useFsiAuxLib=false) |> Async.RunSynchronously - for d in diagnostics do - printfn "ERROR: %A" d - diagnostics.IsEmpty |> shouldEqual true - - printfn "Parse and check..." - let _, checkResults = - checker.ParseAndCheckFileInProject(fileName2, 0, fileSource2, projectOptions) |> Async.RunSynchronously - - match checkResults with - | FSharpCheckFileAnswer.Succeeded results -> - results.Errors |> shouldEqual [| |] - | _ -> failwith "type check was aborted" - - printfn "Getting parsing options..." - let parsingOptions, diagnostics = checker.GetParsingOptionsFromProjectOptions(projectOptions) - for d in diagnostics do - printfn "ERROR: %A" d - diagnostics.IsEmpty |> shouldEqual true - - printfn "Parsing file..." - let parseResults = checker.ParseFile(fileName1, fileSource1, parsingOptions) |> Async.RunSynchronously - printfn "Checking parsetree..." - parseResults.ParseTree.IsSome |> shouldEqual true - printfn "Checking decls..." - match parseResults.ParseTree.Value with - | ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, modules, _)) -> - let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = modules.Head - decls.Length |> shouldEqual 1 - | _ -> failwith "got sig file" - printfn "------Finished Script load closure project----" diff --git a/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj b/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj index 1b2f4b81dd..256f7a6894 100644 --- a/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj +++ b/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj @@ -11,7 +11,6 @@ - diff --git a/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs b/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs deleted file mode 100644 index 787527bbe9..0000000000 --- a/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs +++ /dev/null @@ -1,2 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 9598b23b5c..3692a280de 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -7,7 +7,6 @@ x86 Library $(NoWarn);44;58;75;3005 - NO_PROJECTCRACKER;$(DefineConstants) true true $(SystemValueTupleVersion) @@ -92,9 +91,6 @@ CompilerService\CSharpProjectAnalysis.fs - - CompilerService\ProjectOptionsTests.fs - CompilerService\StructureTests.fs From b328e208c9d1b7fede214df8bde208a5a2da1138 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 17:38:07 +0100 Subject: [PATCH 043/101] cleanup begin / end (#8290) --- src/fsharp/IlxGen.fs | 50 +++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index c39fad857f..6b0228ea02 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -2786,32 +2786,30 @@ and GenNewArray cenv cgbuf eenv (elems: Expr list, elemTy, m) sequel = GenNewArraySimple cenv cgbuf eenv (elems, elemTy, m) sequel and GenCoerce cenv cgbuf eenv (e, tgty, m, srcty) sequel = - let g = cenv.g - // Is this an upcast? - if TypeRelations.TypeDefinitelySubsumesTypeNoCoercion 0 g cenv.amap m tgty srcty && - // Do an extra check - should not be needed - TypeRelations.TypeFeasiblySubsumesType 0 g cenv.amap m tgty TypeRelations.NoCoerce srcty then - begin - if (isInterfaceTy g tgty) then ( - GenExpr cenv cgbuf eenv SPSuppress e Continue - let ilToTy = GenType cenv.amap m eenv.tyenv tgty - // Section "III.1.8.1.3 Merging stack states" of ECMA-335 implies that no unboxing - // is required, but we still push the coerced type on to the code gen buffer. - CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [] - GenSequel cenv eenv.cloc cgbuf sequel - ) else ( - GenExpr cenv cgbuf eenv SPSuppress e sequel - ) - end - else - GenExpr cenv cgbuf eenv SPSuppress e Continue - if not (isObjTy g srcty) then - let ilFromTy = GenType cenv.amap m eenv.tyenv srcty - CG.EmitInstrs cgbuf (pop 1) (Push [g.ilg.typ_Object]) [ I_box ilFromTy ] - if not (isObjTy g tgty) then - let ilToTy = GenType cenv.amap m eenv.tyenv tgty - CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [ I_unbox_any ilToTy ] - GenSequel cenv eenv.cloc cgbuf sequel + let g = cenv.g + // Is this an upcast? + if TypeRelations.TypeDefinitelySubsumesTypeNoCoercion 0 g cenv.amap m tgty srcty && + // Do an extra check - should not be needed + TypeRelations.TypeFeasiblySubsumesType 0 g cenv.amap m tgty TypeRelations.NoCoerce srcty + then + if isInterfaceTy g tgty then + GenExpr cenv cgbuf eenv SPSuppress e Continue + let ilToTy = GenType cenv.amap m eenv.tyenv tgty + // Section "III.1.8.1.3 Merging stack states" of ECMA-335 implies that no unboxing + // is required, but we still push the coerced type on to the code gen buffer. + CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [] + GenSequel cenv eenv.cloc cgbuf sequel + else + GenExpr cenv cgbuf eenv SPSuppress e sequel + else + GenExpr cenv cgbuf eenv SPSuppress e Continue + if not (isObjTy g srcty) then + let ilFromTy = GenType cenv.amap m eenv.tyenv srcty + CG.EmitInstrs cgbuf (pop 1) (Push [g.ilg.typ_Object]) [ I_box ilFromTy ] + if not (isObjTy g tgty) then + let ilToTy = GenType cenv.amap m eenv.tyenv tgty + CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [ I_unbox_any ilToTy ] + GenSequel cenv eenv.cloc cgbuf sequel and GenReraise cenv cgbuf eenv (rtnty, m) sequel = let ilReturnTy = GenType cenv.amap m eenv.tyenv rtnty From 06e0ed450a6ed8ba91b13dd9bcaf7ca119fa09d1 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 17:41:27 +0100 Subject: [PATCH 044/101] Calculate final only when needed (#8284) --- src/fsharp/AugmentWithHashCompare.fs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index ce562dedaa..03ea427a06 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -883,11 +883,15 @@ let nonVirtualMethod c : ValMemberInfo = let unitArg = ValReprInfo.unitArgData let unaryArg = [ ValReprInfo.unnamedTopArg ] let tupArg = [ [ ValReprInfo.unnamedTopArg1; ValReprInfo.unnamedTopArg1 ] ] -let mkValSpec g (tcref: TyconRef) tmty vis slotsig methn ty argData = +let mkValSpec g (tcref: TyconRef) tmty vis slotsig methn ty argData = let m = tcref.Range let tps = tcref.Typars m - let final = isUnionTy g tmty || isRecdTy g tmty || isStructTy g tmty - let membInfo = match slotsig with None -> nonVirtualMethod tcref | Some slotsig -> slotImplMethod(final, tcref, slotsig) + let membInfo = + match slotsig with + | None -> nonVirtualMethod tcref + | Some slotsig -> + let final = isUnionTy g tmty || isRecdTy g tmty || isStructTy g tmty + slotImplMethod(final, tcref, slotsig) let inl = ValInline.Optional let args = ValReprInfo.unnamedTopArg :: argData let topValInfo = Some (ValReprInfo (ValReprInfo.InferTyparInfo tps, args, ValReprInfo.unnamedRetVal)) @@ -899,8 +903,8 @@ let MakeValsForCompareAugmentation g (tcref: TyconRef) = let tps = tcref.Typars m let vis = tcref.TypeReprAccessibility - mkValSpec g tcref tmty vis (Some(mkIComparableCompareToSlotSig g)) "CompareTo" (tps +-> (mkCompareObjTy g tmty)) unaryArg, - mkValSpec g tcref tmty vis (Some(mkGenericIComparableCompareToSlotSig g tmty)) "CompareTo" (tps +-> (mkCompareTy g tmty)) unaryArg + mkValSpec g tcref tmty vis (Some(mkIComparableCompareToSlotSig g)) "CompareTo" (tps +-> (mkCompareObjTy g tmty)) unaryArg, + mkValSpec g tcref tmty vis (Some(mkGenericIComparableCompareToSlotSig g tmty)) "CompareTo" (tps +-> (mkCompareTy g tmty)) unaryArg let MakeValsForCompareWithComparerAugmentation g (tcref: TyconRef) = let m = tcref.Range @@ -915,15 +919,15 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) = let vis = tcref.TypeReprAccessibility let tps = tcref.Typars m - let objEqualsVal = mkValSpec g tcref tmty vis (Some(mkEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsObjTy g tmty)) unaryArg - let nocEqualsVal = mkValSpec g tcref tmty vis (if tcref.Deref.IsExceptionDecl then None else Some(mkGenericIEquatableEqualsSlotSig g tmty)) "Equals" (tps +-> (mkEqualsTy g tmty)) unaryArg + let objEqualsVal = mkValSpec g tcref tmty vis (Some(mkEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsObjTy g tmty)) unaryArg + let nocEqualsVal = mkValSpec g tcref tmty vis (if tcref.Deref.IsExceptionDecl then None else Some(mkGenericIEquatableEqualsSlotSig g tmty)) "Equals" (tps +-> (mkEqualsTy g tmty)) unaryArg objEqualsVal, nocEqualsVal let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) = let _, tmty = mkMinimalTy g tcref let vis = tcref.TypeReprAccessibility let tps = tcref.Typars tcref.Range - let objGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g tmty)) unitArg + let objGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g tmty)) unitArg let withcGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkIStructuralEquatableGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashWithComparerTy g tmty)) unaryArg let withcEqualsVal = mkValSpec g tcref tmty vis (Some(mkIStructuralEquatableEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsWithComparerTy g tmty)) tupArg objGetHashCodeVal, withcGetHashCodeVal, withcEqualsVal From 6b189042e9402ea604b4a3910926b00ab07cc1ff Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 18:10:36 +0100 Subject: [PATCH 045/101] tryDestAppTy instead of isAppTy (#8285) --- src/fsharp/NameResolution.fs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 10e330f207..a63c8e6e13 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -536,11 +536,11 @@ let ExtensionPropInfosOfTypeInScope collectionSettings (infoReader:InfoReader) ( let extMemsFromHierarchy = infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref SelectPropInfosFromExtMembers infoReader ad optFilter ty m extMemInfos - else []) + | _ -> []) extMemsDangling @ extMemsFromHierarchy @@ -606,11 +606,11 @@ let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSetting infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> let g = infoReader.g - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> let extValRefs = nenv.eIndexedExtensionMembers.Find tcref SelectMethInfosFromExtMembers infoReader optFilter ty m extValRefs - else []) + | _ -> []) extMemsDangling @ extMemsFromHierarchy /// Get all the available methods of a type (both intrinsic and extension) @@ -2352,10 +2352,11 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf match lookupKind with | LookupKind.Expr | LookupKind.Pattern -> - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> for uc in tcref.UnionCasesArray do addToBuffer uc.DisplayName + | _ -> () | _ -> () raze (UndefinedName (depth, FSComp.SR.undefinedNameFieldConstructorOrMember, id, suggestMembers)) @@ -2363,7 +2364,12 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf and ResolveLongIdentInNestedTypes (ncenv: NameResolver) nenv lookupKind resInfo depth id m ad (id2: Ident) (rest: Ident list) findFlag typeNameResInfo tys = tys |> CollectAtMostOneResult (fun ty -> - let resInfo = if isAppTy ncenv.g ty then resInfo.AddEntity(id.idRange, tcrefOfAppTy ncenv.g ty) else resInfo + let resInfo = + match tryDestAppTy ncenv.g ty with + | ValueSome tcref -> + resInfo.AddEntity(id.idRange, tcref) + | _ -> + resInfo ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id2 rest findFlag typeNameResInfo ty |> AtMostOneResult m) @@ -2878,8 +2884,10 @@ let ResolvePatternLongIdent sink (ncenv: NameResolver) warnOnUpper newDef m ad n // X.ListEnumerator // does not resolve // let ResolveNestedTypeThroughAbbreviation (ncenv: NameResolver) (tcref: TyconRef) m = - if tcref.IsTypeAbbrev && tcref.Typars(m).IsEmpty && isAppTy ncenv.g tcref.TypeAbbrev.Value && isNil (argsOfAppTy ncenv.g tcref.TypeAbbrev.Value) then - tcrefOfAppTy ncenv.g tcref.TypeAbbrev.Value + if tcref.IsTypeAbbrev && tcref.Typars(m).IsEmpty then + match tryAppTy ncenv.g tcref.TypeAbbrev.Value with + | ValueSome (abbrevTcref, []) -> abbrevTcref + | _ -> tcref else tcref @@ -3527,7 +3535,10 @@ let ItemOfTyconRef ncenv m (x: TyconRef) = Item.Types (x.DisplayName, [FreshenTycon ncenv m x]) let ItemOfTy g x = - let nm = if isAppTy g x then (tcrefOfAppTy g x).DisplayName else "?" + let nm = + match tryDestAppTy g x with + | ValueSome tcref -> tcref.DisplayName + | _ -> "?" Item.Types (nm, [x]) // Filter out 'PrivateImplementationDetail' classes From 6839169d45c110c8683f50119ad585ce510e9c27 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jan 2020 17:24:28 +0000 Subject: [PATCH 046/101] clarify language feature list (#8289) --- src/fsharp/LanguageFeatures.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index eeac561751..2170cee8f7 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -55,11 +55,11 @@ type LanguageVersion (specifiedVersionAsString) = // F# 5.0 LanguageFeature.FixedIndexSlice3d4d, languageVersion50 LanguageFeature.FromEndSlicing, languageVersion50 + LanguageFeature.DotlessFloat32Literal, languageVersion50 // F# preview LanguageFeature.NameOf, previewVersion LanguageFeature.OpenStaticClasses, previewVersion - LanguageFeature.DotlessFloat32Literal, languageVersion50 LanguageFeature.PackageManagement, previewVersion ] From 1069553d1ebb5e335f1a58f75727126263e93d2c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 19:51:02 +0100 Subject: [PATCH 047/101] cleanup begin / end (#8292) --- src/absil/ilread.fs | 40 ++++---- src/fsharp/IlxGen.fs | 211 ++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 134 deletions(-) diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index aa4438cedf..d016c2423e 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -761,37 +761,33 @@ let seekReadIndexedRows (numRows, rowReader, keyFunc, keyComparer, binaryChop, r // now read off rows, forward and backwards let mid = (low + high) / 2 // read forward - begin - let mutable fin = false - let mutable curr = mid - while not fin do - if curr > numRows then - fin <- true - else - let currrow = rowReader curr - if keyComparer (keyFunc currrow) = 0 then - res <- rowConverter currrow :: res - else - fin <- true - curr <- curr + 1 - done - end + let mutable fin = false + let mutable curr = mid + while not fin do + if curr > numRows then + fin <- true + else + let currrow = rowReader curr + if keyComparer (keyFunc currrow) = 0 then + res <- rowConverter currrow :: res + else + fin <- true + curr <- curr + 1 + res <- List.rev res // read backwards - begin - let mutable fin = false - let mutable curr = mid - 1 - while not fin do - if curr = 0 then + let mutable fin = false + let mutable curr = mid - 1 + while not fin do + if curr = 0 then fin <- true - else + else let currrow = rowReader curr if keyComparer (keyFunc currrow) = 0 then res <- rowConverter currrow :: res else fin <- true curr <- curr - 1 - end // sanity check #if CHECKING if checking then diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 6b0228ea02..bae42ad081 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3396,65 +3396,63 @@ and GenTryCatch cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, let startOfFilter = CG.GenerateMark cgbuf "startOfFilter" let afterFilter = CG.GenerateDelayMark cgbuf "afterFilter" let (sequelOnBranches, afterJoin, stackAfterJoin, sequelAfterJoin) = GenJoinPoint cenv cgbuf "filter" eenv g.int_ty m EndFilter - begin - // We emit the sequence point for the 'with' keyword span on the start of the filter - // block. However the targets of the filter block pattern matching should not get any - // sequence points (they will be 'true'/'false' values indicating if the exception has been - // caught or not). - // - // The targets of the handler block DO get sequence points. Thus the expected behaviour - // for a try/with with a complex pattern is that we hit the "with" before the filter is run - // and then jump to the handler for the successful catch (or continue with exception handling - // if the filter fails) - match spWith with - | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m - | NoSequencePointAtWith -> () - - - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vf eenvinner None (startOfFilter, afterFilter) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - - GenStoreVal cenv cgbuf eenvinner vf.Range vf - - // Why SPSuppress? Because we do not emit a sequence point at the start of the List.filter - we've already put one on - // the 'with' keyword above - GenExpr cenv cgbuf eenvinner SPSuppress ef sequelOnBranches - CG.SetMarkToHere cgbuf afterJoin - CG.SetStack cgbuf stackAfterJoin - GenSequel cenv eenv.cloc cgbuf sequelAfterJoin - end + // We emit the sequence point for the 'with' keyword span on the start of the filter + // block. However the targets of the filter block pattern matching should not get any + // sequence points (they will be 'true'/'false' values indicating if the exception has been + // caught or not). + // + // The targets of the handler block DO get sequence points. Thus the expected behaviour + // for a try/with with a complex pattern is that we hit the "with" before the filter is run + // and then jump to the handler for the successful catch (or continue with exception handling + // if the filter fails) + match spWith with + | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m + | NoSequencePointAtWith -> () + + + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vf eenvinner None (startOfFilter, afterFilter) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + + GenStoreVal cenv cgbuf eenvinner vf.Range vf + + // Why SPSuppress? Because we do not emit a sequence point at the start of the List.filter - we've already put one on + // the 'with' keyword above + GenExpr cenv cgbuf eenvinner SPSuppress ef sequelOnBranches + CG.SetMarkToHere cgbuf afterJoin + CG.SetStack cgbuf stackAfterJoin + GenSequel cenv eenv.cloc cgbuf sequelAfterJoin let endOfFilter = CG.GenerateMark cgbuf "endOfFilter" let filterMarks = (startOfFilter.CodeLabel, endOfFilter.CodeLabel) CG.SetMarkToHere cgbuf afterFilter let startOfHandler = CG.GenerateMark cgbuf "startOfHandler" - begin - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - GenStoreVal cenv cgbuf eenvinner vh.Range vh - - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) - end + + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + GenStoreVal cenv cgbuf eenvinner vh.Range vh + + GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) + let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) ILExceptionClause.FilterCatch(filterMarks, handlerMarks) else let startOfHandler = CG.GenerateMark cgbuf "startOfHandler" - begin - match spWith with - | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m - | NoSequencePointAtWith -> () + + match spWith with + | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m + | NoSequencePointAtWith -> () - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - GenStoreVal cenv cgbuf eenvinner m vh + GenStoreVal cenv cgbuf eenvinner m vh - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) - end + GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) + let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) ILExceptionClause.TypeCatch(g.ilg.typ_Object, handlerMarks) @@ -6591,56 +6589,47 @@ and GenTopImpl cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (TImplFile (qname, else [], [] - begin - - match mainInfoOpt with - - // Final file in .EXE - | Some mainInfo -> - - // Generate an explicit main method. If necessary, make a class constructor as - // well for the bindings earlier in the file containing the entry point. - match mgbuf.GetExplicitEntryPointInfo() with - - // Final file, explicit entry point: place the code in a .cctor, and add code to main that forces the .cctor (if topCode has initialization effect). - | Some tref -> - if doesSomething then - lazyInitInfo.Add (fun fspec feefee seqpt -> - // This adds the explicit init of the .cctor to the explicit entry point main method - mgbuf.AddExplicitInitToSpecificMethodDef((fun md -> md.IsEntryPoint), tref, fspec, GenPossibleILSourceMarker cenv m, feefee, seqpt)) - - let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) - mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) - // Final file, implicit entry point. We generate no .cctor. - // void main@() { - // - // } - | None -> - - let ilAttrs = mkILCustomAttrs (GenAttrs cenv eenv mainInfo) - if not cenv.opts.isInteractive && not doesSomething then - let errorM = m.EndRange - warning (Error(FSComp.SR.ilMainModuleEmpty(), errorM)) - - // generate main@ - let ilMainMethodDef = - let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL topCode) - mdef.With(isEntryPoint= true, customAttrs = ilAttrs) - - mgbuf.AddMethodDef(initClassTy.TypeRef, ilMainMethodDef) - - - // Library file: generate an optional .cctor if topCode has initialization effect - | None -> + match mainInfoOpt with + // Final file in .EXE + | Some mainInfo -> + // Generate an explicit main method. If necessary, make a class constructor as + // well for the bindings earlier in the file containing the entry point. + match mgbuf.GetExplicitEntryPointInfo() with + // Final file, explicit entry point: place the code in a .cctor, and add code to main that forces the .cctor (if topCode has initialization effect). + | Some tref -> if doesSomething then + lazyInitInfo.Add (fun fspec feefee seqpt -> + // This adds the explicit init of the .cctor to the explicit entry point main method + mgbuf.AddExplicitInitToSpecificMethodDef((fun md -> md.IsEntryPoint), tref, fspec, GenPossibleILSourceMarker cenv m, feefee, seqpt)) - // Add the cctor let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) + // Final file, implicit entry point. We generate no .cctor. + // void main@() { + // + // } + | None -> + let ilAttrs = mkILCustomAttrs (GenAttrs cenv eenv mainInfo) + if not cenv.opts.isInteractive && not doesSomething then + let errorM = m.EndRange + warning (Error(FSComp.SR.ilMainModuleEmpty(), errorM)) + + // generate main@ + let ilMainMethodDef = + let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL topCode) + mdef.With(isEntryPoint= true, customAttrs = ilAttrs) - end + mgbuf.AddMethodDef(initClassTy.TypeRef, ilMainMethodDef) + + + // Library file: generate an optional .cctor if topCode has initialization effect + | None -> + if doesSomething then + // Add the cctor + let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) + mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) // Commit the directed initializations if doesSomething then @@ -7511,29 +7500,27 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) = let CodegenAssembly cenv eenv mgbuf fileImpls = if not (isNil fileImpls) then - let a, b = List.frontAndBack fileImpls - let eenv = List.fold (GenTopImpl cenv mgbuf None) eenv a - let eenv = GenTopImpl cenv mgbuf cenv.opts.mainMethodInfo eenv b - - // Some constructs generate residue types and bindings. Generate these now. They don't result in any - // top-level initialization code. - begin - let extraBindings = mgbuf.GrabExtraBindingsToGenerate() - //printfn "#extraBindings = %d" extraBindings.Length - if extraBindings.Length > 0 then - let mexpr = TMDefs [ for b in extraBindings -> TMDefLet(b, range0) ] - let _emptyTopInstrs, _emptyTopCode = - CodeGenMethod cenv mgbuf ([], "unused", eenv, 0, (fun cgbuf eenv -> - let lazyInitInfo = ResizeArray() - let qname = QualifiedNameOfFile(mkSynId range0 "unused") - LocalScope "module" cgbuf (fun scopeMarks -> - let eenv = AddBindingsForModuleDef (fun cloc v -> AllocTopValWithinExpr cenv cgbuf cloc scopeMarks v) eenv.cloc eenv mexpr - GenModuleDef cenv cgbuf qname lazyInitInfo eenv mexpr)), range0) - //printfn "#_emptyTopInstrs = %d" _emptyTopInstrs.Length - () - end - - mgbuf.AddInitializeScriptsInOrderToEntryPoint() + let a, b = List.frontAndBack fileImpls + let eenv = List.fold (GenTopImpl cenv mgbuf None) eenv a + let eenv = GenTopImpl cenv mgbuf cenv.opts.mainMethodInfo eenv b + + // Some constructs generate residue types and bindings. Generate these now. They don't result in any + // top-level initialization code. + let extraBindings = mgbuf.GrabExtraBindingsToGenerate() + //printfn "#extraBindings = %d" extraBindings.Length + if extraBindings.Length > 0 then + let mexpr = TMDefs [ for b in extraBindings -> TMDefLet(b, range0) ] + let _emptyTopInstrs, _emptyTopCode = + CodeGenMethod cenv mgbuf ([], "unused", eenv, 0, (fun cgbuf eenv -> + let lazyInitInfo = ResizeArray() + let qname = QualifiedNameOfFile(mkSynId range0 "unused") + LocalScope "module" cgbuf (fun scopeMarks -> + let eenv = AddBindingsForModuleDef (fun cloc v -> AllocTopValWithinExpr cenv cgbuf cloc scopeMarks v) eenv.cloc eenv mexpr + GenModuleDef cenv cgbuf qname lazyInitInfo eenv mexpr)), range0) + //printfn "#_emptyTopInstrs = %d" _emptyTopInstrs.Length + () + + mgbuf.AddInitializeScriptsInOrderToEntryPoint() //------------------------------------------------------------------------- // When generating a module we just write into mutable From fbf60bcaeb191492ff9a8ea29d986dd92c9bba30 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 23:12:47 +0100 Subject: [PATCH 048/101] Remove tryRawToLabel (#8293) --- src/absil/ilread.fs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index d016c2423e..b9994f6418 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -2459,15 +2459,11 @@ and seekReadImplMap (ctxt: ILMetadataReader) nm midx = and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numtypars (sz: int) start seqpoints = let labelsOfRawOffsets = new Dictionary<_, _>(sz/2) let ilOffsetsOfLabels = new Dictionary<_, _>(sz/2) - let tryRawToLabel rawOffset = - match labelsOfRawOffsets.TryGetValue rawOffset with - | true, v -> Some v - | _ -> None - + let rawToLabel rawOffset = - match tryRawToLabel rawOffset with - | Some l -> l - | None -> + match labelsOfRawOffsets.TryGetValue rawOffset with + | true, l -> l + | _ -> let lab = generateCodeLabel() labelsOfRawOffsets.[rawOffset] <- lab lab @@ -2696,9 +2692,9 @@ and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numtypars (sz: int) start s // the start of the next instruction referred to by the raw offset. let raw2nextLab rawOffset = let isInstrStart x = - match tryRawToLabel x with - | None -> false - | Some lab -> ilOffsetsOfLabels.ContainsKey lab + match labelsOfRawOffsets.TryGetValue x with + | true, lab -> ilOffsetsOfLabels.ContainsKey lab + | _ -> false if isInstrStart rawOffset then rawToLabel rawOffset elif isInstrStart (rawOffset+1) then rawToLabel (rawOffset+1) else failwith ("the bytecode raw offset "+string rawOffset+" did not refer either to the start or end of an instruction") From be70bd97e8ca4ce4313c9b626ad88e31ebb9c185 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 21 Jan 2020 23:44:21 +0100 Subject: [PATCH 049/101] Reduce Number of isAppTy calls (#8275) --- src/fsharp/symbols/SymbolHelpers.fs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index cec9bfaf52..48a44c8abb 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -839,19 +839,22 @@ module internal SymbolHelpers = // This may explore assemblies that are not in the reference set. // In this case just assume the item is not suppressed. protectAssemblyExploration true (fun () -> - match item with - | Item.Types(it, [ty]) -> - isAppTy g ty && - g.suppressed_types - |> List.exists (fun supp -> - let generalizedSupp = generalizedTyconRef supp - // check the display name is precisely the one we're suppressing - isAppTy g generalizedSupp && it = supp.DisplayName && - // check if they are the same logical type (after removing all abbreviations) - let tcr1 = tcrefOfAppTy g ty - let tcr2 = tcrefOfAppTy g generalizedSupp - tyconRefEq g tcr1 tcr2) - | _ -> false) + match item with + | Item.Types(it, [ty]) -> + match tryDestAppTy g ty with + | ValueSome tcr1 -> + g.suppressed_types + |> List.exists (fun supp -> + let generalizedSupp = generalizedTyconRef supp + // check the display name is precisely the one we're suppressing + match tryDestAppTy g generalizedSupp with + | ValueSome tcr2 -> + it = supp.DisplayName && + // check if they are the same logical type (after removing all abbreviations) + tyconRefEq g tcr1 tcr2 + | _ -> false) + | _ -> false + | _ -> false) /// Filter types that are explicitly suppressed from the IntelliSense (such as uppercase "FSharpList", "Option", etc.) let RemoveExplicitlySuppressed (g: TcGlobals) (items: ItemWithInst list) = From bb46e3788de820f53eb2b854868ebc061fda7a5e Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 21 Jan 2020 23:52:19 +0100 Subject: [PATCH 050/101] Reduce isAppTy calls in TypeDefinitelyHasEquality (#8286) --- src/fsharp/AugmentWithHashCompare.fs | 43 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 03ea427a06..87917c2950 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -1075,23 +1075,28 @@ let MakeBindingsForEqualsAugmentation (g: TcGlobals) (tycon: Tycon) = elif tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then mkEquals mkRecdEquality else [] -let rec TypeDefinitelyHasEquality g ty = - if isAppTy g ty && HasFSharpAttribute g g.attrib_NoEqualityAttribute (tcrefOfAppTy g ty).Attribs then +let rec TypeDefinitelyHasEquality g ty = + let appTy = tryAppTy g ty + match appTy with + | ValueSome(tcref,_) when HasFSharpAttribute g g.attrib_NoEqualityAttribute tcref.Attribs -> false - elif isTyparTy g ty && - (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then - true - else - match ty with - | SpecialEquatableHeadType g tinst -> - tinst |> List.forall (TypeDefinitelyHasEquality g) - | SpecialNotEquatableHeadType g _ -> - false - | _ -> - // The type is equatable because it has Object.Equals(...) - isAppTy g ty && - let tcref, tinst = destAppTy g ty - // Give a good error for structural types excluded from the equality relation because of their fields - not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) && - // Check the (possibly inferred) structural dependencies - (tinst, tcref.TyparsNoRange) ||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty) + | _ -> + if isTyparTy g ty && + (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then + true + else + match ty with + | SpecialEquatableHeadType g tinst -> + tinst |> List.forall (TypeDefinitelyHasEquality g) + | SpecialNotEquatableHeadType g _ -> + false + | _ -> + // The type is equatable because it has Object.Equals(...) + match appTy with + | ValueSome(tcref,tinst) -> + // Give a good error for structural types excluded from the equality relation because of their fields + not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) && + // Check the (possibly inferred) structural dependencies + (tinst, tcref.TyparsNoRange) + ||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty) + | _ -> false From a373efb222c5ea8649e2282e9d57b903f32619c2 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 21 Jan 2020 14:56:06 -0800 Subject: [PATCH 051/101] Fixed consuming CSharp interface with an inref parameter (#8287) * Added inref interop test * Fixed inref interop when creating a slot sig * 3.1 to 3.0 --- src/fsharp/infos.fs | 2 +- tests/fsharp/Compiler/CompilerAssert.fs | 21 +++++++++- tests/fsharp/Compiler/Language/ByrefTests.fs | 41 ++++++++++++++++++++ tests/fsharp/Compiler/Utilities.fs | 4 +- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 1db4e36b35..63db80bae8 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1536,7 +1536,7 @@ type MethInfo = let formalRetTy = ImportReturnTypeFromMetadata amap m ilminfo.RawMetadata.Return.Type ilminfo.RawMetadata.Return.CustomAttrs ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys let formalParams = [ [ for p in ilminfo.RawMetadata.Parameters do - let paramType = ImportILTypeFromMetadata amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys p.Type + let paramType = ImportILTypeFromMetadataWithAttributes amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys p.Type p.CustomAttrs yield TSlotParam(p.Name, paramType, p.IsIn, p.IsOut, p.IsOptional, []) ] ] formalRetTy, formalParams #if !NO_EXTENSIONTYPING diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 9f0bc09553..ef0e591a0c 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -8,6 +8,7 @@ open System.Diagnostics open System.IO open System.Text open System.Diagnostics +open System.Collections.Generic open System.Reflection open FSharp.Compiler.Text open FSharp.Compiler.SourceCodeServices @@ -17,6 +18,9 @@ open System.Runtime.Loader #endif open NUnit.Framework open System.Reflection.Emit +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.CSharp +open FSharp.Compiler.UnitTests.Utilities [] type ILVerifier (dllFilePath: string) = @@ -52,12 +56,18 @@ type CompileOutput = | Library | Exe -type CompilationReference = private CompilationReference of Compilation * staticLink: bool with +type CompilationReference = + private + | CompilationReference of Compilation * staticLink: bool + | TestCompilationReference of TestCompilation static member CreateFSharp(cmpl: Compilation, ?staticLink) = let staticLink = defaultArg staticLink false CompilationReference(cmpl, staticLink) + static member Create(cmpl: TestCompilation) = + TestCompilationReference cmpl + and Compilation = private Compilation of string * SourceKind * CompileOutput * options: string[] * CompilationReference list with static member Create(source, sourceKind, output, ?options, ?cmplRefs) = @@ -257,7 +267,14 @@ let main argv = 0""" |> List.map (fun cmpl -> match cmpl with | CompilationReference (cmpl, staticLink) -> - compileCompilationAux disposals ignoreWarnings cmpl, staticLink) + compileCompilationAux disposals ignoreWarnings cmpl, staticLink + | TestCompilationReference (cmpl) -> + let tmp = Path.GetTempFileName() + disposals.Add({ new IDisposable with + member _.Dispose() = + try File.Delete tmp with | _ -> () }) + cmpl.EmitAsFile tmp + (([||], tmp), []), false) let compilationRefs = compiledRefs diff --git a/tests/fsharp/Compiler/Language/ByrefTests.fs b/tests/fsharp/Compiler/Language/ByrefTests.fs index 2797125d79..d09f9f4cf2 100644 --- a/tests/fsharp/Compiler/Language/ByrefTests.fs +++ b/tests/fsharp/Compiler/Language/ByrefTests.fs @@ -4,6 +4,7 @@ namespace FSharp.Compiler.UnitTests open NUnit.Framework open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.UnitTests.Utilities [] module ByrefTests = @@ -195,4 +196,44 @@ let test1 () = "The value has been copied to ensure the original is not mutated by this operation or because the copy is implicit when returning a struct from a member and another member is then accessed" ) |] +#endif + +#if NETCOREAPP + [] + let ``Consume CSharp interface with a method that has a readonly byref`` () = + let cs = + """ +using System; +using System.Buffers; + +namespace Example +{ + public interface IMessageReader + { + bool TryParseMessage(in byte input); + } +} + """ + let fs = + """ +module Module1 + +open Example + +type MyClass() = + + interface IMessageReader with + member this.TryParseMessage(input: inref): bool = + failwith "Not Implemented" + """ + + let csCmpl = + CompilationUtil.CreateCSharpCompilation(cs, CSharpLanguageVersion.CSharp8, TargetFramework.NetCoreApp30) + |> CompilationReference.Create + + let fsCmpl = + Compilation.Create(fs, Fsx, Library, cmplRefs = [csCmpl]) + + CompilerAssert.Compile fsCmpl + #endif \ No newline at end of file diff --git a/tests/fsharp/Compiler/Utilities.fs b/tests/fsharp/Compiler/Utilities.fs index 29de21ad3e..b55707fdb4 100644 --- a/tests/fsharp/Compiler/Utilities.fs +++ b/tests/fsharp/Compiler/Utilities.fs @@ -120,7 +120,7 @@ type CompilationUtil private () = [ CSharpSyntaxTree.ParseText (source, CSharpParseOptions lv) ], references.As().AddRange additionalReferences, CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary)) - Some (TestCompilation.CSharp (c, flags)) + TestCompilation.CSharp (c, flags) static member CreateILCompilation (source: string) = let compute = @@ -139,4 +139,4 @@ type CompilationUtil private () = try File.Delete ilFilePath with | _ -> () try File.Delete tmp with | _ -> () try File.Delete dllFilePath with | _ -> () - Some (TestCompilation.IL (source, compute)) \ No newline at end of file + TestCompilation.IL (source, compute) \ No newline at end of file From d3d5e30852454146876dc3af1f3e6ff21fdd67da Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 21 Jan 2020 14:57:41 -0800 Subject: [PATCH 052/101] Merge dependency manager and fsi script testing (#8276) * Merge dependency manager and fsi script testing * Don't forget Linux Duh!!! --- FSharp.sln | 15 ----------- VisualFSharp.sln | 15 ----------- eng/Build.ps1 | 12 --------- eng/build.sh | 1 - .../DependencyManagerInteractiveTests.fs | 0 .../DependencyManagerLineParserTests.fs | 0 ...ompiler.Private.Scripting.UnitTests.fsproj | 2 ++ .../Directory.Build.props | 9 ------- .../FSharp.DependencyManager.UnitTests.fsproj | 25 ------------------- 9 files changed, 2 insertions(+), 77 deletions(-) rename tests/{FSharp.DependencyManager.UnitTests => FSharp.Compiler.Private.Scripting.UnitTests}/DependencyManagerInteractiveTests.fs (100%) rename tests/{FSharp.DependencyManager.UnitTests => FSharp.Compiler.Private.Scripting.UnitTests}/DependencyManagerLineParserTests.fs (100%) delete mode 100644 tests/FSharp.DependencyManager.UnitTests/Directory.Build.props delete mode 100644 tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj diff --git a/FSharp.sln b/FSharp.sln index 23375be628..57620c7864 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -52,8 +52,6 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scr EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting.UnitTests", "tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj", "{4FEDF286-0252-4EBC-9E75-879CCA3B85DC}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.UnitTests", "tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj", "{388FFDAE-A659-422E-9407-6A9062E1986E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -280,18 +278,6 @@ Global {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|Any CPU.Build.0 = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.ActiveCfg = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.Build.0 = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|x86.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|x86.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|Any CPU.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|x86.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|x86.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|Any CPU.Build.0 = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|x86.ActiveCfg = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -314,7 +300,6 @@ Global {8B7BF62E-7D8C-4928-BE40-4E392A9EE851} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {6771860A-614D-4FDD-A655-4C70EBCC91B0} = {B8DDA694-7939-42E3-95E5-265C2217C142} {4FEDF286-0252-4EBC-9E75-879CCA3B85DC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} - {388FFDAE-A659-422E-9407-6A9062E1986E} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8} diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 76bcf8369e..d46221b17b 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -156,8 +156,6 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scr EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{DFA30881-C0B1-4813-B087-C21B5AF9B77F}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.UnitTests", "tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj", "{AF7AE565-E1C4-4A24-BD4B-D7983FC84768}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualFSharpTemplates", "vsintegration\Vsix\VisualFSharpTemplates\VisualFSharpTemplates.csproj", "{AA259A37-418F-4E18-87B2-C7D5F8C26CC4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProjectTemplates", "ProjectTemplates", "{12EF27FD-A34B-4373-860A-F9FCE9651859}" @@ -922,18 +920,6 @@ Global {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|Any CPU.Build.0 = Release|Any CPU {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.ActiveCfg = Release|Any CPU {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.Build.0 = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|x86.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|x86.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|Any CPU.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|x86.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|x86.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|Any CPU.Build.0 = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.ActiveCfg = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.Build.0 = Release|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1055,7 +1041,6 @@ Global {20B7BC36-CF51-4D75-9E13-66681C07977F} = {B8DDA694-7939-42E3-95E5-265C2217C142} {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {DFA30881-C0B1-4813-B087-C21B5AF9B77F} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {AA259A37-418F-4E18-87B2-C7D5F8C26CC4} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {12EF27FD-A34B-4373-860A-F9FCE9651859} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {44155269-9B30-43DA-B97F-4F36F887B211} = {12EF27FD-A34B-4373-860A-F9FCE9651859} diff --git a/eng/Build.ps1 b/eng/Build.ps1 index cf7ce0413c..72ea53f146 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -48,7 +48,6 @@ param ( [switch]$testCoreClr, [switch]$testCambridge, [switch]$testCompiler, - [switch]$testDependencyManager, [switch]$testFSharpCore, [switch]$testFSharpQA, [switch]$testScripting, @@ -86,7 +85,6 @@ function Print-Usage() { Write-Host " -testAll Run all tests" Write-Host " -testCambridge Run Cambridge tests" Write-Host " -testCompiler Run FSharpCompiler unit tests" - Write-Host " -testDependencyManager Run FSharp.DependencyManager.UnitTests" Write-Host " -testDesktop Run tests against full .NET Framework" Write-Host " -testCoreClr Run tests against CoreCLR" Write-Host " -testFSharpCore Run FSharpCore unit tests" @@ -128,7 +126,6 @@ function Process-Arguments() { $script:testAll = $False $script:testCambridge = $False $script:testCompiler = $False - $script:testDependencyManager = $False $script:testDesktop = $False $script:testCoreClr = $False $script:testFSharpCore = $False @@ -348,7 +345,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $desktopTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $desktopTargetFramework @@ -358,7 +354,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $coreclrTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $coreclrTargetFramework @@ -398,13 +393,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework } - if ($testDependencyManager) { - if (-not $noVisualStudio) { - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $desktopTargetFramework - } - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $coreclrTargetFramework - } - if ($testCambridge) { if (-not $noVisualStudio) { TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $desktopTargetFramework diff --git a/eng/build.sh b/eng/build.sh index 6340d55746..218f4ef977 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -292,7 +292,6 @@ if [[ "$test_core_clr" == true ]]; then 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.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj" --targetframework $coreclrtestframework - TestUsingNUnit --testproject "$repo_root/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclrtestframework fi diff --git a/tests/FSharp.DependencyManager.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs similarity index 100% rename from tests/FSharp.DependencyManager.UnitTests/DependencyManagerInteractiveTests.fs rename to tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs diff --git a/tests/FSharp.DependencyManager.UnitTests/DependencyManagerLineParserTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerLineParserTests.fs similarity index 100% rename from tests/FSharp.DependencyManager.UnitTests/DependencyManagerLineParserTests.fs rename to tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerLineParserTests.fs diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj index a16969af73..39a3ca4e68 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj @@ -13,6 +13,8 @@ + + diff --git a/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props b/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props deleted file mode 100644 index 7cd41381b5..0000000000 --- a/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj b/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj deleted file mode 100644 index 042986e8ad..0000000000 --- a/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - net472;netcoreapp3.0 - netcoreapp3.0 - Library - true - nunit - true - - - - - - - - - - - - - - - From db2ba9ea52560fac9f37a27016f82af830a39383 Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Tue, 21 Jan 2020 15:39:56 -0800 Subject: [PATCH 053/101] [RFC 1082] - uint type abbreviation (#8185) * Add uint type abbreviation * Add uint casting function and test * Update surface area tests * update --- src/fsharp/FSharp.Core/prim-types-prelude.fs | 1 + src/fsharp/FSharp.Core/prim-types-prelude.fsi | 3 +++ src/fsharp/FSharp.Core/prim-types.fs | 5 ++++- src/fsharp/FSharp.Core/prim-types.fsi | 9 +++++++++ tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs | 6 ++++++ tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs | 1 + tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs | 1 + tests/fsharp/Compiler/Language/UIntTests.fs | 10 ++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + 9 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/fsharp/Compiler/Language/UIntTests.fs diff --git a/src/fsharp/FSharp.Core/prim-types-prelude.fs b/src/fsharp/FSharp.Core/prim-types-prelude.fs index 74c8410170..b95933a7aa 100644 --- a/src/fsharp/FSharp.Core/prim-types-prelude.fs +++ b/src/fsharp/FSharp.Core/prim-types-prelude.fs @@ -28,6 +28,7 @@ namespace Microsoft.FSharp.Core type bool = System.Boolean type decimal = System.Decimal type int = int32 + type uint = uint32 type ``[]``<'T> = (# "!0[]" #) type ``[,]``<'T> = (# "!0[0 ...,0 ...]" #) diff --git a/src/fsharp/FSharp.Core/prim-types-prelude.fsi b/src/fsharp/FSharp.Core/prim-types-prelude.fsi index ed68965bf2..f4dd023159 100644 --- a/src/fsharp/FSharp.Core/prim-types-prelude.fsi +++ b/src/fsharp/FSharp.Core/prim-types-prelude.fsi @@ -78,6 +78,9 @@ namespace Microsoft.FSharp.Core /// An abbreviation for the CLI type System.Int32. type int = int32 + /// An abbreviation for the CLI type System.UInt32. + type uint = uint32 + /// Single dimensional, zero-based arrays, written int[], string[] etc. /// Use the values in the Array module to manipulate values /// of this type, or the notation arr.[x] to get/set array diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 51c38a9642..4bff05856c 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3731,7 +3731,10 @@ namespace Microsoft.FSharp.Core when ^T : byte = (# "conv.i4" value : int32 #) [] - let inline int value = int32 value + let inline int value = int32 value + + [] + let inline uint value = uint32 value [] let inline enum< ^T when ^T : enum > (value:int32) : ^T = EnumOfValue value diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index fd6c7557ef..afa0719602 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -2639,6 +2639,15 @@ namespace Microsoft.FSharp.Core [] val inline int : value:^T -> int when ^T : (static member op_Explicit : ^T -> int) and default ^T : int + /// Converts the argument to an unsigned 32-bit integer. This is a direct conversion for all + /// primitive numeric types. For strings, the input is converted using UInt32.Parse() + /// with InvariantCulture settings. Otherwise the operation requires an appropriate + /// static conversion method on the input type. + /// The input value. + /// The converted int + [] + val inline uint: value:^T -> uint when ^T: (static member op_Explicit: ^T -> uint) and default ^T: uint + /// Converts the argument to a particular enum type. /// The input value. /// The converted enum type. diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs index 9d92d474cf..4470df289d 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs @@ -16,6 +16,12 @@ type m [] type LanguagePrimitivesModule() = + [] + member _.CastingUint () = + let expected = 12u + let actual = uint 12 + Assert.AreEqual(expected, actual) + [] member this.CastingUnits() = let f = 2.5 diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs index 5e17904137..896e7629da 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs @@ -2077,6 +2077,7 @@ Microsoft.FSharp.Core.Operators: Int32 Sign[T](T) Microsoft.FSharp.Core.Operators: Int32 SizeOf[T]() Microsoft.FSharp.Core.Operators: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators: Int32 ToInt[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) Microsoft.FSharp.Core.Operators: Int32 limitedHash[T](Int32, T) Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs index 42984aa831..82141617d9 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs @@ -2077,6 +2077,7 @@ Microsoft.FSharp.Core.Operators: Int32 Sign[T](T) Microsoft.FSharp.Core.Operators: Int32 SizeOf[T]() Microsoft.FSharp.Core.Operators: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators: Int32 ToInt[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) Microsoft.FSharp.Core.Operators: Int32 limitedHash[T](Int32, T) Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) diff --git a/tests/fsharp/Compiler/Language/UIntTests.fs b/tests/fsharp/Compiler/Language/UIntTests.fs new file mode 100644 index 0000000000..c317f96e02 --- /dev/null +++ b/tests/fsharp/Compiler/Language/UIntTests.fs @@ -0,0 +1,10 @@ +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework + +[] +module UIntTests = + let ``uint type abbreviation works`` () = + let src = "let x = uint 12" + let expectedErrors = [||] + CompilerAssert.TypeCheckWithErrors src expectedErrors \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 0daec217da..66ae7d66b0 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -59,6 +59,7 @@ + From 1a695c9d3ec9c0cb777aabf52703a603de695712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Cie=C5=9Blak?= Date: Wed, 22 Jan 2020 00:56:04 +0100 Subject: [PATCH 054/101] Expose more services (#8291) * Expose simplify name analyzer * Move IsPrivateToFile to the FSharpSymbolUse from extensions * Expose Unused Declarations analyzer * Update src/fsharp/symbols/Symbols.fsi Co-Authored-By: Phillip Carter * Apply feedback Co-authored-by: Phillip Carter --- src/fsharp/service/ServiceAnalysis.fs | 111 ++++++++++++++++++ src/fsharp/service/ServiceAnalysis.fsi | 18 ++- src/fsharp/symbols/Symbols.fs | 25 ++++ src/fsharp/symbols/Symbols.fsi | 2 + .../SimplifyNameDiagnosticAnalyzer.fs | 68 ++--------- .../Diagnostics/UnusedDeclarationsAnalyzer.fs | 65 +--------- .../FSharp.Editor/LanguageService/Symbols.fs | 26 ---- 7 files changed, 167 insertions(+), 148 deletions(-) diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index e568767a1e..33c5a45775 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -226,4 +226,115 @@ module UnusedOpens = let symbolUses = splitSymbolUses symbolUses let openStatements = getOpenStatements checkFileResults.OpenDeclarations return! filterOpenStatements symbolUses openStatements + } + +module SimplifyNames = + type SimplifiableRange = { + Range: range + RelativeName: string + } + + let getPlidLength (plid: string list) = (plid |> List.sumBy String.length) + plid.Length + + let getSimplifiableNames (checkFileResults: FSharpCheckFileResults, getSourceLineStr: int -> string) : Async = + async { + let result = ResizeArray() + let! symbolUses = checkFileResults.GetAllUsesOfAllSymbolsInFile() + let symbolUses = + symbolUses + |> Array.filter (fun symbolUse -> not symbolUse.IsFromOpenStatement) + |> Array.Parallel.map (fun symbolUse -> + let lineStr = getSourceLineStr symbolUse.RangeAlternate.StartLine + // for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now") + let partialName = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) + // `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`, + // so we have to calculate plid's start ourselves. + let plidStartCol = symbolUse.RangeAlternate.EndColumn - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) + symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent) + |> Array.filter (fun (_, plid, _, name) -> name <> "" && not (List.isEmpty plid)) + |> Array.groupBy (fun (symbolUse, _, plidStartCol, _) -> symbolUse.RangeAlternate.StartLine, plidStartCol) + |> Array.map (fun (_, xs) -> xs |> Array.maxBy (fun (symbolUse, _, _, _) -> symbolUse.RangeAlternate.EndColumn)) + + for symbolUse, plid, plidStartCol, name in symbolUses do + if not symbolUse.IsFromDefinition then + let posAtStartOfName = + let r = symbolUse.RangeAlternate + if r.StartLine = r.EndLine then Range.mkPos r.StartLine (r.EndColumn - name.Length) + else r.Start + + let getNecessaryPlid (plid: string list) : Async = + let rec loop (rest: string list) (current: string list) = + async { + match rest with + | [] -> return current + | headIdent :: restPlid -> + let! res = checkFileResults.IsRelativeNameResolvableFromSymbol(posAtStartOfName, current, symbolUse.Symbol) + if res then return current + else return! loop restPlid (headIdent :: current) + } + loop (List.rev plid) [] + + let! necessaryPlid = getNecessaryPlid plid + + match necessaryPlid with + | necessaryPlid when necessaryPlid = plid -> () + | necessaryPlid -> + let r = symbolUse.RangeAlternate + let necessaryPlidStartCol = r.EndColumn - name.Length - (getPlidLength necessaryPlid) + + let unnecessaryRange = + Range.mkRange r.FileName (Range.mkPos r.StartLine plidStartCol) (Range.mkPos r.EndLine necessaryPlidStartCol) + + let relativeName = (String.concat "." plid) + "." + name + result.Add({Range = unnecessaryRange; RelativeName = relativeName}) + + return List.ofSeq result + } + +module UnusedDeclarations = + let isPotentiallyUnusedDeclaration (symbol: FSharpSymbol) : bool = + match symbol with + // Determining that a record, DU or module is used anywhere requires inspecting all their enclosed entities (fields, cases and func / vals) + // for usages, which is too expensive to do. Hence we never gray them out. + | :? FSharpEntity as e when e.IsFSharpRecord || e.IsFSharpUnion || e.IsInterface || e.IsFSharpModule || e.IsClass || e.IsNamespace -> false + // FCS returns inconsistent results for override members; we're skipping these symbols. + | :? FSharpMemberOrFunctionOrValue as f when + f.IsOverrideOrExplicitInterfaceImplementation || + f.IsBaseValue || + f.IsConstructor -> false + // Usage of DU case parameters does not give any meaningful feedback; we never gray them out. + | :? FSharpParameter -> false + | _ -> true + + let getUnusedDeclarationRanges (symbolsUses: FSharpSymbolUse[]) (isScript: bool) = + let definitions = + symbolsUses + |> Array.filter (fun su -> + su.IsFromDefinition && + su.Symbol.DeclarationLocation.IsSome && + (isScript || su.IsPrivateToFile) && + not (su.Symbol.DisplayName.StartsWith "_") && + isPotentiallyUnusedDeclaration su.Symbol) + + let usages = + let usages = + symbolsUses + |> Array.filter (fun su -> not su.IsFromDefinition) + |> Array.choose (fun su -> su.Symbol.DeclarationLocation) + HashSet(usages) + + let unusedRanges = + definitions + |> Array.map (fun defSu -> defSu, usages.Contains defSu.Symbol.DeclarationLocation.Value) + |> Array.groupBy (fun (defSu, _) -> defSu.RangeAlternate) + |> Array.filter (fun (_, defSus) -> defSus |> Array.forall (fun (_, isUsed) -> not isUsed)) + |> Array.map (fun (m, _) -> m) + + Array.toList unusedRanges + + let getUnusedDeclarations(checkFileResults: FSharpCheckFileResults, isScriptFile: bool) : Async = + async { + let! allSymbolUsesInFile = checkFileResults.GetAllUsesOfAllSymbolsInFile() + let unusedRanges = getUnusedDeclarationRanges allSymbolUsesInFile isScriptFile + return unusedRanges } \ No newline at end of file diff --git a/src/fsharp/service/ServiceAnalysis.fsi b/src/fsharp/service/ServiceAnalysis.fsi index 8d97644389..eb277269ab 100644 --- a/src/fsharp/service/ServiceAnalysis.fsi +++ b/src/fsharp/service/ServiceAnalysis.fsi @@ -8,4 +8,20 @@ open FSharp.Compiler.Range module public UnusedOpens = /// Get all unused open declarations in a file - val getUnusedOpens : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async \ No newline at end of file + val getUnusedOpens : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async + +module public SimplifyNames = + /// Data for use in finding unnecessarily-qualified names and generating diagnostics to simplify them + type SimplifiableRange = { + /// The range of a name that can be simplified + Range: range + /// The relative name that can be applied to a simplifiable name + RelativeName: string + } + + /// Get all ranges that can be simplified in a file + val getSimplifiableNames : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async + +module public UnusedDeclarations = + /// Get all unused declarations in a file + val getUnusedDeclarations : checkFileResults: FSharpCheckFileResults * isScriptFile: bool -> Async \ No newline at end of file diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 295e42b02c..f4b2f6babe 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -2518,5 +2518,30 @@ type FSharpSymbolUse(g:TcGlobals, denv: DisplayEnv, symbol:FSharpSymbol, itemOcc member __.Range = Range.toZ range member __.RangeAlternate = range + + member this.IsPrivateToFile = + let isPrivate = + match this.Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || m.Accessibility.IsPrivate + | :? FSharpEntity as m -> m.Accessibility.IsPrivate + | :? FSharpGenericParameter -> true + | :? FSharpUnionCase as m -> m.Accessibility.IsPrivate + | :? FSharpField as m -> m.Accessibility.IsPrivate + | _ -> false + + let declarationLocation = + match this.Symbol.SignatureLocation with + | Some x -> Some x + | _ -> + match this.Symbol.DeclarationLocation with + | Some x -> Some x + | _ -> this.Symbol.ImplementationLocation + + let declaredInTheFile = + match declarationLocation with + | Some declRange -> declRange.FileName = this.RangeAlternate.FileName + | _ -> false + + isPrivate && declaredInTheFile override __.ToString() = sprintf "%O, %O, %O" symbol itemOcc range diff --git a/src/fsharp/symbols/Symbols.fsi b/src/fsharp/symbols/Symbols.fsi index 6893097ed9..ad402418c6 100644 --- a/src/fsharp/symbols/Symbols.fsi +++ b/src/fsharp/symbols/Symbols.fsi @@ -1101,3 +1101,5 @@ type public FSharpSymbolUse = /// The range of text representing the reference to the symbol member RangeAlternate: range + /// Indicates if the FSharpSymbolUse is declared as private + member IsPrivateToFile : bool diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index f90717522a..09ee9cc239 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -16,6 +16,7 @@ open FSharp.Compiler.Range open System.Runtime.Caching open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics +open FSharp.Compiler.SourceCodeServices type private TextVersionHash = int type private PerDocumentSavedData = { Hash: int; Diagnostics: ImmutableArray } @@ -26,7 +27,7 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = static let userOpName = "SimplifyNameDiagnosticAnalyzer" let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - let getPlidLength (plid: string list) = (plid |> List.sumBy String.length) + plid.Length + static let cache = new MemoryCache("FSharp.Editor." + userOpName) // Make sure only one document is being analyzed at a time, to be nice static let guard = new SemaphoreSlim(1) @@ -52,62 +53,15 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = let! sourceText = document.GetTextAsync() let checker = getChecker document let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName=userOpName) - let! symbolUses = checkResults.GetAllUsesOfAllSymbolsInFile() |> liftAsync - let mutable result = ResizeArray() - let symbolUses = - symbolUses - |> Array.filter (fun symbolUse -> not symbolUse.IsFromOpenStatement) - |> Array.Parallel.map (fun symbolUse -> - let lineStr = sourceText.Lines.[Line.toZ symbolUse.RangeAlternate.StartLine].ToString() - // for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now") - let partialName = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) - // `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`, - // so we have to calculate plid's start ourselves. - let plidStartCol = symbolUse.RangeAlternate.EndColumn - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) - symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent) - |> Array.filter (fun (_, plid, _, name) -> name <> "" && not (List.isEmpty plid)) - |> Array.groupBy (fun (symbolUse, _, plidStartCol, _) -> symbolUse.RangeAlternate.StartLine, plidStartCol) - |> Array.map (fun (_, xs) -> xs |> Array.maxBy (fun (symbolUse, _, _, _) -> symbolUse.RangeAlternate.EndColumn)) - - for symbolUse, plid, plidStartCol, name in symbolUses do - if not symbolUse.IsFromDefinition then - let posAtStartOfName = - let r = symbolUse.RangeAlternate - if r.StartLine = r.EndLine then Range.mkPos r.StartLine (r.EndColumn - name.Length) - else r.Start - - let getNecessaryPlid (plid: string list) : Async = - let rec loop (rest: string list) (current: string list) = - async { - match rest with - | [] -> return current - | headIdent :: restPlid -> - let! res = checkResults.IsRelativeNameResolvableFromSymbol(posAtStartOfName, current, symbolUse.Symbol, userOpName=userOpName) - if res then return current - else return! loop restPlid (headIdent :: current) - } - loop (List.rev plid) [] - - do! Async.Sleep DefaultTuning.SimplifyNameEachItemDelay |> liftAsync // be less intrusive, give other work priority most of the time - let! necessaryPlid = getNecessaryPlid plid |> liftAsync - - match necessaryPlid with - | necessaryPlid when necessaryPlid = plid -> () - | necessaryPlid -> - let r = symbolUse.RangeAlternate - let necessaryPlidStartCol = r.EndColumn - name.Length - (getPlidLength necessaryPlid) - - let unnecessaryRange = - Range.mkRange r.FileName (Range.mkPos r.StartLine plidStartCol) (Range.mkPos r.EndLine necessaryPlidStartCol) - - let relativeName = (String.concat "." plid) + "." + name - result.Add( - Diagnostic.Create( - descriptor, - RoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath), - properties = (dict [SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, relativeName]).ToImmutableDictionary())) - - let diagnostics = result.ToImmutableArray() + let! result = SimplifyNames.getSimplifiableNames(checkResults, fun lineNumber -> sourceText.Lines.[Line.toZ lineNumber].ToString()) |> liftAsync + let mutable diag = ResizeArray() + for r in result do + diag.Add( + Diagnostic.Create( + descriptor, + RoslynHelpers.RangeToLocation(r.Range, sourceText, document.FilePath), + properties = (dict [SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, r.RelativeName]).ToImmutableDictionary())) + let diagnostics = diag.ToImmutableArray() cache.Remove(key) |> ignore let data = { Hash = textVersionHash; Diagnostics=diagnostics } let cacheItem = CacheItem(key, data) diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs index ff7c43839d..28f1b1f9c4 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs @@ -22,68 +22,6 @@ type internal UnusedDeclarationsAnalyzer [] () = let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - let isPotentiallyUnusedDeclaration (symbol: FSharpSymbol) : bool = - match symbol with - // Determining that a record, DU or module is used anywhere requires inspecting all their enclosed entities (fields, cases and func / vals) - // for usages, which is too expensive to do. Hence we never gray them out. - | :? FSharpEntity as e when e.IsFSharpRecord || e.IsFSharpUnion || e.IsInterface || e.IsFSharpModule || e.IsClass || e.IsNamespace -> false - // FCS returns inconsistent results for override members; we're skipping these symbols. - | :? FSharpMemberOrFunctionOrValue as f when - f.IsOverrideOrExplicitInterfaceImplementation || - f.IsBaseValue || - f.IsConstructor -> false - // Usage of DU case parameters does not give any meaningful feedback; we never gray them out. - | :? FSharpParameter -> false - | _ -> true - - let getUnusedDeclarationRanges (symbolsUses: FSharpSymbolUse[]) (isScript: bool) = - let definitions = - symbolsUses - |> Array.filter (fun su -> - su.IsFromDefinition && - su.Symbol.DeclarationLocation.IsSome && - (isScript || su.IsPrivateToFile) && - not (su.Symbol.DisplayName.StartsWith "_") && - isPotentiallyUnusedDeclaration su.Symbol) - - let usages = - let usages = - symbolsUses - |> Array.filter (fun su -> not su.IsFromDefinition) - |> Array.choose (fun su -> su.Symbol.DeclarationLocation) - HashSet(usages) - - let unusedRanges = - definitions - |> Array.map (fun defSu -> defSu, usages.Contains defSu.Symbol.DeclarationLocation.Value) - |> Array.groupBy (fun (defSu, _) -> defSu.RangeAlternate) - |> Array.filter (fun (_, defSus) -> defSus |> Array.forall (fun (_, isUsed) -> not isUsed)) - |> Array.map (fun (m, _) -> m) - - //#if DEBUG - //let formatRange (x: FSharp.Compiler.Range.range) = sprintf "(%d, %d) - (%d, %d)" x.StartLine x.StartColumn x.EndLine x.EndColumn - - //symbolsUses - //|> Array.map (fun su -> sprintf "%s, %s, is definition = %b, Symbol (def range = %A)" - // (formatRange su.RangeAlternate) su.Symbol.DisplayName su.IsFromDefinition - // (su.Symbol.DeclarationLocation |> Option.map formatRange)) - //|> Logging.Logging.logInfof "SymbolUses:\n%+A" - // - //definitions - //|> Seq.map (fun su -> sprintf "su range = %s, symbol range = %A, symbol name = %s" - // (formatRange su.RangeAlternate) (su.Symbol.DeclarationLocation |> Option.map formatRange) su.Symbol.DisplayName) - //|> Logging.Logging.logInfof "Definitions:\n%A" - // - //usages - //|> Seq.map formatRange - //|> Seq.toArray - //|> Logging.Logging.logInfof "Used ranges:\n%A" - // - //unusedRanges - //|> Array.map formatRange - //|> Logging.Logging.logInfof "Unused ranges: %A" - //#endif - unusedRanges interface IFSharpUnusedDeclarationsDiagnosticAnalyzer with @@ -98,8 +36,7 @@ type internal UnusedDeclarationsAnalyzer [] () = let! sourceText = document.GetTextAsync() let checker = getChecker document let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName = userOpName) - let! allSymbolUsesInFile = checkResults.GetAllUsesOfAllSymbolsInFile() |> liftAsync - let unusedRanges = getUnusedDeclarationRanges allSymbolUsesInFile (isScriptFile document.FilePath) + let! unusedRanges = UnusedDeclarations.getUnusedDeclarations( checkResults, (isScriptFile document.FilePath)) |> liftAsync return unusedRanges |> Seq.map (fun m -> Diagnostic.Create(descriptor, RoslynHelpers.RangeToLocation(m, sourceText, document.FilePath))) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs b/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs index a3d9b78452..dd7359d08f 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs @@ -77,32 +77,6 @@ type FSharpSymbolUse with | projects -> Some (SymbolDeclarationLocation.Projects (projects, isSymbolLocalForProject)) | None -> None - member this.IsPrivateToFile = - let isPrivate = - match this.Symbol with - | :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || m.Accessibility.IsPrivate - | :? FSharpEntity as m -> m.Accessibility.IsPrivate - | :? FSharpGenericParameter -> true - | :? FSharpUnionCase as m -> m.Accessibility.IsPrivate - | :? FSharpField as m -> m.Accessibility.IsPrivate - | _ -> false - - let declarationLocation = - match this.Symbol.SignatureLocation with - | Some x -> Some x - | _ -> - match this.Symbol.DeclarationLocation with - | Some x -> Some x - | _ -> this.Symbol.ImplementationLocation - - let declaredInTheFile = - match declarationLocation with - | Some declRange -> declRange.FileName = this.RangeAlternate.FileName - | _ -> false - - isPrivate && declaredInTheFile - - type FSharpMemberOrFunctionOrValue with member x.IsConstructor = x.CompiledName = ".ctor" From e086149c79ec2a25ea617d4afb67483d2d20cc14 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 21 Jan 2020 17:12:44 -0800 Subject: [PATCH 055/101] save the contents of the NuGet package cache as a build artifact (#8303) --- azure-pipelines.yml | 40 ++++++++++++++++++++++++++++++++++ eng/AfterSolutionBuild.targets | 18 +++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 eng/AfterSolutionBuild.targets diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1906529ef3..131be207af 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -187,6 +187,14 @@ stages: publishLocation: Container continueOnError: true condition: eq(variables['_testKind'], 'testFSharpQA') + - task: PublishBuildArtifacts@1 + displayName: Publish NuGet cache contents + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\NugetPackageRootContents' + ArtifactName: 'NuGetPackageContents Windows $(_testKind)' + publishLocation: Container + continueOnError: true + condition: always() # Linux - job: Linux @@ -208,6 +216,14 @@ stages: searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' continueOnError: true condition: always() + - task: PublishBuildArtifacts@1 + displayName: Publish NuGet cache contents + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/NugetPackageRootContents' + ArtifactName: 'NuGetPackageContents Linux' + publishLocation: Container + continueOnError: true + condition: always() # MacOS - job: MacOS @@ -229,6 +245,14 @@ stages: searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' continueOnError: true condition: always() + - task: PublishBuildArtifacts@1 + displayName: Publish NuGet cache contents + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/NugetPackageRootContents' + ArtifactName: 'NuGetPackageContents Mac' + publishLocation: Container + continueOnError: true + condition: always() # Source Build Linux - job: SourceBuild_Linux @@ -239,6 +263,14 @@ stages: clean: true - script: ./eng/cibuild.sh --configuration Release /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true displayName: Build + - task: PublishBuildArtifacts@1 + displayName: Publish NuGet cache contents + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/NugetPackageRootContents' + ArtifactName: 'NuGetPackageContents SourceBuild_Linux' + publishLocation: Container + continueOnError: true + condition: always() # Source Build Windows - job: SourceBuild_Windows @@ -249,6 +281,14 @@ stages: clean: true - script: eng\CIBuild.cmd -configuration Release -noSign /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true displayName: Build + - task: PublishBuildArtifacts@1 + displayName: Publish NuGet cache contents + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\NugetPackageRootContents' + ArtifactName: 'NuGetPackageContents SourceBuild_Windows' + publishLocation: Container + continueOnError: true + condition: always() # Up-to-date - job: UpToDate_Windows diff --git a/eng/AfterSolutionBuild.targets b/eng/AfterSolutionBuild.targets new file mode 100644 index 0000000000..ffd633e4f9 --- /dev/null +++ b/eng/AfterSolutionBuild.targets @@ -0,0 +1,18 @@ + + + + + + + + + + + $(ArtifactsDir)NugetPackageRootContents + $(PackageRootArtifactDirectory)/package_contents.txt + + + + + From d2158a11fb62fb34a2b5679a65fe25473ce8bed4 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 21 Jan 2020 17:13:10 -0800 Subject: [PATCH 056/101] Fix nuget and ref assemblies (#8252) * Fix nuget and ref assemblies * Packaging fixes * tweaks * use substring rather than remove * Removed unused md * -1 means not found --- .../FSharp.DependencyManager.Utilities.fs | 52 ++++++++++++++----- .../FSharpScriptTests.fs | 19 +++++++ 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index 493a6ba789..d86ceb3dbb 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -205,7 +205,7 @@ module Utilities = | None -> "" let arguments prefix = - sprintf "%s -restore %s %c%s%c /t:FSI-PackageManagement" prefix binLoggingArguments '\"' projectPath '\"' + sprintf "%s -restore %s %c%s%c /t:InteractivePackageManagement" prefix binLoggingArguments '\"' projectPath '\"' let workingDir = Path.GetDirectoryName projectPath @@ -230,6 +230,10 @@ namespace lib" $(TARGETFRAMEWORK) false + + + 4.7.0 + 4.7.1-* @@ -273,15 +277,31 @@ $(PACKAGEREFERENCES) - - - Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) - $([MSBuild]::EnsureTrailingSlash('$(%(FsxResolvedFile.PackageRootProperty))')) - $(%(FsxResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx - + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx + $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').StartsWith('ref/')) + %(ResolvedCompileFileDefinitions.NuGetPackageId) + %(ResolvedCompileFileDefinitions.NuGetPackageVersion) + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(RuntimeCopyLocalItems.FileName)%(RuntimeCopyLocalItems.Extension).fsx + $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').StartsWith('ref/')) + %(RuntimeCopyLocalItems.NuGetPackageId) + %(RuntimeCopyLocalItems.NuGetPackageVersion) + @@ -290,7 +310,7 @@ $(PACKAGEREFERENCES) - + @@ -300,12 +320,18 @@ $(PACKAGEREFERENCES) - + + + + + + + + - - + - + diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs index 3046c3a76f..9dc326d0ed 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs @@ -190,6 +190,25 @@ printfn ""%A"" result Assert.AreEqual(123, value.ReflectionValue :?> int32) #endif + [] + member __.``ML - use assembly with ref dependencies``() = + let code = @" +#r ""nuget:Microsoft.ML.OnnxTransformer,1.4.0"" + +open System +open System.Numerics.Tensors +let inputValues = [| 12.0; 10.0; 17.0; 5.0 |] +let tInput = new DenseTensor(inputValues.AsMemory(), new ReadOnlySpan([|4|])) +tInput.Length +" + use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) + let mutable assemblyRefCount = 0; + Event.add (fun _ -> assemblyRefCount <- assemblyRefCount + 1) script.AssemblyReferenceAdded + let opt = script.Eval(code) |> getValue + let value = opt.Value + Assert.AreEqual(4L, value.ReflectionValue :?> int64) + + [] member __.``Simple pinvoke should not be impacted by native resolver``() = let code = @" From fd3fedb6720ef7cfd2d760811c4314c7ceb1baf2 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 21 Jan 2020 17:56:45 -0800 Subject: [PATCH 057/101] fix whitespace in resource (#8312) --- .../Resources/Microsoft.VisualStudio.Editors.Designer.resx | 1 - 1 file changed, 1 deletion(-) diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/Microsoft.VisualStudio.Editors.Designer.resx b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/Microsoft.VisualStudio.Editors.Designer.resx index 697e650fcb..8701ba21d7 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/Microsoft.VisualStudio.Editors.Designer.resx +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/Microsoft.VisualStudio.Editors.Designer.resx @@ -1276,7 +1276,6 @@ CONSIDER: get this from CodeDom {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" From 83f1785c2b32379202f425ad4bd898fa9aed6e10 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 21 Jan 2020 19:08:46 -0800 Subject: [PATCH 058/101] Include System.Buffers in vsix (#8277) * Include System.Buffers in vsix * Updated nuspec with System.Buffers * Add buffers to output group Co-authored-by: Kevin Ransom (msft) --- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 1 + .../FSharp.Compiler.Private.netcore.nuspec | 1 + .../FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec | 1 + vsintegration/Directory.Build.targets | 1 + 4 files changed, 4 insertions(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index c919f3056b..e226bcbe98 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -27,6 +27,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec index 9fb4c25cf4..8f148cf1d7 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec @@ -33,6 +33,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec index 94a727bbcc..c124bcffc2 100644 --- a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec +++ b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec @@ -22,6 +22,7 @@ + diff --git a/vsintegration/Directory.Build.targets b/vsintegration/Directory.Build.targets index bc5c6d7195..cd83837f79 100644 --- a/vsintegration/Directory.Build.targets +++ b/vsintegration/Directory.Build.targets @@ -18,6 +18,7 @@ + From b8c748c69c4fca42d2dc66024388d6e7b69a7971 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jan 2020 13:37:18 +0000 Subject: [PATCH 059/101] fix 5580 and better encapsulate constraint solver (#8294) * fix 5580 and better encapsulate constraint solver * fix 5580 and better encapsulate constraint solver * fix 5580 and better encapsulate constraint solver * fix 5580 and better encapsulate constraint solver * add new tests * nudge CI --- src/fsharp/ConstraintSolver.fs | 244 ++++++++++++++++++------- src/fsharp/ConstraintSolver.fsi | 127 +++++++------ src/fsharp/IlxGen.fs | 1 - src/fsharp/TypeChecker.fs | 58 ++---- tests/fsharp/tests.fs | 12 ++ tests/fsharp/typecheck/sigs/neg116.bsl | 12 ++ tests/fsharp/typecheck/sigs/neg116.fs | 10 + tests/fsharp/typecheck/sigs/neg117.bsl | 12 ++ tests/fsharp/typecheck/sigs/neg117.fs | 82 +++++++++ tests/fsharp/typecheck/sigs/neg118.bsl | 12 ++ tests/fsharp/typecheck/sigs/neg118.fs | 28 +++ tests/fsharp/typecheck/sigs/neg119.bsl | 22 +++ tests/fsharp/typecheck/sigs/neg119.fs | 40 ++++ 13 files changed, 498 insertions(+), 162 deletions(-) create mode 100644 tests/fsharp/typecheck/sigs/neg116.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg116.fs create mode 100644 tests/fsharp/typecheck/sigs/neg117.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg117.fs create mode 100644 tests/fsharp/typecheck/sigs/neg118.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg118.fs create mode 100644 tests/fsharp/typecheck/sigs/neg119.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg119.fs diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 0360d253dd..59b10f7be7 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -27,9 +27,19 @@ // can-unify predicates used in method overload resolution and trait constraint // satisfaction. // +// The two main principles are: +// 1. Ensure any solution that is found is sound (no logic is skipped), +// 2. Because of method overloading and SRTP constraints and other constructs, processing of +// constraints is algorithmic and must proceed in a definite, fixed order. +// Once we start doing resolutions in a particular order we must keep doing them +// in the same order. +// +// There is little use of back-tracking/undo or "retry" in the constraint solver, except in the +// limited case ofs of SRTP solving and method overloading, and some other adhoc limited cases +// like checking for "printf" format strings. As a result there are cases involving +// method overloading and SRTP that the solver "can't solve". This is intentional and by-design. //------------------------------------------------------------------------- - module internal FSharp.Compiler.ConstraintSolver open Internal.Utilities.Collections @@ -429,8 +439,39 @@ let ShowAccessDomain ad = exception NonRigidTypar of displayEnv: DisplayEnv * string option * range * TType * TType * range -exception LocallyAbortOperationThatFailsToResolveOverload +/// Signal that there is still an unresolved overload in the constraint problem. The +/// unresolved overload constraint remains in the constraint state, and we skip any +/// further processing related to whichever overall adjustment to constraint solver state +/// is being processed. +/// +// NOTE: The addition of this abort+skip appears to be a mistake which has crept into F# type inference, +// and its status is currently under review. See https://github.com/dotnet/fsharp/pull/8294 and others. +// +// Here is the history: +// 1. The local abort was added as part of an attempted performance optimization https://github.com/dotnet/fsharp/pull/1650 +// This change was released in the VS2017 GA release. +// +// 2. However, it also impacts the logic of type inference, by skipping checking. +// Because of this an attempt was made to revert it in https://github.com/dotnet/fsharp/pull/4173. +// +// Unfortunately, existing code had begun to depend on the new behaviours enabled by the +// change, and the revert was abandoned before release in https://github.com/dotnet/fsharp/pull/4348 +// +// Comments on soundness: +// The use of the abort is normally sound because the SRTP constraint +// will be subject to further processing at a later point. +// +// However, it seems likely that the abort may result in other processing associated +// with an overall constraint being skipped (e.g. the processing related to subsequent elements +// of a tuple constraint). +exception AbortForFailedOverloadResolution + +/// This is used at (nearly all) entry points into the constraint solver to make sure that the +/// AbortForFailedOverloadResolution is caught and processing continues. +let inline TryD_IgnoreAbortForFailedOverloadResolution f1 f2 = + TryD f1 (function AbortForFailedOverloadResolution -> CompleteD | exn -> f2 exn) +/// Represents a very local condition where we prefer to report errors before stripping type abbreviations. exception LocallyAbortOperationThatLosesAbbrevs let localAbortD = ErrorD LocallyAbortOperationThatLosesAbbrevs @@ -929,8 +970,9 @@ and private SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln t // Back out of expansions of type abbreviations to give improved error messages. // Note: any "normalization" of equations on type variables must respect the trace parameter TryD (fun () -> SolveTypeEqualsType csenv ndeep m2 trace cxsln ty1 ty2) - (function LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInEqualityRelation(csenv.DisplayEnv, ty1, ty2, csenv.m, m2, csenv.eContextInfo)) - | err -> ErrorD err) + (function + | LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInEqualityRelation(csenv.DisplayEnv, ty1, ty2, csenv.m, m2, csenv.eContextInfo)) + | err -> ErrorD err) and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = match origl1, origl2 with @@ -1059,8 +1101,9 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional and SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace cxsln ty1 ty2 = let denv = csenv.DisplayEnv TryD (fun () -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln ty1 ty2) - (function LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInSubsumptionRelation(denv, ty1, ty2, csenv.m, m2)) - | err -> ErrorD err) + (function + | LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInSubsumptionRelation(denv, ty1, ty2, csenv.m, m2)) + | err -> ErrorD err) //------------------------------------------------------------------------- // Solve and record non-equality constraints @@ -1451,7 +1494,9 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload Some(CalledMeth(csenv.InfoReader, None, false, FreshenMethInfo, m, AccessibleFromEverywhere, minfo, minst, minst, None, objtys, [(callerArgs, [])], false, false, None))) let methOverloadResult, errors = - trace.CollectThenUndoOrCommit (fun (a, _) -> Option.isSome a) (fun trace -> ResolveOverloading csenv (WithTrace trace) nm ndeep (Some traitInfo) (0, 0) AccessibleFromEverywhere calledMethGroup false (Some rty)) + trace.CollectThenUndoOrCommit + (fun (a, _) -> Option.isSome a) + (fun trace -> ResolveOverloading csenv (WithTrace trace) nm ndeep (Some traitInfo) (0, 0) AccessibleFromEverywhere calledMethGroup false (Some rty)) match anonRecdPropSearch, recdPropSearch, methOverloadResult with | Some (anonInfo, tinst, i), None, None -> @@ -1497,7 +1542,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload match errors with | ErrorResult (_, UnresolvedOverloading _) when not ignoreUnresolvedOverload && (not (nm = "op_Explicit" || nm = "op_Implicit")) -> - return! ErrorD LocallyAbortOperationThatFailsToResolveOverload + return! ErrorD AbortForFailedOverloadResolution | _ -> return TTraitUnsolved } @@ -2183,25 +2228,23 @@ and CanMemberSigsMatchUpToCheck // "ty2 casts to ty1" // "a value of type ty2 can be used where a value of type ty1 is expected" and private SolveTypeSubsumesTypeWithReport (csenv: ConstraintSolverEnv) ndeep m trace cxsln ty1 ty2 = - TryD (fun () -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m trace cxsln ty1 ty2) - (function - | LocallyAbortOperationThatFailsToResolveOverload -> CompleteD - | res -> - match csenv.eContextInfo with - | ContextInfo.RuntimeTypeTest isOperator -> - // test if we can cast other way around - match CollectThenUndo (fun newTrace -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m (OptionalTrace.WithTrace newTrace) cxsln ty2 ty1) with - | OkResult _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, ContextInfo.DowncastUsedInsteadOfUpcast isOperator, m)) - | _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, ContextInfo.NoContext, m)) - | _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, csenv.eContextInfo, m))) + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m trace cxsln ty1 ty2) + (fun res -> + match csenv.eContextInfo with + | ContextInfo.RuntimeTypeTest isOperator -> + // test if we can cast other way around + match CollectThenUndo (fun newTrace -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m (OptionalTrace.WithTrace newTrace) cxsln ty2 ty1) with + | OkResult _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, ContextInfo.DowncastUsedInsteadOfUpcast isOperator, m)) + | _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, ContextInfo.NoContext, m)) + | _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g, csenv.DisplayEnv, ty1, ty2, res, csenv.eContextInfo, m))) // ty1: actual // ty2: expected and private SolveTypeEqualsTypeWithReport (csenv: ConstraintSolverEnv) ndeep m trace cxsln actual expected = - TryD (fun () -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m trace cxsln actual expected) - (function - | LocallyAbortOperationThatFailsToResolveOverload -> CompleteD - | res -> ErrorD (ErrorFromAddingTypeEquation(csenv.g, csenv.DisplayEnv, actual, expected, res, m))) + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m trace cxsln actual expected) + (fun res -> ErrorD (ErrorFromAddingTypeEquation(csenv.g, csenv.DisplayEnv, actual, expected, res, m))) and ArgsMustSubsumeOrConvert (csenv: ConstraintSolverEnv) @@ -2677,16 +2720,22 @@ and ResolveOverloading | None -> None, errors +let ResolveOverloadingForCall denv css m methodName ndeep cx callerArgCounts ad calledMethGroup permitOptArgs reqdRetTyOpt = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + ResolveOverloading csenv NoTrace methodName ndeep cx callerArgCounts ad calledMethGroup permitOptArgs reqdRetTyOpt /// This is used before analyzing the types of arguments in a single overload resolution let UnifyUniqueOverloading - (csenv: ConstraintSolverEnv) + denv + css + m callerArgCounts methodName ad (calledMethGroup: CalledMeth list) reqdRetTy // The expected return type, if known = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv let m = csenv.m // See what candidates we have based on name and arity let candidates = calledMethGroup |> List.filter (fun cmeth -> cmeth.IsCandidate(m, ad)) @@ -2716,15 +2765,17 @@ let UnifyUniqueOverloading | _ -> ResultD false -let EliminateConstraintsForGeneralizedTypars csenv (trace: OptionalTrace) (generalizedTypars: Typars) = - // Remove the global constraints where this type variable appears in the support of the constraint - generalizedTypars - |> List.iter (fun tp -> +/// Remove the global constraints where these type variables appear in the support of the constraint +let EliminateConstraintsForGeneralizedTypars denv css m (trace: OptionalTrace) (generalizedTypars: Typars) = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + for tp in generalizedTypars do let tpn = tp.Stamp let cxst = csenv.SolverState.ExtraCxs let cxs = cxst.FindAll tpn - cxs |> List.iter (fun cx -> trace.Exec (fun () -> cxst.Remove tpn) (fun () -> (csenv.SolverState.ExtraCxs.Add (tpn, cx)))) - ) + for cx in cxs do + trace.Exec + (fun () -> cxst.Remove tpn) + (fun () -> (csenv.SolverState.ExtraCxs.Add (tpn, cx))) //------------------------------------------------------------------------- @@ -2735,7 +2786,8 @@ let EliminateConstraintsForGeneralizedTypars csenv (trace: OptionalTrace) (gener //------------------------------------------------------------------------- let AddCxTypeEqualsType contextInfo denv css m actual expected = - SolveTypeEqualsTypeWithReport (MakeConstraintSolverEnv contextInfo css m denv) 0 m NoTrace None actual expected + let csenv = MakeConstraintSolverEnv contextInfo css m denv + SolveTypeEqualsTypeWithReport csenv 0 m NoTrace None actual expected |> RaiseOperationResult let UndoIfFailed f = @@ -2770,17 +2822,23 @@ let UndoIfFailedOrWarnings f = false let AddCxTypeEqualsTypeUndoIfFailed denv css m ty1 ty2 = - UndoIfFailed (fun trace -> SolveTypeEqualsTypeKeepAbbrevs (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m (WithTrace trace) ty1 ty2) + UndoIfFailed (fun trace -> + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + SolveTypeEqualsTypeKeepAbbrevs csenv 0 m (WithTrace trace) ty1 ty2) let AddCxTypeEqualsTypeUndoIfFailedOrWarnings denv css m ty1 ty2 = - UndoIfFailedOrWarnings (fun trace -> SolveTypeEqualsTypeKeepAbbrevs (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m (WithTrace trace) ty1 ty2) + UndoIfFailedOrWarnings (fun trace -> + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + SolveTypeEqualsTypeKeepAbbrevs csenv 0 m (WithTrace trace) ty1 ty2) let AddCxTypeEqualsTypeMatchingOnlyUndoIfFailed denv css m ty1 ty2 = let csenv = { MakeConstraintSolverEnv ContextInfo.NoContext css m denv with MatchingOnly = true } UndoIfFailed (fun trace -> SolveTypeEqualsTypeKeepAbbrevs csenv 0 m (WithTrace trace) ty1 ty2) let AddCxTypeMustSubsumeTypeUndoIfFailed denv css m ty1 ty2 = - UndoIfFailed (fun trace -> SolveTypeSubsumesTypeKeepAbbrevs (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m (WithTrace trace) None ty1 ty2) + UndoIfFailed (fun trace -> + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + SolveTypeSubsumesTypeKeepAbbrevs csenv 0 m (WithTrace trace) None ty1 ty2) let AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed denv css m ty1 ty2 = let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv @@ -2788,64 +2846,114 @@ let AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed denv css m ty1 ty2 = UndoIfFailed (fun trace -> SolveTypeSubsumesTypeKeepAbbrevs csenv 0 m (WithTrace trace) None ty1 ty2) let AddCxTypeMustSubsumeType contextInfo denv css m trace ty1 ty2 = - SolveTypeSubsumesTypeWithReport (MakeConstraintSolverEnv contextInfo css m denv) 0 m trace None ty1 ty2 + let csenv = MakeConstraintSolverEnv contextInfo css m denv + SolveTypeSubsumesTypeWithReport csenv 0 m trace None ty1 ty2 |> RaiseOperationResult let AddCxMethodConstraint denv css m trace traitInfo = - TryD (fun () -> + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> trackErrors { do! - SolveMemberConstraint (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) true false 0 m trace traitInfo + SolveMemberConstraint csenv true false 0 m trace traitInfo |> OperationResult.ignore }) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeMustSupportNull denv css m trace ty = - TryD (fun () -> SolveTypeSupportsNull (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeSupportsNull csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeMustSupportComparison denv css m trace ty = - TryD (fun () -> SolveTypeSupportsComparison (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeSupportsComparison csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeMustSupportEquality denv css m trace ty = - TryD (fun () -> SolveTypeSupportsEquality (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeSupportsEquality csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeMustSupportDefaultCtor denv css m trace ty = - TryD (fun () -> SolveTypeRequiresDefaultConstructor (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeRequiresDefaultConstructor csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeIsReferenceType denv css m trace ty = - TryD (fun () -> SolveTypeIsReferenceType (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeIsReferenceType csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeIsValueType denv css m trace ty = - TryD (fun () -> SolveTypeIsNonNullableValueType (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeIsNonNullableValueType csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeIsUnmanaged denv css m trace ty = - TryD (fun () -> SolveTypeIsUnmanaged (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeIsUnmanaged csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeIsEnum denv css m trace ty underlying = - TryD (fun () -> SolveTypeIsEnum (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty underlying) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeIsEnum csenv 0 m trace ty underlying) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult let AddCxTypeIsDelegate denv css m trace ty aty bty = - TryD (fun () -> SolveTypeIsDelegate (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m trace ty aty bty) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTypeIsDelegate csenv 0 m trace ty aty bty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + |> RaiseOperationResult + +let AddCxTyparDefaultsTo denv css m ctxtInfo tp ridx ty = + let csenv = MakeConstraintSolverEnv ctxtInfo css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> AddConstraint csenv 0 m NoTrace tp (TyparConstraint.DefaultsTo(ridx, ty, m))) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult +let SolveTypeAsError denv css m ty = + let ty2 = NewErrorType () + assert((destTyparTy css.g ty2).IsFromError) + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + SolveTypeEqualsTypeKeepAbbrevs csenv 0 m NoTrace ty ty2 |> ignore + +let ApplyTyparDefaultAtPriority denv css priority (tp: Typar) = + tp.Constraints |> List.iter (fun tpc -> + match tpc with + | TyparConstraint.DefaultsTo(priority2, ty2, m) when priority2 = priority -> + let ty1 = mkTyparTy tp + if not tp.IsSolved && not (typeEquiv css.g ty1 ty2) then + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> + SolveTyparEqualsType csenv 0 m NoTrace ty1 ty2) + (fun res -> + SolveTypeAsError denv css m ty1 + ErrorD(ErrorFromApplyingDefault(css.g, denv, tp, ty2, res, m))) + |> RaiseOperationResult + | _ -> ()) + let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: TraitConstraintInfo) argExprs = trackErrors { let css = { g = g @@ -2952,24 +3060,34 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra | Choice5Of5 () -> ResultD None } - let ChooseTyparSolutionAndSolve css denv tp = let g = css.g let amap = css.amap let max, m = ChooseTyparSolutionAndRange g amap tp let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv - TryD (fun () -> SolveTyparEqualsType csenv 0 m NoTrace (mkTyparTy tp) max) - (fun err -> ErrorD(ErrorFromApplyingDefault(g, denv, tp, max, err, m))) + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> SolveTyparEqualsType csenv 0 m NoTrace (mkTyparTy tp) max) + (fun err -> ErrorD(ErrorFromApplyingDefault(g, denv, tp, max, err, m))) |> RaiseOperationResult - let CheckDeclaredTypars denv css m typars1 typars2 = - TryD (fun () -> + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> CollectThenUndo (fun trace -> - SolveTypeEqualsTypeEqns (MakeConstraintSolverEnv ContextInfo.NoContext css m denv) 0 m (WithTrace trace) None + SolveTypeEqualsTypeEqns csenv 0 m (WithTrace trace) None (List.map mkTyparTy typars1) (List.map mkTyparTy typars2))) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + (fun res -> + ErrorD (ErrorFromAddingConstraint(denv, res, m))) + |> RaiseOperationResult + +let CanonicalizePartialInferenceProblem css denv m tps = + // Canonicalize constraints prior to generalization + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + TryD_IgnoreAbortForFailedOverloadResolution + (fun () -> CanonicalizeRelevantMemberConstraints csenv 0 NoTrace tps) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult /// An approximation used during name resolution for intellisense to eliminate extension members which will not diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 6aa40c6ea9..8fdaabf82c 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -17,32 +17,32 @@ open FSharp.Compiler.MethodCalls open FSharp.Compiler.InfoReader /// Create a type variable representing the use of a "_" in F# code -val NewAnonTypar : TyparKind * range * TyparRigidity * TyparStaticReq * TyparDynamicReq -> Typar +val NewAnonTypar: TyparKind * range * TyparRigidity * TyparStaticReq * TyparDynamicReq -> Typar /// Create an inference type variable -val NewInferenceType : unit -> TType +val NewInferenceType: unit -> TType /// Create an inference type variable for the kind of a byref pointer -val NewByRefKindInferenceType : TcGlobals -> range -> TType +val NewByRefKindInferenceType: TcGlobals -> range -> TType /// Create an inference type variable representing an error condition when checking an expression -val NewErrorType : unit -> TType +val NewErrorType: unit -> TType /// Create an inference type variable representing an error condition when checking a measure -val NewErrorMeasure : unit -> Measure +val NewErrorMeasure: unit -> Measure /// Create a list of inference type variables, one for each element in the input list -val NewInferenceTypes : 'a list -> TType list +val NewInferenceTypes: 'a list -> TType list /// Given a set of formal type parameters and their constraints, make new inference type variables for /// each and ensure that the constraints on the new type variables are adjusted to refer to these. -val FreshenAndFixupTypars : range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list +val FreshenAndFixupTypars: range -> TyparRigidity -> Typars -> TType list -> Typars -> Typars * TyparInst * TType list -val FreshenTypeInst : range -> Typars -> Typars * TyparInst * TType list +val FreshenTypeInst: range -> Typars -> Typars * TyparInst * TType list -val FreshenTypars : range -> Typars -> TType list +val FreshenTypars: range -> Typars -> TType list -val FreshenMethInfo : range -> MethInfo -> TType list +val FreshenMethInfo: range -> MethInfo -> TType list [] /// Information about the context of a type equation. @@ -114,53 +114,70 @@ type TcValF = (ValRef -> ValUseFlag -> TType list -> range -> Expr * TType) type ConstraintSolverState = static member New: TcGlobals * Import.ImportMap * InfoReader * TcValF -> ConstraintSolverState -type ConstraintSolverEnv - -val BakedInTraitConstraintNames : Set - -val MakeConstraintSolverEnv : ContextInfo -> ConstraintSolverState -> range -> DisplayEnv -> ConstraintSolverEnv +val BakedInTraitConstraintNames: Set [] type Trace type OptionalTrace = -| NoTrace -| WithTrace of Trace - -val SimplifyMeasuresInTypeScheme : TcGlobals -> bool -> Typars -> TType -> TyparConstraint list -> Typars -val SolveTyparEqualsType : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult -val SolveTypeEqualsTypeKeepAbbrevs : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult - -/// Canonicalize constraints prior to generalization -val CanonicalizeRelevantMemberConstraints : ConstraintSolverEnv -> int -> OptionalTrace -> Typars -> OperationResult - -val ResolveOverloading : ConstraintSolverEnv -> OptionalTrace -> string -> ndeep: int -> TraitConstraintInfo option -> int * int -> AccessorDomain -> CalledMeth list -> bool -> TType option -> CalledMeth option * OperationResult -val UnifyUniqueOverloading : ConstraintSolverEnv -> int * int -> string -> AccessorDomain -> CalledMeth list -> TType -> OperationResult -val EliminateConstraintsForGeneralizedTypars : ConstraintSolverEnv -> OptionalTrace -> Typars -> unit - -val CheckDeclaredTypars : DisplayEnv -> ConstraintSolverState -> range -> Typars -> Typars -> unit - -val AddConstraint : ConstraintSolverEnv -> int -> Range.range -> OptionalTrace -> Typar -> TyparConstraint -> OperationResult -val AddCxTypeEqualsType : ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> unit -val AddCxTypeEqualsTypeUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool -val AddCxTypeEqualsTypeUndoIfFailedOrWarnings : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool -val AddCxTypeEqualsTypeMatchingOnlyUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool -val AddCxTypeMustSubsumeType : ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit -val AddCxTypeMustSubsumeTypeUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool -val AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool -val AddCxMethodConstraint : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TraitConstraintInfo -> unit -val AddCxTypeMustSupportNull : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeMustSupportComparison : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeMustSupportEquality : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeMustSupportDefaultCtor : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeIsReferenceType : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeIsValueType : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeIsUnmanaged : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit -val AddCxTypeIsEnum : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit -val AddCxTypeIsDelegate : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> TType -> unit - -val CodegenWitnessThatTypeSupportsTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult - -val ChooseTyparSolutionAndSolve : ConstraintSolverState -> DisplayEnv -> Typar -> unit - -val IsApplicableMethApprox : TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool + | NoTrace + | WithTrace of Trace + +val SimplifyMeasuresInTypeScheme: TcGlobals -> bool -> Typars -> TType -> TyparConstraint list -> Typars + +val ResolveOverloadingForCall: DisplayEnv -> ConstraintSolverState -> range -> string -> ndeep: int -> TraitConstraintInfo option -> int * int -> AccessorDomain -> CalledMeth list -> bool -> TType option -> CalledMeth option * OperationResult + +val UnifyUniqueOverloading: DisplayEnv -> ConstraintSolverState -> range -> int * int -> string -> AccessorDomain -> CalledMeth list -> TType -> OperationResult + +/// Remove the global constraints where these type variables appear in the support of the constraint +val EliminateConstraintsForGeneralizedTypars: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> Typars -> unit + +val CheckDeclaredTypars: DisplayEnv -> ConstraintSolverState -> range -> Typars -> Typars -> unit + +val AddCxTypeEqualsType: ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> unit + +val AddCxTypeEqualsTypeUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool + +val AddCxTypeEqualsTypeUndoIfFailedOrWarnings: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool + +val AddCxTypeEqualsTypeMatchingOnlyUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool + +val AddCxTypeMustSubsumeType: ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit + +val AddCxTypeMustSubsumeTypeUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool + +val AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool + +val AddCxMethodConstraint: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TraitConstraintInfo -> unit + +val AddCxTypeMustSupportNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeMustSupportComparison: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeMustSupportEquality: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeMustSupportDefaultCtor: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeIsReferenceType: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeIsValueType: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeIsUnmanaged: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeIsEnum: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit + +val AddCxTypeIsDelegate: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> TType -> unit + +val AddCxTyparDefaultsTo: DisplayEnv -> ConstraintSolverState -> range -> ContextInfo -> Typar -> int -> TType -> unit + +val SolveTypeAsError: DisplayEnv -> ConstraintSolverState -> range -> TType -> unit + +val ApplyTyparDefaultAtPriority: DisplayEnv -> ConstraintSolverState -> priority: int -> Typar -> unit + +val CodegenWitnessThatTypeSupportsTraitConstraint: TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult + +val ChooseTyparSolutionAndSolve: ConstraintSolverState -> DisplayEnv -> Typar -> unit + +val IsApplicableMethApprox: TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool + +val CanonicalizePartialInferenceProblem: ConstraintSolverState -> DisplayEnv -> range -> Typars -> unit \ No newline at end of file diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index bae42ad081..412d1a62ac 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -7754,4 +7754,3 @@ type IlxAssemblyGenerator(amap: ImportMap, tcGlobals: TcGlobals, tcVal: Constrai /// Invert the compilation of the given value and return its current dynamic value and its compiled System.Type member __.LookupGeneratedValue (ctxt, v) = LookupGeneratedValue amap ctxt ilxGenEnv v - diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 6609d5ad95..c888057686 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -2284,13 +2284,6 @@ module GeneralizationHelpers = ConstraintSolver.ChooseTyparSolutionAndSolve cenv.css denv tp) generalizedTypars - let CanonicalizePartialInferenceProblem (cenv, denv, m) tps = - // Canonicalize constraints prior to generalization - let csenv = (MakeConstraintSolverEnv ContextInfo.NoContext cenv.css m denv) - TryD (fun () -> ConstraintSolver.CanonicalizeRelevantMemberConstraints csenv 0 NoTrace tps) - (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) - |> RaiseOperationResult - let ComputeAndGeneralizeGenericTypars (cenv, denv: DisplayEnv, m, @@ -2333,8 +2326,7 @@ module GeneralizationHelpers = generalizedTypars |> List.iter (SetTyparRigid cenv.g denv m) // Generalization removes constraints related to generalized type variables - let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css m denv - EliminateConstraintsForGeneralizedTypars csenv NoTrace generalizedTypars + EliminateConstraintsForGeneralizedTypars denv cenv.css m NoTrace generalizedTypars generalizedTypars @@ -4333,8 +4325,7 @@ let rec TcTyparConstraint ridx cenv newOk checkCxs occ (env: TcEnv) tpenv c = | WhereTyparDefaultsToType(tp, ty, m) -> let ty', tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv ty let tp', tpenv = TcTypar cenv env newOk tpenv tp - let csenv = MakeConstraintSolverEnv env.eContextInfo cenv.css m env.DisplayEnv - AddConstraint csenv 0 m NoTrace tp' (TyparConstraint.DefaultsTo(ridx, ty', m)) |> CommitOperationResult + AddCxTyparDefaultsTo env.DisplayEnv cenv.css m env.eContextInfo tp' ridx ty' tpenv | WhereTyparSubtypeOfType(tp, ty, m) -> @@ -5595,11 +5586,7 @@ and TcPatterns warnOnUpper cenv env vFlags s argTys args = assert (List.length args = List.length argTys) List.mapFold (fun s (ty, pat) -> TcPat warnOnUpper cenv env None vFlags s ty pat) s (List.zip argTys args) - -and solveTypAsError cenv denv m ty = - let ty2 = NewErrorType () - assert((destTyparTy cenv.g ty2).IsFromError) - SolveTypeEqualsTypeKeepAbbrevs (MakeConstraintSolverEnv ContextInfo.NoContext cenv.css m denv) 0 m NoTrace ty ty2 |> ignore +and solveTypAsError cenv denv m ty = ConstraintSolver.SolveTypeAsError denv cenv.css m ty and RecordNameAndTypeResolutions_IdeallyWithoutHavingOtherEffects cenv env tpenv expr = // This function is motivated by cases like @@ -6782,7 +6769,7 @@ and TcObjectExprBinding cenv (env: TcEnv) implty tpenv (absSlotInfo, bind) = | _ -> declaredTypars // Canonicalize constraints prior to generalization - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, denv, m) declaredTypars + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css denv m declaredTypars let freeInEnv = GeneralizationHelpers.ComputeUngeneralizableTypars env @@ -9638,7 +9625,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela // Canonicalize inference problem prior to '.' lookup on variable types if isTyparTy cenv.g objExprTy then - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, env.DisplayEnv, mExprAndLongId) (freeInTypeLeftToRight cenv.g false objExprTy) + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css env.DisplayEnv mExprAndLongId (freeInTypeLeftToRight cenv.g false objExprTy) let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId findFlag false let mExprAndItem = unionRanges mObjExpr mItem @@ -10089,8 +10076,7 @@ and TcMethodApplication yield makeOneCalledMeth (minfo, pinfoOpt, false) ] let uniquelyResolved = - let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css mMethExpr denv - UnifyUniqueOverloading csenv callerArgCounts methodName ad preArgumentTypeCheckingCalledMethGroup returnTy + UnifyUniqueOverloading denv cenv.css mMethExpr callerArgCounts methodName ad preArgumentTypeCheckingCalledMethGroup returnTy uniquelyResolved, preArgumentTypeCheckingCalledMethGroup @@ -10182,17 +10168,15 @@ and TcMethodApplication CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt)) let callerArgCounts = (unnamedCurriedCallerArgs.Length, namedCurriedCallerArgs.Length) - let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css mMethExpr denv // Commit unassociated constraints prior to member overload resolution where there is ambiguity // about the possible target of the call. if not uniquelyResolved then - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, denv, mItem) + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css denv mItem (//freeInTypeLeftToRight cenv.g false returnTy @ (unnamedCurriedCallerArgs |> List.collectSquared (fun callerArg -> freeInTypeLeftToRight cenv.g false callerArg.Type))) - let result, errors = - ResolveOverloading csenv NoTrace methodName 0 None callerArgCounts ad postArgumentTypeCheckingCalledMethGroup true (Some returnTy) + let result, errors = ResolveOverloadingForCall denv cenv.css mMethExpr methodName 0 None callerArgCounts ad postArgumentTypeCheckingCalledMethGroup true (Some returnTy) match afterResolution, result with | AfterResolution.DoNothing, _ -> () @@ -11150,7 +11134,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (synBinds, synBinds // Canonicalize constraints prior to generalization let denv = env.DisplayEnv - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, denv, synBindsRange) + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css denv synBindsRange (checkedBinds |> List.collect (fun tbinfo -> let (CheckedBindingInfo(_, _, _, _, flex, _, _, _, tauTy, _, _, _, _, _)) = tbinfo let (ExplicitTyparInfo(_, declaredTypars, _)) = flex @@ -12025,7 +12009,7 @@ and TcIncrementalLetRecGeneralization cenv scopem else let supportForBindings = newGeneralizableBindings |> List.collect (TcLetrecComputeSupportForBinding cenv) - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, denv, scopem) supportForBindings + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css denv scopem supportForBindings let generalizedTyparsL = newGeneralizableBindings |> List.map (TcLetrecComputeAndGeneralizeGenericTyparsForBinding cenv denv freeInEnv) @@ -17530,27 +17514,15 @@ let ApplyDefaults cenv g denvAtEnd m mexpr extraAttribs = try let unsolved = FSharp.Compiler.FindUnsolved.UnsolvedTyparsOfModuleDef g cenv.amap denvAtEnd (mexpr, extraAttribs) - GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv, denvAtEnd, m) unsolved + ConstraintSolver.CanonicalizePartialInferenceProblem cenv.css denvAtEnd m unsolved - let applyDefaults priority = - unsolved |> List.iter (fun tp -> + // The priority order comes from the order of declaration of the defaults in FSharp.Core. + for priority = 10 downto 0 do + unsolved |> List.iter (fun tp -> if not tp.IsSolved then // Apply the first default. If we're defaulting one type variable to another then // the defaults will be propagated to the new type variable. - tp.Constraints |> List.iter (fun tpc -> - match tpc with - | TyparConstraint.DefaultsTo(priority2, ty2, m) when priority2 = priority -> - let ty1 = mkTyparTy tp - if not tp.IsSolved && not (typeEquiv cenv.g ty1 ty2) then - let csenv = MakeConstraintSolverEnv ContextInfo.NoContext cenv.css m denvAtEnd - TryD (fun () -> ConstraintSolver.SolveTyparEqualsType csenv 0 m NoTrace ty1 ty2) - (fun e -> solveTypAsError cenv denvAtEnd m ty1 - ErrorD(ErrorFromApplyingDefault(g, denvAtEnd, tp, ty2, e, m))) - |> RaiseOperationResult - | _ -> ())) - - for priority = 10 downto 0 do - applyDefaults priority + ConstraintSolver.ApplyTyparDefaultAtPriority denvAtEnd cenv.css priority tp) // OK, now apply defaults for any unsolved HeadTypeStaticReq unsolved |> List.iter (fun tp -> diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 2247c318f6..e88033a5a2 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -2660,6 +2660,18 @@ module TypecheckTests = [] let ``type check neg115`` () = singleNegTest (testConfig "typecheck/sigs") "neg115" + [] + let ``type check neg116`` () = singleNegTest (testConfig "typecheck/sigs") "neg116" + + [] + let ``type check neg117`` () = singleNegTest (testConfig "typecheck/sigs") "neg117" + + [] + let ``type check neg118`` () = singleNegTest (testConfig "typecheck/sigs") "neg118" + + [] + let ``type check neg119`` () = singleNegTest (testConfig "typecheck/sigs") "neg119" + [] let ``type check neg_anon_1`` () = singleNegTest (testConfig "typecheck/sigs") "neg_anon_1" diff --git a/tests/fsharp/typecheck/sigs/neg116.bsl b/tests/fsharp/typecheck/sigs/neg116.bsl new file mode 100644 index 0000000000..8bd4930a30 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg116.bsl @@ -0,0 +1,12 @@ + +neg116.fs(10,44,10,45): typecheck error FS0043: No overloads match for method 'op_Multiply'. The available overloads are shown below. +neg116.fs(10,44,10,45): typecheck error FS0043: Possible overload: 'static member Polynomial.( * ) : s:Complex * p:Polynomial -> Polynomial'. Type constraint mismatch. The type + 'float' +is not compatible with type + 'Complex' +. +neg116.fs(10,44,10,45): typecheck error FS0043: Possible overload: 'static member Polynomial.( * ) : s:decimal * p:Polynomial -> Polynomial'. Type constraint mismatch. The type + 'float' +is not compatible with type + 'decimal' +. diff --git a/tests/fsharp/typecheck/sigs/neg116.fs b/tests/fsharp/typecheck/sigs/neg116.fs new file mode 100644 index 0000000000..fff55619af --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg116.fs @@ -0,0 +1,10 @@ +module Neg116 + +type Complex = unit + +type Polynomial () = + static member (*) (s: decimal, p: Polynomial) : Polynomial = failwith "" + static member (*) (s: Complex, p: Polynomial) : Polynomial = failwith "" + +module Foo = + let test t (p: Polynomial) = (1.0 - t) * p diff --git a/tests/fsharp/typecheck/sigs/neg117.bsl b/tests/fsharp/typecheck/sigs/neg117.bsl new file mode 100644 index 0000000000..49c2665190 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg117.bsl @@ -0,0 +1,12 @@ + +neg117.fs(79,18,79,59): ilxgen error FS0041: No overloads match for method 'Transform'. The available overloads are shown below. +neg117.fs(79,18,79,59): ilxgen error FS0041: Possible overload: 'static member Neg117.Superpower.Transformer.Transform : ^r * Neg117.TargetA.TargetA * Neg117.Superpower.Transformer -> (Neg117.TargetA.TransformerKind -> ^r) when (Neg117.TargetA.TargetA or ^r) : (static member Transform : ^r * Neg117.TargetA.TargetA -> Neg117.TargetA.TransformerKind -> ^r)'. Type constraint mismatch. The type + 'Neg117.TargetA.M1 Microsoft.FSharp.Core.[]' +is not compatible with type + ''a' +. +neg117.fs(79,18,79,59): ilxgen error FS0041: Possible overload: 'static member Neg117.Superpower.Transformer.Transform : ^f * Neg117.TargetB.TargetB * Neg117.Superpower.Transformer -> (Neg117.TargetB.TransformerKind -> ^f) when (Neg117.TargetB.TargetB or ^f) : (static member Transform : ^f * Neg117.TargetB.TargetB -> Neg117.TargetB.TransformerKind -> ^f)'. Type constraint mismatch. The type + 'Neg117.TargetA.M1 Microsoft.FSharp.Core.[]' +is not compatible with type + ''a' +. diff --git a/tests/fsharp/typecheck/sigs/neg117.fs b/tests/fsharp/typecheck/sigs/neg117.fs new file mode 100644 index 0000000000..a5de1db5a2 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg117.fs @@ -0,0 +1,82 @@ +module Neg117 + +#nowarn "64" // This construct causes code to be less generic than indicated by the type annotations. + +module TargetA = + + [] + type TransformerKind = + | A + | B + + type M1 = int + + type M2 = float + + type Target() = + + member __.TransformM1 (kind: TransformerKind) : M1[] option = [| 0 |] |> Some + member __.TransformM2 (kind: TransformerKind) : M2[] option = [| 1. |] |> Some + + type TargetA = + + static member instance : Target option = None + + static member inline Transform(_: ^r, _: TargetA) = fun (kind:TransformerKind) -> TargetA.instance.Value.TransformM1 kind : ^r + static member inline Transform(_: ^r, _: TargetA) = fun (kind:TransformerKind) -> TargetA.instance.Value.TransformM2 kind : ^r + + static member inline Transform(kind: TransformerKind) = + let inline call2(a:^a, b:^b) = ((^a or ^b) : (static member Transform: _ * _ -> _) b, a) + let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<'r>) x : 'r + call Unchecked.defaultof kind + + let inline Transform kind = TargetA.Transform kind + +module TargetB = + [] + type TransformerKind = + | C + | D + + type M1 = | M1 + + type M2 = | M2 + + type Target() = + + member __.TransformM1 (kind: TransformerKind) = [| M1 |] |> Some + member __.TransformM2 (kind: TransformerKind) = [| M2 |] |> Some + + type TargetB = + + static member instance : Target option = None + + static member inline Transform(_: ^r, _: TargetB) = fun (kind:TransformerKind) -> TargetB.instance.Value.TransformM1 kind : ^r + static member inline Transform(_: ^r, _: TargetB) = fun (kind:TransformerKind) -> TargetB.instance.Value.TransformM2 kind : ^r + + static member inline Transform(kind: TransformerKind) = + let inline call2(a:^a, b:^b) = ((^a or ^b) : (static member Transform: _ * _ -> _) b, a) + let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<'r>) x : 'r + call Unchecked.defaultof kind + let inline Transform kind = TargetB.Transform kind + +module Superpower = + + type Transformer = + + static member inline Transform(_: ^f, _: TargetB.TargetB, _: Transformer) = + fun x -> TargetB.Transform x : ^f + + static member inline Transform(_: ^r, _: TargetA.TargetA, _: Transformer) = + fun x -> TargetA.Transform x : ^r + + static member inline YeahTransform kind = + let inline call2(a:^a, b:^b, c: ^c) = ((^a or ^b or ^c) : (static member Transform: _ * _ * _ -> _) c, b, a) + let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<_>, Unchecked.defaultof<'r>) x : 'r + call Unchecked.defaultof kind + +module Examples = + let a kind = Superpower.Transformer.YeahTransform kind : TargetA.M1[] + let b = Superpower.Transformer.YeahTransform TargetA.TransformerKind.A : TargetA.M2[] option + let c = Superpower.Transformer.YeahTransform TargetB.TransformerKind.C : TargetB.M1[] option + let d = Superpower.Transformer.YeahTransform TargetA.TransformerKind.A : TargetA.M1[] option diff --git a/tests/fsharp/typecheck/sigs/neg118.bsl b/tests/fsharp/typecheck/sigs/neg118.bsl new file mode 100644 index 0000000000..7b70803cc6 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg118.bsl @@ -0,0 +1,12 @@ + +neg118.fs(18,21,18,37): typecheck error FS0003: This value is not a function and cannot be applied. + +neg118.fs(19,21,19,37): typecheck error FS0003: This value is not a function and cannot be applied. + +neg118.fs(20,21,20,39): typecheck error FS0003: This value is not a function and cannot be applied. + +neg118.fs(21,21,21,41): typecheck error FS0003: This value is not a function and cannot be applied. + +neg118.fs(22,21,22,39): typecheck error FS0003: This value is not a function and cannot be applied. + +neg118.fs(25,51,25,67): typecheck error FS0003: This value is not a function and cannot be applied. diff --git a/tests/fsharp/typecheck/sigs/neg118.fs b/tests/fsharp/typecheck/sigs/neg118.fs new file mode 100644 index 0000000000..fb951db31c --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg118.fs @@ -0,0 +1,28 @@ +module Neg118 + +// This is the example provided by Gustavo Leon in https://github.com/dotnet/fsharp/pull/4173 +// The code is potentially valid and, if that PR had been accepted, would compile. +// It's being added as a negative test case to capture the fact that it currently +// fails to compile. + +type FoldArgs<'t> = FoldArgs of ('t -> 't -> 't) + +let inline foldArgs f (x:'t) (y:'t) :'rest = (FoldArgs f $ Unchecked.defaultof<'rest>) x y + +type FoldArgs<'t> with + static member inline ($) (FoldArgs f, _:'t-> 'rest) = fun (a:'t) -> f a >> foldArgs f + static member ($) (FoldArgs f, _:'t ) = f + +let test1() = + let x:int = foldArgs (+) 2 3 + let y:int = foldArgs (+) 2 3 4 + let z:int = foldArgs (+) 2 3 4 5 + let d:decimal = foldArgs (+) 2M 3M 4M + let e:string = foldArgs (+) "h" "e" "l" "l" "o" + let f:float = foldArgs (+) 2. 3. 4. + + let mult3Numbers a b c = a * b * c + let res2 = mult3Numbers 3 (foldArgs (+) 3 4) (foldArgs (+) 2 2 3 3) + () + + diff --git a/tests/fsharp/typecheck/sigs/neg119.bsl b/tests/fsharp/typecheck/sigs/neg119.bsl new file mode 100644 index 0000000000..9f13a88643 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg119.bsl @@ -0,0 +1,22 @@ + +neg119.fs(40,20,40,22): typecheck error FS0071: Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'Return'. The available overloads are shown below. Consider adding further type constraints +neg119.fs(40,20,40,22): typecheck error FS0071: Possible overload: 'static member Applicatives.Ap.Return : ('r -> 'a) * Ap:Applicatives.Ap -> (('a -> 'r -> 'a2) -> 'a3 -> 'a -> 'r -> 'a2)'. Type constraint mismatch. The type + 'obj' +is not compatible with type + ''a -> 'b' +. +neg119.fs(40,20,40,22): typecheck error FS0071: Possible overload: 'static member Applicatives.Ap.Return : System.Tuple<'a> * Ap:Applicatives.Ap -> ('a -> System.Tuple<'a>)'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'System.Tuple<'a>' +. +neg119.fs(40,20,40,22): typecheck error FS0071: Possible overload: 'static member Applicatives.Ap.Return : seq<'a> * Ap:Applicatives.Ap -> ('a -> seq<'a>)'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'seq<'a>' +. +neg119.fs(40,20,40,22): typecheck error FS0071: Possible overload: 'static member Applicatives.Ap.Return : r: ^R * obj -> ('a1 -> ^R) when ^R : (static member Return : 'a1 -> ^R)'. Type constraint mismatch. The type + 'obj' +is not compatible with type + ''a' +. diff --git a/tests/fsharp/typecheck/sigs/neg119.fs b/tests/fsharp/typecheck/sigs/neg119.fs new file mode 100644 index 0000000000..46d64d4939 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg119.fs @@ -0,0 +1,40 @@ +module Neg119 + +// This is an example provided by Gustavo Leon in https://github.com/dotnet/fsharp/pull/4173 +// The code is potentially valid and, if that PR had been accepted, would compile. +// It's being added as a negative test case to capture the fact that it currently +// fails to compile. + +module Applicatives = + open System + + type Ap = Ap with + static member inline Invoke (x:'T) : '``Applicative<'T>`` = + let inline call (mthd : ^M, output : ^R) = ((^M or ^R) : (static member Return: _*_ -> _) output, mthd) + call (Ap, Unchecked.defaultof<'``Applicative<'T>``>) x + static member inline InvokeOnInstance (x:'T) = (^``Applicative<'T>`` : (static member Return: ^T -> ^``Applicative<'T>``) x) + static member inline Return (r:'R , _:obj) = Ap.InvokeOnInstance :_ -> 'R + static member Return (_:seq<'a> , Ap ) = fun x -> Seq.singleton x : seq<'a> + static member Return (_:Tuple<'a>, Ap ) = fun x -> Tuple x : Tuple<'a> + static member Return (_:'r -> 'a , Ap ) = fun k _ -> k : 'a -> 'r -> _ + + let inline result (x:'T) = Ap.Invoke x + + let inline (<*>) (f:'``Applicative<'T->'U>``) (x:'``Applicative<'T>``) : '``Applicative<'U>`` = + (( ^``Applicative<'T->'U>`` or ^``Applicative<'T>`` or ^``Applicative<'U>``) : (static member (<*>): _*_ -> _) f, x) + + let inline (+) (a:'Num) (b:'Num) :'Num = a + b + + type ZipList<'s> = ZipList of 's seq with + static member Return (x:'a) = ZipList (Seq.initInfinite (fun _ -> x)) + static member (<*>) (ZipList (f:seq<'a->'b>), ZipList x) = ZipList (Seq.zip f x |> Seq.map (fun (f, x) -> f x)) :ZipList<'b> + + type Ii = Ii + type Idiomatic = Idiomatic with + static member inline ($) (Idiomatic, si) = fun sfi x -> (Idiomatic $ x) (sfi <*> si) + static member ($) (Idiomatic, Ii) = id + let inline idiomatic a b = (Idiomatic $ b) a + let inline iI x = (idiomatic << result) x + + let res1n2n3 = iI (+) (result 0M ) (ZipList [1M;2M;3M]) Ii + let res2n3n4 = iI (+) (result LanguagePrimitives.GenericOne) (ZipList [1 ;2 ;3 ]) Ii From 5ef3492861a9f19feeec7e503ba993710e1a6dd3 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jan 2020 18:43:21 +0000 Subject: [PATCH 060/101] add more tests for SRTP resolution (#8318) * add more tests * two new tests --- tests/fsharp/tests.fs | 15 ++++ tests/fsharp/typecheck/sigs/neg120.bsl | 27 +++++++ tests/fsharp/typecheck/sigs/neg120.fs | 97 ++++++++++++++++++++++++ tests/fsharp/typecheck/sigs/neg121.bsl | 2 + tests/fsharp/typecheck/sigs/neg121.fs | 19 +++++ tests/fsharp/typecheck/sigs/neg122.bsl | 2 + tests/fsharp/typecheck/sigs/neg122.fs | 19 +++++ tests/fsharp/typecheck/sigs/pos34.fs | 101 +++++++++++++++++++++++++ 8 files changed, 282 insertions(+) create mode 100644 tests/fsharp/typecheck/sigs/neg120.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg120.fs create mode 100644 tests/fsharp/typecheck/sigs/neg121.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg121.fs create mode 100644 tests/fsharp/typecheck/sigs/neg122.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg122.fs create mode 100644 tests/fsharp/typecheck/sigs/pos34.fs diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index e88033a5a2..4dd0f4740a 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -2161,6 +2161,12 @@ module TypecheckTests = fsc cfg "%s --target:library -o:pos33.dll --warnaserror" cfg.fsc_flags ["pos33.fsi"; "pos33.fs"] peverify cfg "pos33.dll" + [] + let ``sigs pos34`` () = + let cfg = testConfig "typecheck/sigs" + fsc cfg "%s --target:library -o:pos34.dll --warnaserror" cfg.fsc_flags ["pos34.fs"] + peverify cfg "pos34.dll" + [] let ``sigs pos23`` () = let cfg = testConfig "typecheck/sigs" @@ -2672,6 +2678,15 @@ module TypecheckTests = [] let ``type check neg119`` () = singleNegTest (testConfig "typecheck/sigs") "neg119" + [] + let ``type check neg120`` () = singleNegTest (testConfig "typecheck/sigs") "neg120" + + [] + let ``type check neg121`` () = singleNegTest (testConfig "typecheck/sigs") "neg121" + + [] + let ``type check neg122`` () = singleNegTest (testConfig "typecheck/sigs") "neg122" + [] let ``type check neg_anon_1`` () = singleNegTest (testConfig "typecheck/sigs") "neg_anon_1" diff --git a/tests/fsharp/typecheck/sigs/neg120.bsl b/tests/fsharp/typecheck/sigs/neg120.bsl new file mode 100644 index 0000000000..1d7137c417 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg120.bsl @@ -0,0 +1,27 @@ + +neg120.fs(95,18,95,21): typecheck error FS0071: Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'op_GreaterGreaterEquals'. The available overloads are shown below. Consider adding further type constraints +neg120.fs(95,18,95,21): typecheck error FS0071: Possible overload: 'static member Bind.( >>= ) : source:Id<'T> * f:('T -> Id<'U>) -> Id<'U>'. Type constraint mismatch. The type + 'int -> obj' +is not compatible with type + ''a -> Id<'b>' +. +neg120.fs(95,18,95,21): typecheck error FS0071: Possible overload: 'static member Bind.( >>= ) : source:Async<'T> * f:('T -> Async<'a1>) -> Async<'a1>'. Type constraint mismatch. The type + 'Id' +is not compatible with type + 'Async<'a>' +. +neg120.fs(95,18,95,21): typecheck error FS0071: Possible overload: 'static member Bind.( >>= ) : source:'T option * f:('T -> 'U option) -> 'U option'. Type constraint mismatch. The type + 'Id' +is not compatible with type + ''a option' +. +neg120.fs(95,18,95,21): typecheck error FS0071: Possible overload: 'static member Bind.( >>= ) : source:Task<'T> * f:('T -> Task<'U>) -> Task<'U>'. Type constraint mismatch. The type + 'Id' +is not compatible with type + 'Task<'a>' +. +neg120.fs(95,18,95,21): typecheck error FS0071: Possible overload: 'static member Bind.( >>= ) : source:Lazy<'T> * f:('T -> Lazy<'U>) -> Lazy<'U>'. Type constraint mismatch. The type + 'Id' +is not compatible with type + 'Lazy<'a>' +. diff --git a/tests/fsharp/typecheck/sigs/neg120.fs b/tests/fsharp/typecheck/sigs/neg120.fs new file mode 100644 index 0000000000..48ab1db0a0 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg120.fs @@ -0,0 +1,97 @@ +module Neg120 + +// From https://github.com/dotnet/fsharp/issues/4171#issuecomment-528063764 +open System.Threading.Tasks +// [] +type Id<'t> (v: 't) = + let value = v + member __.getValue = value + +[] +module Id = + let run (x: Id<_>) = x.getValue + let map f (x: Id<_>) = Id (f x.getValue) + let create x = Id x + + +type Bind = + static member (>>=) (source: Lazy<'T> , f: 'T -> Lazy<'U> ) = lazy (f source.Value).Value : Lazy<'U> + static member (>>=) (source: Task<'T> , f: 'T -> Task<'U> ) = source.ContinueWith(fun (x: Task<_>) -> f x.Result).Unwrap () : Task<'U> + static member (>>=) (source , f: 'T -> _ ) = Option.bind f source : option<'U> + static member (>>=) (source , f: 'T -> _ ) = async.Bind (source, f) + static member (>>=) (source : Id<_> , f: 'T -> _ ) = f source.getValue : Id<'U> + + static member inline Invoke (source: '``Monad<'T>``) (binder: 'T -> '``Monad<'U>``) : '``Monad<'U>`` = + let inline call (_mthd: 'M, input: 'I, _output: 'R, f) = ((^M or ^I or ^R) : (static member (>>=) : _*_ -> _) input, f) + call (Unchecked.defaultof, source, Unchecked.defaultof<'``Monad<'U>``>, binder) + +let inline (>>=) (x: '``Monad<'T>``) (f: 'T->'``Monad<'U>``) : '``Monad<'U>`` = Bind.Invoke x f + +type Return = + static member inline Invoke (x: 'T) : '``Applicative<'T>`` = + let inline call (mthd: ^M, output: ^R) = ((^M or ^R) : (static member Return : _*_ -> _) output, mthd) + call (Unchecked.defaultof, Unchecked.defaultof<'``Applicative<'T>``>) x + + static member Return (_: Lazy<'a> , _: Return ) = fun x -> Lazy<_>.CreateFromValue x : Lazy<'a> + static member Return (_: 'a Task , _: Return ) = fun x -> Task.FromResult x : 'a Task + static member Return (_: option<'a> , _: Return ) = fun x -> Some x : option<'a> + static member Return (_: 'a Async , _: Return ) = fun (x: 'a) -> async.Return x + static member Return (_: 'a Id , _: Return ) = fun (x: 'a) -> Id x + +let inline result (x: 'T) : '``Functor<'T>`` = Return.Invoke x + + +type TypeT<'``monad<'t>``> = TypeT of obj +type Node<'``monad<'t>``,'t> = A | B of 't * TypeT<'``monad<'t>``> + +let inline wrap (mit: 'mit) = + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit + TypeT mit : TypeT<'mt> + +let inline unwrap (TypeT mit : TypeT<'mt>) = + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit + unbox mit : 'mit + +let inline empty () = wrap ((result Node<'mt,'t>.A) : 'mit) : TypeT<'mt> + +let inline concat l1 l2 = + let rec loop (l1: TypeT<'mt>) (lst2: TypeT<'mt>) = + let (l1, l2) = unwrap l1, unwrap lst2 + TypeT (l1 >>= function A -> l2 | B (x: 't, xs) -> ((result (B (x, loop xs lst2))) : 'mit)) + loop l1 l2 : TypeT<'mt> + + +let inline bind f (source: TypeT<'mt>) : TypeT<'mu> = + // let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_: 't) -> (result Unchecked.defaultof<'u>) : 'mu + let rec loop f input = + TypeT ( + (unwrap input : 'mit) >>= function + | A -> result <| (A : Node<'mu,'u>) : 'miu + | B (h:'t, t: TypeT<'mt>) -> + let res = concat (f h: TypeT<'mu>) (loop f t) + unwrap res : 'miu) + loop f source : TypeT<'mu> + + +let inline map (f: 'T->'U) (x: '``Monad<'T>`` ) = Bind.Invoke x (f >> Return.Invoke) : '``Monad<'U>`` + + +let inline unfold (f:'State -> '``M<('T * 'State) option>``) (s:'State) : TypeT<'MT> = + let rec loop f s = f s |> map (function + | Some (a, s) -> B (a, loop f s) + | None -> A) |> wrap + loop f s + +let inline create (al: '``Monad>``) : TypeT<'``Monad<'T>``> = + unfold (fun i -> map (fun (lst:list<_>) -> if lst.Length > i then Some (lst.[i], i+1) else None) al) 0 + +let inline run (lst: TypeT<'MT>) : '``Monad>`` = + let rec loop acc x = unwrap x >>= function + | A -> result (List.rev acc) + | B (x, xs) -> loop (x::acc) xs + loop [] lst + +let c0 = create (Id ([1..10])) +let res0 = c0 |> run |> create |> run + +// See pos34.fs for the Sealed case that compiles without complaint \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg121.bsl b/tests/fsharp/typecheck/sigs/neg121.bsl new file mode 100644 index 0000000000..49d735e729 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg121.bsl @@ -0,0 +1,2 @@ + +neg121.fs(19,28,19,38): typecheck error FS0071: Type constraint mismatch when applying the default type 'int' for a type inference variable. The type 'int' does not support the operator 'ParseApply' Consider adding further type constraints diff --git a/tests/fsharp/typecheck/sigs/neg121.fs b/tests/fsharp/typecheck/sigs/neg121.fs new file mode 100644 index 0000000000..598820f4c9 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg121.fs @@ -0,0 +1,19 @@ +module Neg121 + +// See https://github.com/dotnet/fsharp/pull/3582#issuecomment-399755533, which listed +// this as a test case of interest. +// +// This is to pin down that behaviour doesn't change in the future unless we intend it to. +open System +type System.String with static member inline ParseApply (path:string) (fn: string -> ^b) : ^b = fn "" +type System.Int32 with static member inline ParseApply (path:string) (fn: int -> ^b) : ^b = fn 0 +type System.Double with static member inline ParseApply (path:string) (fn: float -> ^b) : ^b = fn 0. +type System.Boolean with static member inline ParseApply (path:string) (fn: bool -> ^b) : ^b = fn true + +let inline parser (fmt:PrintfFormat< ^a -> ^b,_,_,^b>) (fn:^a -> ^b) (v:string) : ^b + when ^a : (static member ParseApply: string -> (^a -> ^b) -> ^b) = + (^a : (static member ParseApply: string -> (^a -> ^b) -> ^b)(v,fn)) + +let inline patternTest (fmt:PrintfFormat< ^a -> Action< ^T>,_,_,Action< ^T>>) (fn:^a -> Action< ^T>) v : Action< ^T> = parser fmt fn v + +let parseFn1 = patternTest "adfadf%i" (fun v -> printfn "%i" v; Unchecked.defaultof> ) diff --git a/tests/fsharp/typecheck/sigs/neg122.bsl b/tests/fsharp/typecheck/sigs/neg122.bsl new file mode 100644 index 0000000000..7fb422b9f4 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg122.bsl @@ -0,0 +1,2 @@ + +neg122.fs(19,28,19,38): typecheck error FS0001: The type 'string' does not support the operator 'ParseApply' diff --git a/tests/fsharp/typecheck/sigs/neg122.fs b/tests/fsharp/typecheck/sigs/neg122.fs new file mode 100644 index 0000000000..981460feb1 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg122.fs @@ -0,0 +1,19 @@ +module Neg122 + +// See https://github.com/dotnet/fsharp/pull/3582#issuecomment-399755533, which listed +// this as a test case of interest. +// +// This is to pin down that behaviour doesn't change in the future unless we intend it to. +open System +type System.String with static member inline ParseApply (path:string) (fn: string -> ^b) : ^b = fn "" +type System.Int32 with static member inline ParseApply (path:string) (fn: int -> ^b) : ^b = fn 0 +type System.Double with static member inline ParseApply (path:string) (fn: float -> ^b) : ^b = fn 0. +type System.Boolean with static member inline ParseApply (path:string) (fn: bool -> ^b) : ^b = fn true + +let inline parser (fmt:PrintfFormat< ^a -> ^b,_,_,^b>) (fn:^a -> ^b) (v:string) : ^b + when ^a : (static member ParseApply: string -> (^a -> ^b) -> ^b) = + (^a : (static member ParseApply: string -> (^a -> ^b) -> ^b)(v,fn)) + +let inline patternTest (fmt:PrintfFormat< ^a -> Action< ^T>,_,_,Action< ^T>>) (fn:^a -> Action< ^T>) v : Action< ^T> = parser fmt fn v + +let parseFn2 = patternTest "adf%s245" (fun v -> printfn "%s" v; Unchecked.defaultof> ) diff --git a/tests/fsharp/typecheck/sigs/pos34.fs b/tests/fsharp/typecheck/sigs/pos34.fs new file mode 100644 index 0000000000..73cebb2950 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/pos34.fs @@ -0,0 +1,101 @@ +module Pos34 + +// From https://github.com/dotnet/fsharp/issues/4171#issuecomment-528063764 +// This case is where the type gets labelled as Sealed +// This case compiles without complaint +// +// See also neg120.fs +open System.Threading.Tasks + +[] +type Id<'t> (v: 't) = + let value = v + member __.getValue = value + +[] +module Id = + let run (x: Id<_>) = x.getValue + let map f (x: Id<_>) = Id (f x.getValue) + let create x = Id x + + +type Bind = + static member (>>=) (source: Lazy<'T> , f: 'T -> Lazy<'U> ) = lazy (f source.Value).Value : Lazy<'U> + static member (>>=) (source: Task<'T> , f: 'T -> Task<'U> ) = source.ContinueWith(fun (x: Task<_>) -> f x.Result).Unwrap () : Task<'U> + static member (>>=) (source , f: 'T -> _ ) = Option.bind f source : option<'U> + static member (>>=) (source , f: 'T -> _ ) = async.Bind (source, f) + static member (>>=) (source : Id<_> , f: 'T -> _ ) = f source.getValue : Id<'U> + + static member inline Invoke (source: '``Monad<'T>``) (binder: 'T -> '``Monad<'U>``) : '``Monad<'U>`` = + let inline call (_mthd: 'M, input: 'I, _output: 'R, f) = ((^M or ^I or ^R) : (static member (>>=) : _*_ -> _) input, f) + call (Unchecked.defaultof, source, Unchecked.defaultof<'``Monad<'U>``>, binder) + +let inline (>>=) (x: '``Monad<'T>``) (f: 'T->'``Monad<'U>``) : '``Monad<'U>`` = Bind.Invoke x f + +type Return = + static member inline Invoke (x: 'T) : '``Applicative<'T>`` = + let inline call (mthd: ^M, output: ^R) = ((^M or ^R) : (static member Return : _*_ -> _) output, mthd) + call (Unchecked.defaultof, Unchecked.defaultof<'``Applicative<'T>``>) x + + static member Return (_: Lazy<'a> , _: Return ) = fun x -> Lazy<_>.CreateFromValue x : Lazy<'a> + static member Return (_: 'a Task , _: Return ) = fun x -> Task.FromResult x : 'a Task + static member Return (_: option<'a> , _: Return ) = fun x -> Some x : option<'a> + static member Return (_: 'a Async , _: Return ) = fun (x: 'a) -> async.Return x + static member Return (_: 'a Id , _: Return ) = fun (x: 'a) -> Id x + +let inline result (x: 'T) : '``Functor<'T>`` = Return.Invoke x + + +type TypeT<'``monad<'t>``> = TypeT of obj +type Node<'``monad<'t>``,'t> = A | B of 't * TypeT<'``monad<'t>``> + +let inline wrap (mit: 'mit) = + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit + TypeT mit : TypeT<'mt> + +let inline unwrap (TypeT mit : TypeT<'mt>) = + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit + unbox mit : 'mit + +let inline empty () = wrap ((result Node<'mt,'t>.A) : 'mit) : TypeT<'mt> + +let inline concat l1 l2 = + let rec loop (l1: TypeT<'mt>) (lst2: TypeT<'mt>) = + let (l1, l2) = unwrap l1, unwrap lst2 + TypeT (l1 >>= function A -> l2 | B (x: 't, xs) -> ((result (B (x, loop xs lst2))) : 'mit)) + loop l1 l2 : TypeT<'mt> + + +let inline bind f (source: TypeT<'mt>) : TypeT<'mu> = + // let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_: 't) -> (result Unchecked.defaultof<'u>) : 'mu + let rec loop f input = + TypeT ( + (unwrap input : 'mit) >>= function + | A -> result <| (A : Node<'mu,'u>) : 'miu + | B (h:'t, t: TypeT<'mt>) -> + let res = concat (f h: TypeT<'mu>) (loop f t) + unwrap res : 'miu) + loop f source : TypeT<'mu> + + +let inline map (f: 'T->'U) (x: '``Monad<'T>`` ) = Bind.Invoke x (f >> Return.Invoke) : '``Monad<'U>`` + + +let inline unfold (f:'State -> '``M<('T * 'State) option>``) (s:'State) : TypeT<'MT> = + let rec loop f s = f s |> map (function + | Some (a, s) -> B (a, loop f s) + | None -> A) |> wrap + loop f s + +let inline create (al: '``Monad>``) : TypeT<'``Monad<'T>``> = + unfold (fun i -> map (fun (lst:list<_>) -> if lst.Length > i then Some (lst.[i], i+1) else None) al) 0 + +let inline run (lst: TypeT<'MT>) : '``Monad>`` = + let rec loop acc x = unwrap x >>= function + | A -> result (List.rev acc) + | B (x, xs) -> loop (x::acc) xs + loop [] lst + +let c0 = create (Id ([1..10])) +let res0 = c0 |> run |> create |> run + From 5a0117048ba0076b79a3c0e99ba981000aff720d Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 22 Jan 2020 13:20:40 -0800 Subject: [PATCH 061/101] delete language server (#8241) --- FSharp.sln | 30 --- VisualFSharp.sln | 45 ---- eng/Build.ps1 | 2 - eng/Versions.props | 1 - eng/build.sh | 1 - eng/targets/Settings.props | 5 - .../Directory.Build.props | 9 - ...rp.Compiler.LanguageServer.DesignTime.proj | 49 ---- ...Compiler.LanguageServer.DesignTime.targets | 52 ---- .../FSharp.Compiler.LanguageServer.fsproj | 59 ----- .../JsonDUConverter.fs | 18 -- .../JsonOptionConverter.fs | 27 -- .../LspExternalAccess.fs | 30 --- .../LspTypes.fs | 87 ------- .../FSharp.Compiler.LanguageServer/Methods.fs | 72 ------ .../FSharp.Compiler.LanguageServer/Program.fs | 16 -- .../FSharp.Compiler.LanguageServer/Server.fs | 30 --- .../FSharp.Compiler.LanguageServer/State.fs | 233 ------------------ .../TextDocument.fs | 75 ------ .../DiagnosticsTests.fs | 154 ------------ .../Directory.Build.props | 9 - ...p.Compiler.LanguageServer.UnitTests.fsproj | 31 --- .../MiscTests.fs | 43 ---- .../ProtocolTests.fs | 55 ----- .../SerializationTests.fs | 33 --- .../TemporaryDirectory.fs | 20 -- .../TestClient.fs | 121 --------- .../Source.extension.vsixmanifest | 4 - .../VisualFSharpFull/VisualFSharpFull.csproj | 18 -- .../FSharp.Editor.Helpers.csproj | 22 -- .../FSharp.Editor.Helpers/LanguageClient.cs | 46 ---- .../src/FSharp.Editor/Common/LspService.fs | 28 --- .../Diagnostics/DocumentDiagnosticAnalyzer.fs | 11 - .../src/FSharp.Editor/FSharp.Editor.fsproj | 10 - .../LanguageService/FSharpLanguageClient.fs | 70 ------ .../FSharp.Editor/Options/EditorOptions.fs | 20 +- .../QuickInfo/QuickInfoProvider.fs | 4 - ...osoft.VisualStudio.Editors.Designer.cs.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.de.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.es.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.fr.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.it.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ja.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ko.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.pl.xlf | 3 +- ...ft.VisualStudio.Editors.Designer.pt-BR.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ru.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.tr.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hans.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hant.xlf | 3 +- .../AdvancedOptionsControl.xaml | 11 - .../FSharp.UIResources/Strings.Designer.cs | 9 - .../src/FSharp.UIResources/Strings.resx | 3 - .../src/FSharp.UIResources/xlf/Strings.cs.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.de.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.es.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.fr.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.it.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.ja.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.ko.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.pl.xlf | 5 - .../FSharp.UIResources/xlf/Strings.pt-BR.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.ru.xlf | 5 - .../src/FSharp.UIResources/xlf/Strings.tr.xlf | 5 - .../xlf/Strings.zh-Hans.xlf | 5 - .../xlf/Strings.zh-Hant.xlf | 5 - 66 files changed, 28 insertions(+), 1639 deletions(-) delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.proj delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.targets delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/JsonDUConverter.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/JsonOptionConverter.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/LspExternalAccess.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/LspTypes.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/Methods.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/Program.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/Server.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/State.fs delete mode 100644 src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/DiagnosticsTests.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/Directory.Build.props delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/MiscTests.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/ProtocolTests.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/SerializationTests.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/TemporaryDirectory.fs delete mode 100644 tests/FSharp.Compiler.LanguageServer.UnitTests/TestClient.fs delete mode 100644 vsintegration/src/FSharp.Editor.Helpers/FSharp.Editor.Helpers.csproj delete mode 100644 vsintegration/src/FSharp.Editor.Helpers/LanguageClient.cs delete mode 100644 vsintegration/src/FSharp.Editor/Common/LspService.fs delete mode 100644 vsintegration/src/FSharp.Editor/LanguageService/FSharpLanguageClient.fs diff --git a/FSharp.sln b/FSharp.sln index 57620c7864..a3412ddea2 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -42,10 +42,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Packages", "Packages", "{38 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.FSharp.Compiler", "src\fsharp\FSharp.Compiler.nuget\Microsoft.FSharp.Compiler.csproj", "{81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer", "src\fsharp\FSharp.Compiler.LanguageServer\FSharp.Compiler.LanguageServer.fsproj", "{99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer.UnitTests", "tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj", "{C97819B0-B428-4B96-9CD7-497D2D1C738C}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{8B7BF62E-7D8C-4928-BE40-4E392A9EE851}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting", "src\fsharp\FSharp.Compiler.Private.Scripting\FSharp.Compiler.Private.Scripting.fsproj", "{6771860A-614D-4FDD-A655-4C70EBCC91B0}" @@ -218,30 +214,6 @@ Global {81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7}.Release|Any CPU.Build.0 = Release|Any CPU {81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7}.Release|x86.ActiveCfg = Release|Any CPU {81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7}.Release|x86.Build.0 = Release|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Debug|x86.ActiveCfg = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Debug|x86.Build.0 = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Proto|Any CPU.Build.0 = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Proto|x86.ActiveCfg = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Proto|x86.Build.0 = Debug|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Release|Any CPU.Build.0 = Release|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Release|x86.ActiveCfg = Release|Any CPU - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}.Release|x86.Build.0 = Release|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Debug|x86.ActiveCfg = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Debug|x86.Build.0 = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Proto|Any CPU.Build.0 = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Proto|x86.ActiveCfg = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Proto|x86.Build.0 = Debug|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|Any CPU.Build.0 = Release|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|x86.ActiveCfg = Release|Any CPU - {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|x86.Build.0 = Release|Any CPU {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -295,8 +267,6 @@ Global {88E2D422-6852-46E3-A740-83E391DC7973} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {53C0DAAD-158C-4658-8EC7-D7341530239F} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7} = {3840F2E7-3898-45F7-8CF7-1E6829E56DB8} - {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA} = {B8DDA694-7939-42E3-95E5-265C2217C142} - {C97819B0-B428-4B96-9CD7-497D2D1C738C} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {8B7BF62E-7D8C-4928-BE40-4E392A9EE851} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {6771860A-614D-4FDD-A655-4C70EBCC91B0} = {B8DDA694-7939-42E3-95E5-265C2217C142} {4FEDF286-0252-4EBC-9E75-879CCA3B85DC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} diff --git a/VisualFSharp.sln b/VisualFSharp.sln index d46221b17b..346a0071b5 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -144,12 +144,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.FSharp.Compiler", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Core.nuget", "src\fsharp\FSharp.Core.nuget\FSharp.Core.nuget.csproj", "{8EC30B2E-F1F9-4A98-BBB5-DD0CF6C84DDC}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer", "src\fsharp\FSharp.Compiler.LanguageServer\FSharp.Compiler.LanguageServer.fsproj", "{60BAFFA5-6631-4328-B044-2E012AB76DCA}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer.UnitTests", "tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj", "{AAF2D233-1C38-4090-8FFA-F7C545625E06}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.Helpers", "vsintegration\src\FSharp.Editor.Helpers\FSharp.Editor.Helpers.csproj", "{79255A92-ED00-40BA-9D64-12FCC664A976}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting", "src\fsharp\FSharp.Compiler.Private.Scripting\FSharp.Compiler.Private.Scripting.fsproj", "{20B7BC36-CF51-4D75-9E13-66681C07977F}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting.UnitTests", "tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj", "{09F56540-AFA5-4694-B7A6-0DBF6D4618C2}" @@ -848,42 +842,6 @@ Global {8EC30B2E-F1F9-4A98-BBB5-DD0CF6C84DDC}.Release|Any CPU.Build.0 = Release|Any CPU {8EC30B2E-F1F9-4A98-BBB5-DD0CF6C84DDC}.Release|x86.ActiveCfg = Release|Any CPU {8EC30B2E-F1F9-4A98-BBB5-DD0CF6C84DDC}.Release|x86.Build.0 = Release|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Debug|x86.ActiveCfg = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Debug|x86.Build.0 = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Proto|Any CPU.Build.0 = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Proto|x86.ActiveCfg = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Proto|x86.Build.0 = Debug|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Release|Any CPU.Build.0 = Release|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Release|x86.ActiveCfg = Release|Any CPU - {60BAFFA5-6631-4328-B044-2E012AB76DCA}.Release|x86.Build.0 = Release|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Debug|x86.ActiveCfg = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Debug|x86.Build.0 = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Proto|Any CPU.Build.0 = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Proto|x86.ActiveCfg = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Proto|x86.Build.0 = Debug|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Release|Any CPU.Build.0 = Release|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Release|x86.ActiveCfg = Release|Any CPU - {AAF2D233-1C38-4090-8FFA-F7C545625E06}.Release|x86.Build.0 = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Debug|x86.ActiveCfg = Debug|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Debug|x86.Build.0 = Debug|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Proto|Any CPU.ActiveCfg = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Proto|Any CPU.Build.0 = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Proto|x86.ActiveCfg = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Proto|x86.Build.0 = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|Any CPU.Build.0 = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|x86.ActiveCfg = Release|Any CPU - {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|x86.Build.0 = Release|Any CPU {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|Any CPU.Build.0 = Debug|Any CPU {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1035,9 +993,6 @@ Global {9482211E-23D0-4BD0-9893-E4AA5559F67A} = {6235B3AF-774D-4EA1-8F37-789E767F6368} {04C59F6E-1C76-4F6A-AC21-2EA7F296A1B8} = {647810D0-5307-448F-99A2-E83917010DAE} {8EC30B2E-F1F9-4A98-BBB5-DD0CF6C84DDC} = {647810D0-5307-448F-99A2-E83917010DAE} - {60BAFFA5-6631-4328-B044-2E012AB76DCA} = {B8DDA694-7939-42E3-95E5-265C2217C142} - {AAF2D233-1C38-4090-8FFA-F7C545625E06} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} - {79255A92-ED00-40BA-9D64-12FCC664A976} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {20B7BC36-CF51-4D75-9E13-66681C07977F} = {B8DDA694-7939-42E3-95E5-265C2217C142} {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {DFA30881-C0B1-4813-B087-C21B5AF9B77F} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 72ea53f146..a7825b4d4f 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -343,7 +343,6 @@ try { if ($testDesktop -and -not $noVisualStudio) { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $desktopTargetFramework @@ -352,7 +351,6 @@ try { if ($testCoreClr) { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $coreclrTargetFramework diff --git a/eng/Versions.props b/eng/Versions.props index 64a7ddd713..1ee1522072 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -122,7 +122,6 @@ 16.0.28226-alpha 16.1.28916.169 16.1.28917.181 - 16.1.3121 16.1.89 16.1.89 16.1.89 diff --git a/eng/build.sh b/eng/build.sh index 218f4ef977..994263ff7d 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -290,7 +290,6 @@ BuildSolution if [[ "$test_core_clr" == true ]]; then 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.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclrtestframework diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index 474e5d22a8..77f7a0c704 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -11,9 +11,4 @@ false - - - false - - diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props b/src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props deleted file mode 100644 index 7cd41381b5..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.proj b/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.proj deleted file mode 100644 index d02ae419bc..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.proj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - $(MSBuildThisFileDirectory)FSharp.Compiler.LanguageServer.DesignTime.targets - - - - - - - - - - - - - - diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.targets b/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.targets deleted file mode 100644 index ea8f3e2866..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.DesignTime.targets +++ /dev/null @@ -1,52 +0,0 @@ - - - - - true - false - true - true - false - false - false - true - false - true - false - - - - - - - _ComputeTargetFrameworkItems - _PopulateTargetFrameworks - - - - - <_TargetFramework Include="$(TargetFramework)" /> - - - - - - - - - - - - - - diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj b/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj deleted file mode 100644 index 0bb0899140..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - - 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 deleted file mode 100644 index ae8575195d..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/JsonDUConverter.fs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 deleted file mode 100644 index 937dda00e4..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/JsonOptionConverter.fs +++ /dev/null @@ -1,27 +0,0 @@ -// 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 deleted file mode 100644 index 48e4b0b405..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/LspExternalAccess.fs +++ /dev/null @@ -1,30 +0,0 @@ -// 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" - - [] - let TextDocumentPublishDiagnostics = "textDocument/publishDiagnostics" - -type Options = - { usePreviewTextHover: bool - usePreviewDiagnostics: bool } - static member Default() = - { usePreviewTextHover = false - usePreviewDiagnostics = false } - static member AllOn() = - { usePreviewTextHover = true - usePreviewDiagnostics = true } - -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 deleted file mode 100644 index 264e526fcd..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/LspTypes.fs +++ /dev/null @@ -1,87 +0,0 @@ -// 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/specifications/specification-3-14/. -// 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 - 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: TextDocumentClientCapabilities, publishDiagnostics: { relatedInformation: bool option } - 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 deleted file mode 100644 index 453b7f8228..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/Methods.fs +++ /dev/null @@ -1,72 +0,0 @@ -// 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/specifications/specification-3-14/ -type Methods() = - - let 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[], - [] cancellationToken: CancellationToken - ) = - state.Initialize rootPath rootUri (fun projectOptions -> TextDocument.PublishDiagnostics(state, projectOptions) |> Async.Start) - { 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 - ) = - eprintfn "got options %A" options - state.Options <- options - state.InvalidateAllProjects() diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs b/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs deleted file mode 100644 index 13d0c9709f..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/Program.fs +++ /dev/null @@ -1,16 +0,0 @@ -// 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 deleted file mode 100644 index 28d5e49a58..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/Server.fs +++ /dev/null @@ -1,30 +0,0 @@ -// 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 methods = Methods() - let rpc = new JsonRpc(handler, methods) - do methods.State.JsonRpc <- Some rpc - - member __.StartListening() = - rpc.StartListening() - - member __.WaitForExitAsync() = - async { - do! Async.AwaitEvent (methods.State.Shutdown) - do! Async.AwaitEvent (methods.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 deleted file mode 100644 index 0812bb9a7f..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/State.fs +++ /dev/null @@ -1,233 +0,0 @@ -// 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.Collections.Concurrent -open System.Collections.Generic -open System.Diagnostics -open System.IO -open System.Text.RegularExpressions -open FSharp.Compiler.SourceCodeServices -open StreamJsonRpc - -module internal Solution = - // easy unit testing - let getProjectPaths (solutionContent: string) (solutionDir: string) = - // This looks scary, but is much more lightweight than carrying along MSBuild just to have it parse the solution file. - // - // A valid line in .sln looks like: - // Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ConsoleApp2", "ConsoleApp2\ConsoleApp2.fsproj", "{60A4BE67-7E03-4200-AD38-B0E5E8E049C1}" - // and we're hoping to extract this: ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // - // therefore: - // ^Project text 'Project' at the start of the line - // .* any number of characters - // \"" double quote character (it's doubled up to escape from the raw string literal here) - // ( start of capture group - // [^\""] not a quote - // * many of those - // \.fsproj literal string ".fsproj" - // ) end of capture group - // \"" double quote - let pattern = Regex(@"^Project.*\""([^\""]*\.fsproj)\""") - let lines = solutionContent.Split('\n') - let relativeProjects = - lines - |> Array.map pattern.Match - |> Array.filter (fun m -> m.Success) - |> Array.map (fun m -> m.Groups.[1].Value) - // .sln files by convention uses backslashes, which might not be appropriate at runtime - |> Array.map (fun p -> p.Replace('\\', Path.DirectorySeparatorChar)) - let projects = - relativeProjects - |> Array.map (fun p -> if Path.IsPathRooted(p) then p else Path.Combine(solutionDir, p)) - projects - -type State() = - - let checker = FSharpChecker.Create() - - let sourceFileToProjectMap = ConcurrentDictionary() - - let shutdownEvent = new Event<_>() - let exitEvent = new Event<_>() - let cancelEvent = new Event<_>() - let projectInvalidatedEvent = new Event<_>() - - let fileChanged (args: FileSystemEventArgs) = - match sourceFileToProjectMap.TryGetValue args.FullPath with - | true, projectOptions -> projectInvalidatedEvent.Trigger(projectOptions) - | false, _ -> () - let fileRenamed (args: RenamedEventArgs) = - match sourceFileToProjectMap.TryGetValue args.FullPath with - | true, projectOptions -> projectInvalidatedEvent.Trigger(projectOptions) - | false, _ -> () - let fileWatcher = new FileSystemWatcher() - do fileWatcher.IncludeSubdirectories <- true - do fileWatcher.Changed.Add(fileChanged) - do fileWatcher.Created.Add(fileChanged) - do fileWatcher.Deleted.Add(fileChanged) - do fileWatcher.Renamed.Add(fileRenamed) - - let execProcess (name: string) (args: string) = - let startInfo = ProcessStartInfo(name, args) - eprintfn "executing: %s %s" name args - startInfo.CreateNoWindow <- true - startInfo.RedirectStandardOutput <- true - startInfo.UseShellExecute <- false - let lines = List() - use proc = new Process() - proc.StartInfo <- startInfo - proc.OutputDataReceived.Add(fun args -> lines.Add(args.Data)) - proc.Start() |> ignore - proc.BeginOutputReadLine() - proc.WaitForExit() - lines.ToArray() - - let linesWithPrefixClean (prefix: string) (lines: string[]) = - lines - |> Array.filter (isNull >> not) - |> Array.map (fun line -> line.TrimStart(' ')) - |> Array.filter (fun line -> line.StartsWith(prefix)) - |> Array.map (fun line -> line.Substring(prefix.Length)) - - let getProjectOptions (rootDir: string) = - if isNull rootDir then [||] - else - fileWatcher.Path <- rootDir - fileWatcher.EnableRaisingEvents <- true - - /// This function is meant to be temporary. Until we figure out what a language server for a project - /// system looks like, we have to guess based on the files we find in the root. - let getProjectOptions (projectPath: string) = - let projectDir = Path.GetDirectoryName(projectPath) - let normalizePath (path: string) = - if Path.IsPathRooted(path) then path - else Path.Combine(projectDir, path) - - // To avoid essentially re-creating a copy of MSBuild alongside this tool, we instead fake a design- - // time build with this project. The output of building this helper project is text that's easily - // parsable. See the helper project for more information. - let reporterProject = Path.Combine(Path.GetDirectoryName(typeof.Assembly.Location), "FSharp.Compiler.LanguageServer.DesignTime.proj") - let detectedTfmSentinel = "DetectedTargetFramework=" - let detectedCommandLineArgSentinel = "DetectedCommandLineArg=" - - let execTfmReporter = - sprintf "build \"%s\" \"/p:ProjectFile=%s\"" reporterProject projectPath - |> execProcess "dotnet" - - let execArgReporter (tfm: string) = - sprintf "build \"%s\" \"/p:ProjectFile=%s\" \"/p:TargetFramework=%s\"" reporterProject projectPath tfm - |> execProcess "dotnet" - - // find the target frameworks - let targetFrameworks = - execTfmReporter - |> linesWithPrefixClean detectedTfmSentinel - - let getArgs (tfm: string) = - execArgReporter tfm - |> linesWithPrefixClean detectedCommandLineArgSentinel - - let tfmAndArgs = - targetFrameworks - |> Array.map (fun tfm -> tfm, getArgs tfm) - - let separateArgs (args: string[]) = - args - |> Array.partition (fun a -> a.StartsWith("-")) - |> (fun (options, files) -> - let normalizedFiles = files |> Array.map normalizePath - options, normalizedFiles) - - // TODO: for now we're only concerned with the first TFM - let _tfm, args = Array.head tfmAndArgs - - let otherOptions, sourceFiles = separateArgs args - - let projectOptions: FSharpProjectOptions = - { ProjectFileName = projectPath - ProjectId = None - SourceFiles = sourceFiles - OtherOptions = otherOptions - ReferencedProjects = [||] // TODO: populate from @(ProjectReference) - IsIncompleteTypeCheckEnvironment = false - UseScriptResolutionRules = false - LoadTime = DateTime.Now - UnresolvedReferences = None - OriginalLoadReferences = [] - ExtraProjectInfo = None - Stamp = None } - projectOptions - let topLevelProjects = Directory.GetFiles(rootDir, "*.fsproj") - let watchableProjectPaths = - match topLevelProjects with - | [||] -> - match Directory.GetFiles(rootDir, "*.sln") with - // TODO: what to do with multiple .sln or a combo of .sln/.fsproj? - | [| singleSolution |] -> - let content = File.ReadAllText(singleSolution) - let solutionDir = Path.GetDirectoryName(singleSolution) - Solution.getProjectPaths content solutionDir - | _ -> [||] - | _ -> topLevelProjects - let watchableProjectOptions = - watchableProjectPaths - |> Array.map getProjectOptions - - // associate source files with project options - let watchFile file projectOptions = - sourceFileToProjectMap.AddOrUpdate(file, projectOptions, fun _ _ -> projectOptions) - - for projectOptions in watchableProjectOptions do - // watch .fsproj - watchFile projectOptions.ProjectFileName projectOptions |> ignore - // TODO: watch .deps.json - for sourceFile in projectOptions.SourceFiles do - let sourceFileFullPath = - if Path.IsPathRooted(sourceFile) then sourceFile - else - let projectDir = Path.GetDirectoryName(projectOptions.ProjectFileName) - Path.Combine(projectDir, sourceFile) - watchFile sourceFileFullPath projectOptions |> ignore - - watchableProjectOptions - - member __.Checker = checker - - /// Initialize the LSP at the specified location. According to the spec, `rootUri` is to be preferred over `rootPath`. - member __.Initialize (rootPath: string) (rootUri: DocumentUri) (computeDiagnostics: FSharpProjectOptions -> unit) = - let rootDir = - if not (isNull rootUri) then Uri(rootUri).LocalPath - else rootPath - let projectOptions = getProjectOptions rootDir - projectInvalidatedEvent.Publish.Add computeDiagnostics // compute diagnostics on project invalidation - for projectOption in projectOptions do - computeDiagnostics projectOption // compute initial set of diagnostics - - [] - member __.Shutdown = shutdownEvent.Publish - - [] - member __.Exit = exitEvent.Publish - - [] - member __.Cancel = cancelEvent.Publish - - [] - member __.ProjectInvalidated = projectInvalidatedEvent.Publish - - member __.DoShutdown() = shutdownEvent.Trigger() - - member __.DoExit() = exitEvent.Trigger() - - member __.DoCancel() = cancelEvent.Trigger() - - member __.InvalidateAllProjects() = - for projectOptions in sourceFileToProjectMap.Values do - projectInvalidatedEvent.Trigger(projectOptions) - - member val Options = Options.Default() with get, set - - member val JsonRpc: JsonRpc option = None with get, set diff --git a/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs b/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs deleted file mode 100644 index 489b55ebce..0000000000 --- a/src/fsharp/FSharp.Compiler.LanguageServer/TextDocument.fs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer - -open System.Threading - -module TextDocument = - - let mutable publishDiagnosticsCancellationTokenSource = new CancellationTokenSource() - - let Hover (state: State) (textDocument: TextDocumentIdentifier) (position: Position) = - async { - eprintfn "hover at %d, %d" position.line position.character - 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, projectOptions: FSharp.Compiler.SourceCodeServices.FSharpProjectOptions) = - // TODO: honor TextDocumentClientCapabilities.publishDiagnostics.relatedInformation - // cancel any existing request to publish diagnostics - publishDiagnosticsCancellationTokenSource.Cancel() - publishDiagnosticsCancellationTokenSource <- new CancellationTokenSource() - async { - if not state.Options.usePreviewDiagnostics then return () - else - eprintfn "starting diagnostics computation" - match state.JsonRpc with - | None -> eprintfn "state.JsonRpc was null; should not be?" - | Some jsonRpc -> - let! results = state.Checker.ParseAndCheckProject projectOptions - let diagnostics = results.Errors - let diagnosticsPerFile = - diagnostics - |> Array.fold (fun state t -> - let existing = Map.tryFind t.FileName state |> Option.defaultValue [] - Map.add t.FileName (t :: existing) state) Map.empty - for sourceFile in projectOptions.SourceFiles do - let diagnostics = - Map.tryFind sourceFile diagnosticsPerFile - |> Option.defaultValue [] - |> List.map (fun d -> - // F# errors count lines starting at 1, but LSP starts at 0 - let range: Range = - { start = { line = d.StartLineAlternate - 1; character = d.StartColumn } - ``end`` = { line = d.EndLineAlternate - 1; character = d.EndColumn } } - let severity = - match d.Severity with - | FSharp.Compiler.SourceCodeServices.FSharpErrorSeverity.Warning -> Diagnostic.Warning - | FSharp.Compiler.SourceCodeServices.FSharpErrorSeverity.Error -> Diagnostic.Error - let res: Diagnostic = - { range = range - severity = Some severity - code = "FS" + d.ErrorNumber.ToString("0000") - source = Some d.FileName - message = d.Message - relatedInformation = None } - res) - |> List.toArray - let args: PublishDiagnosticsParams = - { uri = System.Uri(sourceFile).AbsoluteUri - diagnostics = diagnostics } - - // fire each notification separately - jsonRpc.NotifyAsync(TextDocumentPublishDiagnostics, args) |> Async.AwaitTask |> Async.Start - } - |> (fun computation -> Async.StartAsTask(computation, cancellationToken=publishDiagnosticsCancellationTokenSource.Token)) - |> Async.AwaitTask diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/DiagnosticsTests.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/DiagnosticsTests.fs deleted file mode 100644 index aaadff258e..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/DiagnosticsTests.fs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System -open System.IO -open System.Linq -open System.Threading.Tasks -open FSharp.Compiler.LanguageServer -open Nerdbank.Streams -open NUnit.Framework - -[] -type DiagnosticsTests() = - - let createTestableProject (tfm: string) (sourceFiles: (string * string) list) = - let testDir = new TemporaryDirectory() - let directoryBuildText = "" - File.WriteAllText(Path.Combine(testDir.Directory, "Directory.Build.props"), directoryBuildText) - File.WriteAllText(Path.Combine(testDir.Directory, "Directory.Build.targets"), directoryBuildText) - for name, contents in sourceFiles do - File.WriteAllText(Path.Combine(testDir.Directory, name), contents) - let compileItems = - sourceFiles - |> List.map fst - |> List.map (sprintf " ") - |> List.fold (fun content line -> content + "\n" + line) "" - let replacements = - [ "{{COMPILE}}", compileItems - "{{TARGETFRAMEWORK}}", tfm ] - let projectTemplate = - @" - - - Library - {{TARGETFRAMEWORK}} - - -{{COMPILE}} - -" - let projectFile = - replacements - |> List.fold (fun (content: string) (find, replace) -> content.Replace(find, replace)) projectTemplate - File.WriteAllText(Path.Combine(testDir.Directory, "test.fsproj"), projectFile) - testDir - - let createRpcClient (tempDir: TemporaryDirectory) = - let clientStream, serverStream = FullDuplexStream.CreatePair().ToTuple() - let server = new Server(serverStream, serverStream) - server.StartListening() - let client = new TestClient(tempDir, clientStream, clientStream, server) - client - - let createClientTest (tfm: string) (sourceFiles: (string * string) list) = - let testDir = createTestableProject tfm sourceFiles - let client = createRpcClient testDir - client - - let getDiagnostics (content: string) = - async { - use client = createClientTest "netstandard2.0" [ "lib.fs", content ] - let! diagnostics = client.WaitForDiagnosticsAsync client.Initialize ["lib.fs"] - return diagnostics.["lib.fs"] - } - - [] - member __.``No diagnostics for correct code``() = - async { - let! diagnostics = getDiagnostics @" -namespace Test - -module Numbers = - let one: int = 1 -" - Assert.AreEqual(0, diagnostics.Length) - } |> Async.StartAsTask :> Task - - [] - member __.``Diagnostics for incorrect code``() = - async { - let! diagnostics = getDiagnostics @" -namespace Test - -module Numbers = - let one: int = false -" - let diag = diagnostics.Single() - Assert.AreEqual("FS0001", diag.code) - Assert.AreEqual(Some 1, diag.severity) - Assert.AreEqual(4, diag.range.start.line) - Assert.AreEqual(19, diag.range.start.character) - Assert.AreEqual(4, diag.range.``end``.line) - Assert.AreEqual(24, diag.range.``end``.character) - Assert.AreEqual("This expression was expected to have type\n 'int' \nbut here has type\n 'bool'", diag.message.Trim()) - Assert.IsTrue(diag.source.Value.EndsWith("lib.fs")) - } |> Async.StartAsTask :> Task - - [] - member __.``Diagnostics added for updated incorrect code``() = - async { - let correct = @" -namespace Test - -module Numbers = - let one: int = 1 -" - let incorrect = @" -namespace Test - -module Numbers = - let one: int = false -" - - // verify initial state - use client = createClientTest "netstandard2.0" [ "lib.fs", correct ] - let! diagnostics = client.WaitForDiagnosticsAsync client.Initialize ["lib.fs"] - Assert.AreEqual(0, diagnostics.["lib.fs"].Length) - - // touch file with incorrect data - let touch () = File.WriteAllText(Path.Combine(client.RootPath, "lib.fs"), incorrect) - let! diagnostics = client.WaitForDiagnostics touch ["lib.fs"] - let diag = diagnostics.["lib.fs"].Single() - Assert.AreEqual("FS0001", diag.code) - } |> Async.StartAsTask :> Task - - [] - member __.``Diagnostics removed for updated correct code``() = - async { - let incorrect = @" -namespace Test - -module Numbers = - let one: int = false -" - let correct = @" -namespace Test - -module Numbers = - let one: int = 1 -" - - // verify initial state - use client = createClientTest "netstandard2.0" [ "lib.fs", incorrect ] - let! diagnostics = client.WaitForDiagnosticsAsync client.Initialize ["lib.fs"] - let diag = diagnostics.["lib.fs"].Single() - Assert.AreEqual("FS0001", diag.code) - - // touch file with correct data - let touch () = File.WriteAllText(Path.Combine(client.RootPath, "lib.fs"), correct) - let! diagnostics = client.WaitForDiagnostics touch ["lib.fs"] - let libActualContents = File.ReadAllText(Path.Combine(client.RootPath, "lib.fs")) - Assert.AreEqual(0, diagnostics.["lib.fs"].Length, "Actual on-disk contents of lib.fs:\n" + libActualContents) - } |> Async.StartAsTask :> Task diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/Directory.Build.props b/tests/FSharp.Compiler.LanguageServer.UnitTests/Directory.Build.props deleted file mode 100644 index 7cd41381b5..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj b/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj deleted file mode 100644 index 4e061f5575..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - net472;netcoreapp3.0 - netcoreapp3.0 - Library - true - nunit - true - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/MiscTests.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/MiscTests.fs deleted file mode 100644 index 02104be2e6..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/MiscTests.fs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System.IO -open FSharp.Compiler.LanguageServer -open NUnit.Framework - -[] -type MiscTests() = - - [] - member __.``Find F# projects in a .sln file``() = - let slnContent = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29201.188 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{F2A71F9B-5D33-465A-A702-920D77279786}"") = ""ConsoleApp1"", ""ConsoleApp1\ConsoleApp1.fsproj"", ""{60A4BE67-7E03-4200-AD38-B0E5E8E049C1}"" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {60A4BE67-7E03-4200-AD38-B0E5E8E049C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {60A4BE67-7E03-4200-AD38-B0E5E8E049C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {60A4BE67-7E03-4200-AD38-B0E5E8E049C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {60A4BE67-7E03-4200-AD38-B0E5E8E049C1}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {80902CFC-54E6-4485-AC17-4516930C8B2B} - EndGlobalSection -EndGlobal -" - let testDir = @"C:\Dir\With\Solution" // don't care about the potentially improper directory separators here, it's really just a dumb string - let foundProjects = Solution.getProjectPaths slnContent testDir - let expected = Path.Combine(testDir, "ConsoleApp1", "ConsoleApp1.fsproj") // proper directory separator characters will be used at runtime - Assert.AreEqual([| expected |], foundProjects) diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/ProtocolTests.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/ProtocolTests.fs deleted file mode 100644 index 8b262e2ceb..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/ProtocolTests.fs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System.Diagnostics -open System.Threading.Tasks -open FSharp.Compiler.LanguageServer -open NUnit.Framework -open StreamJsonRpc - -[] -type ProtocolTests() = - -#if !NETCOREAPP - // The `netcoreapp` version of `FSharp.Compiler.LanguageServer.exe` can't be run without a `publish` step so - // we're artificially restricting this test to the full framework. - [] -#endif - member __.``Server consuming stdin and stdout``() = - async { - // start server as a console app - let serverAssemblyPath = typeof.Assembly.Location - let startInfo = ProcessStartInfo(serverAssemblyPath) - startInfo.UseShellExecute <- false - startInfo.RedirectStandardInput <- true - startInfo.RedirectStandardOutput <- true - let proc = Process.Start(startInfo) - - // create a fake client over stdin/stdout - let client = new JsonRpc(proc.StandardInput.BaseStream, proc.StandardOutput.BaseStream) - client.StartListening() - - // initialize - let capabilities: ClientCapabilities = - { workspace = None - textDocument = None - experimental = None - supportsVisualStudioExtensions = None } - let! result = - client.InvokeWithParameterObjectAsync( - "initialize", - {| processId = Process.GetCurrentProcess().Id - capabilities = capabilities |} - ) |> Async.AwaitTask - Assert.True(result.capabilities.hoverProvider) - do! client.NotifyAsync("initialized") |> Async.AwaitTask - - // shutdown - let! shutdownResponse = client.InvokeAsync("shutdown") |> Async.AwaitTask - Assert.IsNull(shutdownResponse) - - // exit - do! client.NotifyAsync("exit") |> Async.AwaitTask - if not (proc.WaitForExit(5000)) then failwith "Expected server process to exit." - } |> Async.StartAsTask :> Task diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/SerializationTests.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/SerializationTests.fs deleted file mode 100644 index 5d8457c4e5..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/SerializationTests.fs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System -open FSharp.Compiler.LanguageServer -open NUnit.Framework -open Newtonsoft.Json - -[] -type SerializationTests() = - - let verifyRoundTrip (str: string) (typ: Type) = - let deserialized = JsonConvert.DeserializeObject(str, typ) - let roundTripped = JsonConvert.SerializeObject(deserialized) - Assert.AreEqual(str, roundTripped) - - let verifyRoundTripWithConverter (str: string) (typ: Type) (converter: JsonConverter) = - let deserialized = JsonConvert.DeserializeObject(str, typ, converter) - let roundTripped = JsonConvert.SerializeObject(deserialized, converter) - Assert.AreEqual(str, roundTripped) - - [] - member __.``Discriminated union as lower-case string``() = - verifyRoundTrip "\"plaintext\"" typeof - verifyRoundTrip "\"markdown\"" typeof - - [] - member __.``Option<'T> as obj/null``() = - verifyRoundTripWithConverter "1" typeof> (JsonOptionConverter()) - verifyRoundTripWithConverter "null" typeof> (JsonOptionConverter()) - verifyRoundTripWithConverter "{\"contents\":{\"kind\":\"plaintext\",\"value\":\"v\"},\"range\":{\"start\":{\"line\":1,\"character\":2},\"end\":{\"line\":3,\"character\":4}}}" typeof> (JsonOptionConverter()) - verifyRoundTripWithConverter "null" typeof> (JsonOptionConverter()) diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/TemporaryDirectory.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/TemporaryDirectory.fs deleted file mode 100644 index ef3953d781..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/TemporaryDirectory.fs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System -open System.IO - -type TemporaryDirectory() = - - let directory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()) - do Directory.CreateDirectory(directory) |> ignore - - member __.Directory = directory - - interface IDisposable with - member __.Dispose() = - try - Directory.Delete(directory, true) - with - | _ -> () diff --git a/tests/FSharp.Compiler.LanguageServer.UnitTests/TestClient.fs b/tests/FSharp.Compiler.LanguageServer.UnitTests/TestClient.fs deleted file mode 100644 index 0baaaf40eb..0000000000 --- a/tests/FSharp.Compiler.LanguageServer.UnitTests/TestClient.fs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace FSharp.Compiler.LanguageServer.UnitTests - -open System -open System.Collections.Generic -open System.Diagnostics -open System.IO -open System.Threading -open FSharp.Compiler.LanguageServer -open Newtonsoft.Json.Linq -open StreamJsonRpc - -type TestClient(tempDir: TemporaryDirectory, sendingStream: Stream, receivingStream: Stream, server: Server) = - - let rootPath = tempDir.Directory - let rootPath = if rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) then rootPath else rootPath + Path.DirectorySeparatorChar.ToString() - let diagnosticsEvent = Event<_>() - - 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 client = new JsonRpc(handler) - let handler (functionName: string) (args: JToken): JToken = - match functionName with - | TextDocumentPublishDiagnostics -> - let args = args.ToObject(formatter.JsonSerializer) - let fullPath = Uri(args.uri).LocalPath - let shortPath = if fullPath.StartsWith(rootPath) then fullPath.Substring(rootPath.Length) else fullPath - diagnosticsEvent.Trigger((shortPath, args.diagnostics)) - null - | _ -> null - let addHandler (name: string) = - client.AddLocalRpcMethod(name, new Func(handler name)) - do addHandler TextDocumentPublishDiagnostics - do client.StartListening() - - member __.RootPath = rootPath - - member __.Server = server - - [] - member __.PublishDiagnostics = diagnosticsEvent.Publish - - member __.Initialize () = - async { - do! client.NotifyWithParameterObjectAsync(OptionsSet, {| options = Options.AllOn() |}) |> Async.AwaitTask - let capabilities: ClientCapabilities = - { workspace = None - textDocument = None - experimental = None - supportsVisualStudioExtensions = None } - let! _result = - client.InvokeWithParameterObjectAsync( - "initialize", // method - {| processId = Process.GetCurrentProcess().Id - rootPath = rootPath - capabilities = capabilities |} - ) |> Async.AwaitTask - return () - } - - member this.WaitForDiagnostics (triggerAction: unit -> unit) (fileNames: string list) = - async { - // prepare file diagnostic triggers - let diagnosticTriggers = Dictionary() - fileNames |> List.iter (fun f -> diagnosticTriggers.[f] <- new ManualResetEvent(false)) - - // prepare callback handler - let diagnosticsMap = Dictionary() - let handler (fileName: string, diagnostics: Diagnostic[]) = - diagnosticsMap.[fileName] <- diagnostics - // auto-generated files (e.g., AssemblyInfo.fs) won't be in the trigger map - if diagnosticTriggers.ContainsKey(fileName) then - diagnosticTriggers.[fileName].Set() |> ignore - - // subscribe to the event - let wrappedHandler = new Handler(fun _sender args -> handler args) - this.PublishDiagnostics.AddHandler(wrappedHandler) - triggerAction () - - // wait for all triggers to hit - let! results = - diagnosticTriggers - |> Seq.map (fun entry -> - async { - let! result = Async.AwaitWaitHandle(entry.Value, millisecondsTimeout = int (TimeSpan.FromSeconds(10.0).TotalMilliseconds)) - return if result then None - else - let filePath = Path.Combine(rootPath, entry.Key) - let actualContents = File.ReadAllText(filePath) - Some <| sprintf "No diagnostics received for file '%s'. Contents:\n%s\n" entry.Key actualContents - }) - |> Async.Parallel - let results = results |> Array.choose (fun x -> x) - if results.Length > 0 then - let combinedErrors = String.Join("-----\n", results) - let allDiagnosticsEvents = - diagnosticsMap - |> Seq.map (fun entry -> - sprintf "File '%s' reported %d diagnostics." entry.Key entry.Value.Length) - |> (fun s -> String.Join("\n", s)) - failwith <| sprintf "Error waiting for diagnostics:\n%s\n-----\n%s" combinedErrors allDiagnosticsEvents - - // clean up event - this.PublishDiagnostics.RemoveHandler(wrappedHandler) - - // done - return diagnosticsMap - } - - member this.WaitForDiagnosticsAsync (triggerAction: unit -> Async) (fileNames: string list) = - this.WaitForDiagnostics (fun () -> triggerAction () |> Async.RunSynchronously) fileNames - - interface IDisposable with - member __.Dispose() = - try - (tempDir :> IDisposable).Dispose() - with - | _ -> () diff --git a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest index cae7539766..e35e50e78e 100644 --- a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest +++ b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest @@ -28,10 +28,6 @@ - - diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj index d68067fe1e..0bfaa8f1cd 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj @@ -61,14 +61,6 @@ True TargetFramework=$(DependencyTargetFramework) - - {60BAFFA5-6631-4328-B044-2E012AB76DCA} - FSharp.Compiler.LanguageServer - PublishedProjectOutputGroup%3b - false - Build;Publish - TargetFramework=$(DependencyTargetFramework) - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06} FSharp.Compiler.Server.Shared @@ -158,16 +150,6 @@ 2 True - - {0A3099F1-F0C7-4ADE-AB9B-526EF193A56F} - FSharp.Editor.Helpers - BuiltProjectOutputGroup%3bGetCopyToOutputDirectoryItems%3bPkgDefProjectOutputGroup%3bSatelliteDllsProjectOutputGroup%3b - DebugSymbolsProjectOutputGroup%3b - true - All - 2 - True - {c4586a06-1402-48bc-8e35-a1b8642f895b} FSharp.UIResources diff --git a/vsintegration/src/FSharp.Editor.Helpers/FSharp.Editor.Helpers.csproj b/vsintegration/src/FSharp.Editor.Helpers/FSharp.Editor.Helpers.csproj deleted file mode 100644 index cb6cfb36cb..0000000000 --- a/vsintegration/src/FSharp.Editor.Helpers/FSharp.Editor.Helpers.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Library - net472 - - - - - - - - - - - FSharp.Editor.Helpers - $(VSAssemblyVersion) - $PackageFolder$\FSharp.Editor.Helpers.dll - - - - diff --git a/vsintegration/src/FSharp.Editor.Helpers/LanguageClient.cs b/vsintegration/src/FSharp.Editor.Helpers/LanguageClient.cs deleted file mode 100644 index 87759ceef7..0000000000 --- a/vsintegration/src/FSharp.Editor.Helpers/LanguageClient.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.LanguageServer.Client; -using Microsoft.VisualStudio.Threading; - -namespace Microsoft.VisualStudio.FSharp.Editor.Helpers -{ - /// - /// Exists as an abstract implementor of purely to manage the non-standard async - /// event handlers. - /// - public abstract class LanguageClient : ILanguageClient - { - public abstract string Name { get; } - - public abstract IEnumerable ConfigurationSections { get; } - - public abstract object InitializationOptions { get; } - - public abstract IEnumerable FilesToWatch { get; } - - public event AsyncEventHandler StartAsync; - -#pragma warning disable 67 // The event 'LanguageClient.StopAsync' is never used - public event AsyncEventHandler StopAsync; -#pragma warning restore 67 - - public abstract Task ActivateAsync(CancellationToken token); - - protected abstract Task DoLoadAsync(); - - public async Task OnLoadedAsync() - { - await DoLoadAsync(); - await StartAsync.InvokeAsync(this, EventArgs.Empty); - } - - public abstract Task OnServerInitializeFailedAsync(Exception e); - - public abstract Task OnServerInitializedAsync(); - } -} diff --git a/vsintegration/src/FSharp.Editor/Common/LspService.fs b/vsintegration/src/FSharp.Editor/Common/LspService.fs deleted file mode 100644 index 433f833839..0000000000 --- a/vsintegration/src/FSharp.Editor/Common/LspService.fs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System.ComponentModel.Composition -open FSharp.Compiler.LanguageServer -open FSharp.Compiler.LanguageServer.Extensions -open StreamJsonRpc - -[)>] -type LspService() = - let mutable options = Options.Default() - let mutable jsonRpc: JsonRpc option = None - - let sendOptions () = - async { - match jsonRpc with - | None -> () - | Some rpc -> do! rpc.SetOptionsAsync(options) - } - - member __.SetJsonRpc(rpc: JsonRpc) = - jsonRpc <- Some rpc - sendOptions() - - member __.SetOptions(opt: Options) = - options <- opt - sendOptions() diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs index 0d92ce047b..2e7a44e251 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs @@ -34,9 +34,6 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = let getProjectInfoManager(document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager - let getSettings(document: Document) = - document.Project.Solution.Workspace.Services.GetService() - static let errorInfoEqualityComparer = { new IEqualityComparer with member __.Equals (x, y) = @@ -113,10 +110,6 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = interface IFSharpDocumentDiagnosticAnalyzer with member this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task> = - // if using LSP, just bail early - let settings = getSettings document - if settings.Advanced.UsePreviewDiagnostics then Task.FromResult(ImmutableArray.Empty) - else let projectInfoManager = getProjectInfoManager document asyncMaybe { let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) @@ -130,10 +123,6 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = |> RoslynHelpers.StartAsyncAsTask cancellationToken member this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task> = - // if using LSP, just bail early - let settings = getSettings document - if settings.Advanced.UsePreviewDiagnostics then Task.FromResult(ImmutableArray.Empty) - else let projectInfoManager = getProjectInfoManager document asyncMaybe { let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 77add18765..629f7f2b0f 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -35,10 +35,6 @@ - - Common\LspExternalAccess.fs - - @@ -55,10 +51,6 @@ - - LanguageService\JsonOptionConverter.fs - - @@ -122,7 +114,6 @@ - @@ -151,7 +142,6 @@ - diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpLanguageClient.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpLanguageClient.fs deleted file mode 100644 index 7a987d665f..0000000000 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpLanguageClient.fs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor.LanguageService - -open System.ComponentModel.Composition -open System.Diagnostics -open System.IO -open System.Threading -open System.Threading.Tasks -open Microsoft.FSharp.Control -open Microsoft.VisualStudio.FSharp.Editor -open Microsoft.VisualStudio.FSharp.Editor.Helpers -open Microsoft.VisualStudio.LanguageServer.Client -open Microsoft.VisualStudio.Utilities -open StreamJsonRpc - -// https://docs.microsoft.com/en-us/visualstudio/extensibility/adding-an-lsp-extension?view=vs-2019 - -/// Provides exports necessary to register the language client. -type FSharpContentDefinition() = - - [] - [] - [] - static member val FSharpContentTypeDefinition: ContentTypeDefinition = null with get, set - - [] - [] - [] - static member val FSharpFileExtensionDefinition: FileExtensionToContentTypeDefinition = null with get, set - -[)>] -[] -type internal FSharpLanguageClient - [] - ( - lspService: LspService, - settings: EditorOptions - ) = - inherit LanguageClient() - override __.Name = "F# Language Service" - override this.ActivateAsync(_token: CancellationToken) = - async { - let thisAssemblyPath = Path.GetDirectoryName(this.GetType().Assembly.Location) - let serverAssemblyPath = Path.Combine(thisAssemblyPath, "Agent", "FSharp.Compiler.LanguageServer.exe") - let startInfo = ProcessStartInfo(serverAssemblyPath) - startInfo.UseShellExecute <- false - startInfo.CreateNoWindow <- true // comment to see log messages written to stderr - startInfo.RedirectStandardInput <- true - startInfo.RedirectStandardOutput <- true - let proc = new Process() - proc.StartInfo <- startInfo - return - if proc.Start() then new Connection(proc.StandardOutput.BaseStream, proc.StandardInput.BaseStream) - else null - } |> Async.StartAsTask - override __.ConfigurationSections = null - override __.FilesToWatch = null - override __.InitializationOptions = null - override __.DoLoadAsync() = Task.CompletedTask - override __.OnServerInitializeFailedAsync(_e: exn) = Task.CompletedTask - override __.OnServerInitializedAsync() = Task.CompletedTask - interface ILanguageClientCustomMessage with - member __.CustomMessageTarget = null - member __.MiddleLayer = null - member __.AttachForCustomMessageAsync(rpc: JsonRpc) = - async { - do! lspService.SetJsonRpc(rpc) - do! lspService.SetOptions(settings.Advanced.AsLspOptions()) - } |> Async.StartAsTask :> Task diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index af88f02d10..7485176811 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -5,7 +5,6 @@ open System.ComponentModel.Composition open System.Runtime.InteropServices open System.Windows open System.Windows.Controls -open FSharp.Compiler.LanguageServer open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.FSharp.UIResources @@ -92,17 +91,10 @@ type CodeLensOptions = [] type AdvancedOptions = { IsBlockStructureEnabled: bool - IsOutliningEnabled: bool - UsePreviewTextHover: bool - UsePreviewDiagnostics: bool } + IsOutliningEnabled: bool } static member Default = { IsBlockStructureEnabled = true - IsOutliningEnabled = true - UsePreviewTextHover = false - UsePreviewDiagnostics = false } - member this.AsLspOptions(): Options = - { usePreviewTextHover = this.UsePreviewTextHover - usePreviewDiagnostics = this.UsePreviewDiagnostics } + IsOutliningEnabled = true } [] type FormattingOptions = @@ -203,14 +195,6 @@ module internal OptionsUI = inherit AbstractOptionPage() override __.CreateView() = upcast AdvancedOptionsControl() - override this.OnApply(args) = - base.OnApply(args) - async { - let lspService = this.GetService() - let settings = this.GetService() - let options = settings.Advanced.AsLspOptions() - do! lspService.SetOptions options - } |> Async.Start [] type internal FormattingOptionPage() = diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index 7b90bb3aef..a6ea0c9033 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -206,10 +206,6 @@ type internal FSharpAsyncQuickInfoSource // This method can be called from the background thread. // Do not call IServiceProvider.GetService here. override __.GetQuickInfoItemAsync(session:IAsyncQuickInfoSession, cancellationToken:CancellationToken) : Task = - // The following lines should be disabled for branch `release/dev16.2`, enabled otherwise - //// if using LSP, just bail early - //if settings.Advanced.UsePreviewTextHover then Task.FromResult(null) - //else let triggerPoint = session.GetTriggerPoint(textBuffer.CurrentSnapshot) match triggerPoint.HasValue with | false -> Task.FromResult(null) diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index b071e0c5f7..5340031907 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 4184f3edc5..2ca4bd450e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 4b1a5e0d90..394481ad69 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 99d3469919..821545638e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index 8902030751..dd58cb9a11 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index de4d65e71f..c0221174d9 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index e7191ac3c4..6f540b5425 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index 6936b8e97f..f912b6b4c7 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index fefd197867..5a2b75dce0 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 355d363084..2b5303d91d 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 86ac32f4b3..73a72b806a 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 0537632d5f..474f99a3dc 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 17c64ffefb..16b7339b2a 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml index 57ca75df75..7126d6efb8 100644 --- a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml +++ b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml @@ -24,17 +24,6 @@ - - diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index c03ff05d77..fd74fbb404 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -419,14 +419,5 @@ public static string Unused_opens_code_fix { return ResourceManager.GetString("Unused_opens_code_fix", resourceCulture); } } - - /// - /// Looks up a localized string similar to (Preview) Use out of process language server. - /// - public static string Use_out_of_process_language_server { - get { - return ResourceManager.GetString("Use_out_of_process_language_server", resourceCulture); - } - } } } diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index 037596b716..19f6d2658b 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -231,9 +231,6 @@ Suggest names for unresolved identifiers - - (Preview) Use out of process language server - Text hover diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index a9808062bd..da6e649a8b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -202,11 +202,6 @@ Navrhovat názvy pro nerozpoznané identifikátory - - (Preview) Use out of process language server - (Preview) Použít mimoprocesový jazykový server - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index 9e48372cb2..653c542d13 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -202,11 +202,6 @@ Namen für nicht aufgelöste Bezeichner vorschlagen - - (Preview) Use out of process language server - (Vorschauversion) Prozessexternen Sprachserver verwenden - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index cd6b650ec6..39c2877127 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -202,11 +202,6 @@ Sugerir nombres para los identificadores no resueltos - - (Preview) Use out of process language server - (Versión preliminar) Usar el servidor de lenguaje fuera del proceso - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 90b7e5b378..3d73fe222b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -202,11 +202,6 @@ Suggérer des noms pour les identificateurs non résolus - - (Preview) Use out of process language server - (Préversion) Utiliser un serveur de langage hors processus - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index 51b5a87f28..34d9ec6702 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -202,11 +202,6 @@ Suggerisci nomi per gli identificatori non risolti - - (Preview) Use out of process language server - (Anteprima) Usa server di linguaggio out-of-process - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index 7a59c8c4d3..5771c8c584 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -202,11 +202,6 @@ 未解決の識別子の名前を提案します - - (Preview) Use out of process language server - (プレビュー) プロセス外言語サーバーの使用 - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index 8ba93bed1b..dacb999656 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -202,11 +202,6 @@ 확인되지 않은 식별자의 이름 제안 - - (Preview) Use out of process language server - (미리 보기) Out of Process 언어 서버 사용 - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index 3d83c8f6ad..4a205499f2 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -202,11 +202,6 @@ Sugeruj nazwy w przypadku nierozpoznanych identyfikatorów - - (Preview) Use out of process language server - (Wersja zapoznawcza) Korzystanie z serwera języka poza procesem - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index e3a75c3136..13cce041c9 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -202,11 +202,6 @@ Sugerir nomes para identificadores não resolvidos - - (Preview) Use out of process language server - (Versão Prévia) Usar um servidor de idioma fora do processo - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 106dcd8b87..579c059dcd 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -202,11 +202,6 @@ Предлагать имена для неразрешенных идентификаторов - - (Preview) Use out of process language server - (Предварительная версия) Использование сервера языка процессов - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index 8525295e6e..6ff42fad0e 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -202,11 +202,6 @@ Çözümlenmemiş tanımlayıcılar için ad öner - - (Preview) Use out of process language server - (Önizleme) İşlem dışı dil sunucusunu kullanma - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index ff0bad3144..b85bb0227b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -202,11 +202,6 @@ 为未解析标识符建议名称 - - (Preview) Use out of process language server - (预览)使用进程外语言服务器 - - \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 1edc051a59..acbacbce08 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -202,11 +202,6 @@ 為未解析的識別碼建議名稱 - - (Preview) Use out of process language server - (預覽) 使用處理序語言伺服器 - - \ No newline at end of file From 36d779983f60a9233ea386fc3731c42d15b4d44d Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 22 Jan 2020 13:50:36 -0800 Subject: [PATCH 062/101] only dump package list if the run failed (#8320) --- azure-pipelines.yml | 25 +++++++++++++++---- .../DumpPackageRoot.csproj} | 6 ++++- 2 files changed, 25 insertions(+), 6 deletions(-) rename eng/{AfterSolutionBuild.targets => DumpPackageRoot/DumpPackageRoot.csproj} (86%) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 131be207af..9388446102 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -187,6 +187,9 @@ stages: publishLocation: Container continueOnError: true condition: eq(variables['_testKind'], 'testFSharpQA') + - script: dotnet build $(Build.SourcesDirectory)/eng/DumpPackageRoot/DumpPackageRoot.csproj + displayName: Dump NuGet cache contents + condition: failed() - task: PublishBuildArtifacts@1 displayName: Publish NuGet cache contents inputs: @@ -194,7 +197,7 @@ stages: ArtifactName: 'NuGetPackageContents Windows $(_testKind)' publishLocation: Container continueOnError: true - condition: always() + condition: failed() # Linux - job: Linux @@ -216,6 +219,9 @@ stages: searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' continueOnError: true condition: always() + - script: dotnet build $(Build.SourcesDirectory)/eng/DumpPackageRoot/DumpPackageRoot.csproj + displayName: Dump NuGet cache contents + condition: failed() - task: PublishBuildArtifacts@1 displayName: Publish NuGet cache contents inputs: @@ -223,7 +229,7 @@ stages: ArtifactName: 'NuGetPackageContents Linux' publishLocation: Container continueOnError: true - condition: always() + condition: failed() # MacOS - job: MacOS @@ -245,6 +251,9 @@ stages: searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' continueOnError: true condition: always() + - script: dotnet build $(Build.SourcesDirectory)/eng/DumpPackageRoot/DumpPackageRoot.csproj + displayName: Dump NuGet cache contents + condition: failed() - task: PublishBuildArtifacts@1 displayName: Publish NuGet cache contents inputs: @@ -252,7 +261,7 @@ stages: ArtifactName: 'NuGetPackageContents Mac' publishLocation: Container continueOnError: true - condition: always() + condition: failed() # Source Build Linux - job: SourceBuild_Linux @@ -263,6 +272,9 @@ stages: clean: true - script: ./eng/cibuild.sh --configuration Release /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true displayName: Build + - script: dotnet build $(Build.SourcesDirectory)/eng/DumpPackageRoot/DumpPackageRoot.csproj + displayName: Dump NuGet cache contents + condition: failed() - task: PublishBuildArtifacts@1 displayName: Publish NuGet cache contents inputs: @@ -270,7 +282,7 @@ stages: ArtifactName: 'NuGetPackageContents SourceBuild_Linux' publishLocation: Container continueOnError: true - condition: always() + condition: failed() # Source Build Windows - job: SourceBuild_Windows @@ -281,6 +293,9 @@ stages: clean: true - script: eng\CIBuild.cmd -configuration Release -noSign /p:DotNetBuildFromSource=true /p:FSharpSourceBuild=true displayName: Build + - script: dotnet build $(Build.SourcesDirectory)/eng/DumpPackageRoot/DumpPackageRoot.csproj + displayName: Dump NuGet cache contents + condition: failed() - task: PublishBuildArtifacts@1 displayName: Publish NuGet cache contents inputs: @@ -288,7 +303,7 @@ stages: ArtifactName: 'NuGetPackageContents SourceBuild_Windows' publishLocation: Container continueOnError: true - condition: always() + condition: failed() # Up-to-date - job: UpToDate_Windows diff --git a/eng/AfterSolutionBuild.targets b/eng/DumpPackageRoot/DumpPackageRoot.csproj similarity index 86% rename from eng/AfterSolutionBuild.targets rename to eng/DumpPackageRoot/DumpPackageRoot.csproj index ffd633e4f9..c3b2cedf8f 100644 --- a/eng/AfterSolutionBuild.targets +++ b/eng/DumpPackageRoot/DumpPackageRoot.csproj @@ -1,7 +1,11 @@ - + + + netcoreapp3.1 + + From 4a95e6a6cdd245873d0157960211da79170fc98b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jan 2020 22:36:46 +0000 Subject: [PATCH 063/101] cleanup and alignment (#8319) * cleanup and alignment * cleanup and alignment * cleanup and alignment --- src/fsharp/ConstraintSolver.fs | 229 ++++++++++++++++++++------------- src/fsharp/TastOps.fs | 6 +- 2 files changed, 147 insertions(+), 88 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 59b10f7be7..92ae10cd75 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -291,6 +291,22 @@ let rec occursCheck g un ty = // Predicates on types //------------------------------------------------------------------------- +/// Some additional solutions are forced prior to generalization (permitWeakResolution=true). These are, roughly speaking, rules +/// for binary-operand constraints arising from constructs such as "1.0 + x" where "x" is an unknown type. THe constraint here +/// involves two type parameters - one for the left, and one for the right. The left is already known to be Double. +/// In this situation (and in the absence of other evidence prior to generalization), constraint solving forces an assumption that +/// the right is also Double - this is "weak" because there is only weak evidence for it. +/// +/// permitWeakResolution also applies to resolutions of multi-type-variable constraints via method overloads. Method overloading gets applied even if +/// only one of the two type variables is known. +/// +/// During code gen we run with permitWeakResolution on, but we only apply it where one of the argument types for the built-in constraint resolution is +/// a variable type. +type PermitWeakResolution = + | Yes + | No + member x.Permit = match x with Yes -> true | No -> false + let rec isNativeIntegerTy g ty = typeEquivAux EraseMeasures g g.nativeint_ty ty || typeEquivAux EraseMeasures g g.unativeint_ty ty || @@ -310,10 +326,10 @@ let isUnsignedIntegerTy g ty = typeEquivAux EraseMeasures g g.unativeint_ty ty || typeEquivAux EraseMeasures g g.uint64_ty ty -let rec isIntegerOrIntegerEnumTy g ty = +let rec IsIntegerOrIntegerEnumTy g ty = isSignedIntegerTy g ty || isUnsignedIntegerTy g ty || - (isEnumTy g ty && isIntegerOrIntegerEnumTy g (underlyingTypeOfEnumTy g ty)) + (isEnumTy g ty && IsIntegerOrIntegerEnumTy g (underlyingTypeOfEnumTy g ty)) let isIntegerTy g ty = isSignedIntegerTy g ty || @@ -334,7 +350,7 @@ let isFpTy g ty = let isDecimalTy g ty = typeEquivAux EraseMeasures g g.decimal_ty ty -let IsNonDecimalNumericOrIntegralEnumType g ty = isIntegerOrIntegerEnumTy g ty || isFpTy g ty +let IsNonDecimalNumericOrIntegralEnumType g ty = IsIntegerOrIntegerEnumTy g ty || isFpTy g ty let IsNumericOrIntegralEnumType g ty = IsNonDecimalNumericOrIntegralEnumType g ty || isDecimalTy g ty @@ -353,6 +369,28 @@ let GetMeasureOfType g ty = | _ -> None | _ -> None +let IsCharOrStringType g ty = isCharTy g ty || isStringTy g ty + +/// Checks the argument type for a built-in solution to an op_Addition, op_Subtraction or op_Modulus constraint. +let IsAddSubModType nm g ty = IsNumericOrIntegralEnumType g ty || (nm = "op_Addition" && IsCharOrStringType g ty) + +/// Checks the argument type for a built-in solution to a bitwise operator constraint +let IsBitwiseOpType g ty = IsIntegerOrIntegerEnumTy g ty || (isEnumTy g ty) + +/// Check the other type in a built-in solution for a binary operator. +/// For weak resolution, require a relevant primitive on one side. +/// For strong resolution, a variable type is permitted. +let IsBinaryOpOtherArgType g permitWeakResolution ty = + match permitWeakResolution with + | PermitWeakResolution.No -> + not (isTyparTy g ty) + + | PermitWeakResolution.Yes -> true + +/// Checks the argument type for a built-in solution to a get_Sign constraint. +let IsSignType g ty = + isSignedIntegerTy g ty || isFpTy g ty || isDecimalTy g ty + type TraitConstraintSolution = | TTraitUnsolved | TTraitBuiltIn @@ -819,10 +857,12 @@ let rec SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optio // 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. // If so, re-solve the relevant constraints. if csenv.SolverState.ExtraCxs.ContainsKey r.Stamp then - do! RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep false trace r) + do! RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep PermitWeakResolution.No trace r) + // Re-solve the other constraints associated with this type variable return! solveTypMeetsTyparConstraints csenv ndeep m2 trace ty r @@ -867,7 +907,7 @@ and solveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty | TyparConstraint.SimpleChoice(tys, m2) -> SolveTypeChoice csenv ndeep m2 trace ty tys | TyparConstraint.CoercesTo(ty2, m2) -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace None ty2 ty | TyparConstraint.MayResolveMember(traitInfo, m2) -> - SolveMemberConstraint csenv false false ndeep m2 trace traitInfo |> OperationResult.ignore + SolveMemberConstraint csenv false PermitWeakResolution.No ndeep m2 trace traitInfo |> OperationResult.ignore } @@ -1136,16 +1176,9 @@ and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty /// don't. The type-directed static optimization rules in the library code that makes use of this /// will deal with the problem. /// -/// 2. Some additional solutions are forced prior to generalization (permitWeakResolution=true). These are, roughly speaking, rules -/// for binary-operand constraints arising from constructs such as "1.0 + x" where "x" is an unknown type. THe constraint here -/// involves two type parameters - one for the left, and one for the right. The left is already known to be Double. -/// In this situation (and in the absence of other evidence prior to generalization), constraint solving forces an assumption that -/// the right is also Double - this is "weak" because there is only weak evidence for it. -/// -/// permitWeakResolution also applies to resolutions of multi-type-variable constraints via method overloads. Method overloading gets applied even if -/// only one of the two type variables is known -/// -and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace (TTrait(tys, nm, memFlags, argtys, rty, sln)): OperationResult = trackErrors { +/// 2. Some additional solutions are forced prior to generalization (permitWeakResolution= Yes or YesDuringCodeGen). See above +and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = trackErrors { + let (TTrait(tys, nm, memFlags, traitObjAndArgTys, rty, sln)) = traitInfo // Do not re-solve if already solved if sln.Value.IsSome then return true else let g = csenv.g @@ -1158,20 +1191,21 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // Remove duplicates from the set of types in the support let tys = ListSet.setify (typeAEquiv g aenv) tys + // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(tys, nm, memFlags, argtys, rty, sln) + let traitInfo = TTrait(tys, nm, memFlags, traitObjAndArgTys, rty, sln) let rty = GetFSharpViewOfReturnType g rty // Assert the object type if the constraint is for an instance member if memFlags.IsInstance then - match tys, argtys with + match tys, traitObjAndArgTys with | [ty], (h :: _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace h ty | _ -> 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 - let argtys = if memFlags.IsInstance then List.tail argtys else argtys + let argtys = if memFlags.IsInstance then List.tail traitObjAndArgTys else traitObjAndArgTys let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution nm traitInfo @@ -1205,11 +1239,9 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // decimal<'u> * 'a (let checkRuleAppliesInPreferenceToMethods argty1 argty2 = // Check that at least one of the argument types is numeric - (IsNumericOrIntegralEnumType g argty1) && - // Check that the support of type variables is empty. That is, - // if we're canonicalizing, then having one of the types nominal is sufficient. - // If not, then both must be nominal (i.e. not a type variable). - (permitWeakResolution || not (isTyparTy g argty2)) && + IsNumericOrIntegralEnumType g argty1 && + // Check the other type is nominal, unless using weak resolution + IsBinaryOpOtherArgType g permitWeakResolution argty2 && // This next condition checks that either // - Neither type contributes any methods OR // - We have the special case "decimal<_> * decimal". In this case we have some @@ -1244,8 +1276,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | _, _, false, ("op_Addition" | "op_Subtraction" | "op_Modulus"), [argty1;argty2] when // Ignore any explicit +/- overloads from any basic integral types (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.ApparentEnclosingType ) && - ( (IsNumericOrIntegralEnumType g argty1 || (nm = "op_Addition" && (isCharTy g argty1 || isStringTy g argty1))) && (permitWeakResolution || not (isTyparTy g argty2)) - || (IsNumericOrIntegralEnumType g argty2 || (nm = "op_Addition" && (isCharTy g argty2 || isStringTy g argty2))) && (permitWeakResolution || not (isTyparTy g argty1)))) -> + ( IsAddSubModType nm g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsAddSubModType nm g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1)) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn @@ -1253,8 +1285,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | _, _, false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argty1;argty2] when // Ignore any explicit overloads from any basic integral types (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.ApparentEnclosingType ) && - ( (IsRelationalType g argty1 && (permitWeakResolution || not (isTyparTy g argty2))) - || (IsRelationalType g argty2 && (permitWeakResolution || not (isTyparTy g argty1))))) -> + ( IsRelationalType g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsRelationalType g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1)) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.bool_ty return TTraitBuiltIn @@ -1272,21 +1304,21 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty ty return TTraitBuiltIn - | [], _, false, ("DivideByInt"), [argty1;argty2] + | [], _, false, "DivideByInt", [argty1;argty2] when isFpTy g argty1 || isDecimalTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn // We pretend for uniformity that the 'string' and 'array' types have an indexer property called 'Item' - | [], [ty], true, ("get_Item"), [argty1] + | [], [ty], true, "get_Item", [argty1] when isStringTy g ty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty1 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.char_ty return TTraitBuiltIn - | [], [ty], true, ("get_Item"), argtys + | [], [ty], true, "get_Item", argtys when isArrayTy g ty -> if rankOfArrayTy g ty <> argtys.Length then do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), argtys.Length), m, m2)) @@ -1296,7 +1328,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty ety return TTraitBuiltIn - | [], [ty], true, ("set_Item"), argtys + | [], [ty], true, "set_Item", argtys when isArrayTy g ty -> if rankOfArrayTy g ty <> argtys.Length - 1 then do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), (argtys.Length - 1)), m, m2)) @@ -1308,8 +1340,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn | [], _, false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argty1;argty2] - when (isIntegerOrIntegerEnumTy g argty1 || (isEnumTy g argty1)) && (permitWeakResolution || not (isTyparTy g argty2)) - || (isIntegerOrIntegerEnumTy g argty2 || (isEnumTy g argty2)) && (permitWeakResolution || not (isTyparTy g argty1)) -> + when IsBitwiseOpType g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsBitwiseOpType g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 @@ -1317,39 +1349,39 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn | [], _, false, ("op_LeftShift" | "op_RightShift"), [argty1;argty2] - when isIntegerOrIntegerEnumTy g argty1 -> + when IsIntegerOrIntegerEnumTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 do! SolveDimensionlessNumericType csenv ndeep m2 trace argty1 return TTraitBuiltIn - | _, _, false, ("op_UnaryPlus"), [argty] + | _, _, false, "op_UnaryPlus", [argty] when IsNumericOrIntegralEnumType g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, false, ("op_UnaryNegation"), [argty] + | _, _, false, "op_UnaryNegation", [argty] when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, true, ("get_Sign"), [] - when (let argty = tys.Head in isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty) -> + | _, _, true, "get_Sign", [] + when IsSignType g tys.Head -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.int32_ty return TTraitBuiltIn | _, _, false, ("op_LogicalNot" | "op_OnesComplement"), [argty] - when isIntegerOrIntegerEnumTy g argty -> + when IsIntegerOrIntegerEnumTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty do! SolveDimensionlessNumericType csenv ndeep m2 trace argty return TTraitBuiltIn - | _, _, false, ("Abs"), [argty] + | _, _, false, "Abs", [argty] when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty @@ -1374,7 +1406,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, false, ("op_Explicit"), [argty] + | _, _, false, "op_Explicit", [argty] when (// The input type. (IsNonDecimalNumericOrIntegralEnumType g argty || isStringTy g argty || isCharTy g argty) && // The output type @@ -1387,7 +1419,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn - | _, _, false, ("op_Explicit"), [argty] + | _, _, false, "op_Explicit", [argty] when (// The input type. (IsNumericOrIntegralEnumType g argty || isStringTy g argty) && // The output type @@ -1403,7 +1435,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn - | _, _, false, ("Atan2"), [argty1; argty2] + | _, _, false, "Atan2", [argty1; argty2] when isFpTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 match GetMeasureOfType g argty1 with @@ -1534,7 +1566,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // If there's nothing left to learn then raise the errors. // Note: we should likely call MemberConstraintIsReadyForResolution here when permitWeakResolution=false but for stability // reasons we use the more restrictive isNil frees. - if (permitWeakResolution && MemberConstraintIsReadyForWeakResolution csenv traitInfo) || isNil frees then + if (permitWeakResolution.Permit && MemberConstraintIsReadyForWeakResolution csenv traitInfo) || isNil frees then do! errors // Otherwise re-record the trait waiting for canonicalization else @@ -1587,10 +1619,13 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let mref = IL.mkRefToILMethod (ilMeth.DeclaringTyconRef.CompiledRepresentationForNamedType, ilMeth.RawMetadata) let iltref = ilMeth.ILExtensionMethodDeclaringTyconRef |> Option.map (fun tcref -> tcref.CompiledRepresentationForNamedType) ILMethSln(ilMeth.ApparentEnclosingType, iltref, mref, minst) + | FSMeth(_, ty, vref, _) -> FSMethSln(ty, vref, minst) + | MethInfo.DefaultStructCtor _ -> error(InternalError("the default struct constructor was the unexpected solution to a trait constraint", m)) + #if !NO_EXTENSIONTYPING | ProvidedMeth(amap, mi, _, m) -> let g = amap.g @@ -1599,6 +1634,7 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let objArgVars, objArgs = (if minfo.IsInstance then [mkLocal m "this" minfo.ApparentEnclosingType] else []) |> List.unzip let callMethInfoOpt, callExpr, callExprTy = ProvidedMethodCalls.BuildInvokerExpressionForProvidedMethodCall css.TcVal (g, amap, mi, objArgs, NeverMutates, false, ValUseFlag.NormalValUse, allArgs, m) let closedExprSln = ClosedExprSln (mkLambdas m [] (objArgVars@allArgVars) (callExpr, callExprTy) ) + // If the call is a simple call to an IL method with all the arguments in the natural order, then revert to use ILMethSln. // This is important for calls to operators on generated provided types. There is an (unchecked) condition // that generative providers do not re=order arguments or insert any more information into operator calls. @@ -1623,9 +1659,9 @@ and TransactMemberConstraintSolution traitInfo (trace: OptionalTrace) sln = /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads -and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) permitWeakResolution nm (TTrait(tys, _, memFlags, argtys, rty, soln) as traitInfo): MethInfo list = +and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolution: PermitWeakResolution) nm (TTrait(tys, _, memFlags, argtys, rty, soln) as traitInfo): MethInfo list = let results = - if permitWeakResolution || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then + if permitWeakResolution.Permit || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then let m = csenv.m let minfos = match memFlags.MemberKind with @@ -1647,6 +1683,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) permitWeakResolution |> List.exists (fun minfo2 -> MethInfosEquivByNameAndSig EraseAll true csenv.g csenv.amap m minfo2 minfo1))) else [] + // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. if nm = "op_Explicit" then results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" (TTrait(tys, "op_Implicit", memFlags, argtys, rty, soln)) @@ -1711,9 +1748,9 @@ and SolveRelevantMemberConstraintsForTypar (csenv: ConstraintSolverEnv) ndeep pe SolveMemberConstraint csenv true permitWeakResolution (ndeep+1) m2 trace traitInfo) and CanonicalizeRelevantMemberConstraints (csenv: ConstraintSolverEnv) ndeep trace tps = - SolveRelevantMemberConstraints csenv ndeep true trace tps + SolveRelevantMemberConstraints csenv ndeep PermitWeakResolution.Yes trace tps -and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace traitInfo support frees = +and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) traitInfo support (frees: Typar list) = let g = csenv.g let aenv = csenv.EquivEnv let cxst = csenv.SolverState.ExtraCxs @@ -2856,7 +2893,7 @@ let AddCxMethodConstraint denv css m trace traitInfo = (fun () -> trackErrors { do! - SolveMemberConstraint csenv true false 0 m trace traitInfo + SolveMemberConstraint csenv true PermitWeakResolution.No 0 m trace traitInfo |> OperationResult.ignore }) (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) @@ -2963,33 +3000,42 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra InfoReader = new InfoReader(g, amap) } let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) - let! _res = SolveMemberConstraint csenv true true 0 m NoTrace traitInfo + + let! _res = SolveMemberConstraint csenv true PermitWeakResolution.Yes 0 m NoTrace traitInfo + let sln = - match traitInfo.Solution with - | None -> Choice5Of5() - | Some sln -> - match sln with - | ILMethSln(origTy, extOpt, mref, minst) -> - let metadataTy = convertToTypeWithMetadataIfPossible g origTy - let tcref = tcrefOfAppTy g metadataTy - let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref - let ilMethInfo = - match extOpt with - | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) - | Some ilActualTypeRef -> - let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef - MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) - Choice1Of5 (ilMethInfo, minst) - | FSMethSln(ty, vref, minst) -> - Choice1Of5 (FSMeth(g, ty, vref, None), minst) - | FSRecdFieldSln(tinst, rfref, isSetProp) -> - Choice2Of5 (tinst, rfref, isSetProp) - | FSAnonRecdFieldSln(anonInfo, tinst, i) -> - Choice3Of5 (anonInfo, tinst, i) - | BuiltInSln -> - Choice5Of5 () - | ClosedExprSln expr -> - Choice4Of5 expr + match traitInfo.Solution with + | None -> Choice5Of5() + | Some sln -> + + // Given the solution information, reconstruct the MethInfo for the solution + match sln with + | ILMethSln(origTy, extOpt, mref, minst) -> + let metadataTy = convertToTypeWithMetadataIfPossible g origTy + let tcref = tcrefOfAppTy g metadataTy + let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref + let ilMethInfo = + match extOpt with + | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) + | Some ilActualTypeRef -> + let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef + MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) + Choice1Of5 (ilMethInfo, minst) + + | FSMethSln(ty, vref, minst) -> + Choice1Of5 (FSMeth(g, ty, vref, None), minst) + + | FSRecdFieldSln(tinst, rfref, isSetProp) -> + Choice2Of5 (tinst, rfref, isSetProp) + + | FSAnonRecdFieldSln(anonInfo, tinst, i) -> + Choice3Of5 (anonInfo, tinst, i) + + | BuiltInSln -> + Choice5Of5 () + + | ClosedExprSln expr -> + Choice4Of5 expr return! match sln with | Choice1Of5(minfo, methArgTys) -> @@ -3026,19 +3072,27 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra | Choice2Of5 (tinst, rfref, isSet) -> let res = match isSet, rfref.RecdField.IsStatic, argExprs.Length with + + // static setter | true, true, 1 -> - Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) + Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) + + // instance setter | true, false, 2 -> - // If we resolve to an instance field on a struct and we haven't yet taken - // the address of the object then go do that - if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then - let h = List.head argExprs - let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m - Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) - else - Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) + // If we resolve to an instance field on a struct and we haven't yet taken + // the address of the object then go do that + if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then + let h = List.head argExprs + let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m + Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) + else + Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) + + // static getter | false, true, 0 -> Some (mkStaticRecdFieldGet (rfref, tinst, m)) + + // instance getter | false, false, 1 -> if rfref.Tycon.IsStructOrEnumTycon && isByrefTy g (tyOfExpr g argExprs.[0]) then Some (mkRecdFieldGetViaExprAddr (argExprs.[0], rfref, tinst, m)) @@ -3046,6 +3100,7 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) | _ -> None ResultD res + | Choice3Of5 (anonInfo, tinst, i) -> let res = let tupInfo = anonInfo.TupInfo @@ -3055,9 +3110,11 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra Some (mkAnonRecdFieldGet g (anonInfo, argExprs.[0], tinst, i, m)) ResultD res - | Choice4Of5 expr -> ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) + | Choice4Of5 expr -> + ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) - | Choice5Of5 () -> ResultD None + | Choice5Of5 () -> + ResultD None } let ChooseTyparSolutionAndSolve css denv tp = diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 3d474dadbc..9c08ef934f 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -248,12 +248,14 @@ and remapTyparConstraintsAux tyenv cs = Some(TyparConstraint.CoercesTo (remapTypeAux tyenv ty, m)) | TyparConstraint.MayResolveMember(traitInfo, m) -> Some(TyparConstraint.MayResolveMember (remapTraitAux tyenv traitInfo, m)) - | TyparConstraint.DefaultsTo(priority, ty, m) -> Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m)) + | TyparConstraint.DefaultsTo(priority, ty, m) -> + Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m)) | TyparConstraint.IsEnum(uty, m) -> Some(TyparConstraint.IsEnum(remapTypeAux tyenv uty, m)) | TyparConstraint.IsDelegate(uty1, uty2, m) -> Some(TyparConstraint.IsDelegate(remapTypeAux tyenv uty1, remapTypeAux tyenv uty2, m)) - | TyparConstraint.SimpleChoice(tys, m) -> Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m)) + | TyparConstraint.SimpleChoice(tys, m) -> + Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m)) | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ From d35b0e9dd3153f6898643567e85db3b8bf60db5a Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 22 Jan 2020 17:02:08 -0800 Subject: [PATCH 064/101] Slicing and copying on ByteMemory should not throw if length is zero (#8282) * Slicing and copying on ByteMemory should not throw if length is zero * Added slice count check * Changed length check on stream creation * Remove empty * Minor format change * Check length before using AsStream * Remove exception throwing from creating a stream * Added checkCount * Remove checkReadCount --- src/absil/bytes.fs | 114 +++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 29 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 24159a728c..7e2f0ab2c9 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -66,6 +66,10 @@ type ByteMemory () = type ByteArrayMemory(bytes: byte[], offset, length) = inherit ByteMemory() + let checkCount count = + if count < 0 then + raise (ArgumentOutOfRangeException("count", "Count is less than zero.")) + do if length < 0 || length > bytes.Length then raise (ArgumentOutOfRangeException("length")) @@ -80,7 +84,11 @@ type ByteArrayMemory(bytes: byte[], offset, length) = override _.Length = length override _.ReadBytes(pos, count) = - Array.sub bytes (offset + pos) count + checkCount count + if count > 0 then + Array.sub bytes (offset + pos) count + else + Array.empty override _.ReadInt32 pos = let finalOffset = offset + pos @@ -96,25 +104,45 @@ type ByteArrayMemory(bytes: byte[], offset, length) = ((uint16 bytes.[finalOffset + 1]) <<< 8) override _.ReadUtf8String(pos, count) = - System.Text.Encoding.UTF8.GetString(bytes, offset + pos, count) + checkCount count + if count > 0 then + System.Text.Encoding.UTF8.GetString(bytes, offset + pos, count) + else + String.Empty override _.Slice(pos, count) = - ByteArrayMemory(bytes, offset + pos, count) :> ByteMemory + checkCount count + if count > 0 then + ByteArrayMemory(bytes, offset + pos, count) :> ByteMemory + else + ByteArrayMemory(Array.empty, 0, 0) :> ByteMemory override _.CopyTo stream = - stream.Write(bytes, offset, length) + if length > 0 then + stream.Write(bytes, offset, length) override _.Copy(srcOffset, dest, destOffset, count) = - Array.blit bytes (offset + srcOffset) dest destOffset count + checkCount count + if count > 0 then + Array.blit bytes (offset + srcOffset) dest destOffset count override _.ToArray() = - Array.sub bytes offset length + if length > 0 then + Array.sub bytes offset length + else + Array.empty override _.AsStream() = - new MemoryStream(bytes, offset, length) :> Stream + if length > 0 then + new MemoryStream(bytes, offset, length) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream override _.AsReadOnlyStream() = - new MemoryStream(bytes, offset, length, false) :> Stream + if length > 0 then + new MemoryStream(bytes, offset, length, false) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream [] type SafeUnmanagedMemoryStream = @@ -149,6 +177,10 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = if i < 0 || i >= length then raise (ArgumentOutOfRangeException("i")) + let checkCount count = + if count < 0 then + raise (ArgumentOutOfRangeException("count", "Count is less than zero.")) + do if length < 0 then raise (ArgumentOutOfRangeException("length")) @@ -165,16 +197,24 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = override _.Length = length override _.ReadUtf8String(pos, count) = - check pos - check (pos + count - 1) - System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) + else + String.Empty - override _.ReadBytes(pos, count) = - check pos - check (pos + count - 1) - let res = Bytes.zeroCreate count - Marshal.Copy(NativePtr.toNativeInt addr + nativeint pos, res, 0, count) - res + override _.ReadBytes(pos, count) = + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + let res = Bytes.zeroCreate count + Marshal.Copy(NativePtr.toNativeInt addr + nativeint pos, res, 0, count) + res + else + Array.empty override _.ReadInt32 pos = check pos @@ -187,28 +227,44 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = uint16(Marshal.ReadInt16(NativePtr.toNativeInt addr + nativeint pos)) override _.Slice(pos, count) = - check pos - check (pos + count - 1) - RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory + else + ByteArrayMemory(Array.empty, 0, 0) :> ByteMemory override x.CopyTo stream = - use stream2 = x.AsStream() - stream2.CopyTo stream + if length > 0 then + use stream2 = x.AsStream() + stream2.CopyTo stream override _.Copy(srcOffset, dest, destOffset, count) = - check srcOffset - Marshal.Copy(NativePtr.toNativeInt addr + nativeint srcOffset, dest, destOffset, count) + checkCount count + if count > 0 then + check srcOffset + Marshal.Copy(NativePtr.toNativeInt addr + nativeint srcOffset, dest, destOffset, count) override _.ToArray() = - let res = Array.zeroCreate length - Marshal.Copy(NativePtr.toNativeInt addr, res, 0, res.Length) - res + if length > 0 then + let res = Array.zeroCreate length + Marshal.Copy(NativePtr.toNativeInt addr, res, 0, res.Length) + res + else + Array.empty override _.AsStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream + if length > 0 then + new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream override _.AsReadOnlyStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream + if length > 0 then + new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream [] type ReadOnlyByteMemory(bytes: ByteMemory) = From a0cf13d331cfab73539e93bf1ca2de4e550b8d12 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Thu, 23 Jan 2020 10:29:14 -0800 Subject: [PATCH 065/101] safely delete test files and directories --- .../tests/UnitTests/ProjectOptionsBuilder.fs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/vsintegration/tests/UnitTests/ProjectOptionsBuilder.fs b/vsintegration/tests/UnitTests/ProjectOptionsBuilder.fs index 1d3df25165..106b7602a5 100644 --- a/vsintegration/tests/UnitTests/ProjectOptionsBuilder.fs +++ b/vsintegration/tests/UnitTests/ProjectOptionsBuilder.fs @@ -5,6 +5,19 @@ open System.IO open System.Xml.Linq open FSharp.Compiler.SourceCodeServices +module FileSystemHelpers = + let safeDeleteFile (path: string) = + try + File.Delete(path) + with + | _ -> () + + let safeDeleteDirectory (path: string) = + try + Directory.Delete(path) + with + | _ -> () + type FSharpProject = { Directory: string @@ -29,9 +42,10 @@ type FSharpProject = member this.Dispose() = // delete each source file this.Files - |> List.iter (fun (path, _contents) -> File.Delete(path)) + |> List.map fst + |> List.iter FileSystemHelpers.safeDeleteFile // delete the directory - Directory.Delete(this.Directory) + FileSystemHelpers.safeDeleteDirectory (this.Directory) // project file doesn't really exist, nothing to delete () From 5e8984713b182846410d99071abf8f3f6051cc27 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Thu, 23 Jan 2020 11:32:37 -0800 Subject: [PATCH 066/101] re-fix xlf comments (#8337) --- .../xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf | 3 +-- .../xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf | 3 +-- 13 files changed, 13 insertions(+), 26 deletions(-) diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index 5340031907..b071e0c5f7 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 2ca4bd450e..4184f3edc5 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 394481ad69..4b1a5e0d90 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 821545638e..99d3469919 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index dd58cb9a11..8902030751 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index c0221174d9..de4d65e71f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index 6f540b5425..e7191ac3c4 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index f912b6b4c7..6936b8e97f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index 5a2b75dce0..fefd197867 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 2b5303d91d..355d363084 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 73a72b806a..86ac32f4b3 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 474f99a3dc..0537632d5f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 16b7339b2a..17c64ffefb 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,9 +1828,8 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size - # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" From 70883fb00a867f6e81aa9c7cecdd9212c4e78d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Thu, 23 Jan 2020 15:22:23 -0700 Subject: [PATCH 067/101] Remove unused ProjectDiagnosticAnalyzer (#8304) * Remove unused ProjectDiagnosticAnalyzer * Update proj file --- .../Diagnostics/ProjectDiagnosticAnalyzer.fs | 58 ------------------- .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 - .../ProjectDiagnosticAnalyzerTests.fs | 31 ---------- 3 files changed, 90 deletions(-) delete mode 100644 vsintegration/src/FSharp.Editor/Diagnostics/ProjectDiagnosticAnalyzer.fs diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/ProjectDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/ProjectDiagnosticAnalyzer.fs deleted file mode 100644 index 544039aa36..0000000000 --- a/vsintegration/src/FSharp.Editor/Diagnostics/ProjectDiagnosticAnalyzer.fs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System -open System.Composition -open System.Collections.Immutable -open System.IO -open System.Threading -open System.Threading.Tasks - -open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.Diagnostics -open Microsoft.CodeAnalysis.Host.Mef -open Microsoft.CodeAnalysis.Text -open Microsoft.CodeAnalysis.SolutionCrawler -open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics - -open FSharp.Compiler -open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.Range - -// Project-wide error analysis. We don't enable this because ParseAndCheckProject checks projects against the versions of the files -// saves to the file system. This is different to the versions of the files active in the editor. This results in out-of-sync error -// messages while files are being edited - -[)>] -type internal FSharpProjectDiagnosticAnalyzer [] () = - -#if PROJECT_ANALYSIS - static member GetDiagnostics(options: FSharpProjectOptions) = async { - let! checkProjectResults = FSharpLanguageService.Checker.ParseAndCheckProject(options) - let results = - checkProjectResults.Errors - |> Seq.choose(fun (error) -> - if error.StartLineAlternate = 0 || error.EndLineAlternate = 0 then - Some(CommonRoslynHelpers.ConvertError(error, Location.None)) - else - // F# error line numbers are one-based. Errors that have a valid line number are reported by DocumentDiagnosticAnalyzer - None - ) - |> Seq.toImmutableArray - return results - } -#endif - - interface IFSharpProjectDiagnosticAnalyzer with - - member this.AnalyzeProjectAsync(_project: Project, _cancellationToken: CancellationToken): Task> = -#if PROJECT_ANALYSIS - async { - match FSharpLanguageService.GetOptionsForProject(project.Id) with - | Some options -> return! FSharpProjectDiagnosticAnalyzer.GetDiagnostics(options) - | None -> return ImmutableArray.Empty - } |> CommonRoslynHelpers.StartAsyncAsTask cancellationToken -#else - Task.FromResult(ImmutableArray.Empty) -#endif diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 629f7f2b0f..c4cc9fc07f 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -61,7 +61,6 @@ - diff --git a/vsintegration/tests/UnitTests/ProjectDiagnosticAnalyzerTests.fs b/vsintegration/tests/UnitTests/ProjectDiagnosticAnalyzerTests.fs index 6491c77b5c..2d45bef6cd 100644 --- a/vsintegration/tests/UnitTests/ProjectDiagnosticAnalyzerTests.fs +++ b/vsintegration/tests/UnitTests/ProjectDiagnosticAnalyzerTests.fs @@ -32,34 +32,3 @@ type ProjectDiagnosticAnalyzerTests() = let args = mkProjectCommandLineArgs (dllName, [fileName]) checker.GetProjectOptionsFromCommandLineArgs (projectName, args) - -#if PROJECT_ANALYSIS - [] - member public this.ProjectDiagnosticsDontReportJustProjectErrors_Bug1596() = - // https://github.com/Microsoft/visualfsharp/issues/1596 - let fileContents = """ -let x = 3 -printf "%d" x -""" - let options = CreateProjectAndGetOptions(fileContents) - let additionalOptions = {options with OtherOptions = Array.append options.OtherOptions [| "--times" |]} - - let errors = FSharpProjectDiagnosticAnalyzer.GetDiagnostics(additionalOptions) |> Async.RunSynchronously - Assert.AreEqual(1, errors.Length, "Exactly one warning should have been reported") - - let warning = errors.[0] - Assert.AreEqual(DiagnosticSeverity.Warning, warning.Severity, "Diagnostic severity should be a warning") - Assert.AreEqual("The command-line option 'times' is for test purposes only", warning.GetMessage()) - - [] - member public this.ProjectDiagnosticsShouldNotReportDocumentErrors_Bug1596() = - // https://github.com/Microsoft/visualfsharp/issues/1596 - let fileContents = """ -let x = "string value that cannot be printed with %d" -printf "%d" x -""" - let options = CreateProjectAndGetOptions(fileContents) - - let errors = FSharpProjectDiagnosticAnalyzer.GetDiagnostics(options) |> Async.RunSynchronously - Assert.AreEqual(0, errors.Length, "No semantic errors should have been reported") -#endif From a14840b716d52fb5ad3ef01f7102fd773be399ad Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 27 Jan 2020 13:26:29 -0800 Subject: [PATCH 068/101] Clean up nuget project file (#8327) * Clean up project file * remove framework deps * tests * Simplify slightly and resolve package conflicts for dotnet build too. * stuff --- .../FSharp.DependencyManager.Utilities.fs | 128 +++++++----------- .../FSharp.DependencyManager.fs | 9 +- .../DependencyManagerInteractiveTests.fs | 8 +- 3 files changed, 59 insertions(+), 86 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index d86ceb3dbb..fdbb075add 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -221,99 +221,73 @@ module Utilities = let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None succeeded, resultOutFile - // Generate a project files for dependencymanager projects - let generateLibrarySource = @"// Generated dependencymanager library -namespace lib" - - let generateProjectBody = @" + let generateProjectBody = """ + $(TARGETFRAMEWORK) false - 4.7.0 - 4.7.1-* + 4.7.0 + 4.7.1-* - - - -$(PACKAGEREFERENCES) - - - - - - - - - - - fsharp41 - tools - +$(PACKAGEREFERENCES) - - + - - <_ResolvedOutputFiles - Include=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*"" - Exclude=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll"" - Condition=""'%(_ResolvedProjectReferencePaths.IsFSharpDesignTimeProvider)' == 'true'""> - %(_ResolvedProjectReferencePaths.NearestTargetFramework) - - - <_ResolvedOutputFiles - Include=""@(BuiltProjectOutputGroupKeyOutput)"" - Condition=""'$(IsFSharpDesignTimeProvider)' == 'true' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'FSharp.Core.dll' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'System.ValueTuple.dll'""> - $(TargetFramework) - - - - $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedOutputFiles.NearestTargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) - - - + + <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> + <__ConflictsList Include="(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> + + + <__Conflicts>@(__ConflictsList, ';') + - - - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx - $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').StartsWith('ref/')) - %(ResolvedCompileFileDefinitions.NuGetPackageId) - %(ResolvedCompileFileDefinitions.NuGetPackageVersion) + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssemblies.FileName)%(__InteractiveReferencedAssemblies.Extension).fsx + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssemblies.NuGetPackageId) + %(__InteractiveReferencedAssemblies.NuGetPackageVersion) - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(RuntimeCopyLocalItems.FileName)%(RuntimeCopyLocalItems.Extension).fsx - $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').StartsWith('ref/')) - %(RuntimeCopyLocalItems.NuGetPackageId) - %(RuntimeCopyLocalItems.NuGetPackageVersion) + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssembliesCopyLocal.FileName)%(__InteractiveReferencedAssembliesCopyLocal.Extension).fsx + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageId) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageVersion) + - $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) + Include="@(RuntimeTargetsCopyLocalItems)" + Condition="'%(RuntimeTargetsCopyLocalItems.AssetType)' == 'native'"> + $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) - + - + @@ -322,16 +296,16 @@ $(PACKAGEREFERENCES) - + - - + + - + @@ -340,4 +314,4 @@ $(PACKAGEREFERENCES) -" +""" diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs index 9c577e9ca8..0fea32bdb4 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs @@ -28,10 +28,10 @@ module FSharpDependencyManager = let { Include=inc; Version=ver; RestoreSources=src; Script=script } = p seq { match not (String.IsNullOrEmpty(inc)), not (String.IsNullOrEmpty(ver)), not (String.IsNullOrEmpty(script)) with - | true, true, false -> yield sprintf @" true" inc ver - | true, true, true -> yield sprintf @" true" inc ver script - | true, false, false -> yield sprintf @" true" inc - | true, false, true -> yield sprintf @" true" inc script + | true, true, false -> yield sprintf @" " inc ver + | true, true, true -> yield sprintf @" " inc ver script + | true, false, false -> yield sprintf @" " inc + | true, false, true -> yield sprintf @" " inc script | _ -> () match not (String.IsNullOrEmpty(src)) with | true -> yield sprintf @" %s" (concat "$(RestoreAdditionalProjectSources)" src) @@ -158,7 +158,6 @@ type [] FSharpDependencyManager (outputDir:string op generateProjectBody.Replace("$(TARGETFRAMEWORK)", tfm) .Replace("$(PACKAGEREFERENCES)", packageReferenceText) - writeFile (Path.Combine(scriptsPath, "Library.fs")) generateLibrarySource writeFile fsProjectPath generateProjBody let succeeded, resultingFsx = buildProject fsProjectPath binLogPath diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 1b15cd7cfa..fd6148d4e3 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -27,14 +27,14 @@ type DependencyManagerInteractiveTests() = [] member __.``SmokeTest - #r nuget``() = let text = """ -#r @"nuget:System.Collections.Immutable, version=1.5.0" +#r @"nuget:Newtonsoft.Json, Version=9.0.1" 0""" use script = scriptHost() let mutable assemblyResolveEventCount = 0 let mutable foundAssemblyReference = false Event.add (fun (assembly: string) -> assemblyResolveEventCount <- assemblyResolveEventCount + 1 - foundAssemblyReference <- String.Compare("System.Collections.Immutable.dll", Path.GetFileName(assembly), StringComparison.OrdinalIgnoreCase) = 0) + foundAssemblyReference <- String.Compare("Newtonsoft.Json.dll", Path.GetFileName(assembly), StringComparison.OrdinalIgnoreCase) = 0) script.AssemblyReferenceAdded let opt = script.Eval(text) |> getValue let value = opt.Value @@ -61,7 +61,7 @@ type DependencyManagerInteractiveTests() = [] member __.``Dependency add events successful``() = - let referenceText = "System.Collections.Immutable, version=1.5.0" + let referenceText = "Newtonsoft.Json, Version=9.0.1" let text = referenceText |> sprintf """ #r @"nuget:%s" 0""" @@ -118,6 +118,6 @@ type DependencyManagerInteractiveTests() = use script = scriptHost() let mutable dependencyAddingEventCount = 0 Event.add (fun _ -> dependencyAddingEventCount <- dependencyAddingEventCount + 1) script.DependencyAdding - script.Eval("#r \"nuget:System.Collections.Immutable, Version=1.5.0\"") |> ignoreValue + script.Eval("#r \"nuget:NUnit.ConsoleRunner, Version=3.10.0\"") |> ignoreValue script.Eval("#r \"nuget:Newtonsoft.Json, Version=9.0.1\"\n0") |> ignoreValue Assert.AreEqual(2, dependencyAddingEventCount) From 3f9172ada35b6db08f64ee592785879d60ac6cb9 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 28 Jan 2020 03:48:58 +0000 Subject: [PATCH 069/101] squash and-bang implementation (#7756) Co-authored-by: Kevin Ransom (msft) --- src/fsharp/CompileOps.fs | 2 + src/fsharp/FSComp.txt | 3 + src/fsharp/FSStrings.resx | 3 + src/fsharp/LanguageFeatures.fs | 2 + src/fsharp/LanguageFeatures.fsi | 2 +- src/fsharp/LexFilter.fs | 7 + src/fsharp/TypeChecker.fs | 362 ++++++++-- src/fsharp/ast.fs | 9 +- src/fsharp/lex.fsl | 4 +- src/fsharp/pars.fsy | 44 +- src/fsharp/service/ServiceAssemblyContent.fs | 8 +- .../service/ServiceInterfaceStubGenerator.fs | 10 +- src/fsharp/service/ServiceLexing.fs | 4 +- src/fsharp/service/ServiceParseTreeWalk.fs | 14 +- src/fsharp/service/ServiceStructure.fs | 23 +- src/fsharp/service/ServiceUntypedParse.fs | 14 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 15 + src/fsharp/xlf/FSComp.txt.de.xlf | 15 + src/fsharp/xlf/FSComp.txt.es.xlf | 15 + src/fsharp/xlf/FSComp.txt.fr.xlf | 15 + src/fsharp/xlf/FSComp.txt.it.xlf | 15 + src/fsharp/xlf/FSComp.txt.ja.xlf | 15 + src/fsharp/xlf/FSComp.txt.ko.xlf | 15 + src/fsharp/xlf/FSComp.txt.pl.xlf | 15 + src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 15 + src/fsharp/xlf/FSComp.txt.ru.xlf | 15 + src/fsharp/xlf/FSComp.txt.tr.xlf | 15 + src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 15 + src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 15 + src/fsharp/xlf/FSStrings.cs.xlf | 5 + src/fsharp/xlf/FSStrings.de.xlf | 5 + src/fsharp/xlf/FSStrings.es.xlf | 5 + src/fsharp/xlf/FSStrings.fr.xlf | 5 + src/fsharp/xlf/FSStrings.it.xlf | 5 + src/fsharp/xlf/FSStrings.ja.xlf | 5 + src/fsharp/xlf/FSStrings.ko.xlf | 5 + src/fsharp/xlf/FSStrings.pl.xlf | 5 + src/fsharp/xlf/FSStrings.pt-BR.xlf | 5 + src/fsharp/xlf/FSStrings.ru.xlf | 5 + src/fsharp/xlf/FSStrings.tr.xlf | 5 + src/fsharp/xlf/FSStrings.zh-Hans.xlf | 5 + src/fsharp/xlf/FSStrings.zh-Hant.xlf | 5 + tests/fsharp/Compiler/CompilerAssert.fs | 67 +- .../DataExpressions/ComputationExpressions.fs | 628 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../dependency_graph.fsx | 192 ++++++ .../fsharpqa/Source/CodeGen/EmittedIL/.il.bsl | 0 .../ComputationExprLibrary.fs | 2 +- .../Tests.LanguageService.Completion.fs | 320 ++++++++- .../UnitTests/TestLib.LanguageService.fs | 14 +- .../tests/UnitTests/TestLib.Salsa.fs | 1 + 51 files changed, 1834 insertions(+), 162 deletions(-) mode change 100644 => 100755 src/fsharp/TypeChecker.fs mode change 100644 => 100755 src/fsharp/service/ServiceLexing.fs create mode 100644 tests/fsharp/Compiler/Conformance/DataExpressions/ComputationExpressions.fs create mode 100644 tests/fsharp/perf/computation-expressions/dependency_graph.fsx delete mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/.il.bsl diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index c90e75a3ae..29d0408209 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -1004,6 +1004,8 @@ let OutputPhasedErrorR (os: StringBuilder) (err: PhasedDiagnostic) (canSuggestNa | Parser.TOKEN_OLET(_) -> getErrorString("Parser.TOKEN.OLET") | Parser.TOKEN_OBINDER | Parser.TOKEN_BINDER -> getErrorString("Parser.TOKEN.BINDER") + | Parser.TOKEN_OAND_BANG + | Parser.TOKEN_AND_BANG -> getErrorString("Parser.TOKEN.AND.BANG") | Parser.TOKEN_ODO -> getErrorString("Parser.TOKEN.ODO") | Parser.TOKEN_OWITH -> getErrorString("Parser.TOKEN.OWITH") | Parser.TOKEN_OFUNCTION -> getErrorString("Parser.TOKEN.OFUNCTION") diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index de26c9b349..6a4e5da6b1 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1475,6 +1475,9 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl 3301,chkInvalidFunctionReturnType,"The function or method has an invalid return type '%s'. This is not permitted by the rules of Common IL." 3302,packageManagementRequiresVFive,"The package management feature requires language version 5.0 use /langversion:preview" 3303,fromEndSlicingRequiresVFive,"From the end slicing with requires language version 5.0, use /langversion:preview." +3343,tcRequireMergeSourcesOrBindN,"The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '%s' method or appropriate 'MergeSource' and 'Bind' methods" +3344,tcAndBangNotSupported,"This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature." +3345,tcInvalidUseBangBindingNoAndBangs,"use! may not be combined with and!" useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)." fSharpBannerVersion,"%s for F# %s" optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'" diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index cf3d3c92b2..a56e6f1421 100644 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -564,6 +564,9 @@ keyword 'and' + ! + keyword 'and!' + keyword 'as' diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 2170cee8f7..9d23f9e266 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -28,6 +28,7 @@ type LanguageFeature = | PackageManagement | FromEndSlicing | FixedIndexSlice3d4d + | AndBang /// LanguageVersion management type LanguageVersion (specifiedVersionAsString) = @@ -61,6 +62,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.NameOf, previewVersion LanguageFeature.OpenStaticClasses, previewVersion LanguageFeature.PackageManagement, previewVersion + LanguageFeature.AndBang, previewVersion ] let specified = diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index 37a58a50b4..5f274351d7 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -16,7 +16,7 @@ type LanguageFeature = | PackageManagement | FromEndSlicing | FixedIndexSlice3d4d - + | AndBang /// LanguageVersion management type LanguageVersion = diff --git a/src/fsharp/LexFilter.fs b/src/fsharp/LexFilter.fs index 470b54709b..d485399af8 100644 --- a/src/fsharp/LexFilter.fs +++ b/src/fsharp/LexFilter.fs @@ -1784,6 +1784,13 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, pushCtxt tokenTup (CtxtLetDecl(blockLet, tokenStartPos)) returnToken tokenLexbufState (if blockLet then OBINDER b else token) + // and! ... ~~~> CtxtLetDecl + | AND_BANG isUse, (ctxt :: _) -> + let blockLet = match ctxt with CtxtSeqBlock _ -> true | _ -> false + if debug then dprintf "AND!: entering CtxtLetDecl(blockLet=%b), awaiting EQUALS to go to CtxtSeqBlock (%a)\n" blockLet outputPos tokenStartPos + pushCtxt tokenTup (CtxtLetDecl(blockLet,tokenStartPos)) + returnToken tokenLexbufState (if blockLet then OAND_BANG isUse else token) + | (VAL | STATIC | ABSTRACT | MEMBER | OVERRIDE | DEFAULT), ctxtStack when thereIsACtxtMemberBodyOnTheStackAndWeShouldPopStackForUpcomingMember ctxtStack -> if debug then dprintf "STATIC/MEMBER/OVERRIDE/DEFAULT: already inside CtxtMemberBody, popping all that context before starting next member...\n" // save this token, we'll consume it again later... diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs old mode 100644 new mode 100755 index c888057686..ac71f5bb58 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1842,31 +1842,25 @@ let UseCombinedArity g declKind rhsExpr prelimScheme = let UseNoArity prelimScheme = BuildValScheme ExpressionBinding None prelimScheme -let MakeSimpleVals cenv env names = +/// Make and publish the Val nodes for a collection of simple (non-generic) value specifications +let MakeAndPublishSimpleVals cenv env names = let tyschemes = DontGeneralizeVals names let valSchemes = NameMap.map UseNoArity tyschemes let values = MakeAndPublishVals cenv env (ParentNone, false, ExpressionBinding, ValNotInRecScope, valSchemes, [], XmlDoc.Empty, None) let vspecMap = NameMap.map fst values values, vspecMap -let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = - +/// Make and publish the Val nodes for a collection of value specifications at Lambda and Match positions +/// +/// We merge the additions to the name resolution environment into one using a merged range so all values are brought +/// into scope simultaneously. The technique used to do this is a disturbing and unfortunate hack that +/// intercepts `NotifyNameResolution` calls being emitted by `MakeAndPublishSimpleVals` + +let MakeAndPublishSimpleValsForMergedScope cenv env m (names: NameMap<_>) = let values, vspecMap = - if not mergeNamesInOneNameresEnv then MakeSimpleVals cenv env names + if names.Count <= 1 then + MakeAndPublishSimpleVals cenv env names else - // reason: now during typecheck we create new name resolution environment for all components of tupled arguments in lambda. - // When trying to find best environment for the given position first we pick the most deeply nested scope that contains given position - // (and that will be lambda body - correct one), then we look for the better subtree on the left hand side - // (and that will be name resolution environment containing second parameter parameter - without the first one). - // fix: I've tried to make fix as local as possible to reduce overall impact on the source code. - // Idea of the fix: replace existing typecheck results sink and capture all reported name resolutions (this will be all parameters in lambda). - // After that - we restore the sink back, generate new name resolution environment that contains all captured names and report generated environment - // to the old sink. - - - // default behavior - send EnvWithScope notification for every resolved name - // what we do here is override this default behavior and capture only all name resolution notifications - // later we'll process them and create one name resolution env that will contain names from all notifications let nameResolutions = ResizeArray() let values, vspecMap = let sink = @@ -1875,14 +1869,14 @@ let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = member this.NotifyNameResolution(pos, item, itemGroup, itemTyparInst, occurence, denv, nenv, ad, m, replacing) = if not m.IsSynthetic then nameResolutions.Add(pos, item, itemGroup, itemTyparInst, occurence, denv, nenv, ad, m, replacing) - member this.NotifyExprHasType(_, _, _, _, _, _) = assert false // no expr typings in MakeSimpleVals + member this.NotifyExprHasType(_, _, _, _, _, _) = assert false // no expr typings in MakeAndPublishSimpleVals member this.NotifyFormatSpecifierLocation(_, _) = () member this.NotifyOpenDeclaration(_) = () member this.CurrentSourceText = None member this.FormatStringCheckContext = None } use _h = WithNewTypecheckResultsSink(sink, cenv.tcSink) - MakeSimpleVals cenv env names + MakeAndPublishSimpleVals cenv env names if nameResolutions.Count <> 0 then let (_, _, _, _, _, _, _, ad, m1, _replacing) = nameResolutions.[0] @@ -1905,8 +1899,6 @@ let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = let envinner = AddLocalValMap cenv.tcSink m vspecMap env envinner, values, vspecMap - - //------------------------------------------------------------------------- // Helpers to freshen existing types and values, i.e. when a reference // to C<_> occurs then generate C for a fresh type inference variable ?ty. @@ -3535,7 +3527,7 @@ let YieldFree cenv expr = | SynExpr.ForEach (_, _, _, _, _, body, _) -> YieldFree body - | SynExpr.LetOrUseBang(_, _, _, _, _, body, _) -> + | SynExpr.LetOrUseBang(_, _, _, _, _, _, body, _) -> YieldFree body | SynExpr.YieldOrReturn((true, _), _, _) -> false @@ -6249,7 +6241,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = error(Error(FSComp.SR.tcConstructRequiresSequenceOrComputations(), m)) | SynExpr.DoBang (_, m) - | SynExpr.LetOrUseBang (_, _, _, _, _, _, m) -> + | SynExpr.LetOrUseBang (range=m) -> error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m)) | SynExpr.MatchBang (_, _, _, m) -> @@ -6261,7 +6253,7 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = | SynExpr.Lambda (isMember, isSubsequent, spats, bodyExpr, m) when isMember || isFirst || isSubsequent -> let domainTy, resultTy = UnifyFunctionType None cenv env.DisplayEnv m overallTy let vs, (tpenv, names, takenNames) = TcSimplePats cenv isMember CheckCxs domainTy env (tpenv, Map.empty, takenNames) spats - let envinner, _, vspecMap = MakeAndPublishSimpleVals cenv env m names true + let envinner, _, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names let byrefs = vspecMap |> Map.map (fun _ v -> isByrefTy cenv.g v.Type, v) let envinner = if isMember then envinner else ExitFamilyRegion envinner let bodyExpr, tpenv = TcIteratedLambdas cenv false envinner resultTy takenNames tpenv bodyExpr @@ -7529,6 +7521,9 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | [] -> callExpr | _ -> mkSynCall "Source" callExpr.Range [callExpr] + let mkSourceExprConditional isFromSource callExpr = + if isFromSource then mkSourceExpr callExpr else callExpr + /// Decide if the builder is an auto-quote builder let isAutoQuote = hasMethInfo "Quote" @@ -7979,7 +7974,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if not q then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), nm.idRange)) - let firstSource = if isFromSource then mkSourceExpr firstSource else firstSource + let firstSource = mkSourceExprConditional isFromSource firstSource let secondSource = mkSourceExpr secondSource // Add the variables to the variable space, on demand @@ -8123,11 +8118,12 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) -> - let wrappedSourceExpr = if isFromSource then mkSourceExpr sourceExpr else sourceExpr + let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr let mFor = match spForLoop with SequencePointAtForLoop m -> m | _ -> pat.Range let mPat = pat.Range let spBind = match spForLoop with SequencePointAtForLoop m -> SequencePointAtBinding m | NoSequencePointAtForLoop -> NoSequencePointAtStickyBinding - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("For"), mFor)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("For"), mFor)) // Add the variables to the query variable space, on demand let varSpace = @@ -8149,16 +8145,20 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder let mGuard = guardExpr.Range let mWhile = match spWhile with SequencePointAtWhileLoop m -> m | _ -> mGuard if isQuery then error(Error(FSComp.SR.tcNoWhileInQuery(), mWhile)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile)) Some(trans true q varSpace innerComp (fun holeFill -> translatedCtxt (mkSynCall "While" mWhile [mkSynDelay2 guardExpr; mkSynCall "Delay" mWhile [mkSynDelay innerComp.Range holeFill]])) ) | SynExpr.TryFinally (innerComp, unwindExpr, mTryToLast, spTry, _spFinally) -> let mTry = match spTry with SequencePointAtTry m -> m | _ -> mTryToLast if isQuery then error(Error(FSComp.SR.tcNoTryFinallyInQuery(), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) Some (translatedCtxt (mkSynCall "TryFinally" mTry [mkSynCall "Delay" mTry [mkSynDelay innerComp.Range (transNoQueryOps innerComp)]; mkSynDelay2 unwindExpr])) | SynExpr.Paren (_, _, _, m) -> @@ -8238,7 +8238,10 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | StripApps(SingleIdent nm, args) -> if args.Length = expectedArgCount then // Check for the [] attribute on each argument position - let args = args |> List.mapi (fun i arg -> if isCustomOperationProjectionParameter (i+1) nm then SynExpr.Lambda (false, false, varSpaceSimplePat, arg, arg.Range.MakeSynthetic()) else arg) + let args = args |> List.mapi (fun i arg -> + if isCustomOperationProjectionParameter (i+1) nm then + SynExpr.Lambda (false, false, varSpaceSimplePat, arg, arg.Range.MakeSynthetic()) + else arg) mkSynCall methInfo.DisplayName mClause (dataCompPrior :: args) else errorR(Error(FSComp.SR.tcCustomOperationHasIncorrectArgCount(nm.idText, expectedArgCount, args.Length), nm.idRange)) @@ -8266,7 +8269,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // Rebind using either for ... or let!.... let rebind = if maintainsVarSpaceUsingBind then - SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range) + SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, intoPat, dataCompAfterOp, [], contExpr, intoPat.Range) else SynExpr.ForEach (NoSequencePointAtForLoop, SeqExprOnly false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range) @@ -8288,7 +8291,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // Rebind using either for ... or let!.... let rebind = if lastUsesBind then - SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range) + SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, varSpacePat, dataCompPrior, [], compClausesExpr, compClausesExpr.Range) else SynExpr.ForEach (NoSequencePointAtForLoop, SeqExprOnly false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range) @@ -8316,8 +8319,10 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // This is not pretty - we have to decide which range markers we use for the calls to Combine and Delay // NOTE: we should probably suppress these sequence points altogether let m1 = rangeForCombine innerComp1 - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Combine" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Combine"), m)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Combine" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Combine"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), m)) Some (translatedCtxt (mkSynCall "Combine" m1 [c; mkSynCall "Delay" m1 [mkSynDelay innerComp2.Range (transNoQueryOps innerComp2)]])) | None -> // "do! expr; cexpr" is treated as { let! () = expr in cexpr } @@ -8328,7 +8333,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SuppressSequencePointOnStmtOfSequential -> SequencePointAtBinding m | SuppressSequencePointOnExprOfSequential -> NoSequencePointAtDoBinding | SequencePointsAtSeq -> SequencePointAtBinding m - Some(trans true q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, innerComp2, m)) translatedCtxt) + Some(trans true q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m)) translatedCtxt) + // "expr; cexpr" is treated as sequential execution | _ -> Some (trans true q varSpace innerComp2 (fun holeFill -> @@ -8353,7 +8359,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder Some (translatedCtxt (SynExpr.IfThenElse (guardExpr, transNoQueryOps thenComp, Some(transNoQueryOps elseComp), spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch))) | None -> let elseComp = - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mIfToThen ad "Zero" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), mIfToThen)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mIfToThen ad "Zero" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), mIfToThen)) mkSynCall "Zero" mIfToThen [] Some (trans true q varSpace thenComp (fun holeFill -> translatedCtxt (SynExpr.IfThenElse (guardExpr, holeFill, Some elseComp, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch)))) @@ -8385,7 +8392,6 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // error case error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings(), mQueryOp))) - Some (trans true q varSpace innerComp (fun holeFill -> translatedCtxt (SynExpr.LetOrUse (isRec, false, binds, holeFill, m)))) // 'use x = expr in expr' @@ -8394,16 +8400,18 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isQuery then error(Error(FSComp.SR.tcUseMayNotBeUsedInQueries(), bindRange)) let innerCompRange = innerComp.Range let consumeExpr = SynExpr.MatchLambda(false, innerCompRange, [Clause(pat, None, transNoQueryOps innerComp, innerCompRange, SequencePointAtTarget)], spBind, innerCompRange) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) Some (translatedCtxt (mkSynCall "Using" bindRange [rhsExpr; consumeExpr ])) - // 'let! pat = expr in expr' --> build.Bind(e1, (function _argN -> match _argN with pat -> expr)) - | SynExpr.LetOrUseBang (spBind, false, isFromSource, pat, rhsExpr, innerComp, _) -> + // 'let! pat = expr in expr' + // --> build.Bind(e1, (fun _argN -> match _argN with pat -> expr)) + // or + // --> build.BindReturn(e1, (fun _argN -> match _argN with pat -> expr-without-return)) + | SynExpr.LetOrUseBang (spBind, false, isFromSource, pat, rhsExpr, [], innerComp, _) -> let bindRange = match spBind with SequencePointAtBinding m -> m | _ -> rhsExpr.Range if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), bindRange)) - let innerRange = innerComp.Range - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) // Add the variables to the query variable space, on demand let varSpace = @@ -8412,28 +8420,135 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (pat, None) vspecs, envinner) - let rhsExpr = if isFromSource then mkSourceExpr rhsExpr else rhsExpr - Some (trans true q varSpace innerComp (fun holeFill -> - let consumeExpr = SynExpr.MatchLambda (false, pat.Range, [Clause(pat, None, holeFill, innerRange, SequencePointAtTarget)], spBind, innerRange) - translatedCtxt (mkSynCall "Bind" bindRange [rhsExpr; consumeExpr]))) + let rhsExpr = mkSourceExprConditional isFromSource rhsExpr + Some (transBind q varSpace bindRange "Bind" [rhsExpr] pat spBind innerComp translatedCtxt) - // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) - | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.Named (SynPat.Wild _, id, false, _, _) as pat), rhsExpr, innerComp, _) - | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.LongIdent (LongIdentWithDots([id], _), _, _, _, _, _) as pat), rhsExpr, innerComp, _) -> + // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) + | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.Named (SynPat.Wild _, id, false, _, _) as pat) , rhsExpr, [], innerComp, _) + | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.LongIdent (longDotId=LongIdentWithDots([id], _)) as pat), rhsExpr, [], innerComp, _) -> let bindRange = match spBind with SequencePointAtBinding m -> m | _ -> rhsExpr.Range if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), bindRange)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) + let consumeExpr = SynExpr.MatchLambda(false, bindRange, [Clause(pat, None, transNoQueryOps innerComp, innerComp.Range, SequencePointAtTarget)], spBind, bindRange) let consumeExpr = mkSynCall "Using" bindRange [SynExpr.Ident(id); consumeExpr ] let consumeExpr = SynExpr.MatchLambda(false, bindRange, [Clause(pat, None, consumeExpr, id.idRange, SequencePointAtTarget)], spBind, bindRange) - let rhsExpr = if isFromSource then mkSourceExpr rhsExpr else rhsExpr + let rhsExpr = mkSourceExprConditional isFromSource rhsExpr + // TODO: consider allowing translation to BindReturn Some(translatedCtxt (mkSynCall "Bind" bindRange [rhsExpr; consumeExpr])) - // 'use! pat = e1 in e2' where 'pat' is not a simple name --> error - | SynExpr.LetOrUseBang (_spBind, true, _isFromSource, pat, _rhsExpr, _innerComp, _) -> - error(Error(FSComp.SR.tcInvalidUseBangBinding(), pat.Range)) + // 'use! pat = e1 ... in e2' where 'pat' is not a simple name --> error + | SynExpr.LetOrUseBang (_spBind, true, _isFromSource, pat, _rhsExpr, andBangs, _innerComp, _) -> + if isNil andBangs then + error(Error(FSComp.SR.tcInvalidUseBangBinding(), pat.Range)) + else + error(Error(FSComp.SR.tcInvalidUseBangBindingNoAndBangs(), comp.Range)) + + // 'let! pat1 = expr1 and! pat2 = expr2 in ...' --> + // build.BindN(expr1, expr2, ...) + // or + // build.BindNReturn(expr1, expr2, ...) + // or + // build.Bind(build.MergeSources(expr1, expr2), ...) + | SynExpr.LetOrUseBang(letSpBind, false, isFromSource, letPat, letRhsExpr, andBangBindings, innerComp, letBindRange) -> + if cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang then + if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), letBindRange)) + let bindRange = match letSpBind with SequencePointAtBinding m -> m | _ -> letRhsExpr.Range + let sources = (letRhsExpr :: [for (_, _, _, _, andExpr, _) in andBangBindings -> andExpr ]) |> List.map (mkSourceExprConditional isFromSource) + let pats = letPat :: [for (_, _, _, andPat, _, _) in andBangBindings -> andPat ] + let sourcesRange = sources |> List.map (fun e -> e.Range) |> List.reduce unionRanges + + let numSources = sources.Length + let bindReturnNName = "Bind"+string numSources+"Return" + let bindNName = "Bind"+string numSources + + // Check if this is a Bind2Return etc. + let hasBindReturnN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindReturnNName builderTy)) + if hasBindReturnN && Option.isSome (convertSimpleReturnToExpr varSpace innerComp) then + let consumePat = SynPat.Tuple(false, pats, letPat.Range) + Some (transBind q varSpace bindRange bindNName sources consumePat letSpBind innerComp translatedCtxt) + + else + + // Check if this is a Bind2 etc. + let hasBindN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindNName builderTy)) + if hasBindN then + let consumePat = SynPat.Tuple(false, pats, letPat.Range) + + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (consumePat, None) + vspecs, envinner) + + Some (transBind q varSpace bindRange bindNName sources consumePat letSpBind innerComp translatedCtxt) + else + + // Look for the maximum supported MergeSources, MergeSources3, ... + let mkMergeSourcesName n = if n = 2 then "MergeSources" else "MergeSources"+(string n) + + let maxMergeSources = + let rec loop (n: int) = + let mergeSourcesName = mkMergeSourcesName n + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + (n-1) + else + loop (n+1) + loop 2 + + if maxMergeSources = 1 then error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let rec mergeSources (sourcesAndPats: (SynExpr * SynPat) list) = + let numSourcesAndPats = sourcesAndPats.Length + assert (numSourcesAndPats <> 0) + if numSourcesAndPats = 1 then + sourcesAndPats.[0] + + elif numSourcesAndPats <= maxMergeSources then + + // Call MergeSources2(e1, e2), MergeSources3(e1, e2, e3) etc + let mergeSourcesName = mkMergeSourcesName numSourcesAndPats + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let source = mkSynCall mergeSourcesName sourcesRange (List.map fst sourcesAndPats) + let pat = SynPat.Tuple(false, List.map snd sourcesAndPats, letPat.Range) + source, pat + + else + + // Call MergeSourcesMax(e1, e2, e3, e4, (...)) + let nowSourcesAndPats, laterSourcesAndPats = List.splitAt (maxMergeSources - 1) sourcesAndPats + let mergeSourcesName = mkMergeSourcesName maxMergeSources + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let laterSource, laterPat = mergeSources laterSourcesAndPats + let source = mkSynCall mergeSourcesName sourcesRange (List.map fst nowSourcesAndPats @ [laterSource]) + let pat = SynPat.Tuple(false, List.map snd nowSourcesAndPats @ [laterPat], letPat.Range) + source, pat + + let mergedSources, consumePat = mergeSources (List.zip sources pats) + + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (consumePat, None) + vspecs, envinner) + + // Build the 'Bind' call + Some (transBind q varSpace bindRange "Bind" [mergedSources] consumePat letSpBind innerComp translatedCtxt) + else + error(Error(FSComp.SR.tcAndBangNotSupported(), comp.Range)) | SynExpr.Match (spMatch, expr, clauses, m) -> let mMatch = match spMatch with SequencePointAtBinding mMatch -> mMatch | _ -> m @@ -8445,9 +8560,14 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.MatchBang (spMatch, expr, clauses, m) -> let mMatch = match spMatch with SequencePointAtBinding mMatch -> mMatch | _ -> m if isQuery then error(Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery(), mMatch)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mMatch ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), mMatch)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mMatch ad "Bind" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), mMatch)) + let clauses = clauses |> List.map (fun (Clause(pat, cond, innerComp, patm, sp)) -> Clause(pat, cond, transNoQueryOps innerComp, patm, sp)) let consumeExpr = SynExpr.MatchLambda (false, mMatch, clauses, spMatch, mMatch) + + // TODO: consider allowing translation to BindReturn Some(translatedCtxt (mkSynCall "Bind" mMatch [expr; consumeExpr])) | SynExpr.TryWith (innerComp, _mTryToWith, clauses, _mWithToLast, mTryToLast, spTry, _spWith) -> @@ -8456,14 +8576,19 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isQuery then error(Error(FSComp.SR.tcTryWithMayNotBeUsedInQueries(), mTry)) let clauses = clauses |> List.map (fun (Clause(pat, cond, clauseComp, patm, sp)) -> Clause(pat, cond, transNoQueryOps clauseComp, patm, sp)) let consumeExpr = SynExpr.MatchLambda(true, mTryToLast, clauses, NoSequencePointAtStickyBinding, mTryToLast) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("TryWith"), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("TryWith"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + Some(translatedCtxt (mkSynCall "TryWith" mTry [mkSynCall "Delay" mTry [mkSynDelay2 (transNoQueryOps innerComp)]; consumeExpr])) | SynExpr.YieldOrReturnFrom ((isYield, _), yieldExpr, m) -> let yieldExpr = mkSourceExpr yieldExpr if isYield then - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("YieldFrom"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("YieldFrom"), m)) Some (translatedCtxt (mkSynCall "YieldFrom" m [yieldExpr])) else @@ -8477,7 +8602,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.YieldOrReturn ((isYield, _), yieldExpr, m) -> let methName = (if isYield then "Yield" else "Return") if isQuery && not isYield then error(Error(FSComp.SR.tcReturnMayNotBeUsedInQueries(), m)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod(methName), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod(methName), m)) Some(translatedCtxt (mkSynCall methName m [yieldExpr])) | _ -> None @@ -8500,8 +8626,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Return" builderTy) then SynExpr.ImplicitZero m else - SynExpr.YieldOrReturn((false, true), SynExpr.Const (SynConst.Unit, m), m) - trans true q varSpace (SynExpr.LetOrUseBang(NoSequencePointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, bodyExpr, m)) translatedCtxt + SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m) + trans true q varSpace (SynExpr.LetOrUseBang (NoSequencePointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m)) translatedCtxt // "expr;" in final position is treated as { expr; zero } // Suppress the sequence point on the "zero" @@ -8523,6 +8649,104 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder SynExpr.Sequential(SuppressSequencePointOnStmtOfSequential, true, comp, holeFill, comp.Range) translatedCtxt fillExpr) + and transBind q varSpace bindRange bindName bindArgs (consumePat: SynPat) spBind (innerComp: SynExpr) translatedCtxt = + + let innerRange = innerComp.Range + + let innerCompReturn = + if cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang then + convertSimpleReturnToExpr varSpace innerComp + else None + + match innerCompReturn with + | Some innerExpr when + (let bindName = bindName + "Return" + not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy))) -> + + let bindName = bindName + "Return" + + // Build the `BindReturn` call + let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [Clause(consumePat, None, innerExpr, innerRange, SequencePointAtTarget)], spBind, innerRange) + translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr])) + + | _ -> + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod(bindName), bindRange)) + + // Build the `Bind` call + trans true q varSpace innerComp (fun holeFill -> + let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [Clause(consumePat, None, holeFill, innerRange, SequencePointAtTarget)], spBind, innerRange) + translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr]))) + + and convertSimpleReturnToExpr varSpace innerComp = + match innerComp with + | SynExpr.YieldOrReturn ((false, _), returnExpr, _) -> Some returnExpr + | SynExpr.Match (spMatch, expr, clauses, m) -> + let clauses = + clauses |> List.map (fun (Clause(pat, cond, innerComp2, patm, sp)) -> + match convertSimpleReturnToExpr varSpace innerComp2 with + | None -> None + | Some innerExpr2 -> Some (Clause(pat, cond, innerExpr2, patm, sp))) + if clauses |> List.forall Option.isSome then + Some (SynExpr.Match (spMatch, expr, (clauses |> List.map Option.get), m)) + else + None + + | SynExpr.IfThenElse (guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch) -> + match convertSimpleReturnToExpr varSpace thenComp with + | None -> None + | Some thenExpr -> + match Option.map (convertSimpleReturnToExpr varSpace) elseCompOpt with + | Some None -> None + | elseExprOpt -> + Some (SynExpr.IfThenElse (guardExpr, thenExpr, Option.bind id elseExprOpt, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch) ) + + | SynExpr.LetOrUse (isRec, false, binds, innerComp, m) -> + match convertSimpleReturnToExpr varSpace innerComp with + | None -> None + | Some innerExpr -> Some (SynExpr.LetOrUse (isRec, false, binds, innerExpr, m)) + + | SynExpr.Sequential (sp, true, innerComp1, innerComp2, m) -> + + // Check the first part isn't a computation expression construct + if isSimpleExpr innerComp1 then + // Check the second part is a simple return + match convertSimpleReturnToExpr varSpace innerComp2 with + | None -> None + | Some innerExpr2 -> Some (SynExpr.Sequential (sp, true, innerComp1, innerExpr2, m)) + else + None + + | _ -> None + + /// Check is an expression has no computation expression constructs + and isSimpleExpr comp = + + match comp with + | ForEachThenJoinOrGroupJoinOrZipClause _ -> false + | SynExpr.ForEach _ -> false + | SynExpr.For _ -> false + | SynExpr.While _ -> false + | SynExpr.TryFinally _ -> false + | SynExpr.ImplicitZero _ -> false + | OptionalSequential (JoinOrGroupJoinOrZipClause _, _) -> false + | OptionalSequential (CustomOperationClause _, _) -> false + | SynExpr.Sequential (_, _, innerComp1, innerComp2, _) -> isSimpleExpr innerComp1 && isSimpleExpr innerComp2 + | SynExpr.IfThenElse (_, thenComp, elseCompOpt, _, _, _, _) -> + isSimpleExpr thenComp && (match elseCompOpt with None -> true | Some c -> isSimpleExpr c) + | SynExpr.LetOrUse (_, _, _, innerComp, _) -> isSimpleExpr innerComp + | SynExpr.LetOrUseBang _ -> false + | SynExpr.Match (_, _, clauses, _) -> + clauses |> List.forall (fun (Clause(_, _, innerComp, _, _)) -> isSimpleExpr innerComp) + | SynExpr.MatchBang _ -> false + | SynExpr.TryWith (innerComp, _, clauses, _, _, _, _) -> + isSimpleExpr innerComp && + clauses |> List.forall (fun (Clause(_, _, clauseComp, _, _)) -> isSimpleExpr clauseComp) + | SynExpr.YieldOrReturnFrom _ -> false + | SynExpr.YieldOrReturn _ -> false + | _ -> true + let basicSynExpr = trans true (hasCustomOperations ()) (LazyWithContext.NotLazy ([], env)) comp (fun holeFill -> holeFill) @@ -8546,7 +8770,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynSimplePatVar false (mkSynId mBuilderVal builderValName)], mBuilderVal), runExpr, mBuilderVal) let env = - match comp with + match comp with | SynExpr.YieldOrReturn ((true, _), _, _) -> { env with eContextInfo = ContextInfo.YieldInComputationExpression } | SynExpr.YieldOrReturn ((_, true), _, _) -> { env with eContextInfo = ContextInfo.ReturnInComputationExpression } | _ -> env @@ -8693,7 +8917,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m = //SEQPOINT NEEDED - we must consume spBind on this path Some(mkSeqUsing cenv env wholeExprMark bindPatTy genOuterTy inputExpr consumeExpr, tpenv) - | SynExpr.LetOrUseBang (_, _, _, _, _, _, m) -> + | SynExpr.LetOrUseBang (range=m) -> error(Error(FSComp.SR.tcUseForInSequenceExpression(), m)) | SynExpr.Match (spMatch, expr, clauses, _) -> @@ -8711,7 +8935,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m = let matchv, matchExpr = CompilePatternForMatchClauses cenv env inputExprMark inputExprMark true ThrowIncompleteMatchException (Some inputExpr) inputExprTy genOuterTy tclauses Some(mkLet spMatch inputExprMark matchv inputExpr matchExpr, tpenv) - | SynExpr.TryWith (_, mTryToWith, _, _, _, _, _) -> + | SynExpr.TryWith (tryRange=mTryToWith) -> error(Error(FSComp.SR.tcTryIllegalInSequenceExpression(), mTryToWith)) | SynExpr.YieldOrReturnFrom ((isYield, _), yieldExpr, m) -> @@ -10587,7 +10811,7 @@ and TcAndPatternCompileMatchClauses mExpr matchm actionOnFailure cenv inputExprO and TcMatchPattern cenv inputTy env tpenv (pat: SynPat, optWhenExpr) = let m = pat.Range let patf', (tpenv, names, _) = TcPat WarnOnUpperCase cenv env None (ValInline.Optional, permitInferTypars, noArgOrRetAttribs, false, None, false) (tpenv, Map.empty, Set.empty) inputTy pat - let envinner, values, vspecMap = MakeAndPublishSimpleVals cenv env m names false + let envinner, values, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names let optWhenExpr', tpenv = match optWhenExpr with | Some whenExpr -> @@ -12670,7 +12894,7 @@ module IncrClassChecking = let ctorArgNames, (_, names, _) = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv (SynSimplePats.SimplePats (spats, m)) // Create the values with the given names - let _, vspecs = MakeSimpleVals cenv env names + let _, vspecs = MakeAndPublishSimpleVals cenv env names if tcref.IsStructOrEnumTycon && isNil spats then errorR (ParameterlessStructCtor(tcref.Range)) diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index 524f73965e..40e90b679a 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -764,12 +764,13 @@ and /// Computation expressions only | YieldOrReturnFrom of (bool * bool) * expr: SynExpr * range: range - /// SynExpr.LetOrUseBang (spBind, isUse, isFromSource, pat, rhsExpr, bodyExpr, mWholeExpr). + /// SynExpr.LetOrUseAndBang (spBind, isUse, isFromSource, pat, rhsExpr, mLetBangExpr, [(andBangSpBind, andBangIsUse, andBangIsFromSource, andBangPat, andBangRhsExpr, mAndBangExpr)], bodyExpr). /// /// F# syntax: let! pat = expr in expr /// F# syntax: use! pat = expr in expr + /// F# syntax: let! pat = expr and! ... and! ... and! pat = expr in expr /// Computation expressions only - | LetOrUseBang of bindSeqPoint: SequencePointInfoForBinding * isUse: bool * isFromSource: bool * SynPat * SynExpr * SynExpr * range: range + | LetOrUseBang of bindSeqPoint: SequencePointInfoForBinding * isUse: bool * isFromSource: bool * SynPat * rhs: SynExpr * andBangs:(SequencePointInfoForBinding * bool * bool * SynPat * SynExpr * range) list * body:SynExpr * range: range /// F# syntax: match! expr with pat1 -> expr | ... | patN -> exprN | MatchBang of matchSeqPoint: SequencePointInfoForBinding * expr: SynExpr * clauses: SynMatchClause list * range: range (* bool indicates if this is an exception match in a computation expression which throws unmatched exceptions *) @@ -2475,6 +2476,6 @@ let rec synExprContainsError inpExpr = | SynExpr.MatchBang (_, e, cl, _) -> walkExpr e || walkMatchClauses cl - | SynExpr.LetOrUseBang (_, _, _, _, e1, e2, _) -> - walkExpr e1 || walkExpr e2 + | SynExpr.LetOrUseBang (rhs=e1;body=e2;andBangs=es) -> + walkExpr e1 || walkExprs [ for (_,_,_,_,e,_) in es do yield e ] || walkExpr e2 walkExpr inpExpr diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 901a203b83..5970e1fb8c 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -233,10 +233,12 @@ rule token args skip = parse { YIELD_BANG(false) } | "match!" { MATCH_BANG } + | "and!" + { AND_BANG(false) } | ident '!' { let tok = Keywords.KeywordOrIdentifierToken args lexbuf (lexemeTrimRight lexbuf 1) match tok with - | LET _ -> BINDER (lexemeTrimRight lexbuf 1) + | LET _ -> BINDER (lexemeTrimRight lexbuf 1) | _ -> fail args lexbuf (FSComp.SR.lexIdentEndInMarkReserved("!")) (Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf)) } | ident ('#') { fail args lexbuf (FSComp.SR.lexIdentEndInMarkReserved("#")) (Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf)) } diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index e1d888196b..66ee0bd792 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -189,7 +189,7 @@ let rangeOfLongIdent(lid:LongIdent) = %token CHAR %token DECIMAL %token <(string * string)> BIGNUM -%token LET YIELD YIELD_BANG +%token LET YIELD YIELD_BANG AND_BANG %token LESS GREATER /* here the bool indicates if the tokens are part of a type application or type parameter declaration, e.g. C, detected by the lex filter */ %token PERCENT_OP BINDER %token LQUOTE RQUOTE RQUOTE_DOT @@ -218,6 +218,7 @@ let rangeOfLongIdent(lid:LongIdent) = /* for offside rule */ %token OLET /* LexFilter #light converts 'LET' tokens to 'OLET' when starting (CtxtLetDecl(blockLet=true)) */ %token OBINDER /* LexFilter #light converts 'BINDER' tokens to 'OBINDER' when starting (CtxtLetDecl(blockLet=true)) */ +%token OAND_BANG /* LexFilter #light converts 'AND_BANG' tokens to 'OAND_BANG' when starting (CtxtLetDecl(blockLet=true)) */ %token ODO /* LexFilter #light converts 'DO' tokens to 'ODO' */ %token ODO_BANG /* LexFilter #light converts 'DO_BANG' tokens to 'ODO_BANG' */ %token OTHEN /* LexFilter #light converts 'THEN' tokens to 'OTHEN' */ @@ -453,7 +454,8 @@ let rangeOfLongIdent(lid:LongIdent) = %nonassoc paren_pat_colon %nonassoc paren_pat_attribs %left OR BAR_BAR JOIN_IN -%left AND /* check */ +%left AND +%left AND_BANG %left AMP AMP_AMP %nonassoc pat_conj %nonassoc expr_not @@ -3060,6 +3062,20 @@ recover: | error { debugPrint("recovering via error"); true } | EOF { debugPrint("recovering via EOF"); false } +morebinders: + | AND_BANG headBindingPattern EQUALS typedSeqExprBlock IN morebinders %prec expr_let + { let spBind = SequencePointAtBinding(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) + let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) + (spBind,$1,true,$2,$4,m) :: $6 } + + | OAND_BANG headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP morebinders %prec expr_let + { $5 "and!" (rhs parseState 1) // report unterminated error + let spBind = SequencePointAtBinding(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) + let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) + (spBind,$1,true,$2,$4,m) :: $7 } + + | %prec prec_no_more_attr_bindings + { [] } declExpr: | defnBindings IN typedSeqExpr %prec expr_let @@ -3353,27 +3369,35 @@ declExpr: | YIELD_BANG declExpr { SynExpr.YieldOrReturnFrom (($1,not $1), $2, unionRanges (rhs parseState 1) $2.Range) } - | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let + | YIELD recover + { let mYieldAll = rhs parseState 1 + SynExpr.YieldOrReturn (($1, not $1), arbExpr("yield", mYieldAll), mYieldAll) } + + | YIELD_BANG recover + { let mYieldAll = rhs parseState 1 + SynExpr.YieldOrReturnFrom (($1, not $1), arbExpr("yield!", mYieldAll), mYieldAll) } + + | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP morebinders typedSeqExprBlock %prec expr_let { let spBind = SequencePointAtBinding(rhs2 parseState 1 5) - let m = unionRanges (rhs parseState 1) $7.Range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4,$7,m) } + let m = unionRanges (rhs parseState 1) $8.Range + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } - | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP typedSeqExprBlock %prec expr_let + | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP morebinders typedSeqExprBlock %prec expr_let { $5 (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) - let m = unionRanges (rhs parseState 1) $7.Range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4,$7,m) } + let m = unionRanges (rhs parseState 1) $8.Range + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // error recovery that allows intellisense when writing incomplete computation expressions let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) let m = $4.Range.EndRange // zero-width range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4, SynExpr.ImplicitZero m, mAll) } + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll) } | DO_BANG typedSeqExpr IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let { let spBind = NoSequencePointAtDoBinding - SynExpr.LetOrUseBang (spBind,false,true,SynPat.Const(SynConst.Unit,$2.Range),$2,$5, unionRanges (rhs parseState 1) $5.Range) } + SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit,$2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range) } | ODO_BANG typedSeqExprBlock hardwhiteDefnBindingsTerminator %prec expr_let { SynExpr.DoBang ($2, unionRanges (rhs parseState 1) $2.Range) } diff --git a/src/fsharp/service/ServiceAssemblyContent.fs b/src/fsharp/service/ServiceAssemblyContent.fs index e495fa0428..b826728b47 100644 --- a/src/fsharp/service/ServiceAssemblyContent.fs +++ b/src/fsharp/service/ServiceAssemblyContent.fs @@ -703,9 +703,13 @@ module ParsedInput = addLongIdentWithDots ident List.iter walkExpr [e1; e2; e3] | SynExpr.JoinIn (e1, _, e2, _) -> List.iter walkExpr [e1; e2] - | SynExpr.LetOrUseBang (_, _, _, pat, e1, e2, _) -> + | SynExpr.LetOrUseBang (_, _, _, pat, e1, es, e2, _) -> walkPat pat - List.iter walkExpr [e1; e2] + walkExpr e1 + for (_,_,_,patAndBang,eAndBang,_) in es do + walkPat patAndBang + walkExpr eAndBang + walkExpr e2 | SynExpr.TraitCall (ts, sign, e, _) -> List.iter walkTypar ts walkMemberSig sign diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index dfaa9a537a..e5461138bf 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -896,8 +896,14 @@ module InterfaceStubGenerator = | SynExpr.DoBang (synExpr, _range) -> walkExpr synExpr - | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, _synPat, synExpr1, synExpr2, _range) -> - List.tryPick walkExpr [synExpr1; synExpr2] + | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, _synPat, synExpr1, synExprAndBangs, synExpr2, _range) -> + [ + yield synExpr1 + for (_,_,_,_,eAndBang,_) in synExprAndBangs do + yield eAndBang + yield synExpr2 + ] + |> List.tryPick walkExpr | SynExpr.LibraryOnlyILAssembly _ | SynExpr.LibraryOnlyStaticOptimization _ diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs old mode 100644 new mode 100755 index e0792c9d2a..a0e2d57893 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -261,14 +261,14 @@ module internal TokenClassifications = | MEMBER | STATIC | NAMESPACE | OASSERT | OLAZY | ODECLEND | OBLOCKSEP | OEND | OBLOCKBEGIN | ORIGHT_BLOCK_END | OBLOCKEND | OBLOCKEND_COMING_SOON | OBLOCKEND_IS_HERE | OTHEN | OELSE | OLET(_) - | OBINDER _ | BINDER _ | ODO | OWITH | OFUNCTION | OFUN | ORESET | ODUMMY _ | DO_BANG + | OBINDER _ | OAND_BANG _ | BINDER _ | ODO | OWITH | OFUNCTION | OFUN | ORESET | ODUMMY _ | DO_BANG | ODO_BANG | YIELD _ | YIELD_BANG _ | OINTERFACE_MEMBER | ELIF | RARROW | LARROW | SIG | STRUCT | UPCAST | DOWNCAST | NULL | RESERVED | MODULE | AND | AS | ASSERT | ASR | DOWNTO | EXCEPTION | FALSE | FOR | FUN | FUNCTION | FINALLY | LAZY | MATCH | MATCH_BANG | MUTABLE | NEW | OF | OPEN | OR | VOID | EXTERN | INTERFACE | REC | TO | TRUE | TRY | TYPE | VAL | INLINE | WHEN | WHILE | WITH - | IF | THEN | ELSE | DO | DONE | LET(_) | IN (*| NAMESPACE*) | CONST + | IF | THEN | ELSE | DO | DONE | LET _ | AND_BANG _ | IN | CONST | HIGH_PRECEDENCE_PAREN_APP | FIXED | HIGH_PRECEDENCE_BRACK_APP | TYPE_COMING_SOON | TYPE_IS_HERE | MODULE_COMING_SOON | MODULE_IS_HERE -> diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index eeab436524..a1c42f7fa7 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -473,10 +473,16 @@ module public AstTraversal = | SynExpr.ImplicitZero (_range) -> None | SynExpr.YieldOrReturn (_, synExpr, _range) -> traverseSynExpr synExpr | SynExpr.YieldOrReturnFrom (_, synExpr, _range) -> traverseSynExpr synExpr - | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, synPat, synExpr, synExpr2, _range) -> - [dive synPat synPat.Range traversePat - dive synExpr synExpr.Range traverseSynExpr - dive synExpr2 synExpr2.Range traverseSynExpr] + | SynExpr.LetOrUseBang(_sequencePointInfoForBinding, _, _, synPat, synExpr, andBangSynExprs, synExpr2, _range) -> + [ + yield dive synPat synPat.Range traversePat + yield dive synExpr synExpr.Range traverseSynExpr + yield! + [ for (_,_,_,andBangSynPat,andBangSynExpr,_) in andBangSynExprs do + yield (dive andBangSynPat andBangSynPat.Range traversePat) + yield (dive andBangSynExpr andBangSynExpr.Range traverseSynExpr)] + yield dive synExpr2 synExpr2.Range traverseSynExpr + ] |> pick expr | SynExpr.MatchBang (_sequencePointInfoForBinding, synExpr, synMatchClauseList, _range) -> [yield dive synExpr synExpr.Range traverseSynExpr diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index 56f2312da4..8df0fedbb8 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -245,14 +245,21 @@ module Structure = | SynExpr.DoBang (e, r) -> rcheck Scope.Do Collapse.Below r <| Range.modStart 3 r parseExpr e - | SynExpr.LetOrUseBang (_, _, _, pat, e1, e2, _) -> - // for `let!` or `use!` the pattern begins at the end of the keyword so that - // this scope can be used without adjustment if there is no `=` on the same line - // if there is an `=` the range will be adjusted during the tooltip creation - let r = Range.endToEnd pat.Range e1.Range - rcheck Scope.LetOrUseBang Collapse.Below r r - parseExpr e1 - parseExpr e2 + | SynExpr.LetOrUseBang (_, _, _, pat, eLet, es, eBody, _) -> + [ + yield eLet + yield! [ for (_,_,_,_,eAndBang,_) in es do yield eAndBang ] + ] + |> List.iter (fun e -> + // for `let!`, `use!` or `and!` the pattern begins at the end of the + // keyword so that this scope can be used without adjustment if there is no `=` + // on the same line. If there is an `=` the range will be adjusted during the + // tooltip creation + let r = Range.endToEnd pat.Range e.Range + rcheck Scope.LetOrUseBang Collapse.Below r r + parseExpr e + ) + parseExpr eBody | SynExpr.For (_, _, _, _, _, e, r) | SynExpr.ForEach (_, _, _, _, _, e, r) -> rcheck Scope.For Collapse.Below r r diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index f142279474..399b3e8791 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -322,9 +322,12 @@ type FSharpParseFileResults(errors: FSharpErrorInfo[], input: Ast.ParsedInput op yield! walkExpr false e2 yield! walkExpr false e3 - | SynExpr.LetOrUseBang (spBind, _, _, _, e1, e2, _) -> + | SynExpr.LetOrUseBang (spBind, _, _, _, e1, es, e2, _) -> yield! walkBindSeqPt spBind yield! walkExpr true e1 + for (andBangSpBind,_,_,_,eAndBang,_) in es do + yield! walkBindSeqPt andBangSpBind + yield! walkExpr true eAndBang yield! walkExpr true e2 | SynExpr.MatchBang (spBind, e, cl, _) -> @@ -880,7 +883,14 @@ module UntypedParseImpl = | SynExpr.Match (_, e, synMatchClauseList, _) | SynExpr.MatchBang (_, e, synMatchClauseList, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkClause synMatchClauseList) - | SynExpr.LetOrUseBang (_, _, _, _, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] + | SynExpr.LetOrUseBang(_, _, _, _, e1, es, e2, _) -> + [ + yield e1 + for (_,_,_,_,eAndBang,_) in es do + yield eAndBang + yield e2 + ] + |> List.tryPick (walkExprWithKind parentKind) | SynExpr.DoBang (e, _) -> walkExprWithKind parentKind e | SynExpr.TraitCall (ts, sign, e, _) -> List.tryPick walkTypar ts diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index a2e4bf2081..3d85d19f7f 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -57,6 +57,11 @@ Algoritmus {0} není podporovaný. + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Atributy nejde použít pro rozšíření typů. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. Není definovaný obor názvů {0}. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index baf48ce914..d3266324ea 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -57,6 +57,11 @@ Algorithmus "{0}" wird nicht unterstützt + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Attribute können nicht auf Typerweiterungen angewendet werden. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. Der Namespace "{0}" ist nicht definiert. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 1d82a7a42c..0fbf10ee04 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -57,6 +57,11 @@ No se admite el algoritmo '{0}' + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Los atributos no se pueden aplicar a las extensiones de tipo. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. El espacio de nombres "{0}" no está definido. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 54296abddf..208b5df146 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -57,6 +57,11 @@ Algorithme '{0}' non pris en charge + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Impossible d'appliquer des attributs aux extensions de type. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. L'espace de noms '{0}' n'est pas défini. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 850e1233e6..87607c68dd 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -57,6 +57,11 @@ L'algoritmo '{0}' non è supportato + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Gli attributi non possono essere applicati a estensioni di tipo. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. Lo spazio dei nomi '{0}' non è definito. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 9267524fe8..fc807fd3da 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -57,6 +57,11 @@ アルゴリズム '{0}' はサポートされていません + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ 属性を型拡張に適用することはできません。 + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. 名前空間 '{0}' が定義されていません。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 9aab61aa0f..4354b83a01 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -57,6 +57,11 @@ {0}' 알고리즘은 지원되지 않습니다. + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ 형식 확장에 특성을 적용할 수 없습니다. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. '{0}' 네임스페이스가 정의되지 않았습니다. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 07c155e320..2f9150028e 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -57,6 +57,11 @@ Algorytm „{0}” nie jest obsługiwany + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Atrybutów nie można stosować do rozszerzeń typu. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. Nie zdefiniowano przestrzeni nazw „{0}”. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index d6a95f10f3..f09542103c 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -57,6 +57,11 @@ Algoritmo '{0}' sem suporte + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Os atributos não podem ser aplicados às extensões de tipo. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. O namespace '{0}' não está definido. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index d364e6e039..0460038d6f 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -57,6 +57,11 @@ Алгоритм "{0}" не поддерживается + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Атрибуты не могут быть применены к расширениям типа. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. Пространство имен "{0}" не определено. diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 2f05dd2afe..8df54eda5f 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -57,6 +57,11 @@ {0}' algoritması desteklenmiyor + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ Öznitelikler tür uzantılarına uygulanamaz. + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. '{0}' ad alanı tanımlı değil. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 9ee2a500ff..daf8925fab 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -57,6 +57,11 @@ 不支持算法“{0}” + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ 属性不可应用于类型扩展。 + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. 未定义命名空间“{0}”。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index ce66cb1b94..3fe7318b45 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -57,6 +57,11 @@ 不支援演算法 '{0}' + + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature. + + This is the wrong anonymous record. It should have the fields {0}. This is the wrong anonymous record. It should have the fields {0}. @@ -77,6 +82,16 @@ 屬性無法套用到類型延伸模組。 + + use! may not be combined with and! + use! may not be combined with and! + + + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSource' and 'Bind' methods + + The namespace '{0}' is not defined. 未定義命名空間 '{0}'。 diff --git a/src/fsharp/xlf/FSStrings.cs.xlf b/src/fsharp/xlf/FSStrings.cs.xlf index b998717df6..c5ba4efd98 100644 --- a/src/fsharp/xlf/FSStrings.cs.xlf +++ b/src/fsharp/xlf/FSStrings.cs.xlf @@ -1627,6 +1627,11 @@ symbol |} + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.de.xlf b/src/fsharp/xlf/FSStrings.de.xlf index f1ee5ebd68..c31cfafe2c 100644 --- a/src/fsharp/xlf/FSStrings.de.xlf +++ b/src/fsharp/xlf/FSStrings.de.xlf @@ -1627,6 +1627,11 @@ Symbol "|}" + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.es.xlf b/src/fsharp/xlf/FSStrings.es.xlf index 00665ca307..772bda82f2 100644 --- a/src/fsharp/xlf/FSStrings.es.xlf +++ b/src/fsharp/xlf/FSStrings.es.xlf @@ -1627,6 +1627,11 @@ símbolo "|}" + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.fr.xlf b/src/fsharp/xlf/FSStrings.fr.xlf index fc0e0f6e75..e6e3707de7 100644 --- a/src/fsharp/xlf/FSStrings.fr.xlf +++ b/src/fsharp/xlf/FSStrings.fr.xlf @@ -1627,6 +1627,11 @@ symbole '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.it.xlf b/src/fsharp/xlf/FSStrings.it.xlf index cd9a47d880..7b0bb4c286 100644 --- a/src/fsharp/xlf/FSStrings.it.xlf +++ b/src/fsharp/xlf/FSStrings.it.xlf @@ -1627,6 +1627,11 @@ simbolo '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.ja.xlf b/src/fsharp/xlf/FSStrings.ja.xlf index 26a7e52ea1..12b8412734 100644 --- a/src/fsharp/xlf/FSStrings.ja.xlf +++ b/src/fsharp/xlf/FSStrings.ja.xlf @@ -1627,6 +1627,11 @@ シンボル '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.ko.xlf b/src/fsharp/xlf/FSStrings.ko.xlf index d6921f25eb..b4b1f75b9b 100644 --- a/src/fsharp/xlf/FSStrings.ko.xlf +++ b/src/fsharp/xlf/FSStrings.ko.xlf @@ -1627,6 +1627,11 @@ 기호 '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.pl.xlf b/src/fsharp/xlf/FSStrings.pl.xlf index 1bb0d77df7..3f18d2c236 100644 --- a/src/fsharp/xlf/FSStrings.pl.xlf +++ b/src/fsharp/xlf/FSStrings.pl.xlf @@ -1627,6 +1627,11 @@ symbol „|}” + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.pt-BR.xlf b/src/fsharp/xlf/FSStrings.pt-BR.xlf index 180bd4449d..ee303bbede 100644 --- a/src/fsharp/xlf/FSStrings.pt-BR.xlf +++ b/src/fsharp/xlf/FSStrings.pt-BR.xlf @@ -1627,6 +1627,11 @@ símbolo '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.ru.xlf b/src/fsharp/xlf/FSStrings.ru.xlf index 3951b3192b..dcea3abcf1 100644 --- a/src/fsharp/xlf/FSStrings.ru.xlf +++ b/src/fsharp/xlf/FSStrings.ru.xlf @@ -1627,6 +1627,11 @@ Обозначение '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.tr.xlf b/src/fsharp/xlf/FSStrings.tr.xlf index f2acceada2..8c776350a4 100644 --- a/src/fsharp/xlf/FSStrings.tr.xlf +++ b/src/fsharp/xlf/FSStrings.tr.xlf @@ -1627,6 +1627,11 @@ sembol '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.zh-Hans.xlf b/src/fsharp/xlf/FSStrings.zh-Hans.xlf index ab04ab4260..14245558ce 100644 --- a/src/fsharp/xlf/FSStrings.zh-Hans.xlf +++ b/src/fsharp/xlf/FSStrings.zh-Hans.xlf @@ -1627,6 +1627,11 @@ 符号 "|}" + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSStrings.zh-Hant.xlf b/src/fsharp/xlf/FSStrings.zh-Hant.xlf index 3fd801411f..70e5ec8c06 100644 --- a/src/fsharp/xlf/FSStrings.zh-Hant.xlf +++ b/src/fsharp/xlf/FSStrings.zh-Hant.xlf @@ -1627,6 +1627,11 @@ 符號 '|}' + + keyword 'and!' + keyword 'and!' + + \ No newline at end of file diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index ef0e591a0c..f38a105287 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -415,45 +415,58 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - static member TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = + static member TypeCheckWithErrorsAndOptionsAndAdjust options libAdjust (source: string) expectedTypeErrors = lock gate <| fun () -> - let parseResults, fileAnswer = - checker.ParseAndCheckFileInProject( - "test.fs", - 0, - SourceText.ofString source, - { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions}) - |> Async.RunSynchronously - - Assert.IsEmpty(parseResults.Errors, sprintf "Parse errors: %A" parseResults.Errors) + let errors = + let parseResults, fileAnswer = + checker.ParseAndCheckFileInProject( + "test.fs", + 0, + SourceText.ofString source, + { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions}) + |> Async.RunSynchronously + + if parseResults.Errors.Length > 0 then + parseResults.Errors + else - match fileAnswer with - | FSharpCheckFileAnswer.Aborted _ -> Assert.Fail("Type Checker Aborted") - | FSharpCheckFileAnswer.Succeeded(typeCheckResults) -> + match fileAnswer with + | FSharpCheckFileAnswer.Aborted _ -> Assert.Fail("Type Checker Aborted"); [| |] + | FSharpCheckFileAnswer.Succeeded(typeCheckResults) -> typeCheckResults.Errors let errors = - typeCheckResults.Errors + errors |> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message) + |> Array.map (fun info -> + (info.Severity, info.ErrorNumber, (info.StartLineAlternate - libAdjust, info.StartColumn + 1, info.EndLineAlternate - libAdjust, info.EndColumn + 1), info.Message)) - Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" errors) + let checkEqual k a b = + if a <> b then + Assert.AreEqual(a, b, sprintf "Mismatch in %s, expected '%A', got '%A'.\nAll errors:\n%A" k a b errors) + + checkEqual "Type Check Errors" (Array.length expectedTypeErrors) errors.Length Array.zip errors expectedTypeErrors - |> Array.iter (fun (info, expectedError) -> - let (expectedServerity: FSharpErrorSeverity, expectedErrorNumber: int, expectedErrorRange: int * int * int * int, expectedErrorMsg: string) = expectedError - Assert.AreEqual(expectedServerity, info.Severity) - Assert.AreEqual(expectedErrorNumber, info.ErrorNumber, "expectedErrorNumber") - Assert.AreEqual(expectedErrorRange, (info.StartLineAlternate, info.StartColumn + 1, info.EndLineAlternate, info.EndColumn + 1), "expectedErrorRange") - Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") + |> Array.iter (fun (actualError, expectedError) -> + let (expectedSeverity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg) = expectedError + let (actualSeverity, actualErrorNumber, actualErrorRange, actualErrorMsg) = actualError + checkEqual "Severity" expectedSeverity actualSeverity + checkEqual "ErrorNumber" expectedErrorNumber actualErrorNumber + checkEqual "ErrorRange" expectedErrorRange actualErrorRange + checkEqual "Message" expectedErrorMsg actualErrorMsg ) + static member TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = + CompilerAssert.TypeCheckWithErrorsAndOptionsAndAdjust options 0 (source: string) expectedTypeErrors + static member TypeCheckWithErrors (source: string) expectedTypeErrors = CompilerAssert.TypeCheckWithErrorsAndOptions [||] source expectedTypeErrors - static member TypeCheckSingleErrorWithOptions options (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = - CompilerAssert.TypeCheckWithErrorsAndOptions options source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + static member TypeCheckSingleErrorWithOptions options (source: string) (expectedSeverity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + CompilerAssert.TypeCheckWithErrorsAndOptions options source [| expectedSeverity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] - static member TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = - CompilerAssert.TypeCheckWithErrors source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + static member TypeCheckSingleError (source: string) (expectedSeverity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + CompilerAssert.TypeCheckWithErrors source [| expectedSeverity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] static member CompileExeWithOptions options (source: string) = compile true options source (fun (errors, _) -> @@ -543,8 +556,8 @@ let main argv = 0""" Array.zip errors expectedParseErrors |> Array.iter (fun (info, expectedError) -> - let (expectedServerity: FSharpErrorSeverity, expectedErrorNumber: int, expectedErrorRange: int * int * int * int, expectedErrorMsg: string) = expectedError - Assert.AreEqual(expectedServerity, info.Severity) + let (expectedSeverity: FSharpErrorSeverity, expectedErrorNumber: int, expectedErrorRange: int * int * int * int, expectedErrorMsg: string) = expectedError + Assert.AreEqual(expectedSeverity, info.Severity) Assert.AreEqual(expectedErrorNumber, info.ErrorNumber, "expectedErrorNumber") Assert.AreEqual(expectedErrorRange, (info.StartLineAlternate, info.StartColumn + 1, info.EndLineAlternate, info.EndColumn + 1), "expectedErrorRange") Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") diff --git a/tests/fsharp/Compiler/Conformance/DataExpressions/ComputationExpressions.fs b/tests/fsharp/Compiler/Conformance/DataExpressions/ComputationExpressions.fs new file mode 100644 index 0000000000..5ff853eca0 --- /dev/null +++ b/tests/fsharp/Compiler/Conformance/DataExpressions/ComputationExpressions.fs @@ -0,0 +1,628 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``ComputationExpressions`` = + let tmp = 1 + + let applicativeLib (opts: {| includeMergeSourcesOverloads: bool |}) = + """ +/// Used for tracking what operations a Trace builder was asked to perform +[] +type TraceOp = + | ApplicativeBind + | ApplicativeBind2 + | ApplicativeBindReturn + | ApplicativeBind2Return + | ApplicativeReturn + | ApplicativeCombine + | ApplicativeYield + | MergeSources + | MergeSources3 + | MergeSources4 + | MonadicBind + | MonadicBind2 + | MonadicReturn + | Run + | Delay + | Log of string + +/// A pseudo identity functor +type Trace<'T>(v: 'T) = + member x.Value = v + override this.ToString () = + sprintf "%+A" v + +/// A builder which records what operations it is asked to perform +type TraceCore() = + + let mutable trace = ResizeArray<_>() + + member _.GetTrace () = trace.ToArray() + + member _.Trace x = trace.Add(x) + +type TraceMergeSourcesCore() = + inherit TraceCore() + + member builder.MergeSources(x1: Trace<'T1>, x2: Trace<'T2>) : Trace<'T1 * 'T2> = + builder.Trace TraceOp.MergeSources + Trace (x1.Value, x2.Value) + """ + (if opts.includeMergeSourcesOverloads then """ + + // Note the struct tuple is acceptable + member builder.MergeSources3(x1: Trace<'T1>, x2: Trace<'T2>, x3: Trace<'T3>) : Trace = + builder.Trace TraceOp.MergeSources3 + Trace (struct (x1.Value, x2.Value, x3.Value)) + + member builder.MergeSources4(x1: Trace<'T1>, x2: Trace<'T2>, x3: Trace<'T3>, x4: Trace<'T4>) : Trace<'T1 * 'T2 * 'T3 * 'T4> = + builder.Trace TraceOp.MergeSources4 + Trace (x1.Value, x2.Value, x3.Value, x4.Value) + """ else "") + """ + +type TraceApplicative() = + inherit TraceMergeSourcesCore() + + member builder.BindReturn(x: Trace<'T1>, f: 'T1 -> 'T2) : Trace<'T2> = + builder.Trace TraceOp.ApplicativeBindReturn + Trace (f x.Value) + + member builder.Bind2Return(x1: Trace<'T1>, x2: Trace<'T2>, f: 'T1 * 'T2 -> 'T3) : Trace<'T3> = + builder.Trace TraceOp.ApplicativeBind2Return + Trace (f (x1.Value, x2.Value)) + +type TraceApplicativeWithDelayAndRun() = + inherit TraceApplicative() + + member builder.Run(x) = + builder.Trace TraceOp.Run + x + + member builder.Delay(thunk) = + builder.Trace TraceOp.Delay + thunk () + +type TraceApplicativeWithDelay() = + inherit TraceApplicative() + + member builder.Delay(thunk) = + builder.Trace TraceOp.Delay + thunk () + +type TraceApplicativeWithRun() = + inherit TraceApplicative() + + member builder.Run(x) = + builder.Trace TraceOp.Run + x + +type TraceMultiBindingMonadic() = + inherit TraceMergeSourcesCore() + + member builder.Bind(x : Trace<'T1>, f : 'T1 -> Trace<'T2>) : Trace<'T2> = + builder.Trace TraceOp.MonadicBind + f x.Value + + member builder.Bind2(x1 : 'T1 Trace, x2 : 'T2 Trace, f : 'T1 * 'T2 -> Trace<'T3>) : Trace<'T3> = + builder.Trace TraceOp.MonadicBind2 + f (x1.Value, x2.Value) + + member builder.Return(x: 'T) : Trace<'T> = + builder.Trace TraceOp.MonadicReturn + Trace x + +type TraceMultiBindingMonoid() = + inherit TraceMergeSourcesCore() + + member builder.Bind(x : Trace<'T1>, f : 'T1 -> Trace<'T2>) : Trace<'T2> = + builder.Trace TraceOp.MonadicBind + f x.Value + + member builder.Bind2(x1 : 'T1 Trace, x2 : 'T2 Trace, f : 'T1 * 'T2 -> Trace<'T3>) : Trace<'T3> = + builder.Trace TraceOp.MonadicBind2 + f (x1.Value, x2.Value) + + member builder.Yield(x: 'T) : Trace<'T list> = + builder.Trace TraceOp.ApplicativeYield + Trace [x] + + member builder.Combine(x1: Trace<'T list>, x2: Trace<'T list>) : Trace<'T list> = + builder.Trace TraceOp.ApplicativeCombine + Trace (x1.Value @ x2.Value) + + member builder.Delay(thunk) = + builder.Trace TraceOp.Delay + thunk () + + member builder.Zero() = + Trace [] + +type TraceApplicativeNoMergeSources() = + inherit TraceCore() + + member builder.BindReturn(x: Trace<'T1>, f: 'T1 -> 'T2) : Trace<'T2> = + builder.Trace TraceOp.ApplicativeBind + Trace (f x.Value) + +type TraceApplicativeNoBindReturn() = + inherit TraceCore() + + member builder.MergeSources(x1: Trace<'T1>, x2: Trace<'T2>) : Trace<'T1 * 'T2> = + builder.Trace TraceOp.MergeSources + Trace (x1.Value, x2.Value) + +type TraceMultiBindingMonadicCustomOp() = + inherit TraceMultiBindingMonadic() + + [] + member builder.Log(boundValues : Trace<'T>, [] messageFunc: 'T -> string) = + builder.Trace (TraceOp.Log (messageFunc boundValues.Value)) + boundValues + +let check msg actual expected = if actual <> expected then failwithf "FAILED %s, expected %A, got %A" msg expected actual + """ + + let includeAll = {| includeMergeSourcesOverloads = true |} + let includeMinimal = {| includeMergeSourcesOverloads = false |} + + let ApplicativeLibTest opts source = + CompilerAssert.CompileExeAndRunWithOptions [| "/langversion:preview" |] (applicativeLib opts + source) + + let ApplicativeLibErrorTest opts source errors = + let lib = applicativeLib opts + // Adjust the expected errors for the number of lines in the library + let libLineAdjust = lib |> Seq.filter (fun c -> c = '\n') |> Seq.length + CompilerAssert.TypeCheckWithErrorsAndOptionsAndAdjust [| "/langversion:preview" |] libLineAdjust (lib + source) errors + + let ApplicativeLibErrorTestFeatureDisabled opts source errors = + let lib = applicativeLib opts + // Adjust the expected errors for the number of lines in the library + let libLineAdjust = lib |> Seq.filter (fun c -> c = '\n') |> Seq.length + CompilerAssert.TypeCheckWithErrorsAndOptionsAndAdjust [| "/langversion:4.7" |] libLineAdjust (lib + source) errors + + [] + let ``AndBang TraceApplicative`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult : Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + +check "fewljvwerjl1" ceResult.Value 3 +check "fewljvwerj12" (tracer.GetTrace ()) [|TraceOp.ApplicativeBind2Return|] + """ + + [] + let ``AndBang TraceApplicative Disable`` () = + ApplicativeLibErrorTestFeatureDisabled includeAll + """ +let tracer = TraceApplicative() + +let ceResult : Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + """ + [| FSharpErrorSeverity.Error, 3344, (6, 9, 8, 35), "This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature." |] + + [] + let ``AndBang TraceMultiBindingMonoid`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceMultiBindingMonoid() + +let ceResult : Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + yield (if y then x else -1) + yield (if y then 5 else -1) + } + +check "fewljvwerjl5" ceResult.Value [3; 5] +check "fewljvwerj16" (tracer.GetTrace ()) [|TraceOp.Delay; TraceOp.MonadicBind2; TraceOp.ApplicativeYield; TraceOp.Delay; TraceOp.ApplicativeYield; TraceOp.ApplicativeCombine|] + """ + + [] + let ``AndBang TraceMultiBindingMonadic`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceMultiBindingMonadic() + +let ceResult : Trace = + tracer { + let fb = Trace "foobar" + match! fb with + | "bar" -> + let! bar = fb + return String.length bar + | _ -> + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + +check "gwrhjkrwpoiwer1" ceResult.Value 3 +check "gwrhjkrwpoiwer2" (tracer.GetTrace ()) [|TraceOp.MonadicBind; TraceOp.MonadicBind2; TraceOp.MonadicReturn|] + """ + + [] + let ``AndBang TraceMultiBindingMonadicCustomOp A`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceMultiBindingMonadicCustomOp() +let ceResult : Trace = + tracer { + let! x = Trace 3 + log (sprintf "%A" x) + return x + } + +check "gwrhjkrwpoiwer1t4" ceResult.Value 3 + """ + + [] + let ``AndBang TraceMultiBindingMonadicCustomOp B`` () = + ApplicativeLibTest includeAll """ +let tracer = TraceMultiBindingMonadicCustomOp() +let ceResult : Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + log (sprintf "%A" (x,y)) + return (ignore y; x) + } + +check "gwrhjkrwpoiwer1t45" ceResult.Value 3 +check "gwrhjkrwpoiwer2t36" (tracer.GetTrace ()) [|TraceOp.MonadicBind2; TraceOp.MonadicReturn; TraceOp.Log "(3, true)"; TraceOp.MonadicBind; TraceOp.MonadicReturn |] + """ + + [] + let ``AndBang TraceMultiBindingMonadic TwoBind`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceMultiBindingMonadic() + +let ceResult : Trace = + tracer { + let fb = Trace "foobar" + match! fb with + | "bar" -> + let! bar = fb + return String.length bar + | _ -> + let! x = Trace 3 + and! y = Trace true + let! x2 = Trace x + and! y2 = Trace y + if y2 then return x2 else return -1 + } + +check "gwrhjkrwpoiwer38" ceResult.Value 3 +check "gwrhjkrwpoiwer39" (tracer.GetTrace ()) [|TraceOp.MonadicBind; TraceOp.MonadicBind2; TraceOp.MonadicBind2; TraceOp.MonadicReturn|] + """ + + [] + let ``AndBang TraceApplicativeWithDelayAndRun`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicativeWithDelayAndRun() + +let ceResult : Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + +check "vlkjrrlwevlk23" ceResult.Value 3 +check "vlkjrrlwevlk24" (tracer.GetTrace ()) [|TraceOp.Delay; TraceOp.ApplicativeBind2Return; TraceOp.Run|] + """ + + [] + let ``AndBang TraceApplicativeWithDelay`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicativeWithDelay() + +let ceResult : int Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + +check "vlkjrrlwevlk23" ceResult.Value 3 +check "vlkjrrlwevlk24" (tracer.GetTrace ()) [|TraceOp.Delay; TraceOp.ApplicativeBind2Return|] + """ + + [] + let ``AndBang TraceApplicativeWithRun`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicativeWithRun() + +let ceResult : int Trace = + tracer { + let! x = Trace 3 + and! y = Trace true + return if y then x else -1 + } + +check "vwerweberlk3" ceResult.Value 3 +check "vwerweberlk4" (tracer.GetTrace ()) [|TraceOp.ApplicativeBind2Return; TraceOp.Run |] + """ + + + [] + let ``AndBang TraceApplicative Size 3`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x = Trace 3 + and! y = Trace true + and! z = Trace 5 + return if y then x else z + } + +check "fewljvwerjl7" ceResult.Value 3 +check "fewljvwerj18" (tracer.GetTrace ()) [|TraceOp.MergeSources3; TraceOp.ApplicativeBindReturn|] + """ + + [] + let ``AndBang TraceApplicative Size 3 minimal`` () = + ApplicativeLibTest includeMinimal """ + +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x = Trace 3 + and! y = Trace true + and! z = Trace 5 + return if y then x else z + } + +check "fewljvwerjl7" ceResult.Value 3 +check "fewljvwerj18" (tracer.GetTrace ()) [|TraceOp.MergeSources; TraceOp.MergeSources; TraceOp.ApplicativeBindReturn|] + """ + [] + let ``AndBang TraceApplicative Size 4`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x1 = Trace 3 + and! x2 = Trace true + and! x3 = Trace 5 + and! x4 = Trace 5 + return if x2 then x1 else x3+x4 + } + +check "fewljvwerjl191" ceResult.Value 3 +check "fewljvwerj1192" (tracer.GetTrace ()) [|TraceOp.MergeSources4; TraceOp.ApplicativeBindReturn|] + """ + + [] + let ``AndBang TraceApplicative Size 5`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult : Trace = + tracer { + let! x1 = Trace 3 + and! x2 = Trace true + and! x3 = Trace 5 + and! x4 = Trace 5 + and! x5 = Trace 8 + return if x2 then x1+x4+x5 else x3 + } + +check "fewljvwerjl193" ceResult.Value 16 +check "fewljvwerj1194" (tracer.GetTrace ()) [|TraceOp.MergeSources; TraceOp.MergeSources4; TraceOp.ApplicativeBindReturn|] + """ + + [] + let ``AndBang TraceApplicative Size 6`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult : Trace = + tracer { + let! x1 = Trace 3 + and! x2 = Trace true + and! x3 = Trace 5 + and! x4 = Trace 5 + and! x5 = Trace 8 + and! x6 = Trace 9 + return if x2 then x1+x4+x5+x6 else x3 + } + +check "fewljvwerjl195" ceResult.Value 25 +check "fewljvwerj1196" (tracer.GetTrace ()) [|TraceOp.MergeSources3; TraceOp.MergeSources4; TraceOp.ApplicativeBindReturn|] + """ + + [] + let ``AndBang TraceApplicative Size 10`` () = + ApplicativeLibTest includeAll """ + +let tracer = TraceApplicative() + +let ceResult : Trace = + tracer { + let! x1 = Trace 3 + and! x2 = Trace true + and! x3 = Trace 5 + and! x4 = Trace 5 + and! x5 = Trace 8 + and! x6 = Trace 9 + and! x7 = Trace 1 + and! x8 = Trace 2 + and! x9 = Trace 3 + and! x10 = Trace 4 + return if x2 then x1+x4+x5+x6+x7+x8+x9+x10 else x3 + } + +check "fewljvwerjl197" ceResult.Value 35 +check "fewljvwerj1198" (tracer.GetTrace ()) [|TraceOp.MergeSources4; TraceOp.MergeSources4; TraceOp.MergeSources4; TraceOp.ApplicativeBindReturn|] + """ + + + [] + let ``AndBang Negative TraceApplicative missing MergeSources`` () = + ApplicativeLibErrorTest includeAll """ +let tracer = TraceApplicativeNoMergeSources() + +let _ = + tracer { + let! x = Trace 1 + and! y = Trace 2 + return x + y + } + """ + [|(FSharpErrorSeverity.Error, 3343, (6, 9, 6, 25), "The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a 'Bind2' method or appropriate 'MergeSource' and 'Bind' methods")|] + + [] + let ``AndBang Negative TraceApplicative missing Bind and BindReturn`` () = + ApplicativeLibErrorTest includeAll """ +let tracer = TraceApplicativeNoBindReturn() + +let _ = + tracer { + let! x = Trace 1 + and! y = Trace 2 + return x + y + } + """ + [|(FSharpErrorSeverity.Error, 708, (6, 9, 6, 25), "This control construct may only be used if the computation expression builder defines a 'Bind' method")|] + + + [] + let ``AndBang Negative TraceApplicative with bad construct`` () = + ApplicativeLibErrorTest includeAll """ + +let tracer = TraceApplicativeNoBindReturn() + +let _ = + tracer { + let! x = Trace 1 // this is a true bind, check the error message here + let! x2 = Trace 1 + return x + y + } + """ + [| FSharpErrorSeverity.Error, 708, (7, 9, 7, 25), "This control construct may only be used if the computation expression builder defines a 'Bind' method" |] + + [] + let ``AndBang TraceApplicative with do-bang`` () = + ApplicativeLibErrorTest includeAll """ +let tracer = TraceApplicative() + +let _ = + tracer { + do! Trace() + and! x = Trace 1 + and! y = Trace 2 + return x + y + } + """ + [|(FSharpErrorSeverity.Error, 10, (7, 9, 7, 13),"Unexpected keyword 'and!' in expression. Expected '}' or other token."); + (FSharpErrorSeverity.Error, 604, (5, 12, 5, 13), "Unmatched '{'"); + (FSharpErrorSeverity.Error, 10, (8, 9, 8, 13), "Unexpected keyword 'and!' in implementation file")|] + + [] + let ``AndBang Negative TraceApplicative let betweeen let! and and!`` () = + ApplicativeLibErrorTest includeAll """ +let tracer = TraceApplicative() + +let _ = + tracer { + let! x = Trace 1 + let _ = 42 + and! y = Trace 2 + return x + y + } + """ + [| (FSharpErrorSeverity.Error, 10, (8, 9, 8, 13), "Unexpected keyword 'and!' in expression") |] + + + [] + let ``AndBang Negative TraceApplicative no return`` () = + ApplicativeLibErrorTest includeAll """ +let tracer = TraceApplicative() + +let _ = + tracer { + let! x = Trace 1 + and! y = Trace 2 + } + """ + [|(FSharpErrorSeverity.Error, 10, (8, 5, 8, 6), "Unexpected symbol '}' in expression")|] + + [] + let ``AndBang TraceApplicative conditional return`` () = + ApplicativeLibTest includeAll """ +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x = Trace 1 + and! y = Trace 2 + if x = 1 then + return y + else + return 4 + } +check "grwerjkrwejgk" ceResult.Value 2 + """ + + [] + let ``AndBang TraceApplicative match return`` () = + ApplicativeLibTest includeAll """ +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x = Trace 1 + and! y = Trace 2 + match x with + | 1 -> return y + | _ -> return 4 + } +check "grwerjkrwejgk42" ceResult.Value 2 + """ + + [] + let ``AndBang TraceApplicative incomplete match return`` () = + ApplicativeLibTest includeAll """ +#nowarn "25" + +let tracer = TraceApplicative() + +let ceResult = + tracer { + let! x = Trace 1 + and! y = Trace 2 + match x with + | 1 -> return y + } +check "grwerjkrwejgk42" ceResult.Value 2 + """ + diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 66ae7d66b0..ef5a0c7b27 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -38,6 +38,7 @@ + diff --git a/tests/fsharp/perf/computation-expressions/dependency_graph.fsx b/tests/fsharp/perf/computation-expressions/dependency_graph.fsx new file mode 100644 index 0000000000..348aab0349 --- /dev/null +++ b/tests/fsharp/perf/computation-expressions/dependency_graph.fsx @@ -0,0 +1,192 @@ + +let mutable nodes = 0 +let mutable recalcs = 0 + +[] +type Node(dirty) = + do nodes <- nodes + 1 + + let dependees = ResizeArray>() + let mutable dirty = dirty + + member _.Dirty with get() = dirty and set v = dirty <- v + + member _.Dependees = + dependees.ToArray() + |> Array.choose (fun c -> match c.TryGetTarget() with true, tg -> Some tg | _ -> None) + + member _.AddDependee(c) = + dependees.Add(System.WeakReference<_>(c)) + + member _.InputChanged() = + for c in dependees do + match c.TryGetTarget() with + | true, tg -> tg.SetDirty() + | _ -> () + + member n.SetDirty() = + if not dirty then + dirty <- true + n.InputChanged() + + +[] +type Node<'T>(dirty) = + inherit Node(dirty) + abstract Value : 'T + +/// A node that recomputes if any if its inputs change +type RecalcNode<'T>(dirty, initial, f: unit -> 'T) = + inherit Node<'T>(dirty) + + let mutable cachedValue = initial + + new (f) = new RecalcNode<'T>(true, Unchecked.defaultof<_>, f) + + new (initial, f) = new RecalcNode<'T>(false, initial, f) + + override n.Value = + if n.Dirty then + recalcs <- recalcs + 1 + cachedValue <- f() + n.Dirty <- false + cachedValue + + override _.ToString() = sprintf "(latest %A)" cachedValue + +/// A node that never recomputes +type ConstantNode<'T>(x: 'T) = + inherit Node<'T>(false) + + override _.Value = x + + override _.ToString() = sprintf "(latest %A)" x + +type InputNode<'T>(v: 'T) = + inherit Node<'T>(false) + let mutable currentValue = v + override _.Value = currentValue + + member node.SetValue v = + currentValue <- v + node.InputChanged() + +type NodeBuilder() = + + member _.Bind(x: Node<'T1>, f: 'T1 -> Node<'T2>) : Node<'T2> = + let rec n = + RecalcNode<'T2>(fun () -> + let n2 = f x.Value + n2.AddDependee(n) + n2.Value) + x.AddDependee(n) + n :> Node<_> + + member _.BindReturn(x: Node<'T1>, f: 'T1 -> 'T2) : Node<'T2> = + let n = RecalcNode<'T2>(fun () -> f x.Value) + x.AddDependee(n) + n :> Node<_> + + member _.Bind2(x1: Node<'T1>, x2: Node<'T2>, f: 'T1 * 'T2 -> Node<'T3>) : Node<'T3> = + let rec n = + RecalcNode<'T3>(fun () -> + let n2 = f (x1.Value, x2.Value) + n2.AddDependee(n) + n2.Value) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Bind2Return(x1: Node<'T1>, x2: Node<'T2>, f: 'T1 * 'T2 -> 'T3) : Node<'T3> = + let n = RecalcNode<'T3>(fun () -> f (x1.Value, x2.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Bind3(x1: Node<'T1>, x2: Node<'T2>, x3: Node<'T3>, f: 'T1 * 'T2 * 'T3 -> Node<'T4>) : Node<'T4> = + let rec n = + RecalcNode<'T4>(fun () -> + let n2 = f (x1.Value, x2.Value, x3.Value) + n2.AddDependee(n) + n2.Value) + x1.AddDependee(n) + x2.AddDependee(n) + x3.AddDependee(n) + n :> Node<_> + + member _.Bind3Return(x1: Node<'T1>, x2: Node<'T2>, x3: Node<'T3>, f: 'T1 * 'T2 * 'T3 -> 'T4) : Node<'T4> = + let n = RecalcNode<'T4>(fun () -> f (x1.Value, x2.Value, x3.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + x3.AddDependee(n) + n :> Node<_> + + member _.MergeSources(x1: Node<'T1>, x2: Node<'T2>) : Node<'T1 * 'T2> = + let n = RecalcNode<_>(fun () -> (x1.Value, x2.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Return(x: 'T) : Node<'T> = + ConstantNode<'T>(x) :> Node<_> + +let node = NodeBuilder() +let input v = InputNode(v) + +let inp1 = input 3 +let inp2 = input 7 +let inp3 = input 0 + +let test1() = + node { + let! v1 = inp1 + and! v2 = inp2 + and! v3 = inp3 + return v1 + v2 + v3 + } + //let n1 = node.Bind3Return(inp1.Node, inp2.Node, inp3.Node, (fun (v1, v2, v3) -> v1 + v2 + v3)) + +let test2() = + node { + let! v1 = inp1 + let! v2 = inp2 + let! v3 = inp3 + return v1 + v2 + v3 + } + +let test msg f = + recalcs <- 0 + nodes <- 0 + + let (n: Node) = f() + + let v1 = n.Value // now 10 + + recalcs <- 0 + + for i in 1 .. 1000 do + inp1.SetValue 4 + let v2 = n.Value // now 11 + + inp2.SetValue 10 + let v3 = n.Value // now 14 + () + + printfn "inp1.Dependees.Length = %d" inp1.Dependees.Length + printfn "inp2.Dependees.Length = %d" inp2.Dependees.Length + printfn "total recalcs %s = %d" msg recalcs + printfn "total nodes %s = %d" msg nodes + printfn "----" + +test "using and!" test1 +test "using let!" test2 + +//inp1.Dependees.Length = 1 +//inp2.Dependees.Length = 1 +//total recalcs using and! = 2000 +//total nodes using and! = 1 +//---- +//inp1.Dependees.Length = 1 +//inp2.Dependees.Length = 2000 +//total recalcs using let! = 6000 +//total nodes using let! = 4003 \ No newline at end of file diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/.il.bsl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/ComputationExpressions/ComputationExprLibrary.fs b/tests/fsharpqa/Source/CodeGen/EmittedIL/ComputationExpressions/ComputationExprLibrary.fs index 90ae5e8665..4b1c9bd130 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/ComputationExpressions/ComputationExprLibrary.fs +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/ComputationExpressions/ComputationExprLibrary.fs @@ -74,7 +74,7 @@ module Eventually = let tryWith e handler = catch e |> bind (function Result v -> Done v | Exception e -> handler e) - + let rec doWhile f e = if f() then e |> bind (fun () -> doWhile f e) else Eventually.Done () diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs index a1ea76e717..0c1a9f7d37 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs @@ -3,6 +3,7 @@ namespace Tests.LanguageService.AutoCompletion open System +open Microsoft.VisualStudio.FSharp.LanguageService open Salsa.Salsa open Salsa.VsMocks open Salsa.VsOpsUtils @@ -28,19 +29,20 @@ module StandardSettings = type UsingMSBuild() as this = inherit LanguageServiceBaseTests() - let createFile (code : list) fileKind refs = + let createFile (code : list) fileKind refs otherFlags = let (_, _, file) = match code with | [code] when code.IndexOfAny([|'\r'; '\n'|]) <> -1 -> - this.CreateSingleFileProject(code, fileKind = fileKind, references = refs) - | code -> this.CreateSingleFileProject(code, fileKind = fileKind, references = refs) + this.CreateSingleFileProject(code, fileKind = fileKind, references = refs, ?otherFlags=otherFlags) + | code -> + this.CreateSingleFileProject(code, fileKind = fileKind, references = refs, ?otherFlags=otherFlags) file - let DoWithAutoCompleteUsingExtraRefs refs coffeeBreak fileKind reason (code : list) marker f = + let DoWithAutoCompleteUsingExtraRefs refs otherFlags coffeeBreak fileKind reason (code : list) marker f = // Up to 2 untyped parse operations are OK: we do an initial parse to provide breakpoint valdiation etc. // This might be before the before the background builder is ready to process the foreground typecheck. // In this case the background builder calls us back when its ready, and we then request a foreground typecheck - let file = createFile code fileKind refs + let file = createFile code fileKind refs otherFlags if coffeeBreak then TakeCoffeeBreak(this.VS) @@ -51,33 +53,43 @@ type UsingMSBuild() as this = gpatcc.AssertExactly(0,0) - let DoWithAutoComplete coffeeBreak fileKind reason (code : list) marker f = DoWithAutoCompleteUsingExtraRefs [] coffeeBreak fileKind reason code marker f + let DoWithAutoComplete coffeeBreak fileKind reason otherFlags (code : list) marker f = + DoWithAutoCompleteUsingExtraRefs [] otherFlags coffeeBreak fileKind reason code marker f - let AssertAutoCompleteContains, AssertAutoCompleteContainsNoCoffeeBreak, AutoCompleteInInterfaceFileContains, AssertCtrlSpaceCompleteContains, AssertCtrlSpaceCompleteContainsNoCoffeeBreak = - let AssertAutoCompleteContains coffeeBreak filename reason code marker should shouldnot = - DoWithAutoComplete coffeeBreak filename reason code marker <| - fun completions -> - AssertCompListContainsAll(completions, should) - AssertCompListDoesNotContainAny(completions, shouldnot) + let AssertAutoCompleteContainsAux coffeeBreak filename reason otherFlags code marker should shouldnot = + DoWithAutoComplete coffeeBreak filename reason otherFlags code marker (fun completions -> + AssertCompListContainsAll(completions, should) + AssertCompListDoesNotContainAny(completions, shouldnot)) + + let AssertAutoCompleteContains = + AssertAutoCompleteContainsAux true SourceFileKind.FS BackgroundRequestReason.MemberSelect None + + let AssertAutoCompleteContainsNoCoffeeBreak = + AssertAutoCompleteContainsAux false SourceFileKind.FS BackgroundRequestReason.MemberSelect None + + let AutoCompleteInInterfaceFileContains = + AssertAutoCompleteContainsAux true SourceFileKind.FSI BackgroundRequestReason.MemberSelect None - ((AssertAutoCompleteContains true SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect), - (AssertAutoCompleteContains false SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect), - (AssertAutoCompleteContains true SourceFileKind.FSI Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect), - (AssertAutoCompleteContains true SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.CompleteWord), - (AssertAutoCompleteContains false SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.CompleteWord)) + let AssertCtrlSpaceCompleteContains = + AssertAutoCompleteContainsAux true SourceFileKind.FS BackgroundRequestReason.CompleteWord None + + let AssertCtrlSpaceCompleteContainsWithOtherFlags otherFlags = + AssertAutoCompleteContainsAux true SourceFileKind.FS BackgroundRequestReason.CompleteWord (Some otherFlags) + + let AssertCtrlSpaceCompleteContainsNoCoffeeBreak = + AssertAutoCompleteContainsAux false SourceFileKind.FS BackgroundRequestReason.CompleteWord None let AssertCtrlSpaceCompletionListIsEmpty code marker = - DoWithAutoComplete true SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.CompleteWord code marker AssertCompListIsEmpty + DoWithAutoComplete true SourceFileKind.FS BackgroundRequestReason.CompleteWord None code marker AssertCompListIsEmpty let AssertCtrlSpaceCompletionListIsEmptyNoCoffeeBreak code marker = - DoWithAutoComplete false SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.CompleteWord code marker AssertCompListIsEmpty + DoWithAutoComplete false SourceFileKind.FS BackgroundRequestReason.CompleteWord None code marker AssertCompListIsEmpty let AssertAutoCompleteCompletionListIsEmpty code marker = - DoWithAutoComplete true SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect code marker AssertCompListIsEmpty + DoWithAutoComplete true SourceFileKind.FS BackgroundRequestReason.MemberSelect None code marker AssertCompListIsEmpty let AssertAutoCompleteCompletionListIsEmptyNoCoffeeBreak code marker = - DoWithAutoComplete false SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect code marker AssertCompListIsEmpty - + DoWithAutoComplete false SourceFileKind.FS BackgroundRequestReason.MemberSelect None code marker AssertCompListIsEmpty let testAutoCompleteAdjacentToDot op = let text = sprintf "System.Console%s" op @@ -365,7 +377,7 @@ a. [] member this.``TypeProvider.VisibilityChecksForGeneratedTypes``() = let extraRefs = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - let check = DoWithAutoCompleteUsingExtraRefs extraRefs true SourceFileKind.FS Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.MemberSelect + let check = DoWithAutoCompleteUsingExtraRefs extraRefs None true SourceFileKind.FS BackgroundRequestReason.MemberSelect let code = [ @@ -3332,6 +3344,264 @@ let x = query { for bbbb in abbbbc(*D0*) do ["b"] ["i"] + [] + member public this.``CompletionForAndBang_BaseLine0``() = + AssertCtrlSpaceCompleteContains + ["type Builder() =" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "builder {" + " let! xxx3 = 2" + " return x" + "}"] + " return x" + ["xxx3"] + [] + + [] + member public this.``CompletionForAndBang_BaseLine1``() = + AssertCtrlSpaceCompleteContains + ["type Builder() =" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let xxx1 = 1" + "builder {" + " let xxx2 = 1" + " let! xxx3 = 1" + " return (1 + x)" + "}"] + " return (1 + x" + ["xxx1"; "xxx2"; "xxx3"] + [] + + [] + member public this.``CompletionForAndBang_BaseLine2``() = + /// Without closing '}' + AssertCtrlSpaceCompleteContains + ["type Builder() =" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let yyy1 = 1" + "builder {" + " let yyy2 = 1" + " let! yyy3 = 1" + " return (1 + y)"] + " return (1 + y" + ["yyy1"; "yyy2"; "yyy3"] + [] + + [] + member public this.``CompletionForAndBang_BaseLine3``() = + /// Without closing ')' + AssertCtrlSpaceCompleteContains + ["type Builder() =" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let zzz2 = 1" + " let! zzz3 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz2"; "zzz3"] + [] + + [] + member public this.``CompletionForAndBang_BaseLine4``() = + AssertCtrlSpaceCompleteContains + ["type Builder() =" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let! zzz3 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz3"] + [] + + [] + member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return0``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "builder {" + " let! xxx3 = 2" + " and! xxx4 = 2" + " return x" + "}"] + " return x" + ["xxx3"; "xxx4"] + [] + + [] + member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return1``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let xxx1 = 1" + "builder {" + " let xxx2 = 1" + " let! xxx3 = 1" + " and! xxx4 = 1" + " return (1 + x)" + "}"] + " return (1 + x" + ["xxx1"; "xxx2"; "xxx3"; "xxx4"] + [] + + [] + member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return2``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let yyy1 = 1" + "builder {" + " let yyy2 = 1" + " let! yyy3 = 1" + " and! yyy4 = 1" + " return (1 + y)"] + " return (1 + y" + ["yyy1"; "yyy2"; "yyy3"; "yyy4"] + [] + + [] + member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return3``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let zzz2 = 1" + " let! zzz3 = 1" + " and! zzz4 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz2"; "zzz3"; "zzz4"] + [] + + [] + member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return4``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" + " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" + " member x.Return(a: 'T) = a" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let! zzz3 = 1" + " and! zzz4 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz3"; "zzz4"] + [] + + [] + member public this.``CompletionForAndBang_Test_Bind2Return0``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" + "let builder = Builder()" + "builder {" + " let! xxx3 = 2" + " and! xxx4 = 2" + " return x" + "}"] + " return x" + ["xxx3"; "xxx4"] + [] + + [] + member public this.``CompletionForAndBang_Test_Bind2Return1``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" + "let builder = Builder()" + "let xxx1 = 1" + "builder {" + " let xxx2 = 1" + " let! xxx3 = 1" + " and! xxx4 = 1" + " return (1 + x)" + "}"] + " return (1 + x" + ["xxx1"; "xxx2"; "xxx3"; "xxx4"] + [] + + [] + member public this.``CompletionForAndBang_Test_Bind2Return2``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" + "let builder = Builder()" + "let yyy1 = 1" + "builder {" + " let yyy2 = 1" + " let! yyy3 = 1" + " and! yyy4 = 1" + " return (1 + y)"] + " return (1 + y" + ["yyy1"; "yyy2"; "yyy3"; "yyy4"] + [] + + [] + member public this.``CompletionForAndBang_Test_Bind2Return3``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let zzz2 = 1" + " let! zzz3 = 1" + " and! zzz4 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz2"; "zzz3"; "zzz4"] + [] + + [] + member public this.``CompletionForAndBang_Test_Bind2Return4``() = + AssertCtrlSpaceCompleteContainsWithOtherFlags + "/langversion:preview" + ["type Builder() =" + " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" + "let builder = Builder()" + "let zzz1 = 1" + "builder {" + " let! zzz3 = 1" + " and! zzz4 = 1" + " return (1 + z" ] + " return (1 + z" + ["zzz1"; "zzz3"; "zzz4"] + [] (**) [] @@ -5202,11 +5472,11 @@ let x = query { for bbbb in abbbbc(*D0*) do (*------------------------------------------IDE Query automation start -------------------------------------------------*) member private this.AssertAutoCompletionInQuery(fileContent : string list, marker:string,contained:string list) = - let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] + let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] None let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) MoveCursorToEndOfMarker(file, marker) - let completions = CompleteAtCursorForReason(file,Microsoft.VisualStudio.FSharp.LanguageService.BackgroundRequestReason.CompleteWord) + let completions = CompleteAtCursorForReason(file,BackgroundRequestReason.CompleteWord) AssertCompListContainsAll(completions, contained) gpatcc.AssertExactly(0,0) diff --git a/vsintegration/tests/UnitTests/TestLib.LanguageService.fs b/vsintegration/tests/UnitTests/TestLib.LanguageService.fs index f19ecb1ffc..fbd950480f 100644 --- a/vsintegration/tests/UnitTests/TestLib.LanguageService.fs +++ b/vsintegration/tests/UnitTests/TestLib.LanguageService.fs @@ -281,10 +281,11 @@ type LanguageServiceBaseTests() = ?defines : list, ?fileKind : SourceFileKind, ?disabledWarnings : list, - ?fileName : string + ?fileName : string, + ?otherFlags: string ) = let content = content.Split( [|"\r\n"|], StringSplitOptions.None) |> List.ofArray - this.CreateSingleFileProject(content, ?references = references, ?defines = defines, ?fileKind = fileKind, ?disabledWarnings = disabledWarnings, ?fileName = fileName) + this.CreateSingleFileProject(content, ?references = references, ?defines = defines, ?fileKind = fileKind, ?disabledWarnings = disabledWarnings, ?fileName = fileName, ?otherFlags = otherFlags) member internal this.CreateSingleFileProject ( @@ -293,7 +294,8 @@ type LanguageServiceBaseTests() = ?defines : list, ?fileKind : SourceFileKind, ?disabledWarnings : list, - ?fileName : string + ?fileName : string, + ?otherFlags: string ) = assert (box currentVS = box defaultVS) let mkKeyComponent l = @@ -312,7 +314,7 @@ type LanguageServiceBaseTests() = let refs = mkKeyComponent references let defines = mkKeyComponent defines let warnings = mkKeyComponent disabledWarnings - (refs, defines, disabledWarnings, fileName.ToLower()) + (refs, defines, warnings, otherFlags, fileName.ToLower()) match cache.TryGetValue key with | true, (proj, file) -> @@ -337,6 +339,10 @@ type LanguageServiceBaseTests() = for r in (defaultArg references []) do GlobalFunctions.AddAssemblyReference(proj, r) + match otherFlags with + | None -> () + | Some flags -> GlobalFunctions.SetOtherFlags(proj, flags) + let content = String.concat Environment.NewLine content let _ = AddFileFromTextBlob(proj, fileName, content) let file = OpenFile(proj, fileName) diff --git a/vsintegration/tests/UnitTests/TestLib.Salsa.fs b/vsintegration/tests/UnitTests/TestLib.Salsa.fs index 1c4a65c1ed..e97d403460 100644 --- a/vsintegration/tests/UnitTests/TestLib.Salsa.fs +++ b/vsintegration/tests/UnitTests/TestLib.Salsa.fs @@ -79,6 +79,7 @@ module internal GlobalFunctions = let CreateSolution(vs) = CreateSolution(vs) let CloseSolution(sol) = CloseSolution(sol) let Cleanup(vs) = Cleanup(vs) + let SetOtherFlags(proj, flags) = SetOtherFlags(proj, flags) let AddAssemblyReference(proj, ref) = AddAssemblyReference(proj, ref) let AddAssemblyReferenceEx(proj, ref, v) = AddAssemblyReferenceEx(proj, ref, v) let SetProjectDefines(proj, d) = SetProjectDefines(proj, d) From 95e71b10c089e313b564169dcd8bed0b2df68712 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 27 Jan 2020 19:53:47 -0800 Subject: [PATCH 070/101] Typos -- fix a couple of types in the last pm PR (#8358) * Typos * references greater than 0 --- .../FSharp.DependencyManager.Utilities.fs | 6 +++--- .../DependencyManagerInteractiveTests.fs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index fdbb075add..fa1428b042 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -242,15 +242,15 @@ $(PACKAGEREFERENCES) <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> - <__ConflictsList Include="(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> + <__ConflictsList Include="%(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> - <__Conflicts>@(__ConflictsList, ';') + <__Conflicts>@(__ConflictsList, ';'); $([System.String]::Copy('%(Identity)').Replace('\', '/')) $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index fd6148d4e3..4afd6a90a6 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -40,7 +40,7 @@ type DependencyManagerInteractiveTests() = let value = opt.Value Assert.AreEqual(typeof, value.ReflectionType) Assert.AreEqual(0, value.ReflectionValue :?> int) - Assert.AreEqual(1, assemblyResolveEventCount) + Assert.Greater(assemblyResolveEventCount, 0) Assert.AreEqual(true, foundAssemblyReference) [] From 98341d43733bb3dd4d9f697cba9b4b64cacb3df1 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 28 Jan 2020 07:39:18 +0100 Subject: [PATCH 071/101] tryDestAppTy should be called tryTcrefOfAppTy (#8264) --- src/fsharp/ConstraintSolver.fs | 10 ++--- src/fsharp/IlxGen.fs | 2 +- src/fsharp/InfoReader.fs | 12 +++--- src/fsharp/NameResolution.fs | 12 +++--- src/fsharp/PatternMatchCompilation.fs | 2 +- src/fsharp/PostInferenceChecks.fs | 8 ++-- src/fsharp/TastOps.fs | 40 +++++++++---------- src/fsharp/TastOps.fsi | 2 +- src/fsharp/TypeChecker.fs | 12 +++--- src/fsharp/service/FSharpCheckerResults.fs | 8 ++-- src/fsharp/service/ServiceDeclarationLists.fs | 2 +- src/fsharp/symbols/SymbolHelpers.fs | 12 +++--- 12 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 92ae10cd75..cce06e7024 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1973,7 +1973,7 @@ and SolveTypeSupportsComparison (csenv: ConstraintSolverEnv) ndeep m2 trace ty = AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsComparison m) | ValueNone -> // Check it isn't ruled out by the user - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_NoComparisonAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportComparison1(NicePrint.minimalStringOfType denv ty), m, m2)) | _ -> @@ -2016,7 +2016,7 @@ and SolveTypeSupportsEquality (csenv: ConstraintSolverEnv) ndeep m2 trace ty = | ValueSome destTypar -> AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsEquality m) | _ -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_NoEqualityAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportEquality1(NicePrint.minimalStringOfType denv ty), m, m2)) | _ -> @@ -2150,13 +2150,13 @@ and SolveTypeRequiresDefaultConstructor (csenv: ConstraintSolverEnv) ndeep m2 tr if GetIntrinsicConstructorInfosOfType csenv.InfoReader m ty |> List.exists (fun x -> x.IsNullary && IsMethInfoAccessible amap m AccessibleFromEverywhere x) then - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_AbstractClassAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csGenericConstructRequiresNonAbstract(NicePrint.minimalStringOfType denv origTy), m, m2)) | _ -> CompleteD else - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when tcref.PreEstablishedHasDefaultConstructor || // F# 3.1 feature: records with CLIMutable attribute should satisfy 'default constructor' constraint @@ -2582,7 +2582,7 @@ and ResolveOverloading (calledArg1.CalledArgumentType, calledArg2.CalledArgumentType) ||> compareCond (fun ty1 ty2 -> // Func<_> is always considered better than any other delegate type - match tryDestAppTy csenv.g ty1 with + match tryTcrefOfAppTy csenv.g ty1 with | ValueSome tcref1 when tcref1.DisplayName = "Func" && (match tcref1.PublicPath with Some p -> p.EnclosingPath = [| "System" |] | _ -> false) && diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 412d1a62ac..5d18e0d549 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3950,7 +3950,7 @@ and GenDefaultValue cenv cgbuf eenv (ty, m) = if isRefTy g ty then CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) AI_ldnull else - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when (tyconRefEq g g.system_SByte_tcref tcref || tyconRefEq g g.system_Int16_tcref tcref || tyconRefEq g g.system_Int32_tcref tcref || diff --git a/src/fsharp/InfoReader.fs b/src/fsharp/InfoReader.fs index 1fac7a0f6e..1679f46c92 100644 --- a/src/fsharp/InfoReader.fs +++ b/src/fsharp/InfoReader.fs @@ -78,7 +78,7 @@ let rec GetImmediateIntrinsicMethInfosOfTypeAux (optFilter, ad) g amap m origTy GetImmediateIntrinsicMethInfosOfTypeAux (optFilter, ad) g amap m origTy betterMetadataTy |> List.filter (fun minfo -> not minfo.IsInstance) else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> SelectImmediateMemberVals g optFilter (TrySelectMemberVal g optFilter origTy None) tcref @@ -166,7 +166,7 @@ let rec GetImmediateIntrinsicPropInfosOfTypeAux (optFilter, ad) g amap m origTy let betterMetadataTy = convertToTypeWithMetadataIfPossible g metadataTy GetImmediateIntrinsicPropInfosOfTypeAux (optFilter, ad) g amap m origTy betterMetadataTy else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> let propCollector = new PropertyCollector(g, amap, m, origTy, optFilter, ad) @@ -185,7 +185,7 @@ let rec GetImmediateIntrinsicPropInfosOfType (optFilter, ad) g amap m ty = let IsIndexerType g amap ty = isArray1DTy g ty || isListTy g ty || - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let _, entityTy = generalizeTyconRef tcref let props = GetImmediateIntrinsicPropInfosOfType (None, AccessibleFromSomeFSharpCode) g amap range0 entityTy @@ -265,7 +265,7 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) = /// Get the F#-declared record fields or class 'val' fields of a type let GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter, _ad) _m ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> [] | ValueSome tcref -> // Note;secret fields are not allowed in lookups here, as we're only looking @@ -420,7 +420,7 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) = | flds -> // multiple fields with the same name can come from different classes, // so filter them by the given type name - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> ValueNone | ValueSome tcref -> match flds |> List.filter (fun rfinfo -> tyconRefEq g tcref rfinfo.TyconRef) with @@ -466,7 +466,7 @@ let rec GetIntrinsicConstructorInfosOfTypeAux (infoReader: InfoReader) m origTy let betterMetadataTy = convertToTypeWithMetadataIfPossible g metadataTy GetIntrinsicConstructorInfosOfTypeAux infoReader m origTy betterMetadataTy else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> tcref.MembersOfFSharpTyconByName diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index a63c8e6e13..8f3c6863c1 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -536,7 +536,7 @@ let ExtensionPropInfosOfTypeInScope collectionSettings (infoReader:InfoReader) ( let extMemsFromHierarchy = infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref SelectPropInfosFromExtMembers infoReader ad optFilter ty m extMemInfos @@ -606,7 +606,7 @@ let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSetting infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> let g = infoReader.g - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let extValRefs = nenv.eIndexedExtensionMembers.Find tcref SelectMethInfosFromExtMembers infoReader optFilter ty m extValRefs @@ -2352,7 +2352,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf match lookupKind with | LookupKind.Expr | LookupKind.Pattern -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> for uc in tcref.UnionCasesArray do addToBuffer uc.DisplayName @@ -2365,7 +2365,7 @@ and ResolveLongIdentInNestedTypes (ncenv: NameResolver) nenv lookupKind resInfo tys |> CollectAtMostOneResult (fun ty -> let resInfo = - match tryDestAppTy ncenv.g ty with + match tryTcrefOfAppTy ncenv.g ty with | ValueSome tcref -> resInfo.AddEntity(id.idRange, tcref) | _ -> @@ -3222,7 +3222,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) |> List.map (fun x -> ResolutionInfo.Empty, FieldResolution(x, false)) - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText, m, ty) with | ValueSome (RecdFieldInfo(_, rfref)) -> [ResolutionInfo.Empty, FieldResolution(rfref, false)] @@ -3536,7 +3536,7 @@ let ItemOfTyconRef ncenv m (x: TyconRef) = let ItemOfTy g x = let nm = - match tryDestAppTy g x with + match tryTcrefOfAppTy g x with | ValueSome tcref -> tcref.DisplayName | _ -> "?" Item.Types (nm, [x]) diff --git a/src/fsharp/PatternMatchCompilation.fs b/src/fsharp/PatternMatchCompilation.fs index 6c5cc67e5a..915db6e45c 100644 --- a/src/fsharp/PatternMatchCompilation.fs +++ b/src/fsharp/PatternMatchCompilation.fs @@ -255,7 +255,7 @@ let RefuteDiscrimSet g m path discrims = match c' with | None -> raise CannotRefute | Some c -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when tcref.IsEnumTycon -> // We must distinguish between F#-defined enums and other .NET enums, as they are represented differently in the TAST let enumValues = diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index aedf7252d9..35bf453212 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -477,7 +477,7 @@ let CheckTypeForAccess (cenv: cenv) env objName valAcc m ty = let visitType ty = // We deliberately only check the fully stripped type for accessibility, // because references to private type abbreviations are permitted - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueNone -> () | ValueSome tcref -> let thisCompPath = compPathOfCcu cenv.viewCcu @@ -493,7 +493,7 @@ let WarnOnWrongTypeForAccess (cenv: cenv) env objName valAcc m ty = let visitType ty = // We deliberately only check the fully stripped type for accessibility, // because references to private type abbreviations are permitted - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueNone -> () | ValueSome tcref -> let thisCompPath = compPathOfCcu cenv.viewCcu @@ -618,7 +618,7 @@ let CheckTypeAux permitByRefLike (cenv: cenv) env m ty onInnerByrefError = let visitAppTy (tcref, tinst) = if isByrefLikeTyconRef cenv.g m tcref then let visitType ty0 = - match tryDestAppTy cenv.g ty0 with + match tryTcrefOfAppTy cenv.g ty0 with | ValueNone -> () | ValueSome tcref2 -> if isByrefTyconRef cenv.g tcref2 then @@ -1024,7 +1024,7 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi when not virt && baseVal.BaseOrThisInfo = BaseVal -> // Disallow calls to abstract base methods on IL types. - match tryDestAppTy g baseVal.Type with + match tryTcrefOfAppTy g baseVal.Type with | ValueSome tcref when tcref.IsILTycon -> try // This is awkward - we have to explicitly re-resolve back to the IL metadata to determine if the method is abstract. diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 9c08ef934f..a2d6a10a88 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -826,7 +826,7 @@ let tcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> let argsOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(_, tinst) -> tinst | _ -> []) let tryDestTyparTy g ty = ty |> stripTyEqns g |> (function TType_var v -> ValueSome v | _ -> ValueNone) let tryDestFunTy g ty = ty |> stripTyEqns g |> (function TType_fun (tyv, tau) -> ValueSome(tyv, tau) | _ -> ValueNone) -let tryDestAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> ValueSome tcref | _ -> ValueNone) +let tryTcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> ValueSome tcref | _ -> ValueNone) let tryDestAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, tys) -> ValueSome (anonInfo, tys) | _ -> ValueNone) let tryAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var v -> ValueSome v | TType_measure unt when isUnitParMeasure g unt -> ValueSome(destUnitParMeasure g unt) | _ -> ValueNone) @@ -1707,17 +1707,17 @@ let isFSharpObjModelRefTy g ty = | TTyconStruct | TTyconEnum -> false let isFSharpClassTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpClassTycon | _ -> false let isFSharpStructTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpStructOrEnumTycon | _ -> false let isFSharpInterfaceTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpInterfaceTycon | _ -> false @@ -1728,7 +1728,7 @@ let isDelegateTy g ty = #endif | ILTypeMetadata (TILObjectReprData(_, _, td)) -> td.IsDelegate | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpDelegateTycon | _ -> false @@ -1749,12 +1749,12 @@ let isClassTy g ty = | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> isFSharpClassTy g ty let isStructOrEnumTyconTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsStructOrEnumTycon | _ -> false let isStructRecordOrUnionTyconTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsStructRecordOrUnionTycon | _ -> false @@ -1763,7 +1763,7 @@ let isStructTyconRef (tcref: TyconRef) = tycon.IsStructRecordOrUnionTycon || tycon.IsStructOrEnumTycon let isStructTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> isStructTyconRef tcref | _ -> @@ -1794,7 +1794,7 @@ let isRefTy g ty = // [Note: Constructed types and type-parameters are never unmanaged-types. end note] let rec isUnmanagedTy g ty = let ty = stripTyEqnsAndMeasureEqns g ty - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let isEq tcref2 = tyconRefEq g tcref tcref2 if isEq g.nativeptr_tcr || isEq g.nativeint_tcr || @@ -1826,7 +1826,7 @@ let isInterfaceTycon x = let isInterfaceTyconRef (tcref: TyconRef) = isInterfaceTycon tcref.Deref let isEnumTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tcref.IsEnumTycon @@ -3084,7 +3084,7 @@ let destNativePtrTy g ty = | _ -> failwith "destNativePtrTy: not a native ptr type" let isRefCellTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.refcell_tcr_canon tcref @@ -3109,7 +3109,7 @@ let mkOptionTy (g: TcGlobals) ty = TType_app (g.option_tcr_nice, [ty]) let mkListTy (g: TcGlobals) ty = TType_app (g.list_tcr_nice, [ty]) let isOptionTy (g: TcGlobals) ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.option_tcr_canon tcref @@ -3124,7 +3124,7 @@ let destOptionTy g ty = | ValueNone -> failwith "destOptionTy: not an option type" let isNullableTy (g: TcGlobals) ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.system_Nullable_tcref tcref @@ -3149,7 +3149,7 @@ let (|StripNullableTy|) g ty = | _ -> ty let isLinqExpressionTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.system_LinqExpression_tcref tcref @@ -4877,7 +4877,7 @@ let decideStaticOptimizationConstraint g c = checkTypes a b | TTyconIsStruct a -> let a = normalizeEnumTy g (stripTyEqnsAndMeasureEqns g a) - match tryDestAppTy g a with + match tryTcrefOfAppTy g a with | ValueSome tcref1 -> if tcref1.IsStructOrEnumTycon then StaticOptimizationAnswer.Yes else StaticOptimizationAnswer.No | ValueNone -> StaticOptimizationAnswer.Unknown @@ -5986,7 +5986,7 @@ let isRecdOrStructTyconRefReadOnly g m tcref = isRecdOrStructTyconRefReadOnlyAux g m false tcref let isRecdOrStructTyReadOnlyAux (g: TcGlobals) m isInref ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> isRecdOrStructTyconRefReadOnlyAux g m isInref tcref @@ -6532,7 +6532,7 @@ let mkMinusOne g m = mkInt g m (-1) let destInt32 = function Expr.Const (Const.Int32 n, _, _) -> Some n | _ -> None let isIDelegateEventType g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tyconRefEq g g.fslib_IDelegateEvent_tcr tcref | _ -> false @@ -7956,15 +7956,15 @@ let TypeNullNever g ty = let TypeNullIsExtraValue g m ty = if isILReferenceTy g ty || isDelegateTy g ty then // Putting AllowNullLiteralAttribute(false) on an IL or provided type means 'null' can't be used with that type - not (match tryDestAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some false | _ -> false) + not (match tryTcrefOfAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some false | _ -> false) elif TypeNullNever g ty then false else // Putting AllowNullLiteralAttribute(true) on an F# type means 'null' can be used with that type - match tryDestAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true | _ -> false + match tryTcrefOfAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true | _ -> false let TypeNullIsTrueValue g ty = - (match tryDestAppTy g ty with + (match tryTcrefOfAppTy g ty with | ValueSome tcref -> IsUnionTypeWithNullAsTrueValue g tcref.Deref | _ -> false) || (isUnitTy g ty) diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 176f64df72..332d98b35f 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -668,7 +668,7 @@ val destAppTy : TcGlobals -> TType -> TyconRef * TypeInst val tcrefOfAppTy : TcGlobals -> TType -> TyconRef -val tryDestAppTy : TcGlobals -> TType -> ValueOption +val tryTcrefOfAppTy : TcGlobals -> TType -> ValueOption val tryDestTyparTy : TcGlobals -> TType -> ValueOption diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ac71f5bb58..510b0542b7 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1556,7 +1556,7 @@ let MakeAndPublishBaseVal cenv env baseIdOpt ty = let InstanceMembersNeedSafeInitCheck cenv m thisTy = ExistsInEntireHierarchyOfType - (fun ty -> not (isStructTy cenv.g ty) && (match tryDestAppTy cenv.g ty with ValueSome tcref when tcref.HasSelfReferentialConstructor -> true | _ -> false)) + (fun ty -> not (isStructTy cenv.g ty) && (match tryTcrefOfAppTy cenv.g ty with ValueSome tcref when tcref.HasSelfReferentialConstructor -> true | _ -> false)) cenv.g cenv.amap m @@ -5767,7 +5767,7 @@ and TcExprs cenv env m tpenv flexes argTys args = and CheckSuperInit cenv objTy m = // Check the type is not abstract - match tryDestAppTy cenv.g objTy with + match tryTcrefOfAppTy cenv.g objTy with | ValueSome tcref when isAbstractTycon tcref.Deref -> errorR(Error(FSComp.SR.tcAbstractTypeCannotBeInstantiated(), m)) | _ -> () @@ -6285,7 +6285,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg FoldPrimaryHierarchyOfType (fun ty acc -> match acc with | None -> - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueSome tcref -> TryFindTyconRefStringAttribute cenv.g mWholeExpr cenv.g.attrib_DefaultMemberAttribute tcref | _ -> @@ -6852,7 +6852,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, let mObjTy = synObjTy.Range let objTy, tpenv = TcType cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv synObjTy - match tryDestAppTy cenv.g objTy with + match tryTcrefOfAppTy cenv.g objTy with | ValueNone -> error(Error(FSComp.SR.tcNewMustBeUsedWithNamedType(), mNewExpr)) | ValueSome tcref -> let isRecordTy = tcref.IsRecordTycon @@ -14609,7 +14609,7 @@ let TcMutRecDefns_Phase2 cenv envInitial bindsm scopem mutRecNSInfo (envMutRec: module AddAugmentationDeclarations = let tcaugHasNominalInterface g (tcaug: TyconAugmentation) tcref = tcaug.tcaug_interfaces |> List.exists (fun (x, _, _) -> - match tryDestAppTy g x with + match tryTcrefOfAppTy g x with | ValueSome tcref2 when tyconRefEq g tcref2 tcref -> true | _ -> false) @@ -16286,7 +16286,7 @@ module EstablishTypeDefinitionCores = (tycon, tycon2) :: acc else acc // note: all edges added are (tycon, _) let insertEdgeToType ty acc = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> insertEdgeToTycon tcref.Deref acc | _ -> diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 76585ba9d5..13517c0375 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -622,7 +622,7 @@ type internal TypeCheckInfo let getType() = match NameResolution.TryToResolveLongIdentAsType ncenv nenv m plid with - | Some x -> tryDestAppTy g x + | Some x -> tryTcrefOfAppTy g x | None -> match lastDotPos |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) with | Some p when lineStr.[p] = '.' -> @@ -630,7 +630,7 @@ type internal TypeCheckInfo | Some colAtEndOfNames -> let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based match TryGetTypeFromNameResolution(line, colAtEndOfNames, residueOpt, resolveOverloads) with - | Some x -> tryDestAppTy g x + | Some x -> tryTcrefOfAppTy g x | _ -> ValueNone | None -> ValueNone | _ -> ValueNone @@ -675,7 +675,7 @@ type internal TypeCheckInfo // it appears we're getting some typings recorded for non-atomic expressions like "f x" when isNil plid -> // lookup based on expression typings successful - Some (items |> List.map (CompletionItem (tryDestAppTy g ty) ValueNone), denv, m) + Some (items |> List.map (CompletionItem (tryTcrefOfAppTy g ty) ValueNone), denv, m) | GetPreciseCompletionListFromExprTypingsResult.NoneBecauseThereWereTypeErrors, _ -> // There was an error, e.g. we have "." and there is an error determining the type of // In this case, we don't want any of the fallback logic, rather, we want to produce zero results. @@ -708,7 +708,7 @@ type internal TypeCheckInfo // Try again with the qualItems | _, _, GetPreciseCompletionListFromExprTypingsResult.Some(FilterRelevantItems getItem exactMatchResidueOpt (items, denv, m), ty) -> - ValueSome(items |> List.map (CompletionItem (tryDestAppTy g ty) ValueNone), denv, m) + ValueSome(items |> List.map (CompletionItem (tryTcrefOfAppTy g ty) ValueNone), denv, m) | _ -> ValueNone diff --git a/src/fsharp/service/ServiceDeclarationLists.fs b/src/fsharp/service/ServiceDeclarationLists.fs index ef9c0b4098..9f106520d0 100644 --- a/src/fsharp/service/ServiceDeclarationLists.fs +++ b/src/fsharp/service/ServiceDeclarationLists.fs @@ -384,7 +384,7 @@ module internal DescriptionListsImpl = /// Find the glyph for the given type representation. let typeToGlyph ty = - match tryDestAppTy denv.g ty with + match tryTcrefOfAppTy denv.g ty with | ValueSome tcref -> tcref.TypeReprInfo |> reprToGlyph | _ -> if isStructTupleTy denv.g ty then FSharpGlyph.Struct diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index 48a44c8abb..39ca96934b 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -719,9 +719,9 @@ module internal SymbolHelpers = // In this case just bail out and assume items are not equal protectAssemblyExploration false (fun () -> let equalHeadTypes(ty1, ty2) = - match tryDestAppTy g ty1 with + match tryTcrefOfAppTy g ty1 with | ValueSome tcref1 -> - match tryDestAppTy g ty2 with + match tryTcrefOfAppTy g ty2 with | ValueSome tcref2 -> tyconRefEq g tcref1 tcref2 | _ -> typeEquiv g ty1 ty2 | _ -> typeEquiv g ty1 ty2 @@ -780,7 +780,7 @@ module internal SymbolHelpers = protectAssemblyExploration 1027 (fun () -> match item with | ItemWhereTypIsPreferred ty -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> hash tcref.LogicalName | _ -> 1010 | Item.ILField(ILFieldInfo(_, fld)) -> @@ -841,13 +841,13 @@ module internal SymbolHelpers = protectAssemblyExploration true (fun () -> match item with | Item.Types(it, [ty]) -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcr1 -> g.suppressed_types |> List.exists (fun supp -> let generalizedSupp = generalizedTyconRef supp // check the display name is precisely the one we're suppressing - match tryDestAppTy g generalizedSupp with + match tryTcrefOfAppTy g generalizedSupp with | ValueSome tcr2 -> it = supp.DisplayName && // check if they are the same logical type (after removing all abbreviations) @@ -895,7 +895,7 @@ module internal SymbolHelpers = | Item.FakeInterfaceCtor ty | Item.DelegateCtor ty | Item.Types(_, ty :: _) -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> bufs (fun os -> NicePrint.outputTyconRef denv os tcref) | _ -> "" | Item.ModuleOrNamespaces((modref :: _) as modrefs) -> From 82f248393d66984cf263cf5d3f039a6503f3f5d9 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 11:05:13 -0800 Subject: [PATCH 072/101] Feed back (#8365) --- src/fsharp/CompileOps.fs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 29d0408209..5bf304121a 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5240,20 +5240,12 @@ module ScriptPreprocessClosure = let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else [] yield! resolveDependencyManagerSources filename -#if DEBUG - for (_,subFile) in sources do - printfn "visiting %s - has subsource of %s " filename subFile -#endif for (m, subFile) in sources do if IsScript subFile then for subSource in ClosureSourceOfFilename(subFile, m, tcConfigResult.inputCodePage, false) do yield! loop subSource else yield ClosureFile(subFile, m, None, [], [], []) - -#if DEBUG - printfn "yielding source %s" filename -#endif yield ClosureFile(filename, m, Some parsedScriptAst, parseDiagnostics, errorLogger.Diagnostics, noWarns) | None -> From aa54c06f9f7f2f729a320ab0d0712087d952a1c8 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 11:11:31 -0800 Subject: [PATCH 073/101] ngen dependency manager (#8372) --- .../FSharp.DependencyManager.Utilities.fs | 23 +++++++------------ .../Source.extension.vsixmanifest | 1 + 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index fa1428b042..c120ec1f97 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -12,11 +12,6 @@ open System.Runtime.Versioning open Internal.Utilities.FSharpEnvironment -#if !(NETSTANDARD || NETCOREAPP) -open Microsoft.Build.Evaluation -open Microsoft.Build.Framework -#endif - [] type DependencyManagerAttribute() = inherit System.Attribute() @@ -86,7 +81,6 @@ module Utilities = let sdks = "Sdks" -#if !(NETSTANDARD || NETCOREAPP) let msbuildExePath = // Find msbuild.exe when invoked from desktop compiler. // 1. Look relative to F# compiler location Normal retail build @@ -120,7 +114,7 @@ module Utilities = | _ -> None roots |> Array.tryFind(fun root -> msbuildPathExists root) |> msbuildOption -#else + let dotnetHostPath = // How to find dotnet.exe --- woe is me; probing rules make me sad. // Algorithm: @@ -156,7 +150,6 @@ module Utilities = Some dotnet else None -#endif let drainStreamToFile (stream: StreamReader) filename = use file = File.OpenWrite(filename) @@ -210,13 +203,13 @@ module Utilities = let workingDir = Path.GetDirectoryName projectPath let succeeded = -#if !(NETSTANDARD || NETCOREAPP) - // The Desktop build uses "msbuild" to build - executeBuild msbuildExePath (arguments "") workingDir -#else - // The coreclr uses "dotnet msbuild" to build - executeBuild dotnetHostPath (arguments "msbuild") workingDir -#endif + if not (isRunningOnCoreClr) then + // The Desktop build uses "msbuild" to build + executeBuild msbuildExePath (arguments "") workingDir + else + // The coreclr uses "dotnet msbuild" to build + executeBuild dotnetHostPath (arguments "msbuild") workingDir + let outputFile = projectPath + ".fsx" let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None succeeded, resultOutFile diff --git a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest index e35e50e78e..474945f02b 100644 --- a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest +++ b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest @@ -19,6 +19,7 @@ + From 1cc3555b5bcb898f48e54161d417b46497a8444d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2020 19:29:21 +0000 Subject: [PATCH 074/101] Update dependencies from https://github.com/dotnet/arcade build 20200127.3 (#8377) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.20077.3 --- eng/Version.Details.xml | 4 ++-- eng/common/darc-init.ps1 | 2 +- global.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c98fbfbee4..32d8984d89 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - d0833c8e5e58cfc507ce3c8da364e55931190263 + 69a67461460d99125742d5c2dd94dad83add84a3 diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1 index 46d175fdfd..b94c2f4e41 100644 --- a/eng/common/darc-init.ps1 +++ b/eng/common/darc-init.ps1 @@ -27,7 +27,7 @@ function InstallDarcCli ($darcVersion) { Write-Host "Installing Darc CLI version $darcVersion..." Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." - & "$dotnet" tool install $darcCliPackageName --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g + & "$dotnet" tool install $darcCliPackageName --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g --framework netcoreapp2.1 } InstallDarcCli $darcVersion diff --git a/global.json b/global.json index f12de76387..d41648cb6b 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19616.5", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.20077.3", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 9eeaa25ae72e446213679c4fd5bb679ecb576d82 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 13:47:22 -0800 Subject: [PATCH 075/101] Do it properly (#8373) --- .../FSharp.DependencyManager.fsproj | 25 +------------------ .../VisualFSharpFull/VisualFSharpFull.csproj | 2 +- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj index 7faf2884f4..e3e4b385a2 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj @@ -4,8 +4,7 @@ Library - net472;netstandard2.0 - netstandard2.0 + netstandard2.0 FSharp.DependencyManager $(NoWarn);45;55;62;75;1204 true @@ -19,16 +18,6 @@ $(BaseOutputPath)\$(Configuration)\$(TargetFramework) - - - - - - - - - - @@ -41,18 +30,6 @@ - - - - - - - - - - - - diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj index 0bfaa8f1cd..9e373a9efd 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj @@ -91,7 +91,7 @@ All 2 True - TargetFramework=net472 + TargetFramework=netstandard2.0 {DED3BBD7-53F4-428A-8C9F-27968E768605} From fd74e2cdf92b172ea8025f1e55b4ecfb7efd349d Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 29 Jan 2020 16:54:48 -0600 Subject: [PATCH 076/101] add test and prospecttive fix for missing framework versions --- .../FSharp.Compiler.Service.Tests.fsproj | 3 ++ .../FsxCompletionProviderTests.fs | 2 +- src/fsharp/DotNetFrameworkDependencies.fs | 16 ++++++--- tests/service/ScriptOptionsTests.fs | 35 +++++++++++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 tests/service/ScriptOptionsTests.fs diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 874bb28070..4c5cb95eea 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -66,6 +66,9 @@ TreeVisitorTests.fs + + ScriptOptionsTests.fs + Program.fs diff --git a/fcs/FSharp.Compiler.Service.Tests/FsxCompletionProviderTests.fs b/fcs/FSharp.Compiler.Service.Tests/FsxCompletionProviderTests.fs index 468c916dc9..236caff428 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FsxCompletionProviderTests.fs +++ b/fcs/FSharp.Compiler.Service.Tests/FsxCompletionProviderTests.fs @@ -23,7 +23,7 @@ namespace Microsoft.VisualStudio.FSharp.Editor.Tests.Roslyn open System open System.Collections.Generic open System.IO -open System.Linq +open System.Linq open System.Reflection open NUnit.Framework diff --git a/src/fsharp/DotNetFrameworkDependencies.fs b/src/fsharp/DotNetFrameworkDependencies.fs index a454ec8059..129f6eb92e 100644 --- a/src/fsharp/DotNetFrameworkDependencies.fs +++ b/src/fsharp/DotNetFrameworkDependencies.fs @@ -115,13 +115,19 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies let desktopProductVersionMonikers = [| // major, minor, build, revision, moniker 4, 8, 3815, 0, "net48" + 4, 8, 3761, 0, "net48" 4, 7, 3190, 0, "net472" + 4, 7, 3062, 0, "net472" 4, 7, 2600, 0, "net471" + 4, 7, 2558, 0, "net471" 4, 7, 2053, 0, "net47" + 4, 7, 2046, 0, "net47" 4, 6, 1590, 0, "net462" + 4, 6, 57, 0, "net462" 4, 6, 1055, 0, "net461" 4, 6, 81, 0, "net46" 4, 0, 30319, 34209, "net452" + 4, 0, 30319, 17020, "net452" 4, 0, 30319, 18408, "net451" 4, 0, 30319, 17929, "net45" 4, 0, 30319, 1, "net4" @@ -138,14 +144,16 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies with _ -> defaultMscorlibVersion // Get the ProductVersion of this framework compare with table yield compatible monikers - let _, _, _, _, moniker = + match desktopProductVersionMonikers - |> Array.find (fun (major, minor, build, revision, _) -> + |> Array.tryFind (fun (major, minor, build, revision, _) -> (majorPart >= major) && (minorPart >= minor) && (buildPart >= build) && - (privatePart >= revision)) - moniker + (privatePart >= revision)) with + | Some (_,_,_,_,moniker) -> moniker + | None -> // if no moniker can be found, assume latest stable? + "net48" /// Gets the tfm E.g netcore3.0, net472 let executionTfm = diff --git a/tests/service/ScriptOptionsTests.fs b/tests/service/ScriptOptionsTests.fs new file mode 100644 index 0000000000..ec56f47d22 --- /dev/null +++ b/tests/service/ScriptOptionsTests.fs @@ -0,0 +1,35 @@ +#if INTERACTIVE +#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive +#r "../../artifacts/bin/fcs/net461/nunit.framework.dll" +#load "FsUnit.fs" +#load "Common.fs" +#else +module Tests.Service.ScriptOptions +#endif + +open NUnit.Framework +open FsUnit +open System +open FSharp.Compiler +open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Service.Tests.Common + + +let scriptSource = """ +open System +let pi = Math.PI +""" + +[] +[] +[] +let ``can generate options for different frameworks regardless of execution environment``(assumeNetFx, useSdk, flags) = + let path = IO.Path.GetTempPath() + let file = IO.Path.GetTempFileName() + let tempFile = IO.Path.Combine(path, file) + let (options, errors) = + checker.GetProjectOptionsFromScript(tempFile, Text.SourceText.ofString scriptSource, assumeDotNetFramework = assumeNetFx, useSdkRefs = useSdk, otherFlags = flags) + |> Async.RunSynchronously + match errors with + | [] -> () + | errors -> failwithf "Error while parsing script with assumeDotNetFramework:%b, useSdkRefs:%b, and otherFlags:%A:\n%A" assumeNetFx useSdk flags errors \ No newline at end of file From e7555f2421568ae8f24142f6779a94a26937968d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jan 2020 22:36:46 +0000 Subject: [PATCH 077/101] cleanup and alignment (#8319) * cleanup and alignment * cleanup and alignment * cleanup and alignment --- src/fsharp/ConstraintSolver.fs | 229 ++++++++++++++++++++------------- src/fsharp/TastOps.fs | 6 +- 2 files changed, 147 insertions(+), 88 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 59b10f7be7..92ae10cd75 100755 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -291,6 +291,22 @@ let rec occursCheck g un ty = // Predicates on types //------------------------------------------------------------------------- +/// Some additional solutions are forced prior to generalization (permitWeakResolution=true). These are, roughly speaking, rules +/// for binary-operand constraints arising from constructs such as "1.0 + x" where "x" is an unknown type. THe constraint here +/// involves two type parameters - one for the left, and one for the right. The left is already known to be Double. +/// In this situation (and in the absence of other evidence prior to generalization), constraint solving forces an assumption that +/// the right is also Double - this is "weak" because there is only weak evidence for it. +/// +/// permitWeakResolution also applies to resolutions of multi-type-variable constraints via method overloads. Method overloading gets applied even if +/// only one of the two type variables is known. +/// +/// During code gen we run with permitWeakResolution on, but we only apply it where one of the argument types for the built-in constraint resolution is +/// a variable type. +type PermitWeakResolution = + | Yes + | No + member x.Permit = match x with Yes -> true | No -> false + let rec isNativeIntegerTy g ty = typeEquivAux EraseMeasures g g.nativeint_ty ty || typeEquivAux EraseMeasures g g.unativeint_ty ty || @@ -310,10 +326,10 @@ let isUnsignedIntegerTy g ty = typeEquivAux EraseMeasures g g.unativeint_ty ty || typeEquivAux EraseMeasures g g.uint64_ty ty -let rec isIntegerOrIntegerEnumTy g ty = +let rec IsIntegerOrIntegerEnumTy g ty = isSignedIntegerTy g ty || isUnsignedIntegerTy g ty || - (isEnumTy g ty && isIntegerOrIntegerEnumTy g (underlyingTypeOfEnumTy g ty)) + (isEnumTy g ty && IsIntegerOrIntegerEnumTy g (underlyingTypeOfEnumTy g ty)) let isIntegerTy g ty = isSignedIntegerTy g ty || @@ -334,7 +350,7 @@ let isFpTy g ty = let isDecimalTy g ty = typeEquivAux EraseMeasures g g.decimal_ty ty -let IsNonDecimalNumericOrIntegralEnumType g ty = isIntegerOrIntegerEnumTy g ty || isFpTy g ty +let IsNonDecimalNumericOrIntegralEnumType g ty = IsIntegerOrIntegerEnumTy g ty || isFpTy g ty let IsNumericOrIntegralEnumType g ty = IsNonDecimalNumericOrIntegralEnumType g ty || isDecimalTy g ty @@ -353,6 +369,28 @@ let GetMeasureOfType g ty = | _ -> None | _ -> None +let IsCharOrStringType g ty = isCharTy g ty || isStringTy g ty + +/// Checks the argument type for a built-in solution to an op_Addition, op_Subtraction or op_Modulus constraint. +let IsAddSubModType nm g ty = IsNumericOrIntegralEnumType g ty || (nm = "op_Addition" && IsCharOrStringType g ty) + +/// Checks the argument type for a built-in solution to a bitwise operator constraint +let IsBitwiseOpType g ty = IsIntegerOrIntegerEnumTy g ty || (isEnumTy g ty) + +/// Check the other type in a built-in solution for a binary operator. +/// For weak resolution, require a relevant primitive on one side. +/// For strong resolution, a variable type is permitted. +let IsBinaryOpOtherArgType g permitWeakResolution ty = + match permitWeakResolution with + | PermitWeakResolution.No -> + not (isTyparTy g ty) + + | PermitWeakResolution.Yes -> true + +/// Checks the argument type for a built-in solution to a get_Sign constraint. +let IsSignType g ty = + isSignedIntegerTy g ty || isFpTy g ty || isDecimalTy g ty + type TraitConstraintSolution = | TTraitUnsolved | TTraitBuiltIn @@ -819,10 +857,12 @@ let rec SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optio // 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. // If so, re-solve the relevant constraints. if csenv.SolverState.ExtraCxs.ContainsKey r.Stamp then - do! RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep false trace r) + do! RepeatWhileD ndeep (fun ndeep -> SolveRelevantMemberConstraintsForTypar csenv ndeep PermitWeakResolution.No trace r) + // Re-solve the other constraints associated with this type variable return! solveTypMeetsTyparConstraints csenv ndeep m2 trace ty r @@ -867,7 +907,7 @@ and solveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty | TyparConstraint.SimpleChoice(tys, m2) -> SolveTypeChoice csenv ndeep m2 trace ty tys | TyparConstraint.CoercesTo(ty2, m2) -> SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace None ty2 ty | TyparConstraint.MayResolveMember(traitInfo, m2) -> - SolveMemberConstraint csenv false false ndeep m2 trace traitInfo |> OperationResult.ignore + SolveMemberConstraint csenv false PermitWeakResolution.No ndeep m2 trace traitInfo |> OperationResult.ignore } @@ -1136,16 +1176,9 @@ and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty /// don't. The type-directed static optimization rules in the library code that makes use of this /// will deal with the problem. /// -/// 2. Some additional solutions are forced prior to generalization (permitWeakResolution=true). These are, roughly speaking, rules -/// for binary-operand constraints arising from constructs such as "1.0 + x" where "x" is an unknown type. THe constraint here -/// involves two type parameters - one for the left, and one for the right. The left is already known to be Double. -/// In this situation (and in the absence of other evidence prior to generalization), constraint solving forces an assumption that -/// the right is also Double - this is "weak" because there is only weak evidence for it. -/// -/// permitWeakResolution also applies to resolutions of multi-type-variable constraints via method overloads. Method overloading gets applied even if -/// only one of the two type variables is known -/// -and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace (TTrait(tys, nm, memFlags, argtys, rty, sln)): OperationResult = trackErrors { +/// 2. Some additional solutions are forced prior to generalization (permitWeakResolution= Yes or YesDuringCodeGen). See above +and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = trackErrors { + let (TTrait(tys, nm, memFlags, traitObjAndArgTys, rty, sln)) = traitInfo // Do not re-solve if already solved if sln.Value.IsSome then return true else let g = csenv.g @@ -1158,20 +1191,21 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // Remove duplicates from the set of types in the support let tys = ListSet.setify (typeAEquiv g aenv) tys + // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(tys, nm, memFlags, argtys, rty, sln) + let traitInfo = TTrait(tys, nm, memFlags, traitObjAndArgTys, rty, sln) let rty = GetFSharpViewOfReturnType g rty // Assert the object type if the constraint is for an instance member if memFlags.IsInstance then - match tys, argtys with + match tys, traitObjAndArgTys with | [ty], (h :: _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace h ty | _ -> 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 - let argtys = if memFlags.IsInstance then List.tail argtys else argtys + let argtys = if memFlags.IsInstance then List.tail traitObjAndArgTys else traitObjAndArgTys let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution nm traitInfo @@ -1205,11 +1239,9 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // decimal<'u> * 'a (let checkRuleAppliesInPreferenceToMethods argty1 argty2 = // Check that at least one of the argument types is numeric - (IsNumericOrIntegralEnumType g argty1) && - // Check that the support of type variables is empty. That is, - // if we're canonicalizing, then having one of the types nominal is sufficient. - // If not, then both must be nominal (i.e. not a type variable). - (permitWeakResolution || not (isTyparTy g argty2)) && + IsNumericOrIntegralEnumType g argty1 && + // Check the other type is nominal, unless using weak resolution + IsBinaryOpOtherArgType g permitWeakResolution argty2 && // This next condition checks that either // - Neither type contributes any methods OR // - We have the special case "decimal<_> * decimal". In this case we have some @@ -1244,8 +1276,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | _, _, false, ("op_Addition" | "op_Subtraction" | "op_Modulus"), [argty1;argty2] when // Ignore any explicit +/- overloads from any basic integral types (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.ApparentEnclosingType ) && - ( (IsNumericOrIntegralEnumType g argty1 || (nm = "op_Addition" && (isCharTy g argty1 || isStringTy g argty1))) && (permitWeakResolution || not (isTyparTy g argty2)) - || (IsNumericOrIntegralEnumType g argty2 || (nm = "op_Addition" && (isCharTy g argty2 || isStringTy g argty2))) && (permitWeakResolution || not (isTyparTy g argty1)))) -> + ( IsAddSubModType nm g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsAddSubModType nm g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1)) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn @@ -1253,8 +1285,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | _, _, false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argty1;argty2] when // Ignore any explicit overloads from any basic integral types (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.ApparentEnclosingType ) && - ( (IsRelationalType g argty1 && (permitWeakResolution || not (isTyparTy g argty2))) - || (IsRelationalType g argty2 && (permitWeakResolution || not (isTyparTy g argty1))))) -> + ( IsRelationalType g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsRelationalType g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1)) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.bool_ty return TTraitBuiltIn @@ -1272,21 +1304,21 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty ty return TTraitBuiltIn - | [], _, false, ("DivideByInt"), [argty1;argty2] + | [], _, false, "DivideByInt", [argty1;argty2] when isFpTy g argty1 || isDecimalTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn // We pretend for uniformity that the 'string' and 'array' types have an indexer property called 'Item' - | [], [ty], true, ("get_Item"), [argty1] + | [], [ty], true, "get_Item", [argty1] when isStringTy g ty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty1 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.char_ty return TTraitBuiltIn - | [], [ty], true, ("get_Item"), argtys + | [], [ty], true, "get_Item", argtys when isArrayTy g ty -> if rankOfArrayTy g ty <> argtys.Length then do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), argtys.Length), m, m2)) @@ -1296,7 +1328,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty ety return TTraitBuiltIn - | [], [ty], true, ("set_Item"), argtys + | [], [ty], true, "set_Item", argtys when isArrayTy g ty -> if rankOfArrayTy g ty <> argtys.Length - 1 then do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), (argtys.Length - 1)), m, m2)) @@ -1308,8 +1340,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn | [], _, false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argty1;argty2] - when (isIntegerOrIntegerEnumTy g argty1 || (isEnumTy g argty1)) && (permitWeakResolution || not (isTyparTy g argty2)) - || (isIntegerOrIntegerEnumTy g argty2 || (isEnumTy g argty2)) && (permitWeakResolution || not (isTyparTy g argty1)) -> + when IsBitwiseOpType g argty1 && IsBinaryOpOtherArgType g permitWeakResolution argty2 + || IsBitwiseOpType g argty2 && IsBinaryOpOtherArgType g permitWeakResolution argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 @@ -1317,39 +1349,39 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn | [], _, false, ("op_LeftShift" | "op_RightShift"), [argty1;argty2] - when isIntegerOrIntegerEnumTy g argty1 -> + when IsIntegerOrIntegerEnumTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 g.int_ty do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 do! SolveDimensionlessNumericType csenv ndeep m2 trace argty1 return TTraitBuiltIn - | _, _, false, ("op_UnaryPlus"), [argty] + | _, _, false, "op_UnaryPlus", [argty] when IsNumericOrIntegralEnumType g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, false, ("op_UnaryNegation"), [argty] + | _, _, false, "op_UnaryNegation", [argty] when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, true, ("get_Sign"), [] - when (let argty = tys.Head in isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty) -> + | _, _, true, "get_Sign", [] + when IsSignType g tys.Head -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty g.int32_ty return TTraitBuiltIn | _, _, false, ("op_LogicalNot" | "op_OnesComplement"), [argty] - when isIntegerOrIntegerEnumTy g argty -> + when IsIntegerOrIntegerEnumTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty do! SolveDimensionlessNumericType csenv ndeep m2 trace argty return TTraitBuiltIn - | _, _, false, ("Abs"), [argty] + | _, _, false, "Abs", [argty] when isSignedIntegerTy g argty || isFpTy g argty || isDecimalTy g argty -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty @@ -1374,7 +1406,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty return TTraitBuiltIn - | _, _, false, ("op_Explicit"), [argty] + | _, _, false, "op_Explicit", [argty] when (// The input type. (IsNonDecimalNumericOrIntegralEnumType g argty || isStringTy g argty || isCharTy g argty) && // The output type @@ -1387,7 +1419,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload return TTraitBuiltIn - | _, _, false, ("op_Explicit"), [argty] + | _, _, false, "op_Explicit", [argty] when (// The input type. (IsNumericOrIntegralEnumType g argty || isStringTy g argty) && // The output type @@ -1403,7 +1435,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty argty1 return TTraitBuiltIn - | _, _, false, ("Atan2"), [argty1; argty2] + | _, _, false, "Atan2", [argty1; argty2] when isFpTy g argty1 -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argty2 argty1 match GetMeasureOfType g argty1 with @@ -1534,7 +1566,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload // If there's nothing left to learn then raise the errors. // Note: we should likely call MemberConstraintIsReadyForResolution here when permitWeakResolution=false but for stability // reasons we use the more restrictive isNil frees. - if (permitWeakResolution && MemberConstraintIsReadyForWeakResolution csenv traitInfo) || isNil frees then + if (permitWeakResolution.Permit && MemberConstraintIsReadyForWeakResolution csenv traitInfo) || isNil frees then do! errors // Otherwise re-record the trait waiting for canonicalization else @@ -1587,10 +1619,13 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let mref = IL.mkRefToILMethod (ilMeth.DeclaringTyconRef.CompiledRepresentationForNamedType, ilMeth.RawMetadata) let iltref = ilMeth.ILExtensionMethodDeclaringTyconRef |> Option.map (fun tcref -> tcref.CompiledRepresentationForNamedType) ILMethSln(ilMeth.ApparentEnclosingType, iltref, mref, minst) + | FSMeth(_, ty, vref, _) -> FSMethSln(ty, vref, minst) + | MethInfo.DefaultStructCtor _ -> error(InternalError("the default struct constructor was the unexpected solution to a trait constraint", m)) + #if !NO_EXTENSIONTYPING | ProvidedMeth(amap, mi, _, m) -> let g = amap.g @@ -1599,6 +1634,7 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let objArgVars, objArgs = (if minfo.IsInstance then [mkLocal m "this" minfo.ApparentEnclosingType] else []) |> List.unzip let callMethInfoOpt, callExpr, callExprTy = ProvidedMethodCalls.BuildInvokerExpressionForProvidedMethodCall css.TcVal (g, amap, mi, objArgs, NeverMutates, false, ValUseFlag.NormalValUse, allArgs, m) let closedExprSln = ClosedExprSln (mkLambdas m [] (objArgVars@allArgVars) (callExpr, callExprTy) ) + // If the call is a simple call to an IL method with all the arguments in the natural order, then revert to use ILMethSln. // This is important for calls to operators on generated provided types. There is an (unchecked) condition // that generative providers do not re=order arguments or insert any more information into operator calls. @@ -1623,9 +1659,9 @@ and TransactMemberConstraintSolution traitInfo (trace: OptionalTrace) sln = /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads -and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) permitWeakResolution nm (TTrait(tys, _, memFlags, argtys, rty, soln) as traitInfo): MethInfo list = +and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolution: PermitWeakResolution) nm (TTrait(tys, _, memFlags, argtys, rty, soln) as traitInfo): MethInfo list = let results = - if permitWeakResolution || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then + if permitWeakResolution.Permit || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then let m = csenv.m let minfos = match memFlags.MemberKind with @@ -1647,6 +1683,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) permitWeakResolution |> List.exists (fun minfo2 -> MethInfosEquivByNameAndSig EraseAll true csenv.g csenv.amap m minfo2 minfo1))) else [] + // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. if nm = "op_Explicit" then results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" (TTrait(tys, "op_Implicit", memFlags, argtys, rty, soln)) @@ -1711,9 +1748,9 @@ and SolveRelevantMemberConstraintsForTypar (csenv: ConstraintSolverEnv) ndeep pe SolveMemberConstraint csenv true permitWeakResolution (ndeep+1) m2 trace traitInfo) and CanonicalizeRelevantMemberConstraints (csenv: ConstraintSolverEnv) ndeep trace tps = - SolveRelevantMemberConstraints csenv ndeep true trace tps + SolveRelevantMemberConstraints csenv ndeep PermitWeakResolution.Yes trace tps -and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace traitInfo support frees = +and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) traitInfo support (frees: Typar list) = let g = csenv.g let aenv = csenv.EquivEnv let cxst = csenv.SolverState.ExtraCxs @@ -2856,7 +2893,7 @@ let AddCxMethodConstraint denv css m trace traitInfo = (fun () -> trackErrors { do! - SolveMemberConstraint csenv true false 0 m trace traitInfo + SolveMemberConstraint csenv true PermitWeakResolution.No 0 m trace traitInfo |> OperationResult.ignore }) (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) @@ -2963,33 +3000,42 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra InfoReader = new InfoReader(g, amap) } let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) - let! _res = SolveMemberConstraint csenv true true 0 m NoTrace traitInfo + + let! _res = SolveMemberConstraint csenv true PermitWeakResolution.Yes 0 m NoTrace traitInfo + let sln = - match traitInfo.Solution with - | None -> Choice5Of5() - | Some sln -> - match sln with - | ILMethSln(origTy, extOpt, mref, minst) -> - let metadataTy = convertToTypeWithMetadataIfPossible g origTy - let tcref = tcrefOfAppTy g metadataTy - let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref - let ilMethInfo = - match extOpt with - | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) - | Some ilActualTypeRef -> - let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef - MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) - Choice1Of5 (ilMethInfo, minst) - | FSMethSln(ty, vref, minst) -> - Choice1Of5 (FSMeth(g, ty, vref, None), minst) - | FSRecdFieldSln(tinst, rfref, isSetProp) -> - Choice2Of5 (tinst, rfref, isSetProp) - | FSAnonRecdFieldSln(anonInfo, tinst, i) -> - Choice3Of5 (anonInfo, tinst, i) - | BuiltInSln -> - Choice5Of5 () - | ClosedExprSln expr -> - Choice4Of5 expr + match traitInfo.Solution with + | None -> Choice5Of5() + | Some sln -> + + // Given the solution information, reconstruct the MethInfo for the solution + match sln with + | ILMethSln(origTy, extOpt, mref, minst) -> + let metadataTy = convertToTypeWithMetadataIfPossible g origTy + let tcref = tcrefOfAppTy g metadataTy + let mdef = IL.resolveILMethodRef tcref.ILTyconRawMetadata mref + let ilMethInfo = + match extOpt with + | None -> MethInfo.CreateILMeth(amap, m, origTy, mdef) + | Some ilActualTypeRef -> + let actualTyconRef = Import.ImportILTypeRef amap m ilActualTypeRef + MethInfo.CreateILExtensionMeth(amap, m, origTy, actualTyconRef, None, mdef) + Choice1Of5 (ilMethInfo, minst) + + | FSMethSln(ty, vref, minst) -> + Choice1Of5 (FSMeth(g, ty, vref, None), minst) + + | FSRecdFieldSln(tinst, rfref, isSetProp) -> + Choice2Of5 (tinst, rfref, isSetProp) + + | FSAnonRecdFieldSln(anonInfo, tinst, i) -> + Choice3Of5 (anonInfo, tinst, i) + + | BuiltInSln -> + Choice5Of5 () + + | ClosedExprSln expr -> + Choice4Of5 expr return! match sln with | Choice1Of5(minfo, methArgTys) -> @@ -3026,19 +3072,27 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra | Choice2Of5 (tinst, rfref, isSet) -> let res = match isSet, rfref.RecdField.IsStatic, argExprs.Length with + + // static setter | true, true, 1 -> - Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) + Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) + + // instance setter | true, false, 2 -> - // If we resolve to an instance field on a struct and we haven't yet taken - // the address of the object then go do that - if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then - let h = List.head argExprs - let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m - Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) - else - Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) + // If we resolve to an instance field on a struct and we haven't yet taken + // the address of the object then go do that + if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then + let h = List.head argExprs + let wrap, h', _readonly, _writeonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m + Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) + else + Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) + + // static getter | false, true, 0 -> Some (mkStaticRecdFieldGet (rfref, tinst, m)) + + // instance getter | false, false, 1 -> if rfref.Tycon.IsStructOrEnumTycon && isByrefTy g (tyOfExpr g argExprs.[0]) then Some (mkRecdFieldGetViaExprAddr (argExprs.[0], rfref, tinst, m)) @@ -3046,6 +3100,7 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) | _ -> None ResultD res + | Choice3Of5 (anonInfo, tinst, i) -> let res = let tupInfo = anonInfo.TupInfo @@ -3055,9 +3110,11 @@ let CodegenWitnessThatTypeSupportsTraitConstraint tcVal g amap m (traitInfo: Tra Some (mkAnonRecdFieldGet g (anonInfo, argExprs.[0], tinst, i, m)) ResultD res - | Choice4Of5 expr -> ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) + | Choice4Of5 expr -> + ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) - | Choice5Of5 () -> ResultD None + | Choice5Of5 () -> + ResultD None } let ChooseTyparSolutionAndSolve css denv tp = diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 3d474dadbc..9c08ef934f 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -248,12 +248,14 @@ and remapTyparConstraintsAux tyenv cs = Some(TyparConstraint.CoercesTo (remapTypeAux tyenv ty, m)) | TyparConstraint.MayResolveMember(traitInfo, m) -> Some(TyparConstraint.MayResolveMember (remapTraitAux tyenv traitInfo, m)) - | TyparConstraint.DefaultsTo(priority, ty, m) -> Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m)) + | TyparConstraint.DefaultsTo(priority, ty, m) -> + Some(TyparConstraint.DefaultsTo(priority, remapTypeAux tyenv ty, m)) | TyparConstraint.IsEnum(uty, m) -> Some(TyparConstraint.IsEnum(remapTypeAux tyenv uty, m)) | TyparConstraint.IsDelegate(uty1, uty2, m) -> Some(TyparConstraint.IsDelegate(remapTypeAux tyenv uty1, remapTypeAux tyenv uty2, m)) - | TyparConstraint.SimpleChoice(tys, m) -> Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m)) + | TyparConstraint.SimpleChoice(tys, m) -> + Some(TyparConstraint.SimpleChoice(remapTypesAux tyenv tys, m)) | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ From 452da0ca8076e2937e6dcabe290c7d715da0dbd8 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 22 Jan 2020 17:02:08 -0800 Subject: [PATCH 078/101] Slicing and copying on ByteMemory should not throw if length is zero (#8282) * Slicing and copying on ByteMemory should not throw if length is zero * Added slice count check * Changed length check on stream creation * Remove empty * Minor format change * Check length before using AsStream * Remove exception throwing from creating a stream * Added checkCount * Remove checkReadCount --- src/absil/bytes.fs | 114 +++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 29 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 24159a728c..7e2f0ab2c9 100755 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -66,6 +66,10 @@ type ByteMemory () = type ByteArrayMemory(bytes: byte[], offset, length) = inherit ByteMemory() + let checkCount count = + if count < 0 then + raise (ArgumentOutOfRangeException("count", "Count is less than zero.")) + do if length < 0 || length > bytes.Length then raise (ArgumentOutOfRangeException("length")) @@ -80,7 +84,11 @@ type ByteArrayMemory(bytes: byte[], offset, length) = override _.Length = length override _.ReadBytes(pos, count) = - Array.sub bytes (offset + pos) count + checkCount count + if count > 0 then + Array.sub bytes (offset + pos) count + else + Array.empty override _.ReadInt32 pos = let finalOffset = offset + pos @@ -96,25 +104,45 @@ type ByteArrayMemory(bytes: byte[], offset, length) = ((uint16 bytes.[finalOffset + 1]) <<< 8) override _.ReadUtf8String(pos, count) = - System.Text.Encoding.UTF8.GetString(bytes, offset + pos, count) + checkCount count + if count > 0 then + System.Text.Encoding.UTF8.GetString(bytes, offset + pos, count) + else + String.Empty override _.Slice(pos, count) = - ByteArrayMemory(bytes, offset + pos, count) :> ByteMemory + checkCount count + if count > 0 then + ByteArrayMemory(bytes, offset + pos, count) :> ByteMemory + else + ByteArrayMemory(Array.empty, 0, 0) :> ByteMemory override _.CopyTo stream = - stream.Write(bytes, offset, length) + if length > 0 then + stream.Write(bytes, offset, length) override _.Copy(srcOffset, dest, destOffset, count) = - Array.blit bytes (offset + srcOffset) dest destOffset count + checkCount count + if count > 0 then + Array.blit bytes (offset + srcOffset) dest destOffset count override _.ToArray() = - Array.sub bytes offset length + if length > 0 then + Array.sub bytes offset length + else + Array.empty override _.AsStream() = - new MemoryStream(bytes, offset, length) :> Stream + if length > 0 then + new MemoryStream(bytes, offset, length) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream override _.AsReadOnlyStream() = - new MemoryStream(bytes, offset, length, false) :> Stream + if length > 0 then + new MemoryStream(bytes, offset, length, false) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream [] type SafeUnmanagedMemoryStream = @@ -149,6 +177,10 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = if i < 0 || i >= length then raise (ArgumentOutOfRangeException("i")) + let checkCount count = + if count < 0 then + raise (ArgumentOutOfRangeException("count", "Count is less than zero.")) + do if length < 0 then raise (ArgumentOutOfRangeException("length")) @@ -165,16 +197,24 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = override _.Length = length override _.ReadUtf8String(pos, count) = - check pos - check (pos + count - 1) - System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) + else + String.Empty - override _.ReadBytes(pos, count) = - check pos - check (pos + count - 1) - let res = Bytes.zeroCreate count - Marshal.Copy(NativePtr.toNativeInt addr + nativeint pos, res, 0, count) - res + override _.ReadBytes(pos, count) = + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + let res = Bytes.zeroCreate count + Marshal.Copy(NativePtr.toNativeInt addr + nativeint pos, res, 0, count) + res + else + Array.empty override _.ReadInt32 pos = check pos @@ -187,28 +227,44 @@ type RawByteMemory(addr: nativeptr, length: int, holder: obj) = uint16(Marshal.ReadInt16(NativePtr.toNativeInt addr + nativeint pos)) override _.Slice(pos, count) = - check pos - check (pos + count - 1) - RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory + checkCount count + if count > 0 then + check pos + check (pos + count - 1) + RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory + else + ByteArrayMemory(Array.empty, 0, 0) :> ByteMemory override x.CopyTo stream = - use stream2 = x.AsStream() - stream2.CopyTo stream + if length > 0 then + use stream2 = x.AsStream() + stream2.CopyTo stream override _.Copy(srcOffset, dest, destOffset, count) = - check srcOffset - Marshal.Copy(NativePtr.toNativeInt addr + nativeint srcOffset, dest, destOffset, count) + checkCount count + if count > 0 then + check srcOffset + Marshal.Copy(NativePtr.toNativeInt addr + nativeint srcOffset, dest, destOffset, count) override _.ToArray() = - let res = Array.zeroCreate length - Marshal.Copy(NativePtr.toNativeInt addr, res, 0, res.Length) - res + if length > 0 then + let res = Array.zeroCreate length + Marshal.Copy(NativePtr.toNativeInt addr, res, 0, res.Length) + res + else + Array.empty override _.AsStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream + if length > 0 then + new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream override _.AsReadOnlyStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream + if length > 0 then + new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream + else + new MemoryStream([||], 0, 0, false) :> Stream [] type ReadOnlyByteMemory(bytes: ByteMemory) = From 73ec438294466f08a3cc70f8ddb09d4934dc18a3 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Thu, 23 Jan 2020 10:29:14 -0800 Subject: [PATCH 079/101] safely delete test files and directories --- .../ProjectOptionsBuilder.fs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fcs/FSharp.Compiler.Service.Tests/ProjectOptionsBuilder.fs b/fcs/FSharp.Compiler.Service.Tests/ProjectOptionsBuilder.fs index 1d3df25165..106b7602a5 100644 --- a/fcs/FSharp.Compiler.Service.Tests/ProjectOptionsBuilder.fs +++ b/fcs/FSharp.Compiler.Service.Tests/ProjectOptionsBuilder.fs @@ -5,6 +5,19 @@ open System.IO open System.Xml.Linq open FSharp.Compiler.SourceCodeServices +module FileSystemHelpers = + let safeDeleteFile (path: string) = + try + File.Delete(path) + with + | _ -> () + + let safeDeleteDirectory (path: string) = + try + Directory.Delete(path) + with + | _ -> () + type FSharpProject = { Directory: string @@ -29,9 +42,10 @@ type FSharpProject = member this.Dispose() = // delete each source file this.Files - |> List.iter (fun (path, _contents) -> File.Delete(path)) + |> List.map fst + |> List.iter FileSystemHelpers.safeDeleteFile // delete the directory - Directory.Delete(this.Directory) + FileSystemHelpers.safeDeleteDirectory (this.Directory) // project file doesn't really exist, nothing to delete () From df6600921fc3016fe02e7c99745f892d8b7ffebb Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 27 Jan 2020 13:26:29 -0800 Subject: [PATCH 080/101] Clean up nuget project file (#8327) * Clean up project file * remove framework deps * tests * Simplify slightly and resolve package conflicts for dotnet build too. * stuff --- .../FSharp.DependencyManager.Utilities.fs | 128 +++++++----------- .../FSharp.DependencyManager.fs | 9 +- 2 files changed, 55 insertions(+), 82 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index d86ceb3dbb..fdbb075add 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -221,99 +221,73 @@ module Utilities = let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None succeeded, resultOutFile - // Generate a project files for dependencymanager projects - let generateLibrarySource = @"// Generated dependencymanager library -namespace lib" - - let generateProjectBody = @" + let generateProjectBody = """ + $(TARGETFRAMEWORK) false - 4.7.0 - 4.7.1-* + 4.7.0 + 4.7.1-* - - - -$(PACKAGEREFERENCES) - - - - - - - - - - - fsharp41 - tools - +$(PACKAGEREFERENCES) - - + - - <_ResolvedOutputFiles - Include=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*"" - Exclude=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll"" - Condition=""'%(_ResolvedProjectReferencePaths.IsFSharpDesignTimeProvider)' == 'true'""> - %(_ResolvedProjectReferencePaths.NearestTargetFramework) - - - <_ResolvedOutputFiles - Include=""@(BuiltProjectOutputGroupKeyOutput)"" - Condition=""'$(IsFSharpDesignTimeProvider)' == 'true' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'FSharp.Core.dll' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'System.ValueTuple.dll'""> - $(TargetFramework) - - - - $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedOutputFiles.NearestTargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) - - - + + <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> + <__ConflictsList Include="(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> + + + <__Conflicts>@(__ConflictsList, ';') + - - - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx - $([System.String]::Copy('%(ResolvedCompileFileDefinitions.PathInPackage)').StartsWith('ref/')) - %(ResolvedCompileFileDefinitions.NuGetPackageId) - %(ResolvedCompileFileDefinitions.NuGetPackageVersion) + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssemblies.FileName)%(__InteractiveReferencedAssemblies.Extension).fsx + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssemblies.NuGetPackageId) + %(__InteractiveReferencedAssemblies.NuGetPackageVersion) - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(RuntimeCopyLocalItems.FileName)%(RuntimeCopyLocalItems.Extension).fsx - $([System.String]::Copy('%(RuntimeCopyLocalItems.PathInPackage)').StartsWith('ref/')) - %(RuntimeCopyLocalItems.NuGetPackageId) - %(RuntimeCopyLocalItems.NuGetPackageVersion) + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssembliesCopyLocal.FileName)%(__InteractiveReferencedAssembliesCopyLocal.Extension).fsx + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageId) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageVersion) + - $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) + Include="@(RuntimeTargetsCopyLocalItems)" + Condition="'%(RuntimeTargetsCopyLocalItems.AssetType)' == 'native'"> + $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) - + - + @@ -322,16 +296,16 @@ $(PACKAGEREFERENCES) - + - - + + - + @@ -340,4 +314,4 @@ $(PACKAGEREFERENCES) -" +""" diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs index 9c577e9ca8..0fea32bdb4 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs @@ -28,10 +28,10 @@ module FSharpDependencyManager = let { Include=inc; Version=ver; RestoreSources=src; Script=script } = p seq { match not (String.IsNullOrEmpty(inc)), not (String.IsNullOrEmpty(ver)), not (String.IsNullOrEmpty(script)) with - | true, true, false -> yield sprintf @" true" inc ver - | true, true, true -> yield sprintf @" true" inc ver script - | true, false, false -> yield sprintf @" true" inc - | true, false, true -> yield sprintf @" true" inc script + | true, true, false -> yield sprintf @" " inc ver + | true, true, true -> yield sprintf @" " inc ver script + | true, false, false -> yield sprintf @" " inc + | true, false, true -> yield sprintf @" " inc script | _ -> () match not (String.IsNullOrEmpty(src)) with | true -> yield sprintf @" %s" (concat "$(RestoreAdditionalProjectSources)" src) @@ -158,7 +158,6 @@ type [] FSharpDependencyManager (outputDir:string op generateProjectBody.Replace("$(TARGETFRAMEWORK)", tfm) .Replace("$(PACKAGEREFERENCES)", packageReferenceText) - writeFile (Path.Combine(scriptsPath, "Library.fs")) generateLibrarySource writeFile fsProjectPath generateProjBody let succeeded, resultingFsx = buildProject fsProjectPath binLogPath From 54ab82a1c4a6d4150667a945d5ba9eda3838d5e8 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 28 Jan 2020 03:48:58 +0000 Subject: [PATCH 081/101] squash and-bang implementation (#7756) Co-authored-by: Kevin Ransom (msft) --- src/fsharp/CompileOps.fs | 2 + src/fsharp/FSComp.txt | 3 + src/fsharp/FSStrings.resx | 3 + src/fsharp/LanguageFeatures.fs | 2 + src/fsharp/LanguageFeatures.fsi | 1 + src/fsharp/LexFilter.fs | 7 + src/fsharp/TypeChecker.fs | 362 ++++++++++++++---- src/fsharp/ast.fs | 9 +- src/fsharp/lex.fsl | 4 +- src/fsharp/pars.fsy | 44 ++- src/fsharp/service/ServiceAssemblyContent.fs | 8 +- .../service/ServiceInterfaceStubGenerator.fs | 10 +- src/fsharp/service/ServiceLexing.fs | 4 +- src/fsharp/service/ServiceParseTreeWalk.fs | 14 +- src/fsharp/service/ServiceStructure.fs | 23 +- src/fsharp/service/ServiceUntypedParse.fs | 14 +- tests/fsharp/Compiler/Language/UIntTests.fs | 10 - .../dependency_graph.fsx | 192 ++++++++++ 18 files changed, 598 insertions(+), 114 deletions(-) mode change 100644 => 100755 src/fsharp/TypeChecker.fs mode change 100644 => 100755 src/fsharp/service/ServiceLexing.fs delete mode 100644 tests/fsharp/Compiler/Language/UIntTests.fs create mode 100644 tests/fsharp/perf/computation-expressions/dependency_graph.fsx diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 41d863dab0..ac89ff4c40 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -1004,6 +1004,8 @@ let OutputPhasedErrorR (os: StringBuilder) (err: PhasedDiagnostic) (canSuggestNa | Parser.TOKEN_OLET(_) -> getErrorString("Parser.TOKEN.OLET") | Parser.TOKEN_OBINDER | Parser.TOKEN_BINDER -> getErrorString("Parser.TOKEN.BINDER") + | Parser.TOKEN_OAND_BANG + | Parser.TOKEN_AND_BANG -> getErrorString("Parser.TOKEN.AND.BANG") | Parser.TOKEN_ODO -> getErrorString("Parser.TOKEN.ODO") | Parser.TOKEN_OWITH -> getErrorString("Parser.TOKEN.OWITH") | Parser.TOKEN_OFUNCTION -> getErrorString("Parser.TOKEN.OFUNCTION") diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index de26c9b349..6a4e5da6b1 100755 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1475,6 +1475,9 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl 3301,chkInvalidFunctionReturnType,"The function or method has an invalid return type '%s'. This is not permitted by the rules of Common IL." 3302,packageManagementRequiresVFive,"The package management feature requires language version 5.0 use /langversion:preview" 3303,fromEndSlicingRequiresVFive,"From the end slicing with requires language version 5.0, use /langversion:preview." +3343,tcRequireMergeSourcesOrBindN,"The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '%s' method or appropriate 'MergeSource' and 'Bind' methods" +3344,tcAndBangNotSupported,"This feature is not supported in this version of F#. You may need to add /langversion:preview to use this feature." +3345,tcInvalidUseBangBindingNoAndBangs,"use! may not be combined with and!" useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)." fSharpBannerVersion,"%s for F# %s" optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'" diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index cf3d3c92b2..a56e6f1421 100755 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -564,6 +564,9 @@ keyword 'and' + ! + keyword 'and!' + keyword 'as' diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 2170cee8f7..9d23f9e266 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -28,6 +28,7 @@ type LanguageFeature = | PackageManagement | FromEndSlicing | FixedIndexSlice3d4d + | AndBang /// LanguageVersion management type LanguageVersion (specifiedVersionAsString) = @@ -61,6 +62,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.NameOf, previewVersion LanguageFeature.OpenStaticClasses, previewVersion LanguageFeature.PackageManagement, previewVersion + LanguageFeature.AndBang, previewVersion ] let specified = diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index 6b44cd878a..5f274351d7 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -16,6 +16,7 @@ type LanguageFeature = | PackageManagement | FromEndSlicing | FixedIndexSlice3d4d + | AndBang /// LanguageVersion management type LanguageVersion = diff --git a/src/fsharp/LexFilter.fs b/src/fsharp/LexFilter.fs index 470b54709b..d485399af8 100755 --- a/src/fsharp/LexFilter.fs +++ b/src/fsharp/LexFilter.fs @@ -1784,6 +1784,13 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, pushCtxt tokenTup (CtxtLetDecl(blockLet, tokenStartPos)) returnToken tokenLexbufState (if blockLet then OBINDER b else token) + // and! ... ~~~> CtxtLetDecl + | AND_BANG isUse, (ctxt :: _) -> + let blockLet = match ctxt with CtxtSeqBlock _ -> true | _ -> false + if debug then dprintf "AND!: entering CtxtLetDecl(blockLet=%b), awaiting EQUALS to go to CtxtSeqBlock (%a)\n" blockLet outputPos tokenStartPos + pushCtxt tokenTup (CtxtLetDecl(blockLet,tokenStartPos)) + returnToken tokenLexbufState (if blockLet then OAND_BANG isUse else token) + | (VAL | STATIC | ABSTRACT | MEMBER | OVERRIDE | DEFAULT), ctxtStack when thereIsACtxtMemberBodyOnTheStackAndWeShouldPopStackForUpcomingMember ctxtStack -> if debug then dprintf "STATIC/MEMBER/OVERRIDE/DEFAULT: already inside CtxtMemberBody, popping all that context before starting next member...\n" // save this token, we'll consume it again later... diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs old mode 100644 new mode 100755 index c888057686..ac71f5bb58 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1842,31 +1842,25 @@ let UseCombinedArity g declKind rhsExpr prelimScheme = let UseNoArity prelimScheme = BuildValScheme ExpressionBinding None prelimScheme -let MakeSimpleVals cenv env names = +/// Make and publish the Val nodes for a collection of simple (non-generic) value specifications +let MakeAndPublishSimpleVals cenv env names = let tyschemes = DontGeneralizeVals names let valSchemes = NameMap.map UseNoArity tyschemes let values = MakeAndPublishVals cenv env (ParentNone, false, ExpressionBinding, ValNotInRecScope, valSchemes, [], XmlDoc.Empty, None) let vspecMap = NameMap.map fst values values, vspecMap -let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = - +/// Make and publish the Val nodes for a collection of value specifications at Lambda and Match positions +/// +/// We merge the additions to the name resolution environment into one using a merged range so all values are brought +/// into scope simultaneously. The technique used to do this is a disturbing and unfortunate hack that +/// intercepts `NotifyNameResolution` calls being emitted by `MakeAndPublishSimpleVals` + +let MakeAndPublishSimpleValsForMergedScope cenv env m (names: NameMap<_>) = let values, vspecMap = - if not mergeNamesInOneNameresEnv then MakeSimpleVals cenv env names + if names.Count <= 1 then + MakeAndPublishSimpleVals cenv env names else - // reason: now during typecheck we create new name resolution environment for all components of tupled arguments in lambda. - // When trying to find best environment for the given position first we pick the most deeply nested scope that contains given position - // (and that will be lambda body - correct one), then we look for the better subtree on the left hand side - // (and that will be name resolution environment containing second parameter parameter - without the first one). - // fix: I've tried to make fix as local as possible to reduce overall impact on the source code. - // Idea of the fix: replace existing typecheck results sink and capture all reported name resolutions (this will be all parameters in lambda). - // After that - we restore the sink back, generate new name resolution environment that contains all captured names and report generated environment - // to the old sink. - - - // default behavior - send EnvWithScope notification for every resolved name - // what we do here is override this default behavior and capture only all name resolution notifications - // later we'll process them and create one name resolution env that will contain names from all notifications let nameResolutions = ResizeArray() let values, vspecMap = let sink = @@ -1875,14 +1869,14 @@ let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = member this.NotifyNameResolution(pos, item, itemGroup, itemTyparInst, occurence, denv, nenv, ad, m, replacing) = if not m.IsSynthetic then nameResolutions.Add(pos, item, itemGroup, itemTyparInst, occurence, denv, nenv, ad, m, replacing) - member this.NotifyExprHasType(_, _, _, _, _, _) = assert false // no expr typings in MakeSimpleVals + member this.NotifyExprHasType(_, _, _, _, _, _) = assert false // no expr typings in MakeAndPublishSimpleVals member this.NotifyFormatSpecifierLocation(_, _) = () member this.NotifyOpenDeclaration(_) = () member this.CurrentSourceText = None member this.FormatStringCheckContext = None } use _h = WithNewTypecheckResultsSink(sink, cenv.tcSink) - MakeSimpleVals cenv env names + MakeAndPublishSimpleVals cenv env names if nameResolutions.Count <> 0 then let (_, _, _, _, _, _, _, ad, m1, _replacing) = nameResolutions.[0] @@ -1905,8 +1899,6 @@ let MakeAndPublishSimpleVals cenv env m names mergeNamesInOneNameresEnv = let envinner = AddLocalValMap cenv.tcSink m vspecMap env envinner, values, vspecMap - - //------------------------------------------------------------------------- // Helpers to freshen existing types and values, i.e. when a reference // to C<_> occurs then generate C for a fresh type inference variable ?ty. @@ -3535,7 +3527,7 @@ let YieldFree cenv expr = | SynExpr.ForEach (_, _, _, _, _, body, _) -> YieldFree body - | SynExpr.LetOrUseBang(_, _, _, _, _, body, _) -> + | SynExpr.LetOrUseBang(_, _, _, _, _, _, body, _) -> YieldFree body | SynExpr.YieldOrReturn((true, _), _, _) -> false @@ -6249,7 +6241,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = error(Error(FSComp.SR.tcConstructRequiresSequenceOrComputations(), m)) | SynExpr.DoBang (_, m) - | SynExpr.LetOrUseBang (_, _, _, _, _, _, m) -> + | SynExpr.LetOrUseBang (range=m) -> error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m)) | SynExpr.MatchBang (_, _, _, m) -> @@ -6261,7 +6253,7 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = | SynExpr.Lambda (isMember, isSubsequent, spats, bodyExpr, m) when isMember || isFirst || isSubsequent -> let domainTy, resultTy = UnifyFunctionType None cenv env.DisplayEnv m overallTy let vs, (tpenv, names, takenNames) = TcSimplePats cenv isMember CheckCxs domainTy env (tpenv, Map.empty, takenNames) spats - let envinner, _, vspecMap = MakeAndPublishSimpleVals cenv env m names true + let envinner, _, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names let byrefs = vspecMap |> Map.map (fun _ v -> isByrefTy cenv.g v.Type, v) let envinner = if isMember then envinner else ExitFamilyRegion envinner let bodyExpr, tpenv = TcIteratedLambdas cenv false envinner resultTy takenNames tpenv bodyExpr @@ -7529,6 +7521,9 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | [] -> callExpr | _ -> mkSynCall "Source" callExpr.Range [callExpr] + let mkSourceExprConditional isFromSource callExpr = + if isFromSource then mkSourceExpr callExpr else callExpr + /// Decide if the builder is an auto-quote builder let isAutoQuote = hasMethInfo "Quote" @@ -7979,7 +7974,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if not q then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), nm.idRange)) - let firstSource = if isFromSource then mkSourceExpr firstSource else firstSource + let firstSource = mkSourceExprConditional isFromSource firstSource let secondSource = mkSourceExpr secondSource // Add the variables to the variable space, on demand @@ -8123,11 +8118,12 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) -> - let wrappedSourceExpr = if isFromSource then mkSourceExpr sourceExpr else sourceExpr + let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr let mFor = match spForLoop with SequencePointAtForLoop m -> m | _ -> pat.Range let mPat = pat.Range let spBind = match spForLoop with SequencePointAtForLoop m -> SequencePointAtBinding m | NoSequencePointAtForLoop -> NoSequencePointAtStickyBinding - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("For"), mFor)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("For"), mFor)) // Add the variables to the query variable space, on demand let varSpace = @@ -8149,16 +8145,20 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder let mGuard = guardExpr.Range let mWhile = match spWhile with SequencePointAtWhileLoop m -> m | _ -> mGuard if isQuery then error(Error(FSComp.SR.tcNoWhileInQuery(), mWhile)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile)) Some(trans true q varSpace innerComp (fun holeFill -> translatedCtxt (mkSynCall "While" mWhile [mkSynDelay2 guardExpr; mkSynCall "Delay" mWhile [mkSynDelay innerComp.Range holeFill]])) ) | SynExpr.TryFinally (innerComp, unwindExpr, mTryToLast, spTry, _spFinally) -> let mTry = match spTry with SequencePointAtTry m -> m | _ -> mTryToLast if isQuery then error(Error(FSComp.SR.tcNoTryFinallyInQuery(), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) Some (translatedCtxt (mkSynCall "TryFinally" mTry [mkSynCall "Delay" mTry [mkSynDelay innerComp.Range (transNoQueryOps innerComp)]; mkSynDelay2 unwindExpr])) | SynExpr.Paren (_, _, _, m) -> @@ -8238,7 +8238,10 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | StripApps(SingleIdent nm, args) -> if args.Length = expectedArgCount then // Check for the [] attribute on each argument position - let args = args |> List.mapi (fun i arg -> if isCustomOperationProjectionParameter (i+1) nm then SynExpr.Lambda (false, false, varSpaceSimplePat, arg, arg.Range.MakeSynthetic()) else arg) + let args = args |> List.mapi (fun i arg -> + if isCustomOperationProjectionParameter (i+1) nm then + SynExpr.Lambda (false, false, varSpaceSimplePat, arg, arg.Range.MakeSynthetic()) + else arg) mkSynCall methInfo.DisplayName mClause (dataCompPrior :: args) else errorR(Error(FSComp.SR.tcCustomOperationHasIncorrectArgCount(nm.idText, expectedArgCount, args.Length), nm.idRange)) @@ -8266,7 +8269,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // Rebind using either for ... or let!.... let rebind = if maintainsVarSpaceUsingBind then - SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range) + SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, intoPat, dataCompAfterOp, [], contExpr, intoPat.Range) else SynExpr.ForEach (NoSequencePointAtForLoop, SeqExprOnly false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range) @@ -8288,7 +8291,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // Rebind using either for ... or let!.... let rebind = if lastUsesBind then - SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range) + SynExpr.LetOrUseBang (NoSequencePointAtLetBinding, false, false, varSpacePat, dataCompPrior, [], compClausesExpr, compClausesExpr.Range) else SynExpr.ForEach (NoSequencePointAtForLoop, SeqExprOnly false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range) @@ -8316,8 +8319,10 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // This is not pretty - we have to decide which range markers we use for the calls to Combine and Delay // NOTE: we should probably suppress these sequence points altogether let m1 = rangeForCombine innerComp1 - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Combine" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Combine"), m)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Combine" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Combine"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), m)) Some (translatedCtxt (mkSynCall "Combine" m1 [c; mkSynCall "Delay" m1 [mkSynDelay innerComp2.Range (transNoQueryOps innerComp2)]])) | None -> // "do! expr; cexpr" is treated as { let! () = expr in cexpr } @@ -8328,7 +8333,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SuppressSequencePointOnStmtOfSequential -> SequencePointAtBinding m | SuppressSequencePointOnExprOfSequential -> NoSequencePointAtDoBinding | SequencePointsAtSeq -> SequencePointAtBinding m - Some(trans true q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, innerComp2, m)) translatedCtxt) + Some(trans true q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m)) translatedCtxt) + // "expr; cexpr" is treated as sequential execution | _ -> Some (trans true q varSpace innerComp2 (fun holeFill -> @@ -8353,7 +8359,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder Some (translatedCtxt (SynExpr.IfThenElse (guardExpr, transNoQueryOps thenComp, Some(transNoQueryOps elseComp), spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch))) | None -> let elseComp = - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mIfToThen ad "Zero" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), mIfToThen)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mIfToThen ad "Zero" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), mIfToThen)) mkSynCall "Zero" mIfToThen [] Some (trans true q varSpace thenComp (fun holeFill -> translatedCtxt (SynExpr.IfThenElse (guardExpr, holeFill, Some elseComp, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch)))) @@ -8385,7 +8392,6 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // error case error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings(), mQueryOp))) - Some (trans true q varSpace innerComp (fun holeFill -> translatedCtxt (SynExpr.LetOrUse (isRec, false, binds, holeFill, m)))) // 'use x = expr in expr' @@ -8394,16 +8400,18 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isQuery then error(Error(FSComp.SR.tcUseMayNotBeUsedInQueries(), bindRange)) let innerCompRange = innerComp.Range let consumeExpr = SynExpr.MatchLambda(false, innerCompRange, [Clause(pat, None, transNoQueryOps innerComp, innerCompRange, SequencePointAtTarget)], spBind, innerCompRange) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) Some (translatedCtxt (mkSynCall "Using" bindRange [rhsExpr; consumeExpr ])) - // 'let! pat = expr in expr' --> build.Bind(e1, (function _argN -> match _argN with pat -> expr)) - | SynExpr.LetOrUseBang (spBind, false, isFromSource, pat, rhsExpr, innerComp, _) -> + // 'let! pat = expr in expr' + // --> build.Bind(e1, (fun _argN -> match _argN with pat -> expr)) + // or + // --> build.BindReturn(e1, (fun _argN -> match _argN with pat -> expr-without-return)) + | SynExpr.LetOrUseBang (spBind, false, isFromSource, pat, rhsExpr, [], innerComp, _) -> let bindRange = match spBind with SequencePointAtBinding m -> m | _ -> rhsExpr.Range if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), bindRange)) - let innerRange = innerComp.Range - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) // Add the variables to the query variable space, on demand let varSpace = @@ -8412,28 +8420,135 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (pat, None) vspecs, envinner) - let rhsExpr = if isFromSource then mkSourceExpr rhsExpr else rhsExpr - Some (trans true q varSpace innerComp (fun holeFill -> - let consumeExpr = SynExpr.MatchLambda (false, pat.Range, [Clause(pat, None, holeFill, innerRange, SequencePointAtTarget)], spBind, innerRange) - translatedCtxt (mkSynCall "Bind" bindRange [rhsExpr; consumeExpr]))) + let rhsExpr = mkSourceExprConditional isFromSource rhsExpr + Some (transBind q varSpace bindRange "Bind" [rhsExpr] pat spBind innerComp translatedCtxt) - // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) - | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.Named (SynPat.Wild _, id, false, _, _) as pat), rhsExpr, innerComp, _) - | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.LongIdent (LongIdentWithDots([id], _), _, _, _, _, _) as pat), rhsExpr, innerComp, _) -> + // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) + | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.Named (SynPat.Wild _, id, false, _, _) as pat) , rhsExpr, [], innerComp, _) + | SynExpr.LetOrUseBang (spBind, true, isFromSource, (SynPat.LongIdent (longDotId=LongIdentWithDots([id], _)) as pat), rhsExpr, [], innerComp, _) -> let bindRange = match spBind with SequencePointAtBinding m -> m | _ -> rhsExpr.Range if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), bindRange)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Using" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), bindRange)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad "Bind" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), bindRange)) + let consumeExpr = SynExpr.MatchLambda(false, bindRange, [Clause(pat, None, transNoQueryOps innerComp, innerComp.Range, SequencePointAtTarget)], spBind, bindRange) let consumeExpr = mkSynCall "Using" bindRange [SynExpr.Ident(id); consumeExpr ] let consumeExpr = SynExpr.MatchLambda(false, bindRange, [Clause(pat, None, consumeExpr, id.idRange, SequencePointAtTarget)], spBind, bindRange) - let rhsExpr = if isFromSource then mkSourceExpr rhsExpr else rhsExpr + let rhsExpr = mkSourceExprConditional isFromSource rhsExpr + // TODO: consider allowing translation to BindReturn Some(translatedCtxt (mkSynCall "Bind" bindRange [rhsExpr; consumeExpr])) - // 'use! pat = e1 in e2' where 'pat' is not a simple name --> error - | SynExpr.LetOrUseBang (_spBind, true, _isFromSource, pat, _rhsExpr, _innerComp, _) -> - error(Error(FSComp.SR.tcInvalidUseBangBinding(), pat.Range)) + // 'use! pat = e1 ... in e2' where 'pat' is not a simple name --> error + | SynExpr.LetOrUseBang (_spBind, true, _isFromSource, pat, _rhsExpr, andBangs, _innerComp, _) -> + if isNil andBangs then + error(Error(FSComp.SR.tcInvalidUseBangBinding(), pat.Range)) + else + error(Error(FSComp.SR.tcInvalidUseBangBindingNoAndBangs(), comp.Range)) + + // 'let! pat1 = expr1 and! pat2 = expr2 in ...' --> + // build.BindN(expr1, expr2, ...) + // or + // build.BindNReturn(expr1, expr2, ...) + // or + // build.Bind(build.MergeSources(expr1, expr2), ...) + | SynExpr.LetOrUseBang(letSpBind, false, isFromSource, letPat, letRhsExpr, andBangBindings, innerComp, letBindRange) -> + if cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang then + if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), letBindRange)) + let bindRange = match letSpBind with SequencePointAtBinding m -> m | _ -> letRhsExpr.Range + let sources = (letRhsExpr :: [for (_, _, _, _, andExpr, _) in andBangBindings -> andExpr ]) |> List.map (mkSourceExprConditional isFromSource) + let pats = letPat :: [for (_, _, _, andPat, _, _) in andBangBindings -> andPat ] + let sourcesRange = sources |> List.map (fun e -> e.Range) |> List.reduce unionRanges + + let numSources = sources.Length + let bindReturnNName = "Bind"+string numSources+"Return" + let bindNName = "Bind"+string numSources + + // Check if this is a Bind2Return etc. + let hasBindReturnN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindReturnNName builderTy)) + if hasBindReturnN && Option.isSome (convertSimpleReturnToExpr varSpace innerComp) then + let consumePat = SynPat.Tuple(false, pats, letPat.Range) + Some (transBind q varSpace bindRange bindNName sources consumePat letSpBind innerComp translatedCtxt) + + else + + // Check if this is a Bind2 etc. + let hasBindN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindNName builderTy)) + if hasBindN then + let consumePat = SynPat.Tuple(false, pats, letPat.Range) + + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (consumePat, None) + vspecs, envinner) + + Some (transBind q varSpace bindRange bindNName sources consumePat letSpBind innerComp translatedCtxt) + else + + // Look for the maximum supported MergeSources, MergeSources3, ... + let mkMergeSourcesName n = if n = 2 then "MergeSources" else "MergeSources"+(string n) + + let maxMergeSources = + let rec loop (n: int) = + let mergeSourcesName = mkMergeSourcesName n + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + (n-1) + else + loop (n+1) + loop 2 + + if maxMergeSources = 1 then error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let rec mergeSources (sourcesAndPats: (SynExpr * SynPat) list) = + let numSourcesAndPats = sourcesAndPats.Length + assert (numSourcesAndPats <> 0) + if numSourcesAndPats = 1 then + sourcesAndPats.[0] + + elif numSourcesAndPats <= maxMergeSources then + + // Call MergeSources2(e1, e2), MergeSources3(e1, e2, e3) etc + let mergeSourcesName = mkMergeSourcesName numSourcesAndPats + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let source = mkSynCall mergeSourcesName sourcesRange (List.map fst sourcesAndPats) + let pat = SynPat.Tuple(false, List.map snd sourcesAndPats, letPat.Range) + source, pat + + else + + // Call MergeSourcesMax(e1, e2, e3, e4, (...)) + let nowSourcesAndPats, laterSourcesAndPats = List.splitAt (maxMergeSources - 1) sourcesAndPats + let mergeSourcesName = mkMergeSourcesName maxMergeSources + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad mergeSourcesName builderTy) then + error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), bindRange)) + + let laterSource, laterPat = mergeSources laterSourcesAndPats + let source = mkSynCall mergeSourcesName sourcesRange (List.map fst nowSourcesAndPats @ [laterSource]) + let pat = SynPat.Tuple(false, List.map snd nowSourcesAndPats @ [laterPat], letPat.Range) + source, pat + + let mergedSources, consumePat = mergeSources (List.zip sources pats) + + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (consumePat, None) + vspecs, envinner) + + // Build the 'Bind' call + Some (transBind q varSpace bindRange "Bind" [mergedSources] consumePat letSpBind innerComp translatedCtxt) + else + error(Error(FSComp.SR.tcAndBangNotSupported(), comp.Range)) | SynExpr.Match (spMatch, expr, clauses, m) -> let mMatch = match spMatch with SequencePointAtBinding mMatch -> mMatch | _ -> m @@ -8445,9 +8560,14 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.MatchBang (spMatch, expr, clauses, m) -> let mMatch = match spMatch with SequencePointAtBinding mMatch -> mMatch | _ -> m if isQuery then error(Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery(), mMatch)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mMatch ad "Bind" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), mMatch)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mMatch ad "Bind" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), mMatch)) + let clauses = clauses |> List.map (fun (Clause(pat, cond, innerComp, patm, sp)) -> Clause(pat, cond, transNoQueryOps innerComp, patm, sp)) let consumeExpr = SynExpr.MatchLambda (false, mMatch, clauses, spMatch, mMatch) + + // TODO: consider allowing translation to BindReturn Some(translatedCtxt (mkSynCall "Bind" mMatch [expr; consumeExpr])) | SynExpr.TryWith (innerComp, _mTryToWith, clauses, _mWithToLast, mTryToLast, spTry, _spWith) -> @@ -8456,14 +8576,19 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isQuery then error(Error(FSComp.SR.tcTryWithMayNotBeUsedInQueries(), mTry)) let clauses = clauses |> List.map (fun (Clause(pat, cond, clauseComp, patm, sp)) -> Clause(pat, cond, transNoQueryOps clauseComp, patm, sp)) let consumeExpr = SynExpr.MatchLambda(true, mTryToLast, clauses, NoSequencePointAtStickyBinding, mTryToLast) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("TryWith"), mTry)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("TryWith"), mTry)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + Some(translatedCtxt (mkSynCall "TryWith" mTry [mkSynCall "Delay" mTry [mkSynDelay2 (transNoQueryOps innerComp)]; consumeExpr])) | SynExpr.YieldOrReturnFrom ((isYield, _), yieldExpr, m) -> let yieldExpr = mkSourceExpr yieldExpr if isYield then - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("YieldFrom"), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod("YieldFrom"), m)) Some (translatedCtxt (mkSynCall "YieldFrom" m [yieldExpr])) else @@ -8477,7 +8602,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder | SynExpr.YieldOrReturn ((isYield, _), yieldExpr, m) -> let methName = (if isYield then "Yield" else "Return") if isQuery && not isYield then error(Error(FSComp.SR.tcReturnMayNotBeUsedInQueries(), m)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod(methName), m)) + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod(methName), m)) Some(translatedCtxt (mkSynCall methName m [yieldExpr])) | _ -> None @@ -8500,8 +8626,8 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Return" builderTy) then SynExpr.ImplicitZero m else - SynExpr.YieldOrReturn((false, true), SynExpr.Const (SynConst.Unit, m), m) - trans true q varSpace (SynExpr.LetOrUseBang(NoSequencePointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, bodyExpr, m)) translatedCtxt + SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m) + trans true q varSpace (SynExpr.LetOrUseBang (NoSequencePointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m)) translatedCtxt // "expr;" in final position is treated as { expr; zero } // Suppress the sequence point on the "zero" @@ -8523,6 +8649,104 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder SynExpr.Sequential(SuppressSequencePointOnStmtOfSequential, true, comp, holeFill, comp.Range) translatedCtxt fillExpr) + and transBind q varSpace bindRange bindName bindArgs (consumePat: SynPat) spBind (innerComp: SynExpr) translatedCtxt = + + let innerRange = innerComp.Range + + let innerCompReturn = + if cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang then + convertSimpleReturnToExpr varSpace innerComp + else None + + match innerCompReturn with + | Some innerExpr when + (let bindName = bindName + "Return" + not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy))) -> + + let bindName = bindName + "Return" + + // Build the `BindReturn` call + let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [Clause(consumePat, None, innerExpr, innerRange, SequencePointAtTarget)], spBind, innerRange) + translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr])) + + | _ -> + + if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy) then + error(Error(FSComp.SR.tcRequireBuilderMethod(bindName), bindRange)) + + // Build the `Bind` call + trans true q varSpace innerComp (fun holeFill -> + let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [Clause(consumePat, None, holeFill, innerRange, SequencePointAtTarget)], spBind, innerRange) + translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr]))) + + and convertSimpleReturnToExpr varSpace innerComp = + match innerComp with + | SynExpr.YieldOrReturn ((false, _), returnExpr, _) -> Some returnExpr + | SynExpr.Match (spMatch, expr, clauses, m) -> + let clauses = + clauses |> List.map (fun (Clause(pat, cond, innerComp2, patm, sp)) -> + match convertSimpleReturnToExpr varSpace innerComp2 with + | None -> None + | Some innerExpr2 -> Some (Clause(pat, cond, innerExpr2, patm, sp))) + if clauses |> List.forall Option.isSome then + Some (SynExpr.Match (spMatch, expr, (clauses |> List.map Option.get), m)) + else + None + + | SynExpr.IfThenElse (guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch) -> + match convertSimpleReturnToExpr varSpace thenComp with + | None -> None + | Some thenExpr -> + match Option.map (convertSimpleReturnToExpr varSpace) elseCompOpt with + | Some None -> None + | elseExprOpt -> + Some (SynExpr.IfThenElse (guardExpr, thenExpr, Option.bind id elseExprOpt, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch) ) + + | SynExpr.LetOrUse (isRec, false, binds, innerComp, m) -> + match convertSimpleReturnToExpr varSpace innerComp with + | None -> None + | Some innerExpr -> Some (SynExpr.LetOrUse (isRec, false, binds, innerExpr, m)) + + | SynExpr.Sequential (sp, true, innerComp1, innerComp2, m) -> + + // Check the first part isn't a computation expression construct + if isSimpleExpr innerComp1 then + // Check the second part is a simple return + match convertSimpleReturnToExpr varSpace innerComp2 with + | None -> None + | Some innerExpr2 -> Some (SynExpr.Sequential (sp, true, innerComp1, innerExpr2, m)) + else + None + + | _ -> None + + /// Check is an expression has no computation expression constructs + and isSimpleExpr comp = + + match comp with + | ForEachThenJoinOrGroupJoinOrZipClause _ -> false + | SynExpr.ForEach _ -> false + | SynExpr.For _ -> false + | SynExpr.While _ -> false + | SynExpr.TryFinally _ -> false + | SynExpr.ImplicitZero _ -> false + | OptionalSequential (JoinOrGroupJoinOrZipClause _, _) -> false + | OptionalSequential (CustomOperationClause _, _) -> false + | SynExpr.Sequential (_, _, innerComp1, innerComp2, _) -> isSimpleExpr innerComp1 && isSimpleExpr innerComp2 + | SynExpr.IfThenElse (_, thenComp, elseCompOpt, _, _, _, _) -> + isSimpleExpr thenComp && (match elseCompOpt with None -> true | Some c -> isSimpleExpr c) + | SynExpr.LetOrUse (_, _, _, innerComp, _) -> isSimpleExpr innerComp + | SynExpr.LetOrUseBang _ -> false + | SynExpr.Match (_, _, clauses, _) -> + clauses |> List.forall (fun (Clause(_, _, innerComp, _, _)) -> isSimpleExpr innerComp) + | SynExpr.MatchBang _ -> false + | SynExpr.TryWith (innerComp, _, clauses, _, _, _, _) -> + isSimpleExpr innerComp && + clauses |> List.forall (fun (Clause(_, _, clauseComp, _, _)) -> isSimpleExpr clauseComp) + | SynExpr.YieldOrReturnFrom _ -> false + | SynExpr.YieldOrReturn _ -> false + | _ -> true + let basicSynExpr = trans true (hasCustomOperations ()) (LazyWithContext.NotLazy ([], env)) comp (fun holeFill -> holeFill) @@ -8546,7 +8770,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynSimplePatVar false (mkSynId mBuilderVal builderValName)], mBuilderVal), runExpr, mBuilderVal) let env = - match comp with + match comp with | SynExpr.YieldOrReturn ((true, _), _, _) -> { env with eContextInfo = ContextInfo.YieldInComputationExpression } | SynExpr.YieldOrReturn ((_, true), _, _) -> { env with eContextInfo = ContextInfo.ReturnInComputationExpression } | _ -> env @@ -8693,7 +8917,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m = //SEQPOINT NEEDED - we must consume spBind on this path Some(mkSeqUsing cenv env wholeExprMark bindPatTy genOuterTy inputExpr consumeExpr, tpenv) - | SynExpr.LetOrUseBang (_, _, _, _, _, _, m) -> + | SynExpr.LetOrUseBang (range=m) -> error(Error(FSComp.SR.tcUseForInSequenceExpression(), m)) | SynExpr.Match (spMatch, expr, clauses, _) -> @@ -8711,7 +8935,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m = let matchv, matchExpr = CompilePatternForMatchClauses cenv env inputExprMark inputExprMark true ThrowIncompleteMatchException (Some inputExpr) inputExprTy genOuterTy tclauses Some(mkLet spMatch inputExprMark matchv inputExpr matchExpr, tpenv) - | SynExpr.TryWith (_, mTryToWith, _, _, _, _, _) -> + | SynExpr.TryWith (tryRange=mTryToWith) -> error(Error(FSComp.SR.tcTryIllegalInSequenceExpression(), mTryToWith)) | SynExpr.YieldOrReturnFrom ((isYield, _), yieldExpr, m) -> @@ -10587,7 +10811,7 @@ and TcAndPatternCompileMatchClauses mExpr matchm actionOnFailure cenv inputExprO and TcMatchPattern cenv inputTy env tpenv (pat: SynPat, optWhenExpr) = let m = pat.Range let patf', (tpenv, names, _) = TcPat WarnOnUpperCase cenv env None (ValInline.Optional, permitInferTypars, noArgOrRetAttribs, false, None, false) (tpenv, Map.empty, Set.empty) inputTy pat - let envinner, values, vspecMap = MakeAndPublishSimpleVals cenv env m names false + let envinner, values, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names let optWhenExpr', tpenv = match optWhenExpr with | Some whenExpr -> @@ -12670,7 +12894,7 @@ module IncrClassChecking = let ctorArgNames, (_, names, _) = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv (SynSimplePats.SimplePats (spats, m)) // Create the values with the given names - let _, vspecs = MakeSimpleVals cenv env names + let _, vspecs = MakeAndPublishSimpleVals cenv env names if tcref.IsStructOrEnumTycon && isNil spats then errorR (ParameterlessStructCtor(tcref.Range)) diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index 524f73965e..40e90b679a 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -764,12 +764,13 @@ and /// Computation expressions only | YieldOrReturnFrom of (bool * bool) * expr: SynExpr * range: range - /// SynExpr.LetOrUseBang (spBind, isUse, isFromSource, pat, rhsExpr, bodyExpr, mWholeExpr). + /// SynExpr.LetOrUseAndBang (spBind, isUse, isFromSource, pat, rhsExpr, mLetBangExpr, [(andBangSpBind, andBangIsUse, andBangIsFromSource, andBangPat, andBangRhsExpr, mAndBangExpr)], bodyExpr). /// /// F# syntax: let! pat = expr in expr /// F# syntax: use! pat = expr in expr + /// F# syntax: let! pat = expr and! ... and! ... and! pat = expr in expr /// Computation expressions only - | LetOrUseBang of bindSeqPoint: SequencePointInfoForBinding * isUse: bool * isFromSource: bool * SynPat * SynExpr * SynExpr * range: range + | LetOrUseBang of bindSeqPoint: SequencePointInfoForBinding * isUse: bool * isFromSource: bool * SynPat * rhs: SynExpr * andBangs:(SequencePointInfoForBinding * bool * bool * SynPat * SynExpr * range) list * body:SynExpr * range: range /// F# syntax: match! expr with pat1 -> expr | ... | patN -> exprN | MatchBang of matchSeqPoint: SequencePointInfoForBinding * expr: SynExpr * clauses: SynMatchClause list * range: range (* bool indicates if this is an exception match in a computation expression which throws unmatched exceptions *) @@ -2475,6 +2476,6 @@ let rec synExprContainsError inpExpr = | SynExpr.MatchBang (_, e, cl, _) -> walkExpr e || walkMatchClauses cl - | SynExpr.LetOrUseBang (_, _, _, _, e1, e2, _) -> - walkExpr e1 || walkExpr e2 + | SynExpr.LetOrUseBang (rhs=e1;body=e2;andBangs=es) -> + walkExpr e1 || walkExprs [ for (_,_,_,_,e,_) in es do yield e ] || walkExpr e2 walkExpr inpExpr diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 901a203b83..5970e1fb8c 100755 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -233,10 +233,12 @@ rule token args skip = parse { YIELD_BANG(false) } | "match!" { MATCH_BANG } + | "and!" + { AND_BANG(false) } | ident '!' { let tok = Keywords.KeywordOrIdentifierToken args lexbuf (lexemeTrimRight lexbuf 1) match tok with - | LET _ -> BINDER (lexemeTrimRight lexbuf 1) + | LET _ -> BINDER (lexemeTrimRight lexbuf 1) | _ -> fail args lexbuf (FSComp.SR.lexIdentEndInMarkReserved("!")) (Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf)) } | ident ('#') { fail args lexbuf (FSComp.SR.lexIdentEndInMarkReserved("#")) (Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf)) } diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index e1d888196b..66ee0bd792 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -189,7 +189,7 @@ let rangeOfLongIdent(lid:LongIdent) = %token CHAR %token DECIMAL %token <(string * string)> BIGNUM -%token LET YIELD YIELD_BANG +%token LET YIELD YIELD_BANG AND_BANG %token LESS GREATER /* here the bool indicates if the tokens are part of a type application or type parameter declaration, e.g. C, detected by the lex filter */ %token PERCENT_OP BINDER %token LQUOTE RQUOTE RQUOTE_DOT @@ -218,6 +218,7 @@ let rangeOfLongIdent(lid:LongIdent) = /* for offside rule */ %token OLET /* LexFilter #light converts 'LET' tokens to 'OLET' when starting (CtxtLetDecl(blockLet=true)) */ %token OBINDER /* LexFilter #light converts 'BINDER' tokens to 'OBINDER' when starting (CtxtLetDecl(blockLet=true)) */ +%token OAND_BANG /* LexFilter #light converts 'AND_BANG' tokens to 'OAND_BANG' when starting (CtxtLetDecl(blockLet=true)) */ %token ODO /* LexFilter #light converts 'DO' tokens to 'ODO' */ %token ODO_BANG /* LexFilter #light converts 'DO_BANG' tokens to 'ODO_BANG' */ %token OTHEN /* LexFilter #light converts 'THEN' tokens to 'OTHEN' */ @@ -453,7 +454,8 @@ let rangeOfLongIdent(lid:LongIdent) = %nonassoc paren_pat_colon %nonassoc paren_pat_attribs %left OR BAR_BAR JOIN_IN -%left AND /* check */ +%left AND +%left AND_BANG %left AMP AMP_AMP %nonassoc pat_conj %nonassoc expr_not @@ -3060,6 +3062,20 @@ recover: | error { debugPrint("recovering via error"); true } | EOF { debugPrint("recovering via EOF"); false } +morebinders: + | AND_BANG headBindingPattern EQUALS typedSeqExprBlock IN morebinders %prec expr_let + { let spBind = SequencePointAtBinding(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) + let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) + (spBind,$1,true,$2,$4,m) :: $6 } + + | OAND_BANG headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP morebinders %prec expr_let + { $5 "and!" (rhs parseState 1) // report unterminated error + let spBind = SequencePointAtBinding(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) + let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) + (spBind,$1,true,$2,$4,m) :: $7 } + + | %prec prec_no_more_attr_bindings + { [] } declExpr: | defnBindings IN typedSeqExpr %prec expr_let @@ -3353,27 +3369,35 @@ declExpr: | YIELD_BANG declExpr { SynExpr.YieldOrReturnFrom (($1,not $1), $2, unionRanges (rhs parseState 1) $2.Range) } - | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let + | YIELD recover + { let mYieldAll = rhs parseState 1 + SynExpr.YieldOrReturn (($1, not $1), arbExpr("yield", mYieldAll), mYieldAll) } + + | YIELD_BANG recover + { let mYieldAll = rhs parseState 1 + SynExpr.YieldOrReturnFrom (($1, not $1), arbExpr("yield!", mYieldAll), mYieldAll) } + + | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP morebinders typedSeqExprBlock %prec expr_let { let spBind = SequencePointAtBinding(rhs2 parseState 1 5) - let m = unionRanges (rhs parseState 1) $7.Range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4,$7,m) } + let m = unionRanges (rhs parseState 1) $8.Range + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } - | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP typedSeqExprBlock %prec expr_let + | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP morebinders typedSeqExprBlock %prec expr_let { $5 (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) - let m = unionRanges (rhs parseState 1) $7.Range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4,$7,m) } + let m = unionRanges (rhs parseState 1) $8.Range + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // error recovery that allows intellisense when writing incomplete computation expressions let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) let m = $4.Range.EndRange // zero-width range - SynExpr.LetOrUseBang (spBind,($1 = "use"),true,$2,$4, SynExpr.ImplicitZero m, mAll) } + SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll) } | DO_BANG typedSeqExpr IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let { let spBind = NoSequencePointAtDoBinding - SynExpr.LetOrUseBang (spBind,false,true,SynPat.Const(SynConst.Unit,$2.Range),$2,$5, unionRanges (rhs parseState 1) $5.Range) } + SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit,$2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range) } | ODO_BANG typedSeqExprBlock hardwhiteDefnBindingsTerminator %prec expr_let { SynExpr.DoBang ($2, unionRanges (rhs parseState 1) $2.Range) } diff --git a/src/fsharp/service/ServiceAssemblyContent.fs b/src/fsharp/service/ServiceAssemblyContent.fs index e495fa0428..b826728b47 100644 --- a/src/fsharp/service/ServiceAssemblyContent.fs +++ b/src/fsharp/service/ServiceAssemblyContent.fs @@ -703,9 +703,13 @@ module ParsedInput = addLongIdentWithDots ident List.iter walkExpr [e1; e2; e3] | SynExpr.JoinIn (e1, _, e2, _) -> List.iter walkExpr [e1; e2] - | SynExpr.LetOrUseBang (_, _, _, pat, e1, e2, _) -> + | SynExpr.LetOrUseBang (_, _, _, pat, e1, es, e2, _) -> walkPat pat - List.iter walkExpr [e1; e2] + walkExpr e1 + for (_,_,_,patAndBang,eAndBang,_) in es do + walkPat patAndBang + walkExpr eAndBang + walkExpr e2 | SynExpr.TraitCall (ts, sign, e, _) -> List.iter walkTypar ts walkMemberSig sign diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index dfaa9a537a..e5461138bf 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -896,8 +896,14 @@ module InterfaceStubGenerator = | SynExpr.DoBang (synExpr, _range) -> walkExpr synExpr - | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, _synPat, synExpr1, synExpr2, _range) -> - List.tryPick walkExpr [synExpr1; synExpr2] + | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, _synPat, synExpr1, synExprAndBangs, synExpr2, _range) -> + [ + yield synExpr1 + for (_,_,_,_,eAndBang,_) in synExprAndBangs do + yield eAndBang + yield synExpr2 + ] + |> List.tryPick walkExpr | SynExpr.LibraryOnlyILAssembly _ | SynExpr.LibraryOnlyStaticOptimization _ diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs old mode 100644 new mode 100755 index 4a5147bbb6..c7cddd48b1 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -261,14 +261,14 @@ module internal TokenClassifications = | MEMBER | STATIC | NAMESPACE | OASSERT | OLAZY | ODECLEND | OBLOCKSEP | OEND | OBLOCKBEGIN | ORIGHT_BLOCK_END | OBLOCKEND | OBLOCKEND_COMING_SOON | OBLOCKEND_IS_HERE | OTHEN | OELSE | OLET(_) - | OBINDER _ | BINDER _ | ODO | OWITH | OFUNCTION | OFUN | ORESET | ODUMMY _ | DO_BANG + | OBINDER _ | OAND_BANG _ | BINDER _ | ODO | OWITH | OFUNCTION | OFUN | ORESET | ODUMMY _ | DO_BANG | ODO_BANG | YIELD _ | YIELD_BANG _ | OINTERFACE_MEMBER | ELIF | RARROW | LARROW | SIG | STRUCT | UPCAST | DOWNCAST | NULL | RESERVED | MODULE | AND | AS | ASSERT | ASR | DOWNTO | EXCEPTION | FALSE | FOR | FUN | FUNCTION | FINALLY | LAZY | MATCH | MATCH_BANG | MUTABLE | NEW | OF | OPEN | OR | VOID | EXTERN | INTERFACE | REC | TO | TRUE | TRY | TYPE | VAL | INLINE | WHEN | WHILE | WITH - | IF | THEN | ELSE | DO | DONE | LET(_) | IN (*| NAMESPACE*) | CONST + | IF | THEN | ELSE | DO | DONE | LET _ | AND_BANG _ | IN | CONST | HIGH_PRECEDENCE_PAREN_APP | FIXED | HIGH_PRECEDENCE_BRACK_APP | TYPE_COMING_SOON | TYPE_IS_HERE | MODULE_COMING_SOON | MODULE_IS_HERE -> diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index eeab436524..a1c42f7fa7 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -473,10 +473,16 @@ module public AstTraversal = | SynExpr.ImplicitZero (_range) -> None | SynExpr.YieldOrReturn (_, synExpr, _range) -> traverseSynExpr synExpr | SynExpr.YieldOrReturnFrom (_, synExpr, _range) -> traverseSynExpr synExpr - | SynExpr.LetOrUseBang (_sequencePointInfoForBinding, _, _, synPat, synExpr, synExpr2, _range) -> - [dive synPat synPat.Range traversePat - dive synExpr synExpr.Range traverseSynExpr - dive synExpr2 synExpr2.Range traverseSynExpr] + | SynExpr.LetOrUseBang(_sequencePointInfoForBinding, _, _, synPat, synExpr, andBangSynExprs, synExpr2, _range) -> + [ + yield dive synPat synPat.Range traversePat + yield dive synExpr synExpr.Range traverseSynExpr + yield! + [ for (_,_,_,andBangSynPat,andBangSynExpr,_) in andBangSynExprs do + yield (dive andBangSynPat andBangSynPat.Range traversePat) + yield (dive andBangSynExpr andBangSynExpr.Range traverseSynExpr)] + yield dive synExpr2 synExpr2.Range traverseSynExpr + ] |> pick expr | SynExpr.MatchBang (_sequencePointInfoForBinding, synExpr, synMatchClauseList, _range) -> [yield dive synExpr synExpr.Range traverseSynExpr diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index 56f2312da4..8df0fedbb8 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -245,14 +245,21 @@ module Structure = | SynExpr.DoBang (e, r) -> rcheck Scope.Do Collapse.Below r <| Range.modStart 3 r parseExpr e - | SynExpr.LetOrUseBang (_, _, _, pat, e1, e2, _) -> - // for `let!` or `use!` the pattern begins at the end of the keyword so that - // this scope can be used without adjustment if there is no `=` on the same line - // if there is an `=` the range will be adjusted during the tooltip creation - let r = Range.endToEnd pat.Range e1.Range - rcheck Scope.LetOrUseBang Collapse.Below r r - parseExpr e1 - parseExpr e2 + | SynExpr.LetOrUseBang (_, _, _, pat, eLet, es, eBody, _) -> + [ + yield eLet + yield! [ for (_,_,_,_,eAndBang,_) in es do yield eAndBang ] + ] + |> List.iter (fun e -> + // for `let!`, `use!` or `and!` the pattern begins at the end of the + // keyword so that this scope can be used without adjustment if there is no `=` + // on the same line. If there is an `=` the range will be adjusted during the + // tooltip creation + let r = Range.endToEnd pat.Range e.Range + rcheck Scope.LetOrUseBang Collapse.Below r r + parseExpr e + ) + parseExpr eBody | SynExpr.For (_, _, _, _, _, e, r) | SynExpr.ForEach (_, _, _, _, _, e, r) -> rcheck Scope.For Collapse.Below r r diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index f142279474..399b3e8791 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -322,9 +322,12 @@ type FSharpParseFileResults(errors: FSharpErrorInfo[], input: Ast.ParsedInput op yield! walkExpr false e2 yield! walkExpr false e3 - | SynExpr.LetOrUseBang (spBind, _, _, _, e1, e2, _) -> + | SynExpr.LetOrUseBang (spBind, _, _, _, e1, es, e2, _) -> yield! walkBindSeqPt spBind yield! walkExpr true e1 + for (andBangSpBind,_,_,_,eAndBang,_) in es do + yield! walkBindSeqPt andBangSpBind + yield! walkExpr true eAndBang yield! walkExpr true e2 | SynExpr.MatchBang (spBind, e, cl, _) -> @@ -880,7 +883,14 @@ module UntypedParseImpl = | SynExpr.Match (_, e, synMatchClauseList, _) | SynExpr.MatchBang (_, e, synMatchClauseList, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkClause synMatchClauseList) - | SynExpr.LetOrUseBang (_, _, _, _, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] + | SynExpr.LetOrUseBang(_, _, _, _, e1, es, e2, _) -> + [ + yield e1 + for (_,_,_,_,eAndBang,_) in es do + yield eAndBang + yield e2 + ] + |> List.tryPick (walkExprWithKind parentKind) | SynExpr.DoBang (e, _) -> walkExprWithKind parentKind e | SynExpr.TraitCall (ts, sign, e, _) -> List.tryPick walkTypar ts diff --git a/tests/fsharp/Compiler/Language/UIntTests.fs b/tests/fsharp/Compiler/Language/UIntTests.fs deleted file mode 100644 index c317f96e02..0000000000 --- a/tests/fsharp/Compiler/Language/UIntTests.fs +++ /dev/null @@ -1,10 +0,0 @@ -namespace FSharp.Compiler.UnitTests - -open NUnit.Framework - -[] -module UIntTests = - let ``uint type abbreviation works`` () = - let src = "let x = uint 12" - let expectedErrors = [||] - CompilerAssert.TypeCheckWithErrors src expectedErrors \ No newline at end of file diff --git a/tests/fsharp/perf/computation-expressions/dependency_graph.fsx b/tests/fsharp/perf/computation-expressions/dependency_graph.fsx new file mode 100644 index 0000000000..348aab0349 --- /dev/null +++ b/tests/fsharp/perf/computation-expressions/dependency_graph.fsx @@ -0,0 +1,192 @@ + +let mutable nodes = 0 +let mutable recalcs = 0 + +[] +type Node(dirty) = + do nodes <- nodes + 1 + + let dependees = ResizeArray>() + let mutable dirty = dirty + + member _.Dirty with get() = dirty and set v = dirty <- v + + member _.Dependees = + dependees.ToArray() + |> Array.choose (fun c -> match c.TryGetTarget() with true, tg -> Some tg | _ -> None) + + member _.AddDependee(c) = + dependees.Add(System.WeakReference<_>(c)) + + member _.InputChanged() = + for c in dependees do + match c.TryGetTarget() with + | true, tg -> tg.SetDirty() + | _ -> () + + member n.SetDirty() = + if not dirty then + dirty <- true + n.InputChanged() + + +[] +type Node<'T>(dirty) = + inherit Node(dirty) + abstract Value : 'T + +/// A node that recomputes if any if its inputs change +type RecalcNode<'T>(dirty, initial, f: unit -> 'T) = + inherit Node<'T>(dirty) + + let mutable cachedValue = initial + + new (f) = new RecalcNode<'T>(true, Unchecked.defaultof<_>, f) + + new (initial, f) = new RecalcNode<'T>(false, initial, f) + + override n.Value = + if n.Dirty then + recalcs <- recalcs + 1 + cachedValue <- f() + n.Dirty <- false + cachedValue + + override _.ToString() = sprintf "(latest %A)" cachedValue + +/// A node that never recomputes +type ConstantNode<'T>(x: 'T) = + inherit Node<'T>(false) + + override _.Value = x + + override _.ToString() = sprintf "(latest %A)" x + +type InputNode<'T>(v: 'T) = + inherit Node<'T>(false) + let mutable currentValue = v + override _.Value = currentValue + + member node.SetValue v = + currentValue <- v + node.InputChanged() + +type NodeBuilder() = + + member _.Bind(x: Node<'T1>, f: 'T1 -> Node<'T2>) : Node<'T2> = + let rec n = + RecalcNode<'T2>(fun () -> + let n2 = f x.Value + n2.AddDependee(n) + n2.Value) + x.AddDependee(n) + n :> Node<_> + + member _.BindReturn(x: Node<'T1>, f: 'T1 -> 'T2) : Node<'T2> = + let n = RecalcNode<'T2>(fun () -> f x.Value) + x.AddDependee(n) + n :> Node<_> + + member _.Bind2(x1: Node<'T1>, x2: Node<'T2>, f: 'T1 * 'T2 -> Node<'T3>) : Node<'T3> = + let rec n = + RecalcNode<'T3>(fun () -> + let n2 = f (x1.Value, x2.Value) + n2.AddDependee(n) + n2.Value) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Bind2Return(x1: Node<'T1>, x2: Node<'T2>, f: 'T1 * 'T2 -> 'T3) : Node<'T3> = + let n = RecalcNode<'T3>(fun () -> f (x1.Value, x2.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Bind3(x1: Node<'T1>, x2: Node<'T2>, x3: Node<'T3>, f: 'T1 * 'T2 * 'T3 -> Node<'T4>) : Node<'T4> = + let rec n = + RecalcNode<'T4>(fun () -> + let n2 = f (x1.Value, x2.Value, x3.Value) + n2.AddDependee(n) + n2.Value) + x1.AddDependee(n) + x2.AddDependee(n) + x3.AddDependee(n) + n :> Node<_> + + member _.Bind3Return(x1: Node<'T1>, x2: Node<'T2>, x3: Node<'T3>, f: 'T1 * 'T2 * 'T3 -> 'T4) : Node<'T4> = + let n = RecalcNode<'T4>(fun () -> f (x1.Value, x2.Value, x3.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + x3.AddDependee(n) + n :> Node<_> + + member _.MergeSources(x1: Node<'T1>, x2: Node<'T2>) : Node<'T1 * 'T2> = + let n = RecalcNode<_>(fun () -> (x1.Value, x2.Value)) + x1.AddDependee(n) + x2.AddDependee(n) + n :> Node<_> + + member _.Return(x: 'T) : Node<'T> = + ConstantNode<'T>(x) :> Node<_> + +let node = NodeBuilder() +let input v = InputNode(v) + +let inp1 = input 3 +let inp2 = input 7 +let inp3 = input 0 + +let test1() = + node { + let! v1 = inp1 + and! v2 = inp2 + and! v3 = inp3 + return v1 + v2 + v3 + } + //let n1 = node.Bind3Return(inp1.Node, inp2.Node, inp3.Node, (fun (v1, v2, v3) -> v1 + v2 + v3)) + +let test2() = + node { + let! v1 = inp1 + let! v2 = inp2 + let! v3 = inp3 + return v1 + v2 + v3 + } + +let test msg f = + recalcs <- 0 + nodes <- 0 + + let (n: Node) = f() + + let v1 = n.Value // now 10 + + recalcs <- 0 + + for i in 1 .. 1000 do + inp1.SetValue 4 + let v2 = n.Value // now 11 + + inp2.SetValue 10 + let v3 = n.Value // now 14 + () + + printfn "inp1.Dependees.Length = %d" inp1.Dependees.Length + printfn "inp2.Dependees.Length = %d" inp2.Dependees.Length + printfn "total recalcs %s = %d" msg recalcs + printfn "total nodes %s = %d" msg nodes + printfn "----" + +test "using and!" test1 +test "using let!" test2 + +//inp1.Dependees.Length = 1 +//inp2.Dependees.Length = 1 +//total recalcs using and! = 2000 +//total nodes using and! = 1 +//---- +//inp1.Dependees.Length = 1 +//inp2.Dependees.Length = 2000 +//total recalcs using let! = 6000 +//total nodes using let! = 4003 \ No newline at end of file From 78f210ef561f64a2e0694727e0a34192fadbed12 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 27 Jan 2020 19:53:47 -0800 Subject: [PATCH 082/101] Typos -- fix a couple of types in the last pm PR (#8358) * Typos * references greater than 0 --- .../FSharp.DependencyManager.Utilities.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index fdbb075add..fa1428b042 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -242,15 +242,15 @@ $(PACKAGEREFERENCES) <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> - <__ConflictsList Include="(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> + <__ConflictsList Include="%(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> - <__Conflicts>@(__ConflictsList, ';') + <__Conflicts>@(__ConflictsList, ';'); $([System.String]::Copy('%(Identity)').Replace('\', '/')) $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) From 43d9b7bf58cf8f73a9212b7fe1676645a533eac9 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 28 Jan 2020 07:39:18 +0100 Subject: [PATCH 083/101] tryDestAppTy should be called tryTcrefOfAppTy (#8264) --- src/fsharp/ConstraintSolver.fs | 10 ++--- src/fsharp/IlxGen.fs | 2 +- src/fsharp/InfoReader.fs | 12 +++--- src/fsharp/NameResolution.fs | 12 +++--- src/fsharp/PatternMatchCompilation.fs | 2 +- src/fsharp/PostInferenceChecks.fs | 8 ++-- src/fsharp/TastOps.fs | 40 +++++++++---------- src/fsharp/TastOps.fsi | 2 +- src/fsharp/TypeChecker.fs | 12 +++--- src/fsharp/service/FSharpCheckerResults.fs | 8 ++-- src/fsharp/service/ServiceDeclarationLists.fs | 2 +- src/fsharp/symbols/SymbolHelpers.fs | 12 +++--- 12 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 92ae10cd75..cce06e7024 100755 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1973,7 +1973,7 @@ and SolveTypeSupportsComparison (csenv: ConstraintSolverEnv) ndeep m2 trace ty = AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsComparison m) | ValueNone -> // Check it isn't ruled out by the user - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_NoComparisonAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportComparison1(NicePrint.minimalStringOfType denv ty), m, m2)) | _ -> @@ -2016,7 +2016,7 @@ and SolveTypeSupportsEquality (csenv: ConstraintSolverEnv) ndeep m2 trace ty = | ValueSome destTypar -> AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsEquality m) | _ -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_NoEqualityAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportEquality1(NicePrint.minimalStringOfType denv ty), m, m2)) | _ -> @@ -2150,13 +2150,13 @@ and SolveTypeRequiresDefaultConstructor (csenv: ConstraintSolverEnv) ndeep m2 tr if GetIntrinsicConstructorInfosOfType csenv.InfoReader m ty |> List.exists (fun x -> x.IsNullary && IsMethInfoAccessible amap m AccessibleFromEverywhere x) then - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when HasFSharpAttribute g g.attrib_AbstractClassAttribute tcref.Attribs -> ErrorD (ConstraintSolverError(FSComp.SR.csGenericConstructRequiresNonAbstract(NicePrint.minimalStringOfType denv origTy), m, m2)) | _ -> CompleteD else - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when tcref.PreEstablishedHasDefaultConstructor || // F# 3.1 feature: records with CLIMutable attribute should satisfy 'default constructor' constraint @@ -2582,7 +2582,7 @@ and ResolveOverloading (calledArg1.CalledArgumentType, calledArg2.CalledArgumentType) ||> compareCond (fun ty1 ty2 -> // Func<_> is always considered better than any other delegate type - match tryDestAppTy csenv.g ty1 with + match tryTcrefOfAppTy csenv.g ty1 with | ValueSome tcref1 when tcref1.DisplayName = "Func" && (match tcref1.PublicPath with Some p -> p.EnclosingPath = [| "System" |] | _ -> false) && diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 412d1a62ac..5d18e0d549 100755 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3950,7 +3950,7 @@ and GenDefaultValue cenv cgbuf eenv (ty, m) = if isRefTy g ty then CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) AI_ldnull else - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when (tyconRefEq g g.system_SByte_tcref tcref || tyconRefEq g g.system_Int16_tcref tcref || tyconRefEq g g.system_Int32_tcref tcref || diff --git a/src/fsharp/InfoReader.fs b/src/fsharp/InfoReader.fs index 1fac7a0f6e..1679f46c92 100644 --- a/src/fsharp/InfoReader.fs +++ b/src/fsharp/InfoReader.fs @@ -78,7 +78,7 @@ let rec GetImmediateIntrinsicMethInfosOfTypeAux (optFilter, ad) g amap m origTy GetImmediateIntrinsicMethInfosOfTypeAux (optFilter, ad) g amap m origTy betterMetadataTy |> List.filter (fun minfo -> not minfo.IsInstance) else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> SelectImmediateMemberVals g optFilter (TrySelectMemberVal g optFilter origTy None) tcref @@ -166,7 +166,7 @@ let rec GetImmediateIntrinsicPropInfosOfTypeAux (optFilter, ad) g amap m origTy let betterMetadataTy = convertToTypeWithMetadataIfPossible g metadataTy GetImmediateIntrinsicPropInfosOfTypeAux (optFilter, ad) g amap m origTy betterMetadataTy else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> let propCollector = new PropertyCollector(g, amap, m, origTy, optFilter, ad) @@ -185,7 +185,7 @@ let rec GetImmediateIntrinsicPropInfosOfType (optFilter, ad) g amap m ty = let IsIndexerType g amap ty = isArray1DTy g ty || isListTy g ty || - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let _, entityTy = generalizeTyconRef tcref let props = GetImmediateIntrinsicPropInfosOfType (None, AccessibleFromSomeFSharpCode) g amap range0 entityTy @@ -265,7 +265,7 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) = /// Get the F#-declared record fields or class 'val' fields of a type let GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter, _ad) _m ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> [] | ValueSome tcref -> // Note;secret fields are not allowed in lookups here, as we're only looking @@ -420,7 +420,7 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) = | flds -> // multiple fields with the same name can come from different classes, // so filter them by the given type name - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> ValueNone | ValueSome tcref -> match flds |> List.filter (fun rfinfo -> tyconRefEq g tcref rfinfo.TyconRef) with @@ -466,7 +466,7 @@ let rec GetIntrinsicConstructorInfosOfTypeAux (infoReader: InfoReader) m origTy let betterMetadataTy = convertToTypeWithMetadataIfPossible g metadataTy GetIntrinsicConstructorInfosOfTypeAux infoReader m origTy betterMetadataTy else - match tryDestAppTy g metadataTy with + match tryTcrefOfAppTy g metadataTy with | ValueNone -> [] | ValueSome tcref -> tcref.MembersOfFSharpTyconByName diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index a63c8e6e13..8f3c6863c1 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -536,7 +536,7 @@ let ExtensionPropInfosOfTypeInScope collectionSettings (infoReader:InfoReader) ( let extMemsFromHierarchy = infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref SelectPropInfosFromExtMembers infoReader ad optFilter ty m extMemInfos @@ -606,7 +606,7 @@ let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSetting infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> let g = infoReader.g - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let extValRefs = nenv.eIndexedExtensionMembers.Find tcref SelectMethInfosFromExtMembers infoReader optFilter ty m extValRefs @@ -2352,7 +2352,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf match lookupKind with | LookupKind.Expr | LookupKind.Pattern -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> for uc in tcref.UnionCasesArray do addToBuffer uc.DisplayName @@ -2365,7 +2365,7 @@ and ResolveLongIdentInNestedTypes (ncenv: NameResolver) nenv lookupKind resInfo tys |> CollectAtMostOneResult (fun ty -> let resInfo = - match tryDestAppTy ncenv.g ty with + match tryTcrefOfAppTy ncenv.g ty with | ValueSome tcref -> resInfo.AddEntity(id.idRange, tcref) | _ -> @@ -3222,7 +3222,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) |> List.map (fun x -> ResolutionInfo.Empty, FieldResolution(x, false)) - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText, m, ty) with | ValueSome (RecdFieldInfo(_, rfref)) -> [ResolutionInfo.Empty, FieldResolution(rfref, false)] @@ -3536,7 +3536,7 @@ let ItemOfTyconRef ncenv m (x: TyconRef) = let ItemOfTy g x = let nm = - match tryDestAppTy g x with + match tryTcrefOfAppTy g x with | ValueSome tcref -> tcref.DisplayName | _ -> "?" Item.Types (nm, [x]) diff --git a/src/fsharp/PatternMatchCompilation.fs b/src/fsharp/PatternMatchCompilation.fs index 6c5cc67e5a..915db6e45c 100755 --- a/src/fsharp/PatternMatchCompilation.fs +++ b/src/fsharp/PatternMatchCompilation.fs @@ -255,7 +255,7 @@ let RefuteDiscrimSet g m path discrims = match c' with | None -> raise CannotRefute | Some c -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref when tcref.IsEnumTycon -> // We must distinguish between F#-defined enums and other .NET enums, as they are represented differently in the TAST let enumValues = diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index aedf7252d9..35bf453212 100755 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -477,7 +477,7 @@ let CheckTypeForAccess (cenv: cenv) env objName valAcc m ty = let visitType ty = // We deliberately only check the fully stripped type for accessibility, // because references to private type abbreviations are permitted - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueNone -> () | ValueSome tcref -> let thisCompPath = compPathOfCcu cenv.viewCcu @@ -493,7 +493,7 @@ let WarnOnWrongTypeForAccess (cenv: cenv) env objName valAcc m ty = let visitType ty = // We deliberately only check the fully stripped type for accessibility, // because references to private type abbreviations are permitted - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueNone -> () | ValueSome tcref -> let thisCompPath = compPathOfCcu cenv.viewCcu @@ -618,7 +618,7 @@ let CheckTypeAux permitByRefLike (cenv: cenv) env m ty onInnerByrefError = let visitAppTy (tcref, tinst) = if isByrefLikeTyconRef cenv.g m tcref then let visitType ty0 = - match tryDestAppTy cenv.g ty0 with + match tryTcrefOfAppTy cenv.g ty0 with | ValueNone -> () | ValueSome tcref2 -> if isByrefTyconRef cenv.g tcref2 then @@ -1024,7 +1024,7 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi when not virt && baseVal.BaseOrThisInfo = BaseVal -> // Disallow calls to abstract base methods on IL types. - match tryDestAppTy g baseVal.Type with + match tryTcrefOfAppTy g baseVal.Type with | ValueSome tcref when tcref.IsILTycon -> try // This is awkward - we have to explicitly re-resolve back to the IL metadata to determine if the method is abstract. diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 9c08ef934f..a2d6a10a88 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -826,7 +826,7 @@ let tcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> let argsOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(_, tinst) -> tinst | _ -> []) let tryDestTyparTy g ty = ty |> stripTyEqns g |> (function TType_var v -> ValueSome v | _ -> ValueNone) let tryDestFunTy g ty = ty |> stripTyEqns g |> (function TType_fun (tyv, tau) -> ValueSome(tyv, tau) | _ -> ValueNone) -let tryDestAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> ValueSome tcref | _ -> ValueNone) +let tryTcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> ValueSome tcref | _ -> ValueNone) let tryDestAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, tys) -> ValueSome (anonInfo, tys) | _ -> ValueNone) let tryAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var v -> ValueSome v | TType_measure unt when isUnitParMeasure g unt -> ValueSome(destUnitParMeasure g unt) | _ -> ValueNone) @@ -1707,17 +1707,17 @@ let isFSharpObjModelRefTy g ty = | TTyconStruct | TTyconEnum -> false let isFSharpClassTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpClassTycon | _ -> false let isFSharpStructTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpStructOrEnumTycon | _ -> false let isFSharpInterfaceTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpInterfaceTycon | _ -> false @@ -1728,7 +1728,7 @@ let isDelegateTy g ty = #endif | ILTypeMetadata (TILObjectReprData(_, _, td)) -> td.IsDelegate | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsFSharpDelegateTycon | _ -> false @@ -1749,12 +1749,12 @@ let isClassTy g ty = | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> isFSharpClassTy g ty let isStructOrEnumTyconTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsStructOrEnumTycon | _ -> false let isStructRecordOrUnionTyconTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tcref.Deref.IsStructRecordOrUnionTycon | _ -> false @@ -1763,7 +1763,7 @@ let isStructTyconRef (tcref: TyconRef) = tycon.IsStructRecordOrUnionTycon || tycon.IsStructOrEnumTycon let isStructTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> isStructTyconRef tcref | _ -> @@ -1794,7 +1794,7 @@ let isRefTy g ty = // [Note: Constructed types and type-parameters are never unmanaged-types. end note] let rec isUnmanagedTy g ty = let ty = stripTyEqnsAndMeasureEqns g ty - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> let isEq tcref2 = tyconRefEq g tcref tcref2 if isEq g.nativeptr_tcr || isEq g.nativeint_tcr || @@ -1826,7 +1826,7 @@ let isInterfaceTycon x = let isInterfaceTyconRef (tcref: TyconRef) = isInterfaceTycon tcref.Deref let isEnumTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tcref.IsEnumTycon @@ -3084,7 +3084,7 @@ let destNativePtrTy g ty = | _ -> failwith "destNativePtrTy: not a native ptr type" let isRefCellTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.refcell_tcr_canon tcref @@ -3109,7 +3109,7 @@ let mkOptionTy (g: TcGlobals) ty = TType_app (g.option_tcr_nice, [ty]) let mkListTy (g: TcGlobals) ty = TType_app (g.list_tcr_nice, [ty]) let isOptionTy (g: TcGlobals) ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.option_tcr_canon tcref @@ -3124,7 +3124,7 @@ let destOptionTy g ty = | ValueNone -> failwith "destOptionTy: not an option type" let isNullableTy (g: TcGlobals) ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.system_Nullable_tcref tcref @@ -3149,7 +3149,7 @@ let (|StripNullableTy|) g ty = | _ -> ty let isLinqExpressionTy g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> tyconRefEq g g.system_LinqExpression_tcref tcref @@ -4877,7 +4877,7 @@ let decideStaticOptimizationConstraint g c = checkTypes a b | TTyconIsStruct a -> let a = normalizeEnumTy g (stripTyEqnsAndMeasureEqns g a) - match tryDestAppTy g a with + match tryTcrefOfAppTy g a with | ValueSome tcref1 -> if tcref1.IsStructOrEnumTycon then StaticOptimizationAnswer.Yes else StaticOptimizationAnswer.No | ValueNone -> StaticOptimizationAnswer.Unknown @@ -5986,7 +5986,7 @@ let isRecdOrStructTyconRefReadOnly g m tcref = isRecdOrStructTyconRefReadOnlyAux g m false tcref let isRecdOrStructTyReadOnlyAux (g: TcGlobals) m isInref ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueNone -> false | ValueSome tcref -> isRecdOrStructTyconRefReadOnlyAux g m isInref tcref @@ -6532,7 +6532,7 @@ let mkMinusOne g m = mkInt g m (-1) let destInt32 = function Expr.Const (Const.Int32 n, _, _) -> Some n | _ -> None let isIDelegateEventType g ty = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> tyconRefEq g g.fslib_IDelegateEvent_tcr tcref | _ -> false @@ -7956,15 +7956,15 @@ let TypeNullNever g ty = let TypeNullIsExtraValue g m ty = if isILReferenceTy g ty || isDelegateTy g ty then // Putting AllowNullLiteralAttribute(false) on an IL or provided type means 'null' can't be used with that type - not (match tryDestAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some false | _ -> false) + not (match tryTcrefOfAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some false | _ -> false) elif TypeNullNever g ty then false else // Putting AllowNullLiteralAttribute(true) on an F# type means 'null' can be used with that type - match tryDestAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true | _ -> false + match tryTcrefOfAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true | _ -> false let TypeNullIsTrueValue g ty = - (match tryDestAppTy g ty with + (match tryTcrefOfAppTy g ty with | ValueSome tcref -> IsUnionTypeWithNullAsTrueValue g tcref.Deref | _ -> false) || (isUnitTy g ty) diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 176f64df72..332d98b35f 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -668,7 +668,7 @@ val destAppTy : TcGlobals -> TType -> TyconRef * TypeInst val tcrefOfAppTy : TcGlobals -> TType -> TyconRef -val tryDestAppTy : TcGlobals -> TType -> ValueOption +val tryTcrefOfAppTy : TcGlobals -> TType -> ValueOption val tryDestTyparTy : TcGlobals -> TType -> ValueOption diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ac71f5bb58..510b0542b7 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1556,7 +1556,7 @@ let MakeAndPublishBaseVal cenv env baseIdOpt ty = let InstanceMembersNeedSafeInitCheck cenv m thisTy = ExistsInEntireHierarchyOfType - (fun ty -> not (isStructTy cenv.g ty) && (match tryDestAppTy cenv.g ty with ValueSome tcref when tcref.HasSelfReferentialConstructor -> true | _ -> false)) + (fun ty -> not (isStructTy cenv.g ty) && (match tryTcrefOfAppTy cenv.g ty with ValueSome tcref when tcref.HasSelfReferentialConstructor -> true | _ -> false)) cenv.g cenv.amap m @@ -5767,7 +5767,7 @@ and TcExprs cenv env m tpenv flexes argTys args = and CheckSuperInit cenv objTy m = // Check the type is not abstract - match tryDestAppTy cenv.g objTy with + match tryTcrefOfAppTy cenv.g objTy with | ValueSome tcref when isAbstractTycon tcref.Deref -> errorR(Error(FSComp.SR.tcAbstractTypeCannotBeInstantiated(), m)) | _ -> () @@ -6285,7 +6285,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg FoldPrimaryHierarchyOfType (fun ty acc -> match acc with | None -> - match tryDestAppTy cenv.g ty with + match tryTcrefOfAppTy cenv.g ty with | ValueSome tcref -> TryFindTyconRefStringAttribute cenv.g mWholeExpr cenv.g.attrib_DefaultMemberAttribute tcref | _ -> @@ -6852,7 +6852,7 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, let mObjTy = synObjTy.Range let objTy, tpenv = TcType cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv synObjTy - match tryDestAppTy cenv.g objTy with + match tryTcrefOfAppTy cenv.g objTy with | ValueNone -> error(Error(FSComp.SR.tcNewMustBeUsedWithNamedType(), mNewExpr)) | ValueSome tcref -> let isRecordTy = tcref.IsRecordTycon @@ -14609,7 +14609,7 @@ let TcMutRecDefns_Phase2 cenv envInitial bindsm scopem mutRecNSInfo (envMutRec: module AddAugmentationDeclarations = let tcaugHasNominalInterface g (tcaug: TyconAugmentation) tcref = tcaug.tcaug_interfaces |> List.exists (fun (x, _, _) -> - match tryDestAppTy g x with + match tryTcrefOfAppTy g x with | ValueSome tcref2 when tyconRefEq g tcref2 tcref -> true | _ -> false) @@ -16286,7 +16286,7 @@ module EstablishTypeDefinitionCores = (tycon, tycon2) :: acc else acc // note: all edges added are (tycon, _) let insertEdgeToType ty acc = - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> insertEdgeToTycon tcref.Deref acc | _ -> diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 76585ba9d5..13517c0375 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -622,7 +622,7 @@ type internal TypeCheckInfo let getType() = match NameResolution.TryToResolveLongIdentAsType ncenv nenv m plid with - | Some x -> tryDestAppTy g x + | Some x -> tryTcrefOfAppTy g x | None -> match lastDotPos |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) with | Some p when lineStr.[p] = '.' -> @@ -630,7 +630,7 @@ type internal TypeCheckInfo | Some colAtEndOfNames -> let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based match TryGetTypeFromNameResolution(line, colAtEndOfNames, residueOpt, resolveOverloads) with - | Some x -> tryDestAppTy g x + | Some x -> tryTcrefOfAppTy g x | _ -> ValueNone | None -> ValueNone | _ -> ValueNone @@ -675,7 +675,7 @@ type internal TypeCheckInfo // it appears we're getting some typings recorded for non-atomic expressions like "f x" when isNil plid -> // lookup based on expression typings successful - Some (items |> List.map (CompletionItem (tryDestAppTy g ty) ValueNone), denv, m) + Some (items |> List.map (CompletionItem (tryTcrefOfAppTy g ty) ValueNone), denv, m) | GetPreciseCompletionListFromExprTypingsResult.NoneBecauseThereWereTypeErrors, _ -> // There was an error, e.g. we have "." and there is an error determining the type of // In this case, we don't want any of the fallback logic, rather, we want to produce zero results. @@ -708,7 +708,7 @@ type internal TypeCheckInfo // Try again with the qualItems | _, _, GetPreciseCompletionListFromExprTypingsResult.Some(FilterRelevantItems getItem exactMatchResidueOpt (items, denv, m), ty) -> - ValueSome(items |> List.map (CompletionItem (tryDestAppTy g ty) ValueNone), denv, m) + ValueSome(items |> List.map (CompletionItem (tryTcrefOfAppTy g ty) ValueNone), denv, m) | _ -> ValueNone diff --git a/src/fsharp/service/ServiceDeclarationLists.fs b/src/fsharp/service/ServiceDeclarationLists.fs index ef9c0b4098..9f106520d0 100644 --- a/src/fsharp/service/ServiceDeclarationLists.fs +++ b/src/fsharp/service/ServiceDeclarationLists.fs @@ -384,7 +384,7 @@ module internal DescriptionListsImpl = /// Find the glyph for the given type representation. let typeToGlyph ty = - match tryDestAppTy denv.g ty with + match tryTcrefOfAppTy denv.g ty with | ValueSome tcref -> tcref.TypeReprInfo |> reprToGlyph | _ -> if isStructTupleTy denv.g ty then FSharpGlyph.Struct diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index 48a44c8abb..39ca96934b 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -719,9 +719,9 @@ module internal SymbolHelpers = // In this case just bail out and assume items are not equal protectAssemblyExploration false (fun () -> let equalHeadTypes(ty1, ty2) = - match tryDestAppTy g ty1 with + match tryTcrefOfAppTy g ty1 with | ValueSome tcref1 -> - match tryDestAppTy g ty2 with + match tryTcrefOfAppTy g ty2 with | ValueSome tcref2 -> tyconRefEq g tcref1 tcref2 | _ -> typeEquiv g ty1 ty2 | _ -> typeEquiv g ty1 ty2 @@ -780,7 +780,7 @@ module internal SymbolHelpers = protectAssemblyExploration 1027 (fun () -> match item with | ItemWhereTypIsPreferred ty -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> hash tcref.LogicalName | _ -> 1010 | Item.ILField(ILFieldInfo(_, fld)) -> @@ -841,13 +841,13 @@ module internal SymbolHelpers = protectAssemblyExploration true (fun () -> match item with | Item.Types(it, [ty]) -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcr1 -> g.suppressed_types |> List.exists (fun supp -> let generalizedSupp = generalizedTyconRef supp // check the display name is precisely the one we're suppressing - match tryDestAppTy g generalizedSupp with + match tryTcrefOfAppTy g generalizedSupp with | ValueSome tcr2 -> it = supp.DisplayName && // check if they are the same logical type (after removing all abbreviations) @@ -895,7 +895,7 @@ module internal SymbolHelpers = | Item.FakeInterfaceCtor ty | Item.DelegateCtor ty | Item.Types(_, ty :: _) -> - match tryDestAppTy g ty with + match tryTcrefOfAppTy g ty with | ValueSome tcref -> bufs (fun os -> NicePrint.outputTyconRef denv os tcref) | _ -> "" | Item.ModuleOrNamespaces((modref :: _) as modrefs) -> From 5bcb3b8b4f998e49a6eb944ad8a8cebfaa0f4d77 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 11:05:13 -0800 Subject: [PATCH 084/101] Feed back (#8365) --- src/fsharp/CompileOps.fs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index ac89ff4c40..58f8d5982e 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5239,18 +5239,12 @@ module ScriptPreprocessClosure = let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else [] yield! resolveDependencyManagerSources filename -#if DEBUG - for (_,subFile) in sources do - printfn "visiting %s - has subsource of %s " filename subFile -#endif for (m, subFile) in sources do if IsScript subFile then for subSource in ClosureSourceOfFilename(subFile, m, tcConfigResult.inputCodePage, false) do yield! loop subSource else yield ClosureFile(subFile, m, None, [], [], []) - - //printfn "yielding source %s" filename yield ClosureFile(filename, m, Some parsedScriptAst, parseDiagnostics, errorLogger.Diagnostics, noWarns) | None -> From 722ff2ff73378d0fdd4649b8c52cd57b02ebc15e Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 11:11:31 -0800 Subject: [PATCH 085/101] ngen dependency manager (#8372) --- .../FSharp.DependencyManager.Utilities.fs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index fa1428b042..c120ec1f97 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -12,11 +12,6 @@ open System.Runtime.Versioning open Internal.Utilities.FSharpEnvironment -#if !(NETSTANDARD || NETCOREAPP) -open Microsoft.Build.Evaluation -open Microsoft.Build.Framework -#endif - [] type DependencyManagerAttribute() = inherit System.Attribute() @@ -86,7 +81,6 @@ module Utilities = let sdks = "Sdks" -#if !(NETSTANDARD || NETCOREAPP) let msbuildExePath = // Find msbuild.exe when invoked from desktop compiler. // 1. Look relative to F# compiler location Normal retail build @@ -120,7 +114,7 @@ module Utilities = | _ -> None roots |> Array.tryFind(fun root -> msbuildPathExists root) |> msbuildOption -#else + let dotnetHostPath = // How to find dotnet.exe --- woe is me; probing rules make me sad. // Algorithm: @@ -156,7 +150,6 @@ module Utilities = Some dotnet else None -#endif let drainStreamToFile (stream: StreamReader) filename = use file = File.OpenWrite(filename) @@ -210,13 +203,13 @@ module Utilities = let workingDir = Path.GetDirectoryName projectPath let succeeded = -#if !(NETSTANDARD || NETCOREAPP) - // The Desktop build uses "msbuild" to build - executeBuild msbuildExePath (arguments "") workingDir -#else - // The coreclr uses "dotnet msbuild" to build - executeBuild dotnetHostPath (arguments "msbuild") workingDir -#endif + if not (isRunningOnCoreClr) then + // The Desktop build uses "msbuild" to build + executeBuild msbuildExePath (arguments "") workingDir + else + // The coreclr uses "dotnet msbuild" to build + executeBuild dotnetHostPath (arguments "msbuild") workingDir + let outputFile = projectPath + ".fsx" let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None succeeded, resultOutFile From 2825f0925574eb4483ff73232b3fe42b6a5b95ef Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2020 19:29:21 +0000 Subject: [PATCH 086/101] Update dependencies from https://github.com/dotnet/arcade build 20200127.3 (#8377) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.20077.3 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c98fbfbee4..32d8984d89 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - d0833c8e5e58cfc507ce3c8da364e55931190263 + 69a67461460d99125742d5c2dd94dad83add84a3 diff --git a/global.json b/global.json index f12de76387..d41648cb6b 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19616.5", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.20077.3", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 6272697e6b13135f7732f54acd530c00b03a6890 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 28 Jan 2020 13:47:22 -0800 Subject: [PATCH 087/101] Do it properly (#8373) --- .../FSharp.DependencyManager.fsproj | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj index 7faf2884f4..e3e4b385a2 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj @@ -4,8 +4,7 @@ Library - net472;netstandard2.0 - netstandard2.0 + netstandard2.0 FSharp.DependencyManager $(NoWarn);45;55;62;75;1204 true @@ -19,16 +18,6 @@ $(BaseOutputPath)\$(Configuration)\$(TargetFramework) - - - - - - - - - - @@ -41,18 +30,6 @@ - - - - - - - - - - - - From c8517d9b7c464946c29c118d1b5e701e9e367f14 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 29 Jan 2020 18:02:38 -0800 Subject: [PATCH 088/101] Remove assembly load notification (#8393) * Remove assembly addednotification from fsievaluation session * Remove AssemblyReferenceAdded notification * Update FSharpScriptTests.fs --- src/fsharp/CompileOps.fs | 10 ++---- src/fsharp/CompileOps.fsi | 2 +- .../FSharpScript.fs | 3 -- src/fsharp/fsi/fsi.fs | 13 +------- src/fsharp/fsi/fsi.fsi | 4 --- .../DependencyManagerInteractiveTests.fs | 13 -------- .../FSharpScriptTests.fs | 31 ++++++------------- 7 files changed, 14 insertions(+), 62 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 5bf304121a..8473b0a880 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4835,10 +4835,10 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse /// Process #r in F# Interactive. /// Adds the reference to the tcImports and add the ccu to the type checking environment. -let RequireDLL (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, m, file, assemblyReferenceAdded: string -> unit) = +let RequireDLL (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, m, file) = let resolutions = CommitOperationResult(tcImports.TryResolveAssemblyReference(ctok, AssemblyReference(m, file, None), ResolveAssemblyReferenceMode.ReportErrors)) let dllinfos, ccuinfos = tcImports.RegisterAndImportReferencedAssemblies(ctok, resolutions) |> Cancellable.runWithoutCancellation - + let asms = ccuinfos |> List.map (function | ResolvedImportedAssembly asm -> asm @@ -4847,11 +4847,7 @@ let RequireDLL (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, m, file, as let g = tcImports.GetTcGlobals() let amap = tcImports.GetImportMap() let buildTcEnv tcEnv asm = - let tcEnv = AddCcuToTcEnv(g, amap, m, tcEnv, thisAssemblyName, asm.FSharpViewOfMetadata, asm.AssemblyAutoOpenAttributes, asm.AssemblyInternalsVisibleToAttributes) - match asm.FSharpViewOfMetadata.FileName with - | Some asmPath -> assemblyReferenceAdded asmPath - | None -> () - tcEnv + AddCcuToTcEnv(g, amap, m, tcEnv, thisAssemblyName, asm.FSharpViewOfMetadata, asm.AssemblyAutoOpenAttributes, asm.AssemblyInternalsVisibleToAttributes) let tcEnv = (tcEnv, asms) ||> List.fold buildTcEnv tcEnv, (dllinfos, asms) diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index fd95afdd20..c41e901962 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -684,7 +684,7 @@ val WriteOptimizationData: TcGlobals * filename: string * inMem: bool * CcuThunk /// Process #r in F# Interactive. /// Adds the reference to the tcImports and add the ccu to the type checking environment. -val RequireDLL: CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: string * referenceRange: range * file: string * assemblyReferenceAdded: (string -> unit) -> TcEnv * (ImportedBinary list * ImportedAssembly list) +val RequireDLL: CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: string * referenceRange: range * file: string -> TcEnv * (ImportedBinary list * ImportedAssembly list) /// Processing # commands val ProcessMetaCommandsFromInput : diff --git a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs index 9417cca120..ae948bde1a 100644 --- a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs +++ b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs @@ -19,9 +19,6 @@ type FSharpScript(?additionalArgs: string[]) = let argv = Array.append baseArgs additionalArgs let fsi = FsiEvaluationSession.Create (config, argv, stdin, stdout, stderr) - [] - member __.AssemblyReferenceAdded = fsi.AssemblyReferenceAdded - member __.ValueBound = fsi.ValueBound [] diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 9f6df3f16a..b6912b91d3 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -956,7 +956,6 @@ type internal FsiDynamicCompiler let outfile = "TMPFSCI.exe" let assemblyName = "FSI-ASSEMBLY" - let assemblyReferenceAddedEvent = Control.Event() let valueBoundEvent = Control.Event<_>() let dependencyAddingEvent = Control.Event() let dependencyAddedEvent = Control.Event() @@ -1260,7 +1259,7 @@ type internal FsiDynamicCompiler let tcState = istate.tcState let tcEnv,(_dllinfos,ccuinfos) = try - RequireDLL (ctok, tcImports, tcState.TcEnvFromImpls, assemblyName, m, path, assemblyReferenceAddedEvent.Trigger) + RequireDLL (ctok, tcImports, tcState.TcEnvFromImpls, assemblyName, m, path) with e -> tcConfigB.RemoveReferencedAssemblyByPath(m,path) reraise() @@ -1402,8 +1401,6 @@ type internal FsiDynamicCompiler member __.FormatValue(obj:obj, objTy) = valuePrinter.FormatValue(obj, objTy) - member __.AssemblyReferenceAdded = assemblyReferenceAddedEvent.Publish - member __.ValueBound = valueBoundEvent.Publish member __.DependencyAdding = dependencyAddingEvent.Publish @@ -1909,8 +1906,6 @@ type internal FsiInteractionProcessor let referencedAssemblies = Dictionary() - let assemblyReferencedEvent = Control.Event() - let mutable currState = initialInteractiveState let event = Control.Event() let setCurrState s = currState <- s; event.Trigger() @@ -2451,8 +2446,6 @@ type internal FsiInteractionProcessor let fsiInteractiveChecker = FsiInteractiveChecker(legacyReferenceResolver, checker, tcConfig, istate.tcGlobals, istate.tcImports, istate.tcState) fsiInteractiveChecker.ParseAndCheckInteraction(ctok, SourceText.ofString text) - member __.AssemblyReferenceAdded = assemblyReferencedEvent.Publish - //---------------------------------------------------------------------------- // Server mode: @@ -2862,10 +2855,6 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i |> commitResultNonThrowing errorOptions scriptPath errorLogger |> function Choice1Of2 (_), errs -> Choice1Of2 (), errs | Choice2Of2 exn, errs -> Choice2Of2 exn, errs - [] - /// Event fires every time an assembly reference is added to the execution environment, e.g., via `#r`. - member __.AssemblyReferenceAdded = fsiDynamicCompiler.AssemblyReferenceAdded - /// Event fires when a root-level value is bound to an identifier, e.g., via `let x = ...`. member __.ValueBound = fsiDynamicCompiler.ValueBound diff --git a/src/fsharp/fsi/fsi.fsi b/src/fsharp/fsi/fsi.fsi index d9bf96f123..1e18946a26 100644 --- a/src/fsharp/fsi/fsi.fsi +++ b/src/fsharp/fsi/fsi.fsi @@ -234,10 +234,6 @@ type FsiEvaluationSession = /// A host calls this to report an unhandled exception in a standard way, e.g. an exception on the GUI thread gets printed to stderr member ReportUnhandledException : exn: exn -> unit - [] - /// Event fires every time an assembly reference is added to the execution environment, e.g., via `#r`. - member AssemblyReferenceAdded: IEvent - [] /// Event fires every time a path is added to the include search list, e.g., via `#I`. member IncludePathAdded: IEvent diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 4afd6a90a6..4d3a0945ce 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -30,18 +30,10 @@ type DependencyManagerInteractiveTests() = #r @"nuget:Newtonsoft.Json, Version=9.0.1" 0""" use script = scriptHost() - let mutable assemblyResolveEventCount = 0 - let mutable foundAssemblyReference = false - Event.add (fun (assembly: string) -> - assemblyResolveEventCount <- assemblyResolveEventCount + 1 - foundAssemblyReference <- String.Compare("Newtonsoft.Json.dll", Path.GetFileName(assembly), StringComparison.OrdinalIgnoreCase) = 0) - script.AssemblyReferenceAdded let opt = script.Eval(text) |> getValue let value = opt.Value Assert.AreEqual(typeof, value.ReflectionType) Assert.AreEqual(0, value.ReflectionValue :?> int) - Assert.Greater(assemblyResolveEventCount, 0) - Assert.AreEqual(true, foundAssemblyReference) [] member __.``SmokeTest - #r nuget package not found``() = @@ -49,15 +41,10 @@ type DependencyManagerInteractiveTests() = #r @"nuget:System.Collections.Immutable.DoesNotExist, version=1.5.0" 0""" use script = scriptHost() - let mutable assemblyResolveEventCount = 0 - Event.add (fun (assembly: string) -> - assemblyResolveEventCount <- assemblyResolveEventCount + 1) - script.AssemblyReferenceAdded let opt = script.Eval(text) |> getValue let value = opt.Value Assert.AreEqual(typeof, value.ReflectionType) Assert.AreEqual(0, value.ReflectionValue :?> int) - Assert.AreEqual(0, assemblyResolveEventCount) [] member __.``Dependency add events successful``() = diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs index 9dc326d0ed..1006ce3b18 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs @@ -65,26 +65,21 @@ type InteractiveTests() = [] member __.``Assembly reference event successful``() = use script = new FSharpScript() - let testAssembly = "System.dll" - let mutable assemblyResolveEventCount = 0 - let mutable foundAssemblyReference = false - Event.add (fun (assembly: string) -> - assemblyResolveEventCount <- assemblyResolveEventCount + 1 - foundAssemblyReference <- String.Compare(testAssembly, Path.GetFileName(assembly), StringComparison.OrdinalIgnoreCase) = 0) - script.AssemblyReferenceAdded - script.Eval(sprintf "#r \"%s\"" testAssembly) |> ignoreValue - Assert.AreEqual(1, assemblyResolveEventCount) - Assert.True(foundAssemblyReference) + let testCode = """ +#r "System.dll" +let stacktype= typeof +stacktype.Name = "Stack" +""" + let opt = script.Eval(testCode) |> getValue + let value = opt.Value + Assert.AreEqual(true, value.ReflectionValue :?> bool) [] - member __.``Assembly reference event unsuccessful``() = + member __.``Assembly reference unsuccessful``() = use script = new FSharpScript() let testAssembly = "not-an-assembly-that-can-be-found.dll" - let mutable foundAssemblyReference = false - Event.add (fun _ -> foundAssemblyReference <- true) script.AssemblyReferenceAdded let _result, errors = script.Eval(sprintf "#r \"%s\"" testAssembly) Assert.AreEqual(1, errors.Length) - Assert.False(foundAssemblyReference) [] member __.``Add include path event successful``() = @@ -130,13 +125,10 @@ type InteractiveTests() = [] member __.``Nuget reference fires multiple events``() = use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) - let mutable assemblyRefCount = 0 let mutable includeAddCount = 0 - Event.add (fun _ -> assemblyRefCount <- assemblyRefCount + 1) script.AssemblyReferenceAdded Event.add (fun _ -> includeAddCount <- includeAddCount + 1) script.IncludePathAdded script.Eval("#r \"nuget:include=NUnitLite, version=3.11.0\"") |> ignoreValue script.Eval("0") |> ignoreValue - Assert.GreaterOrEqual(assemblyRefCount, 2) Assert.GreaterOrEqual(includeAddCount, 1) /// Native dll resolution is not implemented on desktop @@ -183,8 +175,6 @@ printfn ""%A"" result 123 " use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) - let mutable assemblyRefCount = 0; - Event.add (fun _ -> assemblyRefCount <- assemblyRefCount + 1) script.AssemblyReferenceAdded let opt = script.Eval(code) |> getValue let value = opt.Value Assert.AreEqual(123, value.ReflectionValue :?> int32) @@ -202,8 +192,6 @@ let tInput = new DenseTensor(inputValues.AsMemory(), new ReadOnlySpan assemblyRefCount <- assemblyRefCount + 1) script.AssemblyReferenceAdded let opt = script.Eval(code) |> getValue let value = opt.Value Assert.AreEqual(4L, value.ReflectionValue :?> int64) @@ -230,7 +218,6 @@ else 123 " use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) - let mutable assemblyRefCount = 0; let opt = script.Eval(code) |> getValue let value = opt.Value Assert.AreEqual(123, value.ReflectionValue :?> int32) From b32124df9ebcae95b819b4428f6615ce759d7963 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Thu, 30 Jan 2020 10:16:22 -0800 Subject: [PATCH 089/101] Remove unnecessary diagnostics (#8401) --- src/utils/CompilerLocationUtils.fs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/CompilerLocationUtils.fs b/src/utils/CompilerLocationUtils.fs index 923ab41843..20be5f7483 100644 --- a/src/utils/CompilerLocationUtils.fs +++ b/src/utils/CompilerLocationUtils.fs @@ -292,7 +292,6 @@ module internal FSharpEnvironment = // We look in the directories stepping up from the location of the runtime assembly. let loadFromLocation designTimeAssemblyPath = try - printfn "Using: %s" designTimeAssemblyPath Some (Assembly.UnsafeLoadFrom designTimeAssemblyPath) with e -> raiseError e @@ -315,8 +314,6 @@ module internal FSharpEnvironment = let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName let paths = searchParentDirChain (Some runTimeAssemblyPath) designTimeAssemblyName paths - |> Seq.iter(function res -> printfn ">>>> %s" res) - paths |> Seq.tryHead |> function | Some res -> loadFromLocation res @@ -325,7 +322,6 @@ module internal FSharpEnvironment = let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName loadFromLocation (Path.Combine (runTimeAssemblyPath, designTimeAssemblyName)) - printfn "=============== S T A R T ==========================================" if designTimeAssemblyName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) then loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyName else From fe29cc4115ec273df7a9619712a1e00d3581a899 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Thu, 30 Jan 2020 16:31:42 -0800 Subject: [PATCH 090/101] always run mac tests on latest os (#8405) --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9388446102..566be9e28d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -234,7 +234,7 @@ stages: # MacOS - job: MacOS pool: - vmImage: macOS-10.13 + vmImage: macOS-latest variables: - name: _SignType value: Test @@ -367,7 +367,7 @@ stages: # - job: MacOS_FCS # pool: - # vmImage: macOS-10.13 + # vmImage: macOS-latest # variables: # - name: _SignType # value: Test From 3016aeaffb762386c0ba333eb28235f2309f372a Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Thu, 30 Jan 2020 22:03:00 -0800 Subject: [PATCH 091/101] Remove add include event notification (#8416) --- src/fsharp/CompileOps.fs | 8 +---- src/fsharp/CompileOps.fsi | 7 ++-- .../FSharpScript.fs | 3 -- src/fsharp/fsi/fsi.fs | 9 +---- src/fsharp/fsi/fsi.fsi | 4 --- .../FSharpScriptTests.fs | 33 ------------------- 6 files changed, 4 insertions(+), 60 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 8473b0a880..e3b7d1b71b 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2170,8 +2170,6 @@ type TcConfigBuilder = mutable pathMap: PathMap mutable langVersion: LanguageVersion - - mutable includePathAdded: string -> unit } static member Initial = @@ -2312,18 +2310,16 @@ type TcConfigBuilder = noConditionalErasure = false pathMap = PathMap.empty langVersion = LanguageVersion("default") - includePathAdded = ignore } static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, - isInteractive, isInvalidationSupported, defaultCopyFSharpCore, tryGetMetadataSnapshot, ?includePathAdded: string -> unit) = + isInteractive, isInvalidationSupported, defaultCopyFSharpCore, tryGetMetadataSnapshot) = Debug.Assert(FileSystem.IsPathRootedShim implicitIncludeDir, sprintf "implicitIncludeDir should be absolute: '%s'" implicitIncludeDir) if (String.IsNullOrEmpty defaultFSharpBinariesDir) then failwith "Expected a valid defaultFSharpBinariesDir" - let includePathAdded = defaultArg includePathAdded ignore { TcConfigBuilder.Initial with implicitIncludeDir = implicitIncludeDir defaultFSharpBinariesDir = defaultFSharpBinariesDir @@ -2334,7 +2330,6 @@ type TcConfigBuilder = copyFSharpCore = defaultCopyFSharpCore tryGetMetadataSnapshot = tryGetMetadataSnapshot useFsiAuxLib = isInteractive - includePathAdded = includePathAdded } member tcConfigB.ResolveSourceFile(m, nm, pathLoadedFrom) = @@ -2410,7 +2405,6 @@ type TcConfigBuilder = | None -> false if ok && not (List.contains absolutePath tcConfigB.includes) then tcConfigB.includes <- tcConfigB.includes ++ absolutePath - tcConfigB.includePathAdded absolutePath member tcConfigB.AddLoadedSource(m, originalPath, pathLoadedFrom) = if FileSystem.IsInvalidPathShim originalPath then diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index c41e901962..0c92d463d3 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -389,8 +389,6 @@ type TcConfigBuilder = mutable pathMap : PathMap mutable langVersion : LanguageVersion - - mutable includePathAdded : string -> unit } static member Initial: TcConfigBuilder @@ -403,8 +401,7 @@ type TcConfigBuilder = isInteractive: bool * isInvalidationSupported: bool * defaultCopyFSharpCore: CopyFSharpCoreFlag * - tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * - ?includePathAdded: (string -> unit) + tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot -> TcConfigBuilder member DecideNames: string list -> outfile: string * pdbfile: string option * assemblyName: string @@ -417,7 +414,7 @@ type TcConfigBuilder = member AddEmbeddedSourceFile: string -> unit member AddEmbeddedResource: string -> unit member AddPathMapping: oldPrefix: string * newPrefix: string -> unit - + static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess [] diff --git a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs index ae948bde1a..3106bc4c28 100644 --- a/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs +++ b/src/fsharp/FSharp.Compiler.Private.Scripting/FSharpScript.fs @@ -21,9 +21,6 @@ type FSharpScript(?additionalArgs: string[]) = member __.ValueBound = fsi.ValueBound - [] - member __.IncludePathAdded = fsi.IncludePathAdded - [] member __.DependencyAdding = fsi.DependencyAdding diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index b6912b91d3..076ffe1859 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2540,8 +2540,6 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i | None -> SimulatedMSBuildReferenceResolver.getResolver() | Some rr -> rr - let includePathAddedEvent = Control.Event<_>() - let tcConfigB = TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir=defaultFSharpBinariesDir, @@ -2550,8 +2548,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i isInteractive=true, isInvalidationSupported=false, defaultCopyFSharpCore=CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot=tryGetMetadataSnapshot, - includePathAdded=includePathAddedEvent.Trigger) + tryGetMetadataSnapshot=tryGetMetadataSnapshot) let tcConfigP = TcConfigProvider.BasedOnMutableBuilder(tcConfigB) do tcConfigB.resolutionEnvironment <- ResolutionEnvironment.CompilationAndEvaluation // See Bug 3608 @@ -2858,10 +2855,6 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i /// Event fires when a root-level value is bound to an identifier, e.g., via `let x = ...`. member __.ValueBound = fsiDynamicCompiler.ValueBound - [] - /// Event fires every time a path is added to the include search list, e.g., via `#I`. - member __.IncludePathAdded = includePathAddedEvent.Publish - [] /// Event fires at the start of adding a dependency via the dependency manager. member __.DependencyAdding = fsiDynamicCompiler.DependencyAdding diff --git a/src/fsharp/fsi/fsi.fsi b/src/fsharp/fsi/fsi.fsi index 1e18946a26..453a1a4952 100644 --- a/src/fsharp/fsi/fsi.fsi +++ b/src/fsharp/fsi/fsi.fsi @@ -234,10 +234,6 @@ type FsiEvaluationSession = /// A host calls this to report an unhandled exception in a standard way, e.g. an exception on the GUI thread gets printed to stderr member ReportUnhandledException : exn: exn -> unit - [] - /// Event fires every time a path is added to the include search list, e.g., via `#I`. - member IncludePathAdded: IEvent - [] /// Event fires at the start of adding a dependency via the dependency manager. member DependencyAdding: IEvent diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs index 1006ce3b18..8c51a70707 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs @@ -81,30 +81,6 @@ stacktype.Name = "Stack" let _result, errors = script.Eval(sprintf "#r \"%s\"" testAssembly) Assert.AreEqual(1, errors.Length) - [] - member __.``Add include path event successful``() = - use script = new FSharpScript() - let includePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) - let mutable includePathEventCount = 0 - let mutable foundIncludePath = false - Event.add (fun (inc: string) -> - includePathEventCount <- includePathEventCount + 1 - foundIncludePath <- foundIncludePath || String.Compare(includePath, inc, StringComparison.OrdinalIgnoreCase) = 0) - script.IncludePathAdded - script.Eval(sprintf "#I @\"%s\"" includePath) |> ignoreValue - Assert.AreEqual(1, includePathEventCount) - Assert.True(foundIncludePath) - - [] - member __.``Add include path event unsuccessful``() = - use script = new FSharpScript() - let includePath = Path.Combine("a", "path", "that", "can't", "be", "found") - let mutable foundIncludePath = false - Event.add (fun _ -> foundIncludePath <- true) script.IncludePathAdded - let _result, errors = script.Eval(sprintf "#I @\"%s\"" includePath) - Assert.AreEqual(1, errors.Length) - Assert.False(foundIncludePath) - [] member _.``Compilation errors report a specific exception``() = use script = new FSharpScript() @@ -122,15 +98,6 @@ stacktype.Name = "Stack" | Ok(_) -> Assert.Fail("expected a failure") | Error(ex) -> Assert.IsInstanceOf(ex) - [] - member __.``Nuget reference fires multiple events``() = - use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) - let mutable includeAddCount = 0 - Event.add (fun _ -> includeAddCount <- includeAddCount + 1) script.IncludePathAdded - script.Eval("#r \"nuget:include=NUnitLite, version=3.11.0\"") |> ignoreValue - script.Eval("0") |> ignoreValue - Assert.GreaterOrEqual(includeAddCount, 1) - /// Native dll resolution is not implemented on desktop #if NETSTANDARD [] From de0637f902d0a9ef0a4d91f6515e3e0e91df9bcc Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Fri, 31 Jan 2020 13:30:20 -0800 Subject: [PATCH 092/101] Refactor dependency manager for notebooks and C# (#8415) * Refactor dependency manager * name change --- src/fsharp/CompileOps.fs | 4 +- src/fsharp/DependencyManager.Integration.fs | 12 +- src/fsharp/DependencyManager.Integration.fsi | 4 +- .../FSharp.DependencyManager.ProjectFile.fs | 190 ++++++++++++++++++ .../FSharp.DependencyManager.Utilities.fs | 116 ++--------- .../FSharp.DependencyManager.fs | 47 +++-- .../FSharp.DependencyManager.fsproj | 1 + src/fsharp/fsi/fsi.fs | 2 +- 8 files changed, 248 insertions(+), 128 deletions(-) create mode 100644 src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.ProjectFile.fs diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index e3b7d1b71b..23bd2ebc3e 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5152,7 +5152,7 @@ module ScriptPreprocessClosure = let tcConfigB = tcConfig.CloneOfOriginalBuilder TcConfig.Create(tcConfigB, validate=false), nowarns - let FindClosureFiles(mainFile, _m, closureSources, origTcConfig:TcConfig, codeContext, lexResourceManager: Lexhelp.LexResourceManager) = + let FindClosureFiles(_mainFile, _m, closureSources, origTcConfig:TcConfig, codeContext, lexResourceManager: Lexhelp.LexResourceManager) = let mutable tcConfig = origTcConfig let observedSources = Observed() @@ -5176,7 +5176,7 @@ module ScriptPreprocessClosure = let inline snd3 (_, b, _) = b let packageManagerTextLines = packageManagerLines |> List.map snd3 - match DependencyManagerIntegration.resolve packageManager tcConfig.implicitIncludeDir mainFile scriptName m packageManagerTextLines with + match DependencyManagerIntegration.resolve packageManager ".fsx" m packageManagerTextLines with | None -> () // error already reported | Some (succeeded, generatedScripts, additionalIncludeFolders) -> //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // This may incrementally update tcConfig too with new #r references diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 9f1ecd35f3..c1eacf1b5b 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -62,7 +62,7 @@ module ReflectionHelper = type internal IDependencyManagerProvider = abstract Name: string abstract Key: string - abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list + abstract ResolveDependencies: scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list abstract DependencyAdding: IEvent abstract DependencyAdded: IEvent abstract DependencyFailed: IEvent @@ -86,7 +86,7 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn match ReflectionHelper.getAttributeNamed theType dependencyManagerAttributeName, ReflectionHelper.getInstanceProperty theType namePropertyName, ReflectionHelper.getInstanceProperty theType keyPropertyName, - ReflectionHelper.getInstanceMethod theType [| typeof; typeof; typeof; typeof; typeof |] resolveDependenciesMethodName + ReflectionHelper.getInstanceMethod theType [| typeof; typeof; typeof |] resolveDependenciesMethodName with | None, _, _, _ -> None | _, None, _, _ -> None @@ -98,13 +98,13 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn interface IDependencyManagerProvider with member __.Name = instance |> nameProperty member __.Key = instance |> keyProperty - member this.ResolveDependencies(scriptDir, mainScriptName, scriptName, packageManagerTextLines, tfm) = + member this.ResolveDependencies(scriptDir, packageManagerTextLines, tfm) = let key = (this :> IDependencyManagerProvider).Key let triggerEvent (evt: Event) = for prLine in packageManagerTextLines do evt.Trigger(key, prLine) triggerEvent dependencyAddingEvent - let arguments = [| box scriptDir; box mainScriptName; box scriptName; box packageManagerTextLines; box tfm |] + let arguments = [| box scriptDir; box packageManagerTextLines; box tfm |] let succeeded, generatedScripts, additionalIncludeFolders = resolveDeps.Invoke(instance, arguments) :?> _ if succeeded then triggerEvent dependencyAddedEvent else triggerEvent dependencyFailedEvent @@ -191,9 +191,9 @@ let tryFindDependencyManagerByKey (compilerTools: string list) (outputDir:string errorR(Error(FSComp.SR.packageManagerError(e.Message), m)) None -let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir mainScriptName fileName m packageManagerTextLines = +let resolve (packageManager:IDependencyManagerProvider) scriptExt m packageManagerTextLines = try - Some(packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, packageManagerTextLines, executionTfm)) + Some(packageManager.ResolveDependencies(scriptExt, packageManagerTextLines, executionTfm)) with e -> let e = ReflectionHelper.stripTieWrapper e errorR(Error(FSComp.SR.packageManagerError(e.Message), m)) diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 62af44898d..352a052a56 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -8,7 +8,7 @@ open FSharp.Compiler.Range type IDependencyManagerProvider = abstract Name: string abstract Key: string - abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list + abstract ResolveDependencies: scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list abstract DependencyAdding: IEvent abstract DependencyAdded: IEvent abstract DependencyFailed: IEvent @@ -23,4 +23,4 @@ val tryFindDependencyManagerInPath: string list -> string option -> range -> str val tryFindDependencyManagerByKey: string list -> string option -> range -> string -> IDependencyManagerProvider option val removeDependencyManagerKey: string -> string -> string val createPackageManagerUnknownError: string list -> string option -> string -> range -> exn -val resolve: IDependencyManagerProvider -> string -> string -> string -> range -> string seq -> (bool * string list * string list) option +val resolve: IDependencyManagerProvider -> string -> range -> string seq -> (bool * string list * string list) option diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.ProjectFile.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.ProjectFile.fs new file mode 100644 index 0000000000..d39f0fab2c --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.ProjectFile.fs @@ -0,0 +1,190 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +namespace FSharp.DependencyManager + +open System +open System.Collections +open System.Collections.Generic +open System.Diagnostics +open System.IO +open System.Reflection +open System.Runtime.CompilerServices +open System.Runtime.Versioning + +open Internal.Utilities.FSharpEnvironment + +// Package reference information +type PackageReference = { + Include:string + Version:string + RestoreSources:string + Script:string } + + +// Resolved assembly information +type Resolution = { + NugetPackageId : string + NugetPackageVersion : string + PackageRoot : string + FullPath : string + IsNotImplementationReference: string + NativePath : string + AppHostRuntimeIdentifier : string + InitializeSourcePath : string } + + +module ProjectFile = + + let findLoadsFromResolutions (resolutions:Resolution array) = + resolutions + |> Array.filter(fun r -> not(String.IsNullOrEmpty(r.NugetPackageId) || + String.IsNullOrEmpty(r.InitializeSourcePath)) && + File.Exists(r.InitializeSourcePath)) + |> Array.map(fun r -> r.InitializeSourcePath) + |> Array.distinct + + let findIncludesFromResolutions (resolutions:Resolution array) = + let managedRoots = + resolutions + |> Array.filter(fun r -> not(String.IsNullOrEmpty(r.NugetPackageId) || + String.IsNullOrEmpty(r.PackageRoot)) && + Directory.Exists(r.PackageRoot)) + |> Array.map(fun r -> r.PackageRoot) + |> Array.distinct + + let nativeRoots = + resolutions + |> Array.filter(fun r -> not(String.IsNullOrEmpty(r.NugetPackageId) || + String.IsNullOrEmpty(r.NativePath)) && + Directory.Exists(r.NativePath)) + |> Array.map(fun r -> r.NativePath) + |> Array.distinct + + Array.concat [|managedRoots; nativeRoots|] + + let getResolutionsFromFile resolutionsFile = + + let lines = + try + File.ReadAllText(resolutionsFile).Split([| '\r'; '\n'|], StringSplitOptions.None) + |> Array.filter(fun line -> not(String.IsNullOrEmpty(line))) + with + | _ -> [||] + + [| for line in lines do + let fields = line.Split(',') + if fields.Length < 8 then raise (new System.InvalidOperationException(sprintf "Internal error - Invalid resolutions file format '%s'" line)) + else { + NugetPackageId = fields.[0] + NugetPackageVersion = fields.[1] + PackageRoot = fields.[2] + FullPath = fields.[3] + IsNotImplementationReference = fields.[4] + InitializeSourcePath = fields.[5] + NativePath = fields.[6] + AppHostRuntimeIdentifier = fields.[7] + } + |] + + let makeScriptFromResolutions (resolutions:Resolution array) poundRprefix = + let expandReferences = + resolutions + |> Array.filter(fun r -> not(String.IsNullOrEmpty(r.NugetPackageId) || + String.IsNullOrEmpty(r.FullPath)) && + String.Compare(r.IsNotImplementationReference, "true", StringComparison.InvariantCultureIgnoreCase) <> 0 && + File.Exists(r.FullPath)) + |> Array.fold(fun acc r -> acc + poundRprefix + r.FullPath + "\"" + Environment.NewLine) "" + + let projectTemplate =""" +// Generated from #r "nuget:Package References" +// ============================================ +// +// DOTNET_HOST_PATH:(C:\Program Files\dotnet\dotnet.exe) +// MSBuildSDKsPath:(C:\Program Files\dotnet\sdk\3.1.200-preview-014883\Sdks) +// MSBuildExtensionsPath:(C:\Program Files\dotnet\sdk\3.1.200-preview-014883\) +// +// References +// +$(POUND_R) + +""" + projectTemplate.Replace("$(POUND_R)", expandReferences) + + let generateProjectBody = """ + + + + $(TARGETFRAMEWORK) + false + true + true + + + 4.7.0 + 4.7.1-* + + +$(PACKAGEREFERENCES) + + + + + <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> + <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> + <__ConflictsList Include="%(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> + + + + <__Conflicts>@(__ConflictsList, ';'); + + + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssemblies.FileName)%(__InteractiveReferencedAssemblies.Extension)$(SCRIPTEXTENSION) + $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssemblies.NuGetPackageId) + %(__InteractiveReferencedAssemblies.NuGetPackageVersion) + + + + $([System.String]::Copy('%(Identity)').Replace('\', '/')) + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').Replace('\', '/')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) + $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) + %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssembliesCopyLocal.FileName)%(__InteractiveReferencedAssembliesCopyLocal.Extension)$(SCRIPTEXTENSION) + $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').StartsWith('ref/')) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageId) + %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageVersion) + + + + $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) + + + + + + + + + + + + + + +""" diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs index c120ec1f97..2f13ac26e4 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -10,6 +10,7 @@ open System.Reflection open System.Runtime.CompilerServices open System.Runtime.Versioning +open FSharp.DependencyManager.ProjectFile open Internal.Utilities.FSharpEnvironment [] @@ -18,7 +19,7 @@ type DependencyManagerAttribute() = inherit System.Attribute() module Utilities = /// Return a string array delimited by commas - /// Note that a quoted string is not going to be mangled into pieces. + /// Note that a quoted string is not going to be mangled into pieces. let trimChars = [| ' '; '\t'; '\''; '\"' |] let inline private isNotQuotedQuotation (text: string) n = n > 0 && text.[n-1] <> '\\' @@ -165,7 +166,6 @@ module Utilities = let executeBuild pathToExe arguments workingDir = match pathToExe with | Some path -> - let psi = ProcessStartInfo() psi.FileName <- path psi.WorkingDirectory <- workingDir @@ -179,10 +179,21 @@ module Utilities = p.StartInfo <- psi p.Start() |> ignore - drainStreamToFile p.StandardOutput (Path.Combine(workingDir, "StandardOutput.txt")) - drainStreamToFile p.StandardError (Path.Combine(workingDir, "StandardError.txt")) + let standardOutput = Path.Combine(workingDir, "StandardOutput.txt") + let standardError = Path.Combine(workingDir, "StandardError.txt") + drainStreamToFile p.StandardOutput (Path.Combine(workingDir, standardOutput)) + drainStreamToFile p.StandardError (Path.Combine(workingDir, standardError)) p.WaitForExit() + if p.ExitCode <> 0 then + //Write StandardError.txt to err stream + let text = File.ReadAllText(standardOutput) + Console.Out.Write(text) + + //Write StandardOutput.txt to out stream + let text = File.ReadAllText(standardError) + Console.Out.Write(text) + p.ExitCode = 0 | None -> false @@ -210,101 +221,6 @@ module Utilities = // The coreclr uses "dotnet msbuild" to build executeBuild dotnetHostPath (arguments "msbuild") workingDir - let outputFile = projectPath + ".fsx" + let outputFile = projectPath + ".resolvedReferences.paths" let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None succeeded, resultOutFile - - let generateProjectBody = """ - - - - $(TARGETFRAMEWORK) - false - - - 4.7.0 - 4.7.1-* - - -$(PACKAGEREFERENCES) - - - - - <__InteractiveReferencedAssemblies Include = "@(ReferencePath)" /> - <__InteractiveReferencedAssembliesCopyLocal Include = "@(RuntimeCopyLocalItems)" Condition="'$(TargetFrameworkIdentifier)'!='.NETFramework'" /> - <__InteractiveReferencedAssembliesCopyLocal Include = "@(ReferenceCopyLocalPaths)" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" /> - <__ConflictsList Include="%(_ConflictPackageFiles.ConflictItemType)=%(_ConflictPackageFiles.Filename)%(_ConflictPackageFiles.Extension)" /> - - - <__Conflicts>@(__ConflictsList, ';'); - - - - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssemblies.FileName)%(__InteractiveReferencedAssemblies.Extension).fsx - $([System.String]::Copy('%(__InteractiveReferencedAssemblies.PathInPackage)').StartsWith('ref/')) - %(__InteractiveReferencedAssemblies.NuGetPackageId) - %(__InteractiveReferencedAssemblies.NuGetPackageVersion) - - - - $([System.String]::Copy('%(Identity)').Replace('\', '/')) - $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').Replace('\', '/')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').IndexOf('%(InteractiveResolvedFile.NormalizedPathInPackage)')) - $([System.String]::Copy('%(InteractiveResolvedFile.NormalizedIdentity)').Substring(0, %(InteractiveResolvedFile.PositionPathInPackage))) - %(InteractiveResolvedFile.PackageRoot)content\%(__InteractiveReferencedAssembliesCopyLocal.FileName)%(__InteractiveReferencedAssembliesCopyLocal.Extension).fsx - $([System.String]::Copy('%(__InteractiveReferencedAssembliesCopyLocal.PathInPackage)').StartsWith('ref/')) - %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageId) - %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageVersion) - - - - $([MSBuild]::EnsureTrailingSlash('$([System.String]::Copy('%(FullPath)').Substring(0, $([System.String]::Copy('%(FullPath)').LastIndexOf('runtimes'))))')) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -""" diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs index 0fea32bdb4..c2bf63c88d 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs @@ -8,15 +8,14 @@ open System.Diagnostics open System.IO open FSharp.DependencyManager open FSharp.DependencyManager.Utilities +open FSharp.DependencyManager.ProjectFile -module Attributes = - [] - do () - -type PackageReference = { Include:string; Version:string; RestoreSources:string; Script:string } module FSharpDependencyManager = + [] + do () + let private concat (s:string) (v:string) : string = match String.IsNullOrEmpty(s), String.IsNullOrEmpty(v) with | false, false -> s + ";" + v @@ -107,7 +106,9 @@ type [] FSharpDependencyManager (outputDir:string op match outputDir with | None -> path | Some v -> Path.Combine(path, v) + let generatedScripts = new ConcurrentDictionary() + let deleteScripts () = try if Directory.Exists(scriptsPath) then @@ -134,8 +135,12 @@ type [] FSharpDependencyManager (outputDir:string op member __.Key = key - member __.ResolveDependencies(_scriptDir:string, _mainScriptName:string, _scriptName:string, packageManagerTextLines:string seq, tfm: string) : bool * string list * string list = + member __.ResolveDependencies(scriptExt:string, packageManagerTextLines:string seq, tfm: string) : bool * string list * string list = + let scriptExt, poundRprefix = + match scriptExt with + | ".csx" -> ".csx", "#r \"" + | _ -> ".fsx", "#r @\"" let packageReferences, binLogPath = packageManagerTextLines |> List.ofSeq @@ -152,20 +157,28 @@ type [] FSharpDependencyManager (outputDir:string op if not (generatedScripts.ContainsKey(body.GetHashCode().ToString())) then emitFile path body - let fsProjectPath = Path.Combine(scriptsPath, "Project.fsproj") + let projectPath = Path.Combine(scriptsPath, "Project.fsproj") let generateProjBody = generateProjectBody.Replace("$(TARGETFRAMEWORK)", tfm) .Replace("$(PACKAGEREFERENCES)", packageReferenceText) - - writeFile fsProjectPath generateProjBody - - let succeeded, resultingFsx = buildProject fsProjectPath binLogPath - let fsx = - match resultingFsx with - | Some fsx -> [fsx] - | None -> [] - - succeeded, fsx, List.empty + .Replace("$(SCRIPTEXTENSION)", scriptExt) + + writeFile projectPath generateProjBody + + let result, resolutionsFile = buildProject projectPath binLogPath + match resolutionsFile with + | Some file -> + let resolutions = getResolutionsFromFile file + let scripts = + let scriptPath = projectPath + scriptExt + let scriptBody = makeScriptFromResolutions resolutions poundRprefix + emitFile scriptPath scriptBody + let loads = (findLoadsFromResolutions resolutions) |> Array.toList + List.concat [ [scriptPath]; loads] + let includes = (findIncludesFromResolutions resolutions) |> Array.toList + + result, scripts, includes + | None -> result, [], [] generateAndBuildProjectArtifacts diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj index e3e4b385a2..8836a4cf62 100644 --- a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj @@ -23,6 +23,7 @@ + diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 076ffe1859..97259cd372 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1302,7 +1302,7 @@ type internal FsiDynamicCompiler Event.add dependencyAddingEvent.Trigger packageManager.DependencyAdding Event.add dependencyAddedEvent.Trigger packageManager.DependencyAdded Event.add dependencyFailedEvent.Trigger packageManager.DependencyFailed - match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" "stdin.fsx" m packageManagerTextLines with + match DependencyManagerIntegration.resolve packageManager ".fsx" m packageManagerTextLines with | None -> istate // error already reported | Some (succeeded, generatedScripts, additionalIncludeFolders) -> //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if succeeded then From 7f14ea0d7f36bd80dbba548ed6d4426c06f47f05 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 3 Feb 2020 17:13:40 +0000 Subject: [PATCH 093/101] add more tests for SRTP variations (#8435) * add more tests for SRTP variations * teak names of tests * fix baseline --- tests/fsharp/tests.fs | 27 ++ tests/fsharp/typecheck/sigs/neg123.bsl | 2 + .../typecheck/sigs/neg123.fs} | 12 +- tests/fsharp/typecheck/sigs/neg124.bsl | 42 +++ tests/fsharp/typecheck/sigs/neg124.fs | 40 +++ tests/fsharp/typecheck/sigs/neg125.bsl | 26 ++ tests/fsharp/typecheck/sigs/neg125.fs | 51 +++ tests/fsharp/typecheck/sigs/neg126.bsl | 2 + tests/fsharp/typecheck/sigs/neg126.fs | 32 ++ tests/fsharp/typecheck/sigs/neg127.bsl | 26 ++ tests/fsharp/typecheck/sigs/neg127.fs | 59 ++++ tests/fsharp/typecheck/sigs/neg128.bsl | 2 + tests/fsharp/typecheck/sigs/neg128.fs | 36 ++ tests/fsharp/typecheck/sigs/neg129.bsl | 2 + tests/fsharp/typecheck/sigs/neg129.fs | 67 ++++ tests/fsharp/typecheck/sigs/pos35.fs | 315 ++++++++++++++++++ .../OverloadingMembers/env.lst | 2 - 17 files changed, 732 insertions(+), 11 deletions(-) create mode 100644 tests/fsharp/typecheck/sigs/neg123.bsl rename tests/{fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/SlowOverloadResolution.fs => fsharp/typecheck/sigs/neg123.fs} (55%) create mode 100644 tests/fsharp/typecheck/sigs/neg124.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg124.fs create mode 100644 tests/fsharp/typecheck/sigs/neg125.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg125.fs create mode 100644 tests/fsharp/typecheck/sigs/neg126.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg126.fs create mode 100644 tests/fsharp/typecheck/sigs/neg127.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg127.fs create mode 100644 tests/fsharp/typecheck/sigs/neg128.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg128.fs create mode 100644 tests/fsharp/typecheck/sigs/neg129.bsl create mode 100644 tests/fsharp/typecheck/sigs/neg129.fs create mode 100644 tests/fsharp/typecheck/sigs/pos35.fs diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 4dd0f4740a..493aeb30ed 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -2167,6 +2167,12 @@ module TypecheckTests = fsc cfg "%s --target:library -o:pos34.dll --warnaserror" cfg.fsc_flags ["pos34.fs"] peverify cfg "pos34.dll" + [] + let ``sigs pos35`` () = + let cfg = testConfig "typecheck/sigs" + fsc cfg "%s --target:library -o:pos35.dll --warnaserror" cfg.fsc_flags ["pos35.fs"] + peverify cfg "pos35.dll" + [] let ``sigs pos23`` () = let cfg = testConfig "typecheck/sigs" @@ -2687,6 +2693,27 @@ module TypecheckTests = [] let ``type check neg122`` () = singleNegTest (testConfig "typecheck/sigs") "neg122" + [] + let ``type check neg123`` () = singleNegTest (testConfig "typecheck/sigs") "neg123" + + [] + let ``type check neg124`` () = singleNegTest (testConfig "typecheck/sigs") "neg124" + + [] + let ``type check neg125`` () = singleNegTest (testConfig "typecheck/sigs") "neg125" + + [] + let ``type check neg126`` () = singleNegTest (testConfig "typecheck/sigs") "neg126" + + [] + let ``type check neg127`` () = singleNegTest (testConfig "typecheck/sigs") "neg127" + + [] + let ``type check neg128`` () = singleNegTest (testConfig "typecheck/sigs") "neg128" + + [] + let ``type check neg129`` () = singleNegTest (testConfig "typecheck/sigs") "neg129" + [] let ``type check neg_anon_1`` () = singleNegTest (testConfig "typecheck/sigs") "neg_anon_1" diff --git a/tests/fsharp/typecheck/sigs/neg123.bsl b/tests/fsharp/typecheck/sigs/neg123.bsl new file mode 100644 index 0000000000..a944f08750 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg123.bsl @@ -0,0 +1,2 @@ + +neg123.fs(19,18,19,27): typecheck error FS0003: This value is not a function and cannot be applied. diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/SlowOverloadResolution.fs b/tests/fsharp/typecheck/sigs/neg123.fs similarity index 55% rename from tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/SlowOverloadResolution.fs rename to tests/fsharp/typecheck/sigs/neg123.fs index 5737cdebf2..1494305813 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/SlowOverloadResolution.fs +++ b/tests/fsharp/typecheck/sigs/neg123.fs @@ -1,6 +1,5 @@ -// #Conformance #DeclarationElements #MemberDefinitions #Overloading -// https://github.com/Microsoft/visualfsharp/issues/351 - slow overlaod resolution -//This value is not a function and cannot be applied +module Neg123 + type Switcher = Switcher let inline checker< ^s, ^r when (^s or ^r) : (static member pass : ^r -> unit)> (s : ^s) (r : ^r) = () @@ -17,9 +16,4 @@ type Switcher with static member inline pass(_ : unit) = () static member inline pass(_ : int) = () -[] -let main argv = - let res : unit = format () "text" 5 "more text" () - printfn "%A" res - System.Console.ReadKey() - 0 // return an integer exit code +let res : unit = format () "text" 5 "more text" () diff --git a/tests/fsharp/typecheck/sigs/neg124.bsl b/tests/fsharp/typecheck/sigs/neg124.bsl new file mode 100644 index 0000000000..b9c55eba73 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg124.bsl @@ -0,0 +1,42 @@ + +neg124.fs(39,27,39,35): typecheck error FS0071: Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'unsigned_witness'. The available overloads are shown below. Consider adding further type constraints +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:uint64 -> uint64'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'uint64' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:int64 -> uint64'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'int64' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:uint32 -> uint32'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'uint32' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:int32 -> uint32'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'int32' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:uint16 -> uint16'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'uint16' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:int16 -> uint16'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'int16' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:byte -> byte'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'byte' +. +neg124.fs(39,27,39,35): typecheck error FS0071: Possible overload: 'static member Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector.witnesses.unsigned_witness : x:sbyte -> uint8'. Type constraint mismatch. The type + 'obj' +is not compatible with type + 'sbyte' +. diff --git a/tests/fsharp/typecheck/sigs/neg124.fs b/tests/fsharp/typecheck/sigs/neg124.fs new file mode 100644 index 0000000000..d8a7c937dd --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg124.fs @@ -0,0 +1,40 @@ +module Neg124 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +module Negative_SelectOverloadedWitnessBasedOnInputAndReturnTypeWithoutOutputTypeSelector = + type witnesses = + static member inline unsigned_witness (x : sbyte) = uint8 x + static member inline unsigned_witness (x : byte) = x + static member inline unsigned_witness (x : int16) = uint16 x + static member inline unsigned_witness (x : uint16) = x + static member inline unsigned_witness (x : int32) = uint32 x + static member inline unsigned_witness (x : uint32) = x + static member inline unsigned_witness (x : int64) = uint64 x + static member inline unsigned_witness (x : uint64) = x + + // Note, this doesn't try to use the output to select + let inline call_unsigned_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member unsigned_witness : ^input -> ^output)> (x : ^input) = + ((^witnesses or ^input) : (static member unsigned_witness : ^input -> ^output) x) + + // unsigned: ^a -> ^b + let inline unsigned num = call_unsigned_witness num + + // Positive cases + let v1 = unsigned 0y + let v2 = unsigned 0s + let v3 = unsigned 0 + let v4 = unsigned 0L + + let f1 : int8 -> uint8 = unsigned + let f2 : int16 -> uint16 = unsigned + let f3 : int32 -> uint32 = unsigned + let f4 : int64 -> uint64 = unsigned + + let g1 : int8 -> _ = unsigned + let g2 : int16 -> _ = unsigned + let g3 : int32 -> _ = unsigned + let g4 : int64 -> _ = unsigned + + // Negative case - not enough information here + let h1 : _ -> uint8 = unsigned + \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg125.bsl b/tests/fsharp/typecheck/sigs/neg125.bsl new file mode 100644 index 0000000000..4c96bbcc15 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg125.bsl @@ -0,0 +1,26 @@ + +neg125.fs(39,30,39,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(40,30,40,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(41,31,41,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(42,30,42,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(43,30,43,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(44,30,44,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(45,29,45,31): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(46,31,46,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(47,31,47,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(48,32,48,34): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(49,33,49,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(50,33,50,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg125.fs(51,33,51,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 diff --git a/tests/fsharp/typecheck/sigs/neg125.fs b/tests/fsharp/typecheck/sigs/neg125.fs new file mode 100644 index 0000000000..f2a0975a06 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg125.fs @@ -0,0 +1,51 @@ +module Neg125 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// See also pos35.fs +// +// This removes ^output as a type selector for the witness, and no longer passes a dummy ^output +// +// This means that when both ^witnesses and ^input are known, the overload determining the ^output still can't be determined, +// and overload resolutiuon failures are reported +module Negative_SelectOverloadedWitnessBasedOnReturnTypeWithoutOutputTypeSelectAndWithoutPassingDummyArgument = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint) = x + static member inline convert_witness (x : bigint) = float x + static member inline convert_witness (x : bigint) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint) = float32 x + static member inline convert_witness (x : bigint) = decimal x + static member inline convert_witness (x : bigint) = Complex(float x, 0.0) + // Note ^output in the list of "or" types + let inline call_convert_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member convert_witness : ^input -> ^output)> (b : ^input) = + ((^witnesses or ^input) : (static member convert_witness : ^input -> ^output) (b)) + + let inline convert num = + call_convert_witness (num) + + let v1 : int32 = convert 0I + let v2 : int64 = convert 0I + let v3 : bigint = convert 0I + let v4 : float = convert 0I + let v5 : sbyte = convert 0I + let v6 : int16 = convert 0I + let v7 : byte = convert 0I + let v8 : uint16 = convert 0I + let v9 : uint32 = convert 0I + let v10 : uint64 = convert 0I + let v11 : float32 = convert 0I + let v12 : decimal = convert 0I + let v13 : Complex = convert 0I diff --git a/tests/fsharp/typecheck/sigs/neg126.bsl b/tests/fsharp/typecheck/sigs/neg126.bsl new file mode 100644 index 0000000000..b8808b8514 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg126.bsl @@ -0,0 +1,2 @@ + +neg126.fs(30,32,30,48): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'sbyte'. diff --git a/tests/fsharp/typecheck/sigs/neg126.fs b/tests/fsharp/typecheck/sigs/neg126.fs new file mode 100644 index 0000000000..232a35bb9c --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg126.fs @@ -0,0 +1,32 @@ +module Neg126 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// Here we are attempting to select a witness based on input type. +// +// However, only one witness is present. +// +// Due to the problem described in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580396911, +// "generic inline code we apply weak resolution to constraints that could otherwise be generalised", +// this generates a warning because overload resolution is invoked and the input type of "foo" becomes "sbyte" +// +// The inferred type should ideally be +// foo: ^a -> ^b +// but is actually +// foo: sbyte -> byte +// +// That is, the code is not generic at all, because the F# compiler thinks that it commit to the one and only witness. +// +// This test exists to pin down that we get a warning produced saying ^a has been instantiated to "sbyte" + +module Negative_SelectOverloadedWitnessBasedOnInputTypeOneWitness = + type witnesses = + static member inline foo_witness (x : sbyte) : byte = byte x + + // Note, this doesn't try to use the output to select + let inline call_foo_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member foo_witness : ^input -> ^output)> (x : ^input) = + ((^witnesses or ^input) : (static member foo_witness : ^input -> ^output) x) + + let inline foo (num: ^a) = call_foo_witness num + let v1 = foo 0y + diff --git a/tests/fsharp/typecheck/sigs/neg127.bsl b/tests/fsharp/typecheck/sigs/neg127.bsl new file mode 100644 index 0000000000..0ab9e8c534 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg127.bsl @@ -0,0 +1,26 @@ + +neg127.fs(47,30,47,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(48,30,48,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(49,31,49,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(50,30,50,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(51,30,51,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(52,30,52,32): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(53,29,53,31): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(54,31,54,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(55,31,55,33): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(56,32,56,34): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(57,33,57,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(58,33,58,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 + +neg127.fs(59,33,59,35): typecheck error FS0001: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint -> Complex, static member witnesses.convert_witness : x:bigint -> bigint, static member witnesses.convert_witness : x:bigint -> byte, static member witnesses.convert_witness : x:bigint -> decimal, static member witnesses.convert_witness : x:bigint -> float, static member witnesses.convert_witness : x:bigint -> float32, static member witnesses.convert_witness : x:bigint -> int, static member witnesses.convert_witness : x:bigint -> int16, static member witnesses.convert_witness : x:bigint -> int64, static member witnesses.convert_witness : x:bigint -> sbyte, static member witnesses.convert_witness : x:bigint -> uint16, static member witnesses.convert_witness : x:bigint -> uint32, static member witnesses.convert_witness : x:bigint -> uint64 diff --git a/tests/fsharp/typecheck/sigs/neg127.fs b/tests/fsharp/typecheck/sigs/neg127.fs new file mode 100644 index 0000000000..ba44a1ae77 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg127.fs @@ -0,0 +1,59 @@ +module Neg127 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// See also pos35.fs, neg125.fs +// +// This no longer passes a dummy ^output but keeps ^output as a witness selector +// +// When both ^witnesses and ^input are known, the overload determining the ^output still can't be determined. +// However overload resolution is **not** delayed because the language rule is that overload resolution +// goes ahead once the support in the **argument** types of the constraint have all been resolved. +// +// This design decision for SRTP resolution was based on the (technically false but normally true) assumption that +// overload resolution will not depend on return type. +// +// The workaround for this in SRTP generic code is to pass a dummy Unchecked.defaultof<_> argument of the type of the +// return type. + +module Negative_SelectOverloadedWitnessBasedOnReturnTypeWithoutPassingDummyArgument = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint) = x + static member inline convert_witness (x : bigint) = float x + static member inline convert_witness (x : bigint) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint) = float32 x + static member inline convert_witness (x : bigint) = decimal x + static member inline convert_witness (x : bigint) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, ^output when (^witnesses or ^input or ^output) : (static member convert_witness : ^input -> ^output)> (b : ^input) = + ((^witnesses or ^input or ^output) : (static member convert_witness : ^input -> ^output) (b)) + + let inline convert num = + call_convert_witness (num) + // These all cause errors + let v1 : int32 = convert 0I + let v2 : int64 = convert 0I + let v3 : bigint = convert 0I + let v4 : float = convert 0I + let v5 : sbyte = convert 0I + let v6 : int16 = convert 0I + let v7 : byte = convert 0I + let v8 : uint16 = convert 0I + let v9 : uint32 = convert 0I + let v10 : uint64 = convert 0I + let v11 : float32 = convert 0I + let v12 : decimal = convert 0I + let v13 : Complex = convert 0I diff --git a/tests/fsharp/typecheck/sigs/neg128.bsl b/tests/fsharp/typecheck/sigs/neg128.bsl new file mode 100644 index 0000000000..3d91ad25b5 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg128.bsl @@ -0,0 +1,2 @@ + +neg128.fs(36,47,36,54): typecheck error FS0043: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint * _output:Complex -> Complex, static member witnesses.convert_witness : x:bigint * _output:bigint -> bigint, static member witnesses.convert_witness : x:bigint * _output:byte -> byte, static member witnesses.convert_witness : x:bigint * _output:decimal -> decimal, static member witnesses.convert_witness : x:bigint * _output:float -> float, static member witnesses.convert_witness : x:bigint * _output:float32 -> float32, static member witnesses.convert_witness : x:bigint * _output:int16 -> int16, static member witnesses.convert_witness : x:bigint * _output:int32 -> int, static member witnesses.convert_witness : x:bigint * _output:int64 -> int64, static member witnesses.convert_witness : x:bigint * _output:sbyte -> sbyte, static member witnesses.convert_witness : x:bigint * _output:uint16 -> uint16, static member witnesses.convert_witness : x:bigint * _output:uint32 -> uint32, static member witnesses.convert_witness : x:bigint * _output:uint64 -> uint64 diff --git a/tests/fsharp/typecheck/sigs/neg128.fs b/tests/fsharp/typecheck/sigs/neg128.fs new file mode 100644 index 0000000000..b936ee254b --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg128.fs @@ -0,0 +1,36 @@ +module Neg128 + +module Negative_SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentGenericOutputSelector = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint, _output : int32) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint, _output : int64) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint, _output : bigint) = x + static member inline convert_witness (x : bigint, _output : float) = float x + static member inline convert_witness (x : bigint, _output : sbyte) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint, _output : int16) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint, _output : byte) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint, _output : uint16) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint, _output : uint32) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint, _output : uint64) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint, _output : float32) = float32 x + static member inline convert_witness (x : bigint, _output : decimal) = decimal x + static member inline convert_witness (x : bigint, _output : Complex) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, 'output when (^witnesses or ^input) : (static member convert_witness : ^input * 'output -> 'output)> (b : ^input, c : 'output) = + ((^witnesses or ^input) : (static member convert_witness : ^input * 'output -> 'output) (b, c)) + + let inline convert num : 'output = + call_convert_witness (num, Unchecked.defaultof<'output>) + + // These solve ok + let v1 : int32 = convert 777I + let v2 : int64 = convert 777I + + // This gives an error, because solving kicks in once all selector types are known + let inline inst (num: bigint) : 'output = convert num diff --git a/tests/fsharp/typecheck/sigs/neg129.bsl b/tests/fsharp/typecheck/sigs/neg129.bsl new file mode 100644 index 0000000000..8e34cc5331 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg129.bsl @@ -0,0 +1,2 @@ + +neg129.fs(67,47,67,54): typecheck error FS0043: A unique overload for method 'convert_witness' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member witnesses.convert_witness : x:bigint * _output:Complex -> Complex, static member witnesses.convert_witness : x:bigint * _output:bigint -> bigint, static member witnesses.convert_witness : x:bigint * _output:byte -> byte, static member witnesses.convert_witness : x:bigint * _output:decimal -> decimal, static member witnesses.convert_witness : x:bigint * _output:float -> float, static member witnesses.convert_witness : x:bigint * _output:float32 -> float32, static member witnesses.convert_witness : x:bigint * _output:int16 -> int16, static member witnesses.convert_witness : x:bigint * _output:int32 -> int, static member witnesses.convert_witness : x:bigint * _output:int64 -> int64, static member witnesses.convert_witness : x:bigint * _output:sbyte -> sbyte, static member witnesses.convert_witness : x:bigint * _output:uint16 -> uint16, static member witnesses.convert_witness : x:bigint * _output:uint32 -> uint32, static member witnesses.convert_witness : x:bigint * _output:uint64 -> uint64 diff --git a/tests/fsharp/typecheck/sigs/neg129.fs b/tests/fsharp/typecheck/sigs/neg129.fs new file mode 100644 index 0000000000..d65671900b --- /dev/null +++ b/tests/fsharp/typecheck/sigs/neg129.fs @@ -0,0 +1,67 @@ +module Neg129 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// This removes ^output as a type selector for the witness, but continues to pass a dummy ^output +// +// This is sufficient to make nearly all resolutions go through except when we instantiate by input type alone +module Negative_SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentNoOutputSelector = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint, _output : int32) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint, _output : int64) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint, _output : bigint) = x + static member inline convert_witness (x : bigint, _output : float) = float x + static member inline convert_witness (x : bigint, _output : sbyte) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint, _output : int16) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint, _output : byte) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint, _output : uint16) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint, _output : uint32) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint, _output : uint64) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint, _output : float32) = float32 x + static member inline convert_witness (x : bigint, _output : decimal) = decimal x + static member inline convert_witness (x : bigint, _output : Complex) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member convert_witness : ^input * ^output -> ^output)> (b : ^input, c : ^output) = + ((^witnesses or ^input) : (static member convert_witness : ^input * ^output -> ^output) (b, c)) + + let inline convert num = + call_convert_witness (num, Unchecked.defaultof<'b>) + + // These are ok + let v1 : int32 = convert 777I + let v2 : int64 = convert 777I + let v3 : bigint = convert 777I + let v4 : float = convert 777I + let v5 : sbyte = convert 777I + let v6 : int16 = convert 777I + let v7 : byte = convert 777I + let v8 : uint16 = convert 777I + let v9 : uint32 = convert 777I + let v10 : uint64 = convert 777I + let v11 : float32 = convert 777I + let v12 : decimal = convert 777I + let v13 : Complex = convert 777I + + // These are ok + let f1 : _ -> int32 = convert + let f2 : _ -> int64 = convert + let f3 : _ -> bigint = convert + let f4 : _ -> float = convert + let f5 : _ -> sbyte = convert + let f6 : _ -> int16 = convert + let f7 : _ -> byte = convert + let f8 : _ -> uint16 = convert + let f9 : _ -> uint32 = convert + let f10 : _ -> uint64 = convert + let f11 : _ -> float32 = convert + let f12 : _ -> decimal = convert + let f13 : _ -> Complex = convert + + // This gives an error, because all selector types are known and overload resolution kicks in + let inline inst (num: bigint) : ^output = convert num diff --git a/tests/fsharp/typecheck/sigs/pos35.fs b/tests/fsharp/typecheck/sigs/pos35.fs new file mode 100644 index 0000000000..8848c965cd --- /dev/null +++ b/tests/fsharp/typecheck/sigs/pos35.fs @@ -0,0 +1,315 @@ +module Pos35 + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// We are selecting an overloaded witness based on input type +module SelectOverloadedWitnessBasedOnInputType = + type witnesses = + static member inline unsigned_witness (x : sbyte) = uint8 x + static member inline unsigned_witness (x : byte) = x + static member inline unsigned_witness (x : int16) = uint16 x + static member inline unsigned_witness (x : uint16) = x + static member inline unsigned_witness (x : int32) = uint32 x + static member inline unsigned_witness (x : uint32) = x + static member inline unsigned_witness (x : int64) = uint64 x + static member inline unsigned_witness (x : uint64) = x + + // Note, this doesn't try to use the output to select + let inline call_unsigned_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member unsigned_witness : ^input -> ^output)> (x : ^input) = + ((^witnesses or ^input) : (static member unsigned_witness : ^input -> ^output) x) + + // unsigned: ^a -> ^b + let inline unsigned num = call_unsigned_witness num + let v1 = unsigned 0y + let v2 = unsigned 0s + let v3 = unsigned 0 + let v4 = unsigned 0L + + let f1 : int8 -> uint8 = unsigned + let f2 : int16 -> uint16 = unsigned + let f3 : int32 -> uint32 = unsigned + let f4 : int64 -> uint64 = unsigned + + let g1 : int8 -> _ = unsigned + let g2 : int16 -> _ = unsigned + let g3 : int32 -> _ = unsigned + let g4 : int64 -> _ = unsigned + + // Negative cases - not enough information here - see neg124.fs which checks these + //let h1 : _ -> uint8 = unsigned + //let h2 : _ -> uint16 = unsigned + //let h3 : _ -> uint32 = unsigned + //let h4 : _ -> uint64 = unsigned + + +// Variation on the previous test case +// +// Note, this adds output as a selector though that shouldn't make any difference +module SelectOverloadedWitnessBasedOnInputTypePlusNeedlessOutputTypeSelector = + type witnesses = + static member inline unsigned_witness (x : sbyte) = uint8 x + static member inline unsigned_witness (x : byte) = x + static member inline unsigned_witness (x : int16) = uint16 x + static member inline unsigned_witness (x : uint16) = x + static member inline unsigned_witness (x : int32) = uint32 x + static member inline unsigned_witness (x : uint32) = x + static member inline unsigned_witness (x : int64) = uint64 x + static member inline unsigned_witness (x : uint64) = x + + let inline call_unsigned_witness< ^witnesses, ^input, ^output when (^witnesses or ^input or ^output) : (static member unsigned_witness : ^input -> ^output)> (x : ^input) = + ((^witnesses or ^input or ^output) : (static member unsigned_witness : ^input -> ^output) x) + + // unsigned: ^a -> ^b + let inline unsigned num = call_unsigned_witness num + let v1 = unsigned 0y + let v2 = unsigned 0s + let v3 = unsigned 0 + let v4 = unsigned 0L + + let f1 : int8 -> uint8 = unsigned + let f2 : int16 -> uint16 = unsigned + let f3 : int32 -> uint32 = unsigned + let f4 : int64 -> uint64 = unsigned + + let g1 : int8 -> _ = unsigned + let g2 : int16 -> _ = unsigned + let g3 : int32 -> _ = unsigned + let g4 : int64 -> _ = unsigned + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +module SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentAndUsingOutputSelector = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint, _output : int32) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint, _output : int64) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint, _output : bigint) = x + static member inline convert_witness (x : bigint, _output : float) = float x + static member inline convert_witness (x : bigint, _output : sbyte) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint, _output : int16) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint, _output : byte) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint, _output : uint16) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint, _output : uint32) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint, _output : uint64) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint, _output : float32) = float32 x + static member inline convert_witness (x : bigint, _output : decimal) = decimal x + static member inline convert_witness (x : bigint, _output : Complex) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, ^output when (^witnesses or ^input or ^output) : (static member convert_witness : ^input * ^output -> ^output)> (b : ^input, c : ^output) = + ((^witnesses or ^input or ^output) : (static member convert_witness : ^input * ^output -> ^output) (b, c)) + + let inline convert num = + call_convert_witness (num, Unchecked.defaultof<'b>) + + let v1 : int32 = convert 777I + let v2 : int64 = convert 777I + let v3 : bigint = convert 777I + let v4 : float = convert 777I + let v5 : sbyte = convert 777I + let v6 : int16 = convert 777I + let v7 : byte = convert 777I + let v8 : uint16 = convert 777I + let v9 : uint32 = convert 777I + let v10 : uint64 = convert 777I + let v11 : float32 = convert 777I + let v12 : decimal = convert 777I + let v13 : Complex = convert 777I + + // This is enough to determine the input as bigint because those are the only solutions available + let f1 : _ -> int32 = convert + let f2 : _ -> int64 = convert + let f3 : _ -> bigint = convert + let f4 : _ -> float = convert + let f5 : _ -> sbyte = convert + let f6 : _ -> int16 = convert + let f7 : _ -> byte = convert + let f8 : _ -> uint16 = convert + let f9 : _ -> uint32 = convert + let f10 : _ -> uint64 = convert + let f11 : _ -> float32 = convert + let f12 : _ -> decimal = convert + let f13 : _ -> Complex = convert + + // This is permitted because the ^output type is still a selector + // + // The resulting type is like this: + // + // val inline inst : num:bigint -> ^output when (witnesses or bigint or ^output) : (static member convert_witness : bigint * ^output -> ^output) + let inline inst (num: bigint) : ^output = convert num + let i1 : int32 = inst 777I + let i2 : int64 = inst 777I + let i3 : bigint = inst 777I + let i4 : float = inst 777I + let i5 : sbyte = inst 777I + let i6 : int16 = inst 777I + let i7 : byte = inst 777I + let i8 : uint16 = inst 777I + let i9 : uint32 = inst 777I + let i10 : uint64 = inst 777I + let i11 : float32 = inst 777I + let i12 : decimal = inst 777I + let i13 : Complex = inst 777I + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// This removes ^output as a type selector for the witness, but continues to pass a dummy ^output +// +// This is sufficient to make the resolutions go through +module SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentNoOutputSelector = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint, _output : int32) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint, _output : int64) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint, _output : bigint) = x + static member inline convert_witness (x : bigint, _output : float) = float x + static member inline convert_witness (x : bigint, _output : sbyte) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint, _output : int16) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint, _output : byte) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint, _output : uint16) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint, _output : uint32) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint, _output : uint64) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint, _output : float32) = float32 x + static member inline convert_witness (x : bigint, _output : decimal) = decimal x + static member inline convert_witness (x : bigint, _output : Complex) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, ^output when (^witnesses or ^input) : (static member convert_witness : ^input * ^output -> ^output)> (b : ^input, c : ^output) = + ((^witnesses or ^input) : (static member convert_witness : ^input * ^output -> ^output) (b, c)) + + let inline convert num = + call_convert_witness (num, Unchecked.defaultof<'b>) + + let v1 : int32 = convert 777I + let v2 : int64 = convert 777I + let v3 : bigint = convert 777I + let v4 : float = convert 777I + let v5 : sbyte = convert 777I + let v6 : int16 = convert 777I + let v7 : byte = convert 777I + let v8 : uint16 = convert 777I + let v9 : uint32 = convert 777I + let v10 : uint64 = convert 777I + let v11 : float32 = convert 777I + let v12 : decimal = convert 777I + let v13 : Complex = convert 777I + + // This is enough to determine the input as bigint because those are the only solutions available + let f1 : _ -> int32 = convert + let f2 : _ -> int64 = convert + let f3 : _ -> bigint = convert + let f4 : _ -> float = convert + let f5 : _ -> sbyte = convert + let f6 : _ -> int16 = convert + let f7 : _ -> byte = convert + let f8 : _ -> uint16 = convert + let f9 : _ -> uint32 = convert + let f10 : _ -> uint64 = convert + let f11 : _ -> float32 = convert + let f12 : _ -> decimal = convert + let f13 : _ -> Complex = convert + + // Adding this gives an error, see neg129.fs for the test for this + // let inline inst (num: bigint) : ^output = convert num + +// Variation on test case mentioned in https://github.com/dotnet/fsharp/pull/6805#issuecomment-580368303 +// +// Same as SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentNoOutputSelector but the output type +// parameter is generic 'output rather than SRTP ^output +// + +module SelectOverloadedWitnessBasedOnReturnTypeByPassingDummyArgumentGenericOutputType = + open System + open System.Numerics + let _uint8max = bigint (uint32 Byte.MaxValue) + let _uint16max = bigint (uint32 UInt16.MaxValue) + let _uint32max = bigint UInt32.MaxValue + let _uint64max = bigint UInt64.MaxValue + type witnesses = + static member inline convert_witness (x : bigint, _output : int32) = int (uint32 (x &&& _uint32max)) + static member inline convert_witness (x : bigint, _output : int64) = int64 (uint64 (x &&& _uint64max)) + static member inline convert_witness (x : bigint, _output : bigint) = x + static member inline convert_witness (x : bigint, _output : float) = float x + static member inline convert_witness (x : bigint, _output : sbyte) = sbyte (byte (x &&& _uint8max)) + static member inline convert_witness (x : bigint, _output : int16) = int16 (uint16 (x &&& _uint16max)) + static member inline convert_witness (x : bigint, _output : byte) = byte (x &&& _uint8max) + static member inline convert_witness (x : bigint, _output : uint16) = uint16 (x &&& _uint16max) + static member inline convert_witness (x : bigint, _output : uint32) = uint32 (x &&& _uint32max) + static member inline convert_witness (x : bigint, _output : uint64) = uint64 (x &&& _uint64max) + static member inline convert_witness (x : bigint, _output : float32) = float32 x + static member inline convert_witness (x : bigint, _output : decimal) = decimal x + static member inline convert_witness (x : bigint, _output : Complex) = Complex(float x, 0.0) + + let inline call_convert_witness< ^witnesses, ^input, 'output when (^witnesses or ^input) : (static member convert_witness : ^input * 'output -> 'output)> (b : ^input, c : 'output) = + ((^witnesses or ^input) : (static member convert_witness : ^input * 'output -> 'output) (b, c)) + + let inline convert num : 'output = + call_convert_witness (num, Unchecked.defaultof<'output>) + + let v1 : int32 = convert 777I + let v2 : int64 = convert 777I + let v3 : bigint = convert 777I + let v4 : float = convert 777I + let v5 : sbyte = convert 777I + let v6 : int16 = convert 777I + let v7 : byte = convert 777I + let v8 : uint16 = convert 777I + let v9 : uint32 = convert 777I + let v10 : uint64 = convert 777I + let v11 : float32 = convert 777I + let v12 : decimal = convert 777I + let v13 : Complex = convert 777I + + // This is enough to determine the input as bigint because those are the only solutions available + let f1 : _ -> int32 = convert + let f2 : _ -> int64 = convert + let f3 : _ -> bigint = convert + let f4 : _ -> float = convert + let f5 : _ -> sbyte = convert + let f6 : _ -> int16 = convert + let f7 : _ -> byte = convert + let f8 : _ -> uint16 = convert + let f9 : _ -> uint32 = convert + let f10 : _ -> uint64 = convert + let f11 : _ -> float32 = convert + let f12 : _ -> decimal = convert + let f13 : _ -> Complex = convert + + // Adding this gives an error, see neg128.fs for the test for this + // let inline inst (num: bigint) : 'output = convert num + + +// Reduced FSharpPlus tests case from https://github.com/dotnet/fsharp/pull/6805#issuecomment-580365649 +module PositiveTestCase3 = + [] + module Extensions = + + type Async<'T> with + + static member Quack (x:seq>) : Async> = failwith "" + + type Option<'T> with + + static member Quack (x: seq>) : option> = failwith "" + + let inline CallQuack (x: ^a) : ^Output = (^a : (static member Quack : ^a -> ^Output) x) + + type Witnesses = + + static member inline QuackWitness (x: ^a, _output: ^Output, _impl: Witnesses) : ^Output = CallQuack x + static member inline QuackWitness (x: ref<_>, _output: ^Output, _impl: Witnesses) : ^Output = Unchecked.defaultof<_> + + let inline CallQuackWitness (x: ^a, output: ^Output, witnesses: ^Witnesses) = + ((^a or ^Output or ^Witnesses) : (static member QuackWitness : _*_*_ -> _) (x, output, witnesses)) + + let inline call (x: seq< ^b > ) : ^Output = + CallQuackWitness (x, Unchecked.defaultof< ^Output >, Unchecked.defaultof) + + + diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/env.lst b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/env.lst index a738455663..44481e7ef7 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/env.lst +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/env.lst @@ -26,8 +26,6 @@ NOMONO,NoMT SOURCE=ConsumeOverloadGenericMethods.fs SCFLAGS="-r:lib.dll" PRECMD= SOURCE=InferenceForLambdaArgs.fs # InferenceForLambdaArgs.fs - SOURCE=SlowOverloadResolution.fs # SlowOverloadResolution.fs - SOURCE=E_OverloadCurriedFunc.fs # E_OverloadCurriedFunc.fs SOURCE=E_OverloadMismatch.fs # E_OverloadMismatch.fs SOURCE=NoWarningWhenOverloadingInSubClass01.fs SCFLAGS="--warnaserror" # NoWarningWhenOverloadingInSubClass01.fs From 3b9f82baed2972ab7846d2d7ab365e95031c8dd7 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 3 Feb 2020 12:15:24 -0800 Subject: [PATCH 094/101] Enable language preview option for fsi in the ide (#8443) --- src/fsharp/service/service.fs | 14 +++++++++---- src/fsharp/service/service.fsi | 2 +- .../FSharpProjectOptionsManager.fs | 3 ++- .../BackgroundRequests.fs | 3 ++- .../src/FSharp.VS.FSI/Properties.resx | 10 +++++++++ .../src/FSharp.VS.FSI/fsiLanguageService.fs | 21 ++++++++++++------- vsintegration/src/FSharp.VS.FSI/sessions.fs | 20 ++++++++++++------ .../src/FSharp.VS.FSI/xlf/Properties.cs.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.de.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.es.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.fr.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.it.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.ja.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.ko.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.pl.xlf | 15 +++++++++++++ .../FSharp.VS.FSI/xlf/Properties.pt-BR.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.ru.xlf | 15 +++++++++++++ .../src/FSharp.VS.FSI/xlf/Properties.tr.xlf | 15 +++++++++++++ .../FSharp.VS.FSI/xlf/Properties.zh-Hans.xlf | 15 +++++++++++++ .../FSharp.VS.FSI/xlf/Properties.zh-Hant.xlf | 15 +++++++++++++ vsintegration/tests/Salsa/salsa.fs | 2 +- 21 files changed, 248 insertions(+), 22 deletions(-) diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 978d6cd087..a5db4e09b4 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -742,7 +742,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC member bc.ParseAndCheckProject(options, userOpName) = reactor.EnqueueAndAwaitOpAsync(userOpName, "ParseAndCheckProject", options.ProjectFileName, fun ctok -> bc.ParseAndCheckProjectImpl(options, ctok, userOpName)) - member __.GetProjectOptionsFromScript(filename, sourceText, loadedTimeStamp, otherFlags, useFsiAuxLib: bool option, useSdkRefs: bool option, assumeDotNetFramework: bool option, extraProjectInfo: obj option, optionsStamp: int64 option, userOpName) = + member __.GetProjectOptionsFromScript(filename, sourceText, previewEnabled, loadedTimeStamp, otherFlags, useFsiAuxLib: bool option, useSdkRefs: bool option, assumeDotNetFramework: bool option, extraProjectInfo: obj option, optionsStamp: int64 option, userOpName) = reactor.EnqueueAndAwaitOpAsync (userOpName, "GetProjectOptionsFromScript", filename, fun ctok -> cancellable { use errors = new ErrorScope() @@ -751,10 +751,16 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let useFsiAuxLib = defaultArg useFsiAuxLib true let useSdkRefs = defaultArg useSdkRefs true let reduceMemoryUsage = ReduceMemoryFlag.Yes + let previewEnabled = defaultArg previewEnabled false // Do we assume .NET Framework references for scripts? let assumeDotNetFramework = defaultArg assumeDotNetFramework true - let otherFlags = defaultArg otherFlags [| |] + let extraFlags = + if previewEnabled then + [| "--langversion:preview" |] + else + [||] + let otherFlags = defaultArg otherFlags extraFlags let useSimpleResolution = #if ENABLE_MONO_SUPPORT runningOnMono || otherFlags |> Array.exists (fun x -> x = "--simpleresolution") @@ -1142,9 +1148,9 @@ type FSharpChecker(legacyReferenceResolver, backgroundCompiler.ParseAndCheckProject(options, userOpName) /// For a given script file, get the ProjectOptions implied by the #load closure - member __.GetProjectOptionsFromScript(filename, source, ?loadedTimeStamp, ?otherFlags, ?useFsiAuxLib, ?useSdkRefs, ?assumeDotNetFramework, ?extraProjectInfo: obj, ?optionsStamp: int64, ?userOpName: string) = + member __.GetProjectOptionsFromScript(filename, source, ?previewEnabled, ?loadedTimeStamp, ?otherFlags, ?useFsiAuxLib, ?useSdkRefs, ?assumeDotNetFramework, ?extraProjectInfo: obj, ?optionsStamp: int64, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" - backgroundCompiler.GetProjectOptionsFromScript(filename, source, loadedTimeStamp, otherFlags, useFsiAuxLib, useSdkRefs, assumeDotNetFramework, extraProjectInfo, optionsStamp, userOpName) + backgroundCompiler.GetProjectOptionsFromScript(filename, source, previewEnabled, loadedTimeStamp, otherFlags, useFsiAuxLib, useSdkRefs, assumeDotNetFramework, extraProjectInfo, optionsStamp, userOpName) member __.GetProjectOptionsFromCommandLineArgs(projectFileName, argv, ?loadedTimeStamp, ?extraProjectInfo: obj) = let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index c463f2a2ee..a209e8e428 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -228,7 +228,7 @@ type public FSharpChecker = /// so that an 'unload' and 'reload' action will cause the script to be considered as a new project, /// so that references are re-resolved. /// An optional string used for tracing compiler operations associated with this request. - member GetProjectOptionsFromScript : filename: string * sourceText: ISourceText * ?loadedTimeStamp: DateTime * ?otherFlags: string[] * ?useFsiAuxLib: bool * ?useSdkRefs: bool * ?assumeDotNetFramework: bool * ?extraProjectInfo: obj * ?optionsStamp: int64 * ?userOpName: string -> Async + member GetProjectOptionsFromScript : filename: string * sourceText: ISourceText * ?previewEnabled:bool * ?loadedTimeStamp: DateTime * ?otherFlags: string[] * ?useFsiAuxLib: bool * ?useSdkRefs: bool * ?assumeDotNetFramework: bool * ?extraProjectInfo: obj * ?optionsStamp: int64 * ?userOpName: string -> Async /// /// Get the FSharpProjectOptions implied by a set of command line arguments. diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index 5a2c3eed96..085ccfcff9 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -20,6 +20,7 @@ open System.Threading open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.LanguageServices.Implementation.TaskList open Microsoft.CodeAnalysis.ExternalAccess.FSharp.LanguageServices +open Microsoft.VisualStudio.FSharp.Interactive.Session [] module private FSharpProjectOptionsHelpers = @@ -97,7 +98,7 @@ type private FSharpProjectOptionsReactor (_workspace: VisualStudioWorkspace, set match singleFileCache.TryGetValue(document.Id) with | false, _ -> let! sourceText = document.GetTextAsync(ct) |> Async.AwaitTask - let! scriptProjectOptions, _ = checkerProvider.Checker.GetProjectOptionsFromScript(document.FilePath, sourceText.ToFSharpSourceText()) + let! scriptProjectOptions, _ = checkerProvider.Checker.GetProjectOptionsFromScript(document.FilePath, sourceText.ToFSharpSourceText(), SessionsProperties.fsiPreview) let projectOptions = if isScriptFile document.FilePath then scriptProjectOptions diff --git a/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs b/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs index 10cd776b0d..7bc288a551 100644 --- a/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs +++ b/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs @@ -11,6 +11,7 @@ open Microsoft.VisualStudio.TextManager.Interop open Microsoft.VisualStudio.Text open FSharp.Compiler.SourceCodeServices open Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider +open Microsoft.VisualStudio.FSharp.Interactive.Session #nowarn "44" // use of obsolete CheckFileInProjectAllowingStaleCachedResults @@ -94,7 +95,7 @@ type internal FSharpLanguageServiceBackgroundRequests_DEPRECATED lazy // This portion is executed on the language service thread let timestamp = if source=null then System.DateTime(2000,1,1) else source.OpenedTime // source is null in unit tests let checker = getInteractiveChecker() - let checkOptions, _diagnostics = checker.GetProjectOptionsFromScript(fileName, FSharp.Compiler.Text.SourceText.ofString sourceText, timestamp, [| |]) |> Async.RunSynchronously + let checkOptions, _diagnostics = checker.GetProjectOptionsFromScript(fileName, FSharp.Compiler.Text.SourceText.ofString sourceText, SessionsProperties.fsiPreview, timestamp, [| |]) |> Async.RunSynchronously let referencedProjectFileNames = [| |] let projectSite = ProjectSitesAndFiles.CreateProjectSiteForScript(fileName, referencedProjectFileNames, checkOptions) { ProjectSite = projectSite diff --git a/vsintegration/src/FSharp.VS.FSI/Properties.resx b/vsintegration/src/FSharp.VS.FSI/Properties.resx index 8739ec83ee..bf0ca9896e 100644 --- a/vsintegration/src/FSharp.VS.FSI/Properties.resx +++ b/vsintegration/src/FSharp.VS.FSI/Properties.resx @@ -148,4 +148,14 @@ Debugging + + FSI Preview + + + Enable preview of in-development language features in F# Interactive + + + Enable preview language features + + \ No newline at end of file diff --git a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs index 6177d8bba2..19f5489b51 100644 --- a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs +++ b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs @@ -36,30 +36,35 @@ module internal ContentType = [] [] type FsiPropertyPage() = - inherit DialogPage() - + inherit DialogPage() + [] - [] - [] + [] + [] member this.FsiPreferAnyCPUVersion with get() = SessionsProperties.useAnyCpuVersion and set (x:bool) = SessionsProperties.useAnyCpuVersion <- x [] [] - [] + [] member this.FsiCommandLineArgs with get() = SessionsProperties.fsiArgs and set (x:string) = SessionsProperties.fsiArgs <- x [] [] - [] + [] member this.FsiShadowCopy with get() = SessionsProperties.fsiShadowCopy and set (x:bool) = SessionsProperties.fsiShadowCopy <- x [] [] - [] + [] member this.FsiDebugMode with get() = SessionsProperties.fsiDebugMode and set (x:bool) = SessionsProperties.fsiDebugMode <- x + [] + [] + [] + member this.FsiPreview with get() = SessionsProperties.fsiPreview and set (x:bool) = SessionsProperties.fsiPreview <- x + // CompletionSet -type internal FsiCompletionSet(imageList,source:Source) = +type internal FsiCompletionSet(imageList,source:Source) = inherit CompletionSet(imageList, source) // Declarations diff --git a/vsintegration/src/FSharp.VS.FSI/sessions.fs b/vsintegration/src/FSharp.VS.FSI/sessions.fs index b1b5a85616..96585aafcc 100644 --- a/vsintegration/src/FSharp.VS.FSI/sessions.fs +++ b/vsintegration/src/FSharp.VS.FSI/sessions.fs @@ -70,6 +70,7 @@ module SessionsProperties = let mutable fsiArgs = "--optimize" let mutable fsiShadowCopy = true let mutable fsiDebugMode = false + let mutable fsiPreview = false // This code pre-dates the events/object system. // Later: Tidy up. @@ -218,7 +219,7 @@ let fsiStartInfo channelName = let addBoolOption name value args = sprintf "%s --%s%s" args name (if value then "+" else "-") let addStringOption name value args = sprintf "%s --%s:%O" args name value - + let procArgs = "" |> addStringOption "fsi-server-output-codepage" outCP @@ -227,11 +228,18 @@ let fsiStartInfo channelName = |> addStringOption "fsi-server" channelName |> (fun s -> s + sprintf " %s" SessionsProperties.fsiArgs) |> addBoolOption "shadowcopyreferences" SessionsProperties.fsiShadowCopy - |> (fun args -> if SessionsProperties.fsiDebugMode then - // for best debug experience, need optimizations OFF and debug info ON - // tack these on the the end, they will override whatever comes earlier - args |> addBoolOption "optimize" false |> addBoolOption "debug" true - else args) + |> (fun args -> + // for best debug experience, need optimizations OFF and debug info ON + // tack these on the the end, they will override whatever comes earlier + if SessionsProperties.fsiDebugMode then + args |> addBoolOption "optimize" false |> addBoolOption "debug" true + else + args) + |> (fun args -> + if SessionsProperties.fsiPreview then + args |> addStringOption "langversion" "preview" + else + args) procInfo.Arguments <- procArgs procInfo.CreateNoWindow <- true diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.cs.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.cs.xlf index 33f237c69b..68935f93c5 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.cs.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.cs.xlf @@ -27,6 +27,21 @@ Různé + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Sestavení stínových kopií diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.de.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.de.xlf index 989b2031fe..940aab17bf 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.de.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.de.xlf @@ -27,6 +27,21 @@ Verschiedene + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Schattenkopie-Assemblys diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.es.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.es.xlf index 725e86521e..0a1b501be4 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.es.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.es.xlf @@ -27,6 +27,21 @@ Varios + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Ensamblados de instantánea diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.fr.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.fr.xlf index 1c66865aea..fa844fde19 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.fr.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.fr.xlf @@ -27,6 +27,21 @@ Divers + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Assemblys de cliché instantané diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.it.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.it.xlf index 3ab00cc2b5..8ddc458706 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.it.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.it.xlf @@ -27,6 +27,21 @@ Varie + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Assembly copie shadow diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ja.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ja.xlf index 1b938bc2d4..11e95770cf 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ja.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ja.xlf @@ -27,6 +27,21 @@ その他 + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies シャドウ コピーのアセンブリ diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ko.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ko.xlf index b030fad5e5..76d4b3216f 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ko.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ko.xlf @@ -27,6 +27,21 @@ 기타 + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies 섀도 복사본 어셈블리 diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pl.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pl.xlf index 48e1694269..3f38d85c15 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pl.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pl.xlf @@ -27,6 +27,21 @@ Różne + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Zestawy kopii w tle diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pt-BR.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pt-BR.xlf index 6099d3d9fd..d2b6dfe97d 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pt-BR.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.pt-BR.xlf @@ -27,6 +27,21 @@ Diversos + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Assemblies de cópia de sombra diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ru.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ru.xlf index a4acb57958..36b620b843 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ru.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.ru.xlf @@ -27,6 +27,21 @@ Прочее + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Теневое копирование сборок diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.tr.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.tr.xlf index 5fef942b6e..022e212e42 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.tr.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.tr.xlf @@ -27,6 +27,21 @@ Çeşitli + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies Gölge kopya bütünleştirilmiş kodları diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hans.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hans.xlf index fa1db48b94..e31cd895f0 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hans.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hans.xlf @@ -27,6 +27,21 @@ 杂项 + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies 卷影副本程序集 diff --git a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hant.xlf b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hant.xlf index dd4f7af326..7b89906118 100644 --- a/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hant.xlf +++ b/vsintegration/src/FSharp.VS.FSI/xlf/Properties.zh-Hant.xlf @@ -27,6 +27,21 @@ 其他 + + FSI Preview + FSI Preview + + + + Enable preview language features + Enable preview language features + + + + Enable preview of in-development language features in F# Interactive + Enable preview of in-development language features in F# Interactive + + Shadow copy assemblies 陰影複製組件 diff --git a/vsintegration/tests/Salsa/salsa.fs b/vsintegration/tests/Salsa/salsa.fs index 52f2de8c90..b4ca688c17 100644 --- a/vsintegration/tests/Salsa/salsa.fs +++ b/vsintegration/tests/Salsa/salsa.fs @@ -1101,7 +1101,7 @@ module internal Salsa = member file.GetFileName() = filename member file.GetProjectOptionsOfScript() = - project.Solution.Vs.LanguageService.FSharpChecker.GetProjectOptionsFromScript(filename, FSharp.Compiler.Text.SourceText.ofString file.CombinedLines, System.DateTime(2000,1,1), [| |]) + project.Solution.Vs.LanguageService.FSharpChecker.GetProjectOptionsFromScript(filename, FSharp.Compiler.Text.SourceText.ofString file.CombinedLines, false, System.DateTime(2000,1,1), [| |]) |> Async.RunSynchronously |> fst // drop diagnostics From 3cefbba59dec3f4e787216cee5dbeea4bfeeddc8 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 3 Feb 2020 14:26:28 -0800 Subject: [PATCH 095/101] Reattach comment (#8445) --- src/fsharp/AttributeChecking.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/AttributeChecking.fs b/src/fsharp/AttributeChecking.fs index fb19937c53..056858d93f 100644 --- a/src/fsharp/AttributeChecking.fs +++ b/src/fsharp/AttributeChecking.fs @@ -265,9 +265,10 @@ let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = | _ -> CompleteD +let langVersionPrefix = "--langversion:preview" + /// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute', /// returning errors and warnings as data -let langVersionPrefix = "--langversion:preview" let CheckFSharpAttributes (g:TcGlobals) attribs m = let isExperimentalAttributeDisabled (s:string) = if g.compilingFslib then From e71fd0365e8561ee02fd0bd3970ec1ae847d06ad Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 4 Feb 2020 16:36:55 -0800 Subject: [PATCH 096/101] Update dependency notification (#8455) * Rework dependency notifications * rework Dependency events --- src/fsharp/DependencyManager.Integration.fs | 18 +++++++++++++++--- src/fsharp/DependencyManager.Integration.fsi | 2 +- src/fsharp/fsi/fsi.fs | 2 +- src/fsharp/fsi/fsi.fsi | 2 +- .../DependencyManagerInteractiveTests.fs | 12 ++++++++++-- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index c1eacf1b5b..453dcfa6a6 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -64,7 +64,7 @@ type internal IDependencyManagerProvider = abstract Key: string abstract ResolveDependencies: scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list abstract DependencyAdding: IEvent - abstract DependencyAdded: IEvent + abstract DependencyAdded: IEvent abstract DependencyFailed: IEvent [] @@ -96,9 +96,12 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn Some (fun () -> new ReflectionDependencyManagerProvider(theType, nameProperty, keyProperty, resolveDependenciesMethod, outputDir) :> IDependencyManagerProvider) interface IDependencyManagerProvider with + member __.Name = instance |> nameProperty + member __.Key = instance |> keyProperty member this.ResolveDependencies(scriptDir, packageManagerTextLines, tfm) = + let key = (this :> IDependencyManagerProvider).Key let triggerEvent (evt: Event) = for prLine in packageManagerTextLines do @@ -106,13 +109,22 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn triggerEvent dependencyAddingEvent let arguments = [| box scriptDir; box packageManagerTextLines; box tfm |] let succeeded, generatedScripts, additionalIncludeFolders = resolveDeps.Invoke(instance, arguments) :?> _ - if succeeded then triggerEvent dependencyAddedEvent - else triggerEvent dependencyFailedEvent + + for prLine in packageManagerTextLines do + if succeeded then + dependencyAddedEvent.Trigger(key, prLine, generatedScripts, additionalIncludeFolders) + else + dependencyFailedEvent.Trigger(key, prLine) + succeeded, generatedScripts, additionalIncludeFolders + member __.DependencyAdding = dependencyAddingEvent.Publish + member __.DependencyAdded = dependencyAddedEvent.Publish + member __.DependencyFailed = dependencyFailedEvent.Publish + // Resolution Path = Location of FSharp.Compiler.Private.dll let assemblySearchPaths = lazy ( [ diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 352a052a56..3029da21b0 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -10,7 +10,7 @@ type IDependencyManagerProvider = abstract Key: string abstract ResolveDependencies: scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list abstract DependencyAdding: IEvent - abstract DependencyAdded: IEvent + abstract DependencyAdded: IEvent abstract DependencyFailed: IEvent [] diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 97259cd372..aece6638ff 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -958,7 +958,7 @@ type internal FsiDynamicCompiler let valueBoundEvent = Control.Event<_>() let dependencyAddingEvent = Control.Event() - let dependencyAddedEvent = Control.Event() + let dependencyAddedEvent = Control.Event() let dependencyFailedEvent = Control.Event() let mutable fragmentId = 0 diff --git a/src/fsharp/fsi/fsi.fsi b/src/fsharp/fsi/fsi.fsi index 453a1a4952..d8f66297e7 100644 --- a/src/fsharp/fsi/fsi.fsi +++ b/src/fsharp/fsi/fsi.fsi @@ -240,7 +240,7 @@ type FsiEvaluationSession = [] /// Event fires at the successful completion of adding a dependency via the dependency manager. - member DependencyAdded: IEvent + member DependencyAdded: IEvent [] /// Event fires at the failure to adding a dependency via the dependency manager. diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 4d3a0945ce..3a10bf231e 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -57,19 +57,27 @@ type DependencyManagerInteractiveTests() = let mutable dependencyAddedEventCount = 0 let mutable foundDependencyAdding = false let mutable foundDependencyAdded = false + let mutable packageRootsCount = 0 + let mutable generatedScriptsCount = 0 Event.add (fun (dep: string * string) -> let key, dependency = dep dependencyAddingEventCount <- dependencyAddingEventCount + 1 foundDependencyAdding <- foundDependencyAdding || (key = "nuget" && dependency = referenceText)) script.DependencyAdding - Event.add (fun (dep: string * string) -> - let key, dependency = dep + Event.add (fun (dep: string * string * string list * string list) -> + let key, dependency, _generatedScripts, _packageRoots = dep + generatedScriptsCount <- _generatedScripts.Length + packageRootsCount <- _packageRoots.Length dependencyAddedEventCount <- dependencyAddedEventCount + 1 foundDependencyAdded <- foundDependencyAdded || (key = "nuget" && dependency = referenceText)) script.DependencyAdded script.Eval(text) |> ignoreValue Assert.AreEqual(1, dependencyAddingEventCount) Assert.AreEqual(1, dependencyAddedEventCount) + Assert.AreEqual(1, dependencyAddingEventCount) + Assert.AreEqual(1, dependencyAddedEventCount) + Assert.AreEqual(1, generatedScriptsCount) + Assert.AreEqual(1, dependencyAddedEventCount) Assert.AreEqual(true, foundDependencyAdding) Assert.AreEqual(true, foundDependencyAdded) From ff20f70d4d973f69b2661318918332aafab50a79 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 09:44:55 -0600 Subject: [PATCH 097/101] cross-platform wrapper around memory-backed memorymappedfile creation (#8403) * cross-platform wrapper around memory-backed memorymappedfile creation * reenable FCS tests on non-windows platforms * publish test results on non-windows platforms * ensure correct .net sdk versions are installed regardless of VM image preloads * simple workaround for missing mscorlib versions to TFMs * publish per-framework xml results and report them in AZDO * rework mono fixes to use ByteArrayMemory directly * move runningOnMono call to bytes.fs and patch up callsites * revert to build-only on mono-containing platforms another MR will be required to fix the underlying logic before those can be changed to run tests again * trigger ci --- azure-pipelines.yml | 58 ++++++-- eng/Versions.props | 2 +- .../FSharp.Compiler.Service.Tests.fsproj | 10 +- fcs/build.fsx | 6 +- fcs/samples/FscExe/FscMain.fs | 2 +- src/absil/bytes.fs | 128 +++++++++++------- src/absil/bytes.fsi | 3 +- src/absil/il.fs | 18 --- src/absil/il.fsi | 2 - src/absil/ilread.fs | 7 +- src/absil/ilreflect.fs | 1 + src/absil/ilsupp.fs | 8 +- src/absil/ilwrite.fs | 13 +- src/absil/ilwritepdb.fs | 3 +- src/fsharp/CompileOps.fs | 1 + src/fsharp/CompileOptions.fs | 3 +- src/fsharp/DotNetFrameworkDependencies.fs | 25 ++-- src/fsharp/LegacyMSBuildReferenceResolver.fs | 2 +- src/fsharp/fsc.fs | 3 +- src/fsharp/fsi/fsi.fs | 1 + src/fsharp/service/service.fs | 3 +- tests/service/ScriptOptionsTests.fs | 36 +++++ 22 files changed, 217 insertions(+), 118 deletions(-) create mode 100644 tests/service/ScriptOptionsTests.fs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 566be9e28d..966baf9ee2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -342,6 +342,11 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs - script: fcs\build.cmd TestAndNuget displayName: Build / Test - task: PublishTestResults@2 @@ -350,6 +355,7 @@ stages: testResultsFormat: 'NUnit' testResultsFiles: '*.xml' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true continueOnError: true condition: always() @@ -362,20 +368,48 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs - script: ./fcs/build.sh - displayName: Build + displayName: Build / Test + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true + continueOnError: true + condition: always() - # - job: MacOS_FCS - # pool: - # vmImage: macOS-latest - # variables: - # - name: _SignType - # value: Test - # steps: - # - checkout: self - # clean: true - # - script: ./fcs/build.sh - # displayName: Build + - job: MacOS_FCS + pool: + vmImage: macOS-latest + variables: + - name: _SignType + value: Test + steps: + - checkout: self + clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs + - script: ./fcs/build.sh + displayName: Build / Test + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true + continueOnError: true + condition: always() #---------------------------------------------------------------------------------------------------------------------# # Post Build # diff --git a/eng/Versions.props b/eng/Versions.props index 1ee1522072..5b0f95663e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -183,7 +183,7 @@ 3.11.0 3.11.2 3.11.0 - 2.1.36 + 2.1.41 1.0.0-beta2-dev3 5.28.0.1 2.0.187 diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 072e2e0a58..2c80e36b01 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -1,5 +1,6 @@ + $(FcsTargetNetFxFramework);netcoreapp3.0 true @@ -60,6 +61,9 @@ TreeVisitorTests.fs + + ScriptOptionsTests.fs + Program.fs @@ -71,10 +75,10 @@ - - - + + + diff --git a/fcs/build.fsx b/fcs/build.fsx index 00dc80cf6f..c599d58135 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -73,9 +73,9 @@ Target.create "Test" (fun _ -> // This project file is used for the netcoreapp2.0 tests to work out reference sets runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -nodereuse:false -v n /restore /p:DisableCompilerRedirection=true" - // Now run the tests - let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") - runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath) + // Now run the tests (different output files per TFM) + let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.{framework}.xml") + runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --logger \"nunit;LogFilePath=%s\"" logFilePath) ) Target.create "NuGet" (fun _ -> diff --git a/fcs/samples/FscExe/FscMain.fs b/fcs/samples/FscExe/FscMain.fs index b2d5d6a899..36b980cbbb 100644 --- a/fcs/samples/FscExe/FscMain.fs +++ b/fcs/samples/FscExe/FscMain.fs @@ -8,7 +8,7 @@ open System.IO open System.Reflection open System.Runtime.CompilerServices open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.AbstractIL.IL // runningOnMono +open FSharp.Compiler.AbstractIL.Internal.Utils // runningOnMono open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.ErrorLogger diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 7e2f0ab2c9..52d041c367 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -12,6 +12,25 @@ open FSharp.NativeInterop #nowarn "9" +module Utils = + let runningOnMono = + #if ENABLE_MONO_SUPPORT + // Officially supported way to detect if we are running on Mono. + // See http://www.mono-project.com/FAQ:_Technical + // "How can I detect if am running in Mono?" section + try + System.Type.GetType ("Mono.Runtime") <> null + with _ -> + // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent + // that is not reliable. + // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is + // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get + // their issue fixed but we need to be robust here anyway. + false + #else + false + #endif + module internal Bytes = let b0 n = (n &&& 0xFF) let b1 n = ((n >>> 8) &&& 0xFF) @@ -296,65 +315,72 @@ type ByteMemory with member x.AsReadOnly() = ReadOnlyByteMemory x static member CreateMemoryMappedFile(bytes: ReadOnlyByteMemory) = - let length = int64 bytes.Length - let mmf = + if Utils.runningOnMono + then + // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245 + ByteArrayMemory.FromArray (bytes.ToArray()) :> ByteMemory + else + let length = int64 bytes.Length let mmf = - MemoryMappedFile.CreateNew( - null, - length, - MemoryMappedFileAccess.ReadWrite, - MemoryMappedFileOptions.None, - HandleInheritability.None) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) - bytes.CopyTo stream - mmf - - let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + let mmf = MemoryMappedFile.CreateNew(null, length, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, HandleInheritability.None) + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) + bytes.CopyTo stream + mmf + + let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromFile(path, access, ?canShadowCopy: bool) = let canShadowCopy = defaultArg canShadowCopy false - let memoryMappedFileAccess = - match access with - | FileAccess.Read -> MemoryMappedFileAccess.Read - | FileAccess.Write -> MemoryMappedFileAccess.Write - | _ -> MemoryMappedFileAccess.ReadWrite + if Utils.runningOnMono + then + // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245 + let bytes = File.ReadAllBytes path + ByteArrayMemory.FromArray bytes + else + let memoryMappedFileAccess = + match access with + | FileAccess.Read -> MemoryMappedFileAccess.Read + | FileAccess.Write -> MemoryMappedFileAccess.Write + | _ -> MemoryMappedFileAccess.ReadWrite - let mmf, accessor, length = let fileStream = File.Open(path, FileMode.Open, access, FileShare.Read) + let length = fileStream.Length - let mmf = - if canShadowCopy then - let mmf = - MemoryMappedFile.CreateNew( - null, - length, - MemoryMappedFileAccess.ReadWrite, - MemoryMappedFileOptions.None, - HandleInheritability.None) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) - fileStream.CopyTo(stream) - fileStream.Dispose() - mmf - else - MemoryMappedFile.CreateFromFile( - fileStream, - null, - length, - memoryMappedFileAccess, - HandleInheritability.None, - leaveOpen=false) - mmf, mmf.CreateViewAccessor(0L, length, memoryMappedFileAccess), length - - // Validate MMF with the access that was intended. - match access with - | FileAccess.Read when not accessor.CanRead -> invalidOp "Cannot read file" - | FileAccess.Write when not accessor.CanWrite -> invalidOp "Cannot write file" - | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" - | _ -> () - - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + + let mmf, accessor, length = + let mmf = + if canShadowCopy then + let mmf = + MemoryMappedFile.CreateNew( + null, + length, + MemoryMappedFileAccess.ReadWrite, + MemoryMappedFileOptions.None, + HandleInheritability.None) + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) + fileStream.CopyTo(stream) + fileStream.Dispose() + mmf + else + MemoryMappedFile.CreateFromFile( + fileStream, + null, + length, + memoryMappedFileAccess, + HandleInheritability.None, + leaveOpen=false) + mmf, mmf.CreateViewAccessor(0L, length, memoryMappedFileAccess), length + + // Validate MMF with the access that was intended. + match access with + | FileAccess.Read when not accessor.CanRead -> invalidOp "Cannot read file" + | FileAccess.Write when not accessor.CanWrite -> invalidOp "Cannot write file" + | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" + | _ -> () + + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromUnsafePointer(addr, length, holder: obj) = RawByteMemory(NativePtr.ofNativeInt addr, length, holder) :> ByteMemory diff --git a/src/absil/bytes.fsi b/src/absil/bytes.fsi index 46b30b6c5a..55a48e3e46 100644 --- a/src/absil/bytes.fsi +++ b/src/absil/bytes.fsi @@ -5,10 +5,11 @@ namespace FSharp.Compiler.AbstractIL.Internal open System.IO open Internal.Utilities - open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.Internal +module Utils = + val runningOnMono: bool module internal Bytes = /// returned int will be 0 <= x <= 255 diff --git a/src/absil/il.fs b/src/absil/il.fs index 7e27e71da2..09cdbd5d32 100644 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -25,24 +25,6 @@ open Internal.Utilities let logging = false -let runningOnMono = -#if ENABLE_MONO_SUPPORT -// Officially supported way to detect if we are running on Mono. -// See http://www.mono-project.com/FAQ:_Technical -// "How can I detect if am running in Mono?" section - try - System.Type.GetType ("Mono.Runtime") <> null - with e-> - // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent - // that is not reliable. - // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is - // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get - // their issue fixed but we need to be robust here anyway. - false -#else - false -#endif - let _ = if logging then dprintn "* warning: Il.logging is on" let int_order = LanguagePrimitives.FastGenericComparer diff --git a/src/absil/il.fsi b/src/absil/il.fsi index 506878e1d6..7bbfad1eb2 100644 --- a/src/absil/il.fsi +++ b/src/absil/il.fsi @@ -2012,8 +2012,6 @@ type ILPropertyRef = member Name: string interface System.IComparable -val runningOnMono: bool - type ILReferences = { AssemblyReferences: ILAssemblyRef list ModuleReferences: ILModuleRef list } diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index b9994f6418..f399c05684 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -20,12 +20,13 @@ open System.Text open Internal.Utilities open Internal.Utilities.Collections open FSharp.NativeInterop -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Diagnostics +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.BinaryConstants -open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Support +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range open System.Reflection diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index 9657cf1794..7f048dd5b9 100644 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -17,6 +17,7 @@ open System.Collections.Generic open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.ErrorLogger diff --git a/src/absil/ilsupp.fs b/src/absil/ilsupp.fs index a5dbe768b8..5773486388 100644 --- a/src/absil/ilsupp.fs +++ b/src/absil/ilsupp.fs @@ -3,9 +3,9 @@ module internal FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL -open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Internal.NativeRes +open FSharp.Compiler.AbstractIL.Internal.Utils #if FX_NO_CORHOST_SIGNER open FSharp.Compiler.AbstractIL.Internal.StrongNameSign #endif @@ -1287,7 +1287,7 @@ let getICLRStrongName () = | Some sn -> sn let signerGetPublicKeyForKeyPair kp = - if IL.runningOnMono then + if runningOnMono then let snt = System.Type.GetType("Mono.Security.StrongName") let sn = System.Activator.CreateInstance(snt, [| box kp |]) snt.InvokeMember("PublicKey", (BindingFlags.GetProperty ||| BindingFlags.Instance ||| BindingFlags.Public), null, sn, [| |], Globalization.CultureInfo.InvariantCulture) :?> byte[] @@ -1319,7 +1319,7 @@ let signerCloseKeyContainer kc = iclrSN.StrongNameKeyDelete kc |> ignore let signerSignatureSize (pk: byte[]) = - if IL.runningOnMono then + if runningOnMono then if pk.Length > 32 then pk.Length - 32 else 128 else let mutable pSize = 0u @@ -1328,7 +1328,7 @@ let signerSignatureSize (pk: byte[]) = int pSize let signerSignFileWithKeyPair fileName kp = - if IL.runningOnMono then + if runningOnMono then let snt = System.Type.GetType("Mono.Security.StrongName") let sn = System.Activator.CreateInstance(snt, [| box kp |]) let conv (x: obj) = if (unbox x: bool) then 0 else -1 diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 1464e29923..d86a2a710c 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -6,12 +6,13 @@ open System.Collections.Generic open System.IO open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL -open FSharp.Compiler.AbstractIL.Diagnostics -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.Internal.BinaryConstants -open FSharp.Compiler.AbstractIL.Internal.Support -open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.Diagnostics +open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.Internal.BinaryConstants +open FSharp.Compiler.AbstractIL.Internal.Support +open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 682b20a688..564cd99083 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -15,6 +15,7 @@ open Internal.Utilities open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range @@ -244,7 +245,7 @@ let pdbGetDebugInfo (contentId: byte[]) (timestamp: int32) (filepath: string) // This function takes output file name and returns debug file name. let getDebugFileName outfile (portablePDB: bool) = #if ENABLE_MONO_SUPPORT - if IL.runningOnMono && not portablePDB then + if runningOnMono && not portablePDB then outfile + ".mdb" else #else diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 23bd2ebc3e..dba6a0bd7d 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -20,6 +20,7 @@ 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.Internal.Utils open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 6510790668..911f913f2f 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -8,10 +8,11 @@ open Internal.Utilities open System open System.IO open FSharp.Compiler -open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.CompileOps diff --git a/src/fsharp/DotNetFrameworkDependencies.fs b/src/fsharp/DotNetFrameworkDependencies.fs index a454ec8059..2d27290586 100644 --- a/src/fsharp/DotNetFrameworkDependencies.fs +++ b/src/fsharp/DotNetFrameworkDependencies.fs @@ -115,13 +115,19 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies let desktopProductVersionMonikers = [| // major, minor, build, revision, moniker 4, 8, 3815, 0, "net48" + 4, 8, 3761, 0, "net48" 4, 7, 3190, 0, "net472" + 4, 7, 3062, 0, "net472" 4, 7, 2600, 0, "net471" + 4, 7, 2558, 0, "net471" 4, 7, 2053, 0, "net47" + 4, 7, 2046, 0, "net47" 4, 6, 1590, 0, "net462" + 4, 6, 57, 0, "net462" 4, 6, 1055, 0, "net461" 4, 6, 81, 0, "net46" 4, 0, 30319, 34209, "net452" + 4, 0, 30319, 17020, "net452" 4, 0, 30319, 18408, "net451" 4, 0, 30319, 17929, "net45" 4, 0, 30319, 1, "net4" @@ -138,14 +144,17 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies with _ -> defaultMscorlibVersion // Get the ProductVersion of this framework compare with table yield compatible monikers - let _, _, _, _, moniker = - desktopProductVersionMonikers - |> Array.find (fun (major, minor, build, revision, _) -> - (majorPart >= major) && - (minorPart >= minor) && - (buildPart >= build) && - (privatePart >= revision)) - moniker + match desktopProductVersionMonikers + |> Array.tryFind (fun (major, minor, build, revision, _) -> + (majorPart >= major) && + (minorPart >= minor) && + (buildPart >= build) && + (privatePart >= revision)) with + | Some (_,_,_,_,moniker) -> + moniker + | None -> + // no TFM could be found, assume latest stable? + "net48" /// Gets the tfm E.g netcore3.0, net472 let executionTfm = diff --git a/src/fsharp/LegacyMSBuildReferenceResolver.fs b/src/fsharp/LegacyMSBuildReferenceResolver.fs index a07941509f..c0f2596c39 100644 --- a/src/fsharp/LegacyMSBuildReferenceResolver.fs +++ b/src/fsharp/LegacyMSBuildReferenceResolver.fs @@ -344,7 +344,7 @@ module LegacyMSBuildReferenceResolver #if ENABLE_MONO_SUPPORT // The properties TargetedRuntimeVersion and CopyLocalDependenciesWhenParentReferenceInGac // are not available on Mono. So we only set them if available (to avoid a compile-time dependency). - if not FSharp.Compiler.AbstractIL.IL.runningOnMono then + if not FSharp.Compiler.AbstractIL.Internal.Utils.runningOnMono then typeof.InvokeMember("TargetedRuntimeVersion",(BindingFlags.Instance ||| BindingFlags.SetProperty ||| BindingFlags.Public),null,rar,[| box targetedRuntimeVersionValue |]) |> ignore typeof.InvokeMember("CopyLocalDependenciesWhenParentReferenceInGac",(BindingFlags.Instance ||| BindingFlags.SetProperty ||| BindingFlags.Public),null,rar,[| box true |]) |> ignore #else diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index c717d9b6e3..7bb4306668 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -29,8 +29,9 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader -open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.IlxGen diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index aece6638ff..cf634a6103 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -29,6 +29,7 @@ open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.ILRuntimeWriter open FSharp.Compiler.Lib open FSharp.Compiler.AccessibilityLogic diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index a5db4e09b4..d0852143ee 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -12,7 +12,8 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader -open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.Ast open FSharp.Compiler.CompileOps diff --git a/tests/service/ScriptOptionsTests.fs b/tests/service/ScriptOptionsTests.fs new file mode 100644 index 0000000000..be38f9ff72 --- /dev/null +++ b/tests/service/ScriptOptionsTests.fs @@ -0,0 +1,36 @@ +#if INTERACTIVE +#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive +#r "../../artifacts/bin/fcs/net461/nunit.framework.dll" +#load "FsUnit.fs" +#load "Common.fs" +#else +module Tests.Service.ScriptOptions +#endif + +open NUnit.Framework +open FsUnit +open System +open FSharp.Compiler +open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Service.Tests.Common + +// Add additional imports/constructs into this script text to verify that common scenarios +// for FCS script typechecking can be supported +let scriptSource = """ +open System +let pi = Math.PI +""" + +[] +[] +[] +let ``can generate options for different frameworks regardless of execution environment``(assumeNetFx, useSdk, flags) = + let path = IO.Path.GetTempPath() + let file = IO.Path.GetTempFileName() + let tempFile = IO.Path.Combine(path, file) + let (options, errors) = + checker.GetProjectOptionsFromScript(tempFile, Text.SourceText.ofString scriptSource, assumeDotNetFramework = assumeNetFx, useSdkRefs = useSdk, otherFlags = flags) + |> Async.RunSynchronously + match errors with + | [] -> () + | errors -> failwithf "Error while parsing script with assumeDotNetFramework:%b, useSdkRefs:%b, and otherFlags:%A:\n%A" assumeNetFx useSdk flags errors \ No newline at end of file From 3e7f2fcba00c258e20c3405b5036cd7ac37f0c61 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 16:51:50 -0600 Subject: [PATCH 098/101] update release notes --- fcs/RELEASE_NOTES.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fcs/RELEASE_NOTES.md b/fcs/RELEASE_NOTES.md index d97e3851ae..7c84f0c6ea 100644 --- a/fcs/RELEASE_NOTES.md +++ b/fcs/RELEASE_NOTES.md @@ -1,8 +1,8 @@ -#### 34.0.0 +#### 34.0.1 -Contains commits from 32b124966 to 5a0117048 from dotnet/fsharp. Notable changes include: +Contains commits from 32b124966 to d7018737c from dotnet/fsharp. Notable changes include: -* lowered allocations for large strings and char arrays (notable source file texts) +* lowered allocations for large strings and char arrays (notably source file texts) * improved support for byreflike rules with regards to type abbreviations * better support for scopes in recursive modules * better location of .net core reference assemblies @@ -11,8 +11,9 @@ Contains commits from 32b124966 to 5a0117048 from dotnet/fsharp. Notable changes * FSharpChecker learned how to keep background symbol uses * Project cracker/project cracker tool were removed * Better support for consuming C# inref parameters -* preview-level functionality for #r "nuget" in scripts * new services around simplifing names and finding unused declarations +* package management in scripts (in preview) +* and-bang syntax support (in preview) #### 33.0.1 From d2206908d8252f63e1f4f8c2e07f19d641969d8c Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 17:12:02 -0600 Subject: [PATCH 099/101] fake verbosity --- fcs/build.cmd | 2 +- fcs/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fcs/build.cmd b/fcs/build.cmd index dc47a88f8c..790dbe5405 100644 --- a/fcs/build.cmd +++ b/fcs/build.cmd @@ -19,7 +19,7 @@ if errorlevel 1 ( :: don't care if this fails dotnet build-server shutdown >NUL 2>&1 -dotnet fake build -t %* +dotnet fake -v build -t %* if errorlevel 1 ( endlocal diff --git a/fcs/build.sh b/fcs/build.sh index 4c4819aca7..e70bb34513 100755 --- a/fcs/build.sh +++ b/fcs/build.sh @@ -11,7 +11,7 @@ cd $(dirname ${BASH_SOURCE[0]}) dotnet tool restore dotnet paket restore -dotnet fake build -t $@ +dotnet fake -v build-t $@ # but we'll be nice and go back to the start dir at the end cd $start_pwd \ No newline at end of file From 0868a46e4492d552aecf434e6bca46f2a5f19eff Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 18:09:42 -0600 Subject: [PATCH 100/101] Revert "fake verbosity" This reverts commit d2206908d8252f63e1f4f8c2e07f19d641969d8c. --- fcs/build.cmd | 2 +- fcs/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fcs/build.cmd b/fcs/build.cmd index 790dbe5405..dc47a88f8c 100644 --- a/fcs/build.cmd +++ b/fcs/build.cmd @@ -19,7 +19,7 @@ if errorlevel 1 ( :: don't care if this fails dotnet build-server shutdown >NUL 2>&1 -dotnet fake -v build -t %* +dotnet fake build -t %* if errorlevel 1 ( endlocal diff --git a/fcs/build.sh b/fcs/build.sh index e70bb34513..4c4819aca7 100755 --- a/fcs/build.sh +++ b/fcs/build.sh @@ -11,7 +11,7 @@ cd $(dirname ${BASH_SOURCE[0]}) dotnet tool restore dotnet paket restore -dotnet fake -v build-t $@ +dotnet fake build -t $@ # but we'll be nice and go back to the start dir at the end cd $start_pwd \ No newline at end of file From f878196a1ba5567783c218c84d1cf39367a3e813 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 18:39:23 -0600 Subject: [PATCH 101/101] bump to 3.1, fix paths in build script for buildtools --- .travis.yml | 4 ++-- fcs/build.fsx | 4 ++-- fcs/global.json | 2 +- src/buildtools/fslex/fslex.fsproj | 2 +- src/buildtools/fsyacc/fsyacc.fsproj | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22acb82a11..94ef8462d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ osx_image: xcode11.2 mono: - weekly - latest - - 6.0.0 + - 6.6.0 -dotnet: 3.0.100 +dotnet: 3.1.100 sudo: false diff --git a/fcs/build.fsx b/fcs/build.fsx index 80d6890436..aba0c0fdc9 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -64,8 +64,8 @@ Target.create "BuildVersion" (fun _ -> Target.create "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build" "../src/buildtools/buildtools.proj -v n -c Proto" - let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp3.0/fslex.dll" - let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp3.0/fsyacc.dll" + let fslexPath = Path.GetFullPath <| Path.Combine(__SOURCE_DIRECTORY__, "../artifacts/bin/fslex/Proto/netcoreapp3.1/fslex.dll") + let fsyaccPath = Path.GetFullPath <| Path.Combine(__SOURCE_DIRECTORY__, "../artifacts/bin/fsyacc/Proto/netcoreapp3.1/fsyacc.dll") runDotnet __SOURCE_DIRECTORY__ "build" (sprintf "FSharp.Compiler.Service.sln -nodereuse:false -v n -c Release /p:DisableCompilerRedirection=true /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) diff --git a/fcs/global.json b/fcs/global.json index 2223a05e31..7c332016b7 100644 --- a/fcs/global.json +++ b/fcs/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.0.100" + "version": "3.1.100" } } \ No newline at end of file diff --git a/src/buildtools/fslex/fslex.fsproj b/src/buildtools/fslex/fslex.fsproj index 2766098c25..b705f606c8 100644 --- a/src/buildtools/fslex/fslex.fsproj +++ b/src/buildtools/fslex/fslex.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + netcoreapp3.1 INTERNALIZED_FSLEXYACC_RUNTIME;$(DefineConstant) true diff --git a/src/buildtools/fsyacc/fsyacc.fsproj b/src/buildtools/fsyacc/fsyacc.fsproj index dc5a4f67f3..fb744a43cd 100644 --- a/src/buildtools/fsyacc/fsyacc.fsproj +++ b/src/buildtools/fsyacc/fsyacc.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + netcoreapp3.1 INTERNALIZED_FSLEXYACC_RUNTIME;$(DefineConstant) true