This commit is contained in:
Kevin Ransom 2019-07-26 16:42:50 -07:00
Родитель b3811d2ac0 969a9c4661
Коммит 2304ea482a
119 изменённых файлов: 1734 добавлений и 915 удалений

Просмотреть файл

@ -105,6 +105,14 @@ jobs:
continueOnError: true
condition: succeeded()
# Publish native PDBs for archiving
- task: PublishBuildArtifacts@1
displayName: Publish Artifact Symbols
inputs:
PathtoPublish: '$(Build.SourcesDirectory)/artifacts/SymStore/$(BuildConfiguration)'
ArtifactName: NativeSymbols
condition: succeeded()
# Execute cleanup tasks
- task: ms-vseng.MicroBuildTasks.521a94ea-9e68-468a-8167-6dcf361ea776.MicroBuildCleanup@1
displayName: Execute cleanup tasks

Просмотреть файл

@ -75,6 +75,7 @@
<RepositoryUrl Condition="'$(RepositoryUrl)' == ''">https://github.com/Microsoft/visualfsharp</RepositoryUrl>
<RepositoryType Condition="'$(RepositoryType)' == ''">git</RepositoryType>
</PropertyGroup>
<PropertyGroup Condition="'$(FSharpSourceBuild)' == 'true' AND '$(RepositoryCommit)' == ''">
<_DotGitDir>$(RepoRoot).git</_DotGitDir>
<_HeadFileContent Condition="Exists('$(_DotGitDir)/HEAD')">$([System.IO.File]::ReadAllText('$(_DotGitDir)/HEAD').Trim())</_HeadFileContent>
@ -87,7 +88,7 @@
<PropertyGroup>
<NoWarn Condition="'$(Language)' == 'F#'">$(NoWarn);FS2003</NoWarn><!-- warning when AssemblyInformationalVersion looks like '1.2.3-dev' -->
<NoCompilerStandardLib>true</NoCompilerStandardLib><!-- necessary for resource generation using csc.exe -->
<DebugType>portable</DebugType>
<DebugType>embedded</DebugType>
<MicroBuildAssemblyFileLanguage>fs</MicroBuildAssemblyFileLanguage>
<UseStandardResourceNames>false</UseStandardResourceNames>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

Просмотреть файл

@ -113,6 +113,12 @@ jobs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\VSSetup\$(_BuildConfig)\VisualFSharpFull.vsix'
ArtifactName: 'Nightly'
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Publish Artifact Symbols
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\SymStore\$(_BuildConfig)'
ArtifactName: 'NativeSymbols'
condition: succeeded()
#---------------------------------------------------------------------------------------------------------------------#
# PR builds #

Просмотреть файл

@ -225,13 +225,14 @@ function UpdatePath() {
TestAndAddToPath "$ArtifactsDir\bin\fsiAnyCpu\$configuration\net472"
}
function VerifyAssemblyVersions() {
$fsiPath = Join-Path $ArtifactsDir "bin\fsi\Proto\net472\publish\fsi.exe"
function VerifyAssemblyVersionsAndSymbols() {
$assemblyVerCheckPath = Join-Path $ArtifactsDir "Bootstrap\AssemblyCheck\AssemblyCheck.dll"
# Only verify versions on CI or official build
if ($ci -or $official) {
$asmVerCheckPath = "$RepoRoot\scripts"
Exec-Console $fsiPath """$asmVerCheckPath\AssemblyVersionCheck.fsx"" -- ""$ArtifactsDir"""
$dotnetPath = InitializeDotNetCli
$dotnetExe = Join-Path $dotnetPath "dotnet.exe"
Exec-Console $dotnetExe """$assemblyVerCheckPath"" ""$ArtifactsDir"""
}
}
@ -308,7 +309,7 @@ try {
}
if ($build) {
VerifyAssemblyVersions
VerifyAssemblyVersionsAndSymbols
}
$desktopTargetFramework = "net472"

Просмотреть файл

@ -3,9 +3,9 @@
<ProductDependencies>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19364.1">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19375.15">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>0c81c2bbdc49749e9940bc8858ebd16026d51277</Sha>
<Sha>ef1c110152df0d500fffb87878a86f88d1ca5295</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>

Просмотреть файл

@ -236,10 +236,11 @@ function Make-BootstrapBuild() {
Remove-Item -re $dir -ErrorAction SilentlyContinue
Create-Directory $dir
# prepare FsLex and Fsyacc
# prepare FsLex and Fsyacc and AssemblyCheck
Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration
Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fslex" -Force -Recurse
Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fsyacc" -Force -Recurse
Copy-Item "$ArtifactsDir\bin\AssemblyCheck\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\AssemblyCheck" -Force -Recurse
# prepare compiler
$projectPath = "$RepoRoot\proto.proj"

0
eng/common/build.sh Normal file → Executable file
Просмотреть файл

0
eng/common/cibuild.sh Normal file → Executable file
Просмотреть файл

0
eng/common/cross/armel/tizen-build-rootfs.sh Normal file → Executable file
Просмотреть файл

0
eng/common/cross/armel/tizen-fetch.sh Normal file → Executable file
Просмотреть файл

0
eng/common/cross/build-android-rootfs.sh Normal file → Executable file
Просмотреть файл

0
eng/common/cross/build-rootfs.sh Normal file → Executable file
Просмотреть файл

0
eng/common/darc-init.sh Normal file → Executable file
Просмотреть файл

Просмотреть файл

@ -98,12 +98,18 @@ try {
}
Write-Verbose "Installing $ToolName version $ToolVersion"
Write-Verbose "Executing '$InstallerPath $LocalInstallerArguments'"
Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'"
& $InstallerPath @LocalInstallerArguments
if ($LASTEXITCODE -Ne "0") {
$errMsg = "$ToolName installation failed"
if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) {
Write-Warning $errMsg
$showNativeToolsWarning = $true
if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) {
$showNativeToolsWarning = $false
}
if ($showNativeToolsWarning) {
Write-Warning $errMsg
}
$toolInstallationFailure = $true
} else {
Write-Error $errMsg

2
eng/common/init-tools-native.sh Normal file → Executable file
Просмотреть файл

@ -71,7 +71,7 @@ function ReadGlobalJsonNativeTools {
local native_tools_list=$(echo $native_tools_section | awk -F"[{}]" '{print $2}')
native_tools_list=${native_tools_list//[\" ]/}
native_tools_list=${native_tools_list//,/$'\n'}
native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[:space:]')"
native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[[:space:]]')"
local old_IFS=$IFS
while read -r line; do

0
eng/common/internal-feed-operations.sh Normal file → Executable file
Просмотреть файл

0
eng/common/msbuild.sh Normal file → Executable file
Просмотреть файл

Просмотреть файл

@ -59,9 +59,38 @@ function DownloadAndExtract {
-Verbose:$Verbose
if ($UnzipStatus -Eq $False) {
Write-Error "Unzip failed"
return $False
# Retry Download one more time with Force=true
$DownloadRetryStatus = CommonLibrary\Get-File -Uri $Uri `
-Path $TempToolPath `
-DownloadRetries 1 `
-RetryWaitTimeInSeconds $RetryWaitTimeInSeconds `
-Force:$True `
-Verbose:$Verbose
if ($DownloadRetryStatus -Eq $False) {
Write-Error "Last attempt of download failed as well"
return $False
}
# Retry unzip again one more time with Force=true
$UnzipRetryStatus = CommonLibrary\Expand-Zip -ZipPath $TempToolPath `
-OutputDirectory $InstallDirectory `
-Force:$True `
-Verbose:$Verbose
if ($UnzipRetryStatus -Eq $False)
{
Write-Error "Last attempt of unzip failed as well"
# Clean up partial zips and extracts
if (Test-Path $TempToolPath) {
Remove-Item $TempToolPath -Force
}
if (Test-Path $InstallDirectory) {
Remove-Item $InstallDirectory -Force -Recurse
}
return $False
}
}
return $True
}

0
eng/common/native/common-library.sh Normal file → Executable file
Просмотреть файл

0
eng/common/native/install-cmake.sh Normal file → Executable file
Просмотреть файл

0
eng/common/performance/performance-setup.sh Normal file → Executable file
Просмотреть файл

82
eng/common/pipeline-logging-functions.sh Normal file → Executable file
Просмотреть файл

@ -39,11 +39,11 @@ function Write-PipelineTaskError {
return
fi
message_type="error"
sourcepath=''
linenumber=''
columnnumber=''
error_code=''
local message_type="error"
local sourcepath=''
local linenumber=''
local columnnumber=''
local error_code=''
while [[ $# -gt 0 ]]; do
opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
@ -76,7 +76,7 @@ function Write-PipelineTaskError {
shift
done
message="##vso[task.logissue"
local message="##vso[task.logissue"
message="$message type=$message_type"
@ -100,3 +100,73 @@ function Write-PipelineTaskError {
echo "$message"
}
function Write-PipelineSetVariable {
if [[ "$ci" != true ]]; then
return
fi
local name=''
local value=''
local secret=false
local as_output=false
local is_multi_job_variable=true
while [[ $# -gt 0 ]]; do
opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
case "$opt" in
-name|-n)
name=$2
shift
;;
-value|-v)
value=$2
shift
;;
-secret|-s)
secret=true
;;
-as_output|-a)
as_output=true
;;
-is_multi_job_variable|-i)
is_multi_job_variable=$2
shift
;;
esac
shift
done
value=${value/;/%3B}
value=${value/\\r/%0D}
value=${value/\\n/%0A}
value=${value/]/%5D}
local message="##vso[task.setvariable variable=$name;isSecret=$secret;isOutput=$is_multi_job_variable]$value"
if [[ "$as_output" == true ]]; then
$message
else
echo "$message"
fi
}
function Write-PipelinePrependPath {
local prepend_path=''
while [[ $# -gt 0 ]]; do
opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
case "$opt" in
-path|-p)
prepend_path=$2
shift
;;
esac
shift
done
export PATH="$prepend_path:$PATH"
if [[ "$ci" == true ]]; then
echo "##vso[task.prependpath]$prepend_path"
fi
}

Просмотреть файл

@ -0,0 +1,36 @@
param(
[Parameter(Mandatory=$true)][string] $BarBuildId, # ID of the build which assets should be downloaded
[Parameter(Mandatory=$true)][string] $MaestroAccessToken, # Token used to access Maestro API
[Parameter(Mandatory=$true)][string] $DropLocation # Where the assets should be downloaded to
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2.0
. $PSScriptRoot\..\tools.ps1
try {
Write-Host "Installing DARC ..."
. $PSScriptRoot\..\darc-init.ps1
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0) {
Write-PipelineTaskError "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..."
ExitWithExitCode $exitCode
}
darc gather-drop --non-shipping `
--continue-on-error `
--id $BarBuildId `
--output-dir $DropLocation `
--bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ `
--password $MaestroAccessToken `
--latest-location
}
catch {
Write-Host $_
Write-Host $_.Exception
Write-Host $_.ScriptStackTrace
ExitWithExitCode 1
}

Просмотреть файл

@ -84,6 +84,7 @@ stages:
/p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName)
/p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1)
/p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url)
/p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url)
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
/p:BARBuildId=$(BARBuildId)
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
@ -142,29 +143,6 @@ stages:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
- job:
displayName: Gather Drop
dependsOn: setupMaestroVars
variables:
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id)
pool:
vmImage: 'windows-2019'
steps:
- task: PowerShell@2
displayName: Setup Darc CLI
inputs:
targetType: filePath
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
- task: PowerShell@2
displayName: Run Darc gather-drop
inputs:
targetType: inline
script: |
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
enabled: false
- template: ../promote-build.yml
parameters:
ChannelId: ${{ variables.InternalServicing_30_Channel_Id }}

Просмотреть файл

@ -77,7 +77,7 @@ stages:
filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
/p:ChannelId=$(PublicDevRelease_30_Channel_Id)
/p:ArtifactsCategory=.NetCore
/p:ArtifactsCategory=$(_DotNetArtifactsCategory)
/p:IsStableBuild=$(IsStableBuild)
/p:IsInternalBuild=$(IsInternalBuild)
/p:RepositoryName=$(Build.Repository.Name)
@ -139,27 +139,9 @@ stages:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
- job:
displayName: Gather Drop
dependsOn: setupMaestroVars
variables:
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id)
pool:
vmImage: 'windows-2019'
steps:
- task: PowerShell@2
displayName: Setup Darc CLI
inputs:
targetType: filePath
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
- task: PowerShell@2
displayName: Run Darc gather-drop
inputs:
targetType: inline
script: |
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
- template: ../darc-gather-drop.yml
parameters:
ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }}
- template: ../promote-build.yml
parameters:

Просмотреть файл

@ -84,6 +84,7 @@ stages:
/p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName)
/p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1)
/p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url)
/p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url)
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
/p:BARBuildId=$(BARBuildId)
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
@ -142,29 +143,6 @@ stages:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
- job:
displayName: Gather Drop
dependsOn: setupMaestroVars
variables:
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id)
pool:
vmImage: 'windows-2019'
steps:
- task: PowerShell@2
displayName: Setup Darc CLI
inputs:
targetType: filePath
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
- task: PowerShell@2
displayName: Run Darc gather-drop
inputs:
targetType: inline
script: |
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
enabled: false
- template: ../promote-build.yml
parameters:
ChannelId: ${{ variables.PublicRelease_30_Channel_Id }}

Просмотреть файл

@ -48,7 +48,7 @@ stages:
filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
/p:ChannelId=$(PublicValidationRelease_30_Channel_Id)
/p:ArtifactsCategory=.NetCoreValidation
/p:ArtifactsCategory=$(_DotNetArtifactsCategory)
/p:IsStableBuild=$(IsStableBuild)
/p:IsInternalBuild=$(IsInternalBuild)
/p:RepositoryName=$(Build.Repository.Name)
@ -91,29 +91,9 @@ stages:
jobs:
- template: ../setup-maestro-vars.yml
- job:
displayName: Gather Drop
dependsOn: setupMaestroVars
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id)
variables:
- name: BARBuildId
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- group: Publish-Build-Assets
pool:
vmImage: 'windows-2019'
steps:
- task: PowerShell@2
displayName: Setup Darc CLI
inputs:
targetType: filePath
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
- task: PowerShell@2
displayName: Run Darc gather-drop
inputs:
targetType: inline
script: |
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com --password $(MaestroAccessToken) --latest-location
- template: ../darc-gather-drop.yml
parameters:
ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }}
- template: ../promote-build.yml
parameters:

Просмотреть файл

@ -0,0 +1,22 @@
parameters:
ChannelId: 0
jobs:
- job: gatherDrop
displayName: Gather Drop
dependsOn: setupMaestroVars
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }})
variables:
- group: Publish-Build-Assets
- name: BARBuildId
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
pool:
vmImage: 'windows-2019'
steps:
- task: PowerShell@2
displayName: Darc gather-drop
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1
arguments: -BarBuildId $(BARBuildId)
-DropLocation $(Agent.BuildDirectory)/Temp/Drop/
-MaestroAccessToken $(MaestroAccessToken)

Просмотреть файл

@ -8,4 +8,4 @@ steps:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1
arguments: -SourceRepo $(Build.Repository.Uri)
-ChannelId ${{ parameters.ChannelId }}
-BarToken $(MaestroAccessTokenInt)
-BarToken $(MaestroAccessToken)

Просмотреть файл

@ -169,7 +169,7 @@ function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $arc
InstallDotNet $dotnetRoot $version $architecture
}
function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot
function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) {
$installScript = GetDotNetInstallScript $dotnetRoot
$installParameters = @{
Version = $version

23
eng/common/tools.sh Normal file → Executable file
Просмотреть файл

@ -77,7 +77,7 @@ function ReadGlobalVersion {
local pattern="\"$key\" *: *\"(.*)\""
if [[ ! $line =~ $pattern ]]; then
Write-PipelineTelemetryError -category 'InitializeTools' "Error: Cannot find \"$key\" in $global_json_file"
Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file"
ExitWithExitCode 1
fi
@ -146,14 +146,10 @@ function InitializeDotNetCli {
# Add dotnet to PATH. This prevents any bare invocation of dotnet in custom
# build steps from using anything other than what we've downloaded.
export PATH="$dotnet_root:$PATH"
Write-PipelinePrependPath -path "$dotnet_root"
if [[ $ci == true ]]; then
# Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build
echo "##vso[task.prependpath]$dotnet_root"
echo "##vso[task.setvariable variable=DOTNET_MULTILEVEL_LOOKUP]0"
echo "##vso[task.setvariable variable=DOTNET_SKIP_FIRST_TIME_EXPERIENCE]1"
fi
Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0"
Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1"
# return value
_InitializeDotNetCli="$dotnet_root"
@ -249,7 +245,7 @@ function InitializeNativeTools() {
then
local nativeArgs=""
if [[ "$ci" == true ]]; then
nativeArgs="-InstallDirectory $tools_dir"
nativeArgs="--installDirectory $tools_dir"
fi
"$_script_dir/init-tools-native.sh" $nativeArgs
fi
@ -389,7 +385,8 @@ mkdir -p "$toolset_dir"
mkdir -p "$temp_dir"
mkdir -p "$log_dir"
if [[ $ci == true ]]; then
export TEMP="$temp_dir"
export TMP="$temp_dir"
fi
Write-PipelineSetVariable -name "Artifacts" -value "$artifacts_dir"
Write-PipelineSetVariable -name "Artifacts.Toolset" -value "$toolset_dir"
Write-PipelineSetVariable -name "Artifacts.Log" -value "$log_dir"
Write-PipelineSetVariable -name "Temp" -value "$temp_dir"
Write-PipelineSetVariable -name "TMP" -value "$temp_dir"

Просмотреть файл

@ -10,7 +10,7 @@
}
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19364.1",
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19375.15",
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2"
}
}

Просмотреть файл

@ -3025,7 +3025,8 @@ let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : IL
//=====================================================================
// TABLES+BLOBS --> PHYSICAL METADATA+BLOBS
//=====================================================================
let chunk sz next = ({addr=next; size=sz}, next + sz)
let chunk sz next = ({addr=next; size=sz}, next + sz)
let emptychunk next = ({addr=next; size=0}, next)
let nochunk next = ({addr= 0x0;size= 0x0; }, next)
let count f arr =
@ -3513,7 +3514,7 @@ let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Len
let writeBinaryAndReportMappings (outfile,
ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB,
embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap)
embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap)
modul normalizeAssemblyRefs =
// Store the public key from the signer into the manifest. This means it will be written
// to the binary and also acts as an indicator to leave space for delay sign
@ -3562,7 +3563,7 @@ let writeBinaryAndReportMappings (outfile,
with e ->
failwith ("Could not open file for writing (binary mode): " + outfile)
let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings =
let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings =
try
let imageBaseReal = modul.ImageBase // FIXED CHOICE
@ -3667,42 +3668,61 @@ let writeBinaryAndReportMappings (outfile,
let pdbOpt =
match portablePDB with
| true ->
let (uncompressedLength, contentId, stream) as pdbStream =
generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap
let (uncompressedLength, contentId, stream, algorithmName, checkSum) as pdbStream =
generatePortablePdb embedAllSource embedSourceList sourceLink checksumAlgorithm showTimes pdbData pathMap
if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream)
if embeddedPDB then
let uncompressedLength, contentId, stream = compressPortablePdbStream uncompressedLength contentId stream
Some (uncompressedLength, contentId, stream, algorithmName, checkSum)
else Some pdbStream
| _ -> None
let debugDirectoryChunk, next =
chunk (if pdbfile = None then
0x0
else if embeddedPDB && portablePDB then
sizeof_IMAGE_DEBUG_DIRECTORY * 2
let debugDirectoryChunk, next =
chunk (if pdbfile = None then
0x0
else
sizeof_IMAGE_DEBUG_DIRECTORY
sizeof_IMAGE_DEBUG_DIRECTORY * 2 +
(if embeddedPDB then sizeof_IMAGE_DEBUG_DIRECTORY else 0) +
(if deterministic then sizeof_IMAGE_DEBUG_DIRECTORY else 0)
) next
// The debug data is given to us by the PDB writer and appears to
// typically be the type of the data plus the PDB file name. We fill
// this in after we've written the binary. We approximate the size according
// to what PDB writers seem to require and leave extra space just in case...
let debugDataJustInCase = 40
let debugDataChunk, next =
let debugDataChunk, next =
chunk (align 0x4 (match pdbfile with
| None -> 0
| Some f -> (24
+ System.Text.Encoding.Unicode.GetByteCount f // See bug 748444
+ debugDataJustInCase))) next
let debugEmbeddedPdbChunk, next =
let streamLength =
match pdbOpt with
| Some (_, _, stream) -> int stream.Length
| None -> 0
chunk (align 0x4 (match embeddedPDB with
| true -> 8 + streamLength
| _ -> 0 )) next
let debugChecksumPdbChunk, next =
chunk (align 0x4 (match pdbOpt with
| Some (_, _, _, algorithmName, checkSum) ->
let alg = System.Text.Encoding.UTF8.GetBytes(algorithmName)
let size = alg.Length + 1 + checkSum.Length
size
| None -> 0)) next
let debugEmbeddedPdbChunk, next =
if embeddedPDB then
let streamLength =
match pdbOpt with
| Some (_, _, stream, _, _) -> int stream.Length
| None -> 0
chunk (align 0x4 (match embeddedPDB with
| true -> 8 + streamLength
| _ -> 0 )) next
else
nochunk next
let debugDeterministicPdbChunk, next =
if deterministic then emptychunk next
else nochunk next
let textSectionSize = next - textSectionAddr
let nextPhys = align alignPhys (textSectionPhysLoc + textSectionSize)
@ -3801,35 +3821,39 @@ let writeBinaryAndReportMappings (outfile,
if pCurrent <> pExpected then
failwith ("warning: "+chunkName+" not where expected, pCurrent = "+string pCurrent+", p.addr = "+string pExpected)
writeBytes os chunk
let writePadding (os: BinaryWriter) _comment sz =
if sz < 0 then failwith "writePadding: size < 0"
for i = 0 to sz - 1 do
os.Write 0uy
// Now we've computed all the offsets, write the image
write (Some msdosHeaderChunk.addr) os "msdos header" msdosHeader
write (Some peSignatureChunk.addr) os "pe signature" [| |]
writeInt32 os 0x4550
write (Some peFileHeaderChunk.addr) os "pe file header" [| |]
if (modul.Platform = Some AMD64) then
writeInt32AsUInt16 os 0x8664 // Machine - IMAGE_FILE_MACHINE_AMD64
elif isItanium then
writeInt32AsUInt16 os 0x200
else
writeInt32AsUInt16 os 0x014c // Machine - IMAGE_FILE_MACHINE_I386
writeInt32AsUInt16 os numSections
let pdbData =
let pdbData =
// Hash code, data and metadata
if deterministic then
// Hash code, data and metadata
use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only
use sha =
match checksumAlgorithm with
| HashAlgorithm.Sha1 -> System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm
| HashAlgorithm.Sha256 -> System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm
let hCode = sha.ComputeHash code
let hData = sha.ComputeHash data
let hMeta = sha.ComputeHash metadata
@ -3845,6 +3869,7 @@ let writeBinaryAndReportMappings (outfile,
// Use last 4 bytes for timestamp - High bit set, to stop tool chains becoming confused
let timestamp = int final.[16] ||| (int final.[17] <<< 8) ||| (int final.[18] <<< 16) ||| (int (final.[19] ||| 128uy) <<< 24)
writeInt32 os timestamp
// Update pdbData with new guid and timestamp. Portable and embedded PDBs don't need the ModuleID
// Full and PdbOnly aren't supported under deterministic builds currently, they rely on non-determinsitic Windows native code
{ pdbData with ModuleID = final.[0..15] ; Timestamp = timestamp }
@ -4130,10 +4155,14 @@ let writeBinaryAndReportMappings (outfile,
if pdbfile.IsSome then
write (Some (textV2P debugDirectoryChunk.addr)) os "debug directory" (Array.create debugDirectoryChunk.size 0x0uy)
write (Some (textV2P debugDataChunk.addr)) os "debug data" (Array.create debugDataChunk.size 0x0uy)
write (Some (textV2P debugChecksumPdbChunk.addr)) os "debug checksum" (Array.create debugChecksumPdbChunk.size 0x0uy)
if embeddedPDB then
write (Some (textV2P debugEmbeddedPdbChunk.addr)) os "debug data" (Array.create debugEmbeddedPdbChunk.size 0x0uy)
if deterministic then
write (Some (textV2P debugDeterministicPdbChunk.addr)) os "debug deterministic" Array.empty
writePadding os "end of .text" (dataSectionPhysLoc - textSectionPhysLoc - textSectionSize)
// DATA SECTION
@ -4179,7 +4208,7 @@ let writeBinaryAndReportMappings (outfile,
FileSystemUtilites.setExecutablePermission outfile
with _ ->
()
pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings
pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings
// Looks like a finally
with e ->
@ -4204,11 +4233,11 @@ let writeBinaryAndReportMappings (outfile,
try
let idd =
match pdbOpt with
| Some (originalLength, contentId, stream) ->
| Some (originalLength, contentId, stream, algorithmName, checkSum) ->
if embeddedPDB then
embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk
embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic
else
writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk
writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic
| None ->
#if FX_NO_PDB_WRITER
Array.empty<idd>
@ -4229,16 +4258,17 @@ let writeBinaryAndReportMappings (outfile,
writeInt32AsUInt16 os2 i.iddMajorVersion
writeInt32AsUInt16 os2 i.iddMinorVersion
writeInt32 os2 i.iddType
writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData
writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData
writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData
writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData
writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData
writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData
// Write the Debug Data
for i in idd do
// write the debug raw data as given us by the PDB writer
os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore
if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable"
writeBytes os2 i.iddData
if i.iddChunk.size <> 0 then
// write the debug raw data as given us by the PDB writer
os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore
if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable"
writeBytes os2 i.iddData
os2.Dispose()
with e ->
failwith ("Error while writing debug directory entry: "+e.Message)
@ -4247,9 +4277,7 @@ let writeBinaryAndReportMappings (outfile,
with e ->
reraise()
end
ignore debugDataChunk
ignore debugEmbeddedPdbChunk
end
reportTime showTimes "Finalize PDB"
/// Sign the binary. No further changes to binary allowed past this point!
@ -4277,9 +4305,10 @@ type options =
embedAllSource: bool
embedSourceList: string list
sourceLink: string
checksumAlgorithm: HashAlgorithm
signer: ILStrongNameSigner option
emitTailcalls : bool
deterministic : bool
emitTailcalls: bool
deterministic: bool
showTimes: bool
dumpDebugInfo: bool
pathMap: PathMap }
@ -4287,5 +4316,5 @@ type options =
let WriteILBinary (outfile, (args: options), modul, normalizeAssemblyRefs) =
writeBinaryAndReportMappings (outfile,
args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource,
args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs
args.embedSourceList, args.sourceLink, args.checksumAlgorithm, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs
|> ignore

Просмотреть файл

@ -1,12 +1,13 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
/// The IL Binary writer.
module internal FSharp.Compiler.AbstractIL.ILBinaryWriter
module internal FSharp.Compiler.AbstractIL.ILBinaryWriter
open Internal.Utilities
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.Internal
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.Internal
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILPdbWriter
[<Sealed>]
type ILStrongNameSigner =
@ -24,6 +25,7 @@ type options =
embedAllSource: bool
embedSourceList: string list
sourceLink: string
checksumAlgorithm: HashAlgorithm
signer : ILStrongNameSigner option
emitTailcalls: bool
deterministic: bool

Просмотреть файл

@ -11,8 +11,9 @@ open System.Reflection
open System.Reflection.Metadata
open System.Reflection.Metadata.Ecma335
open System.Reflection.PortableExecutable
open System.Text
open Internal.Utilities
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.Diagnostics
open FSharp.Compiler.AbstractIL.Internal.Support
open FSharp.Compiler.AbstractIL.Internal.Library
@ -125,6 +126,27 @@ type idd =
iddData: byte[]
iddChunk: BinaryChunk }
/// The specified Hash algorithm to use on portable pdb files.
type HashAlgorithm =
| Sha1
| Sha256
// Document checksum algorithms
let guidSha1 = Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460")
let guidSha2 = Guid("8829d00f-11b8-4213-878b-770e8597ac16")
let checkSum (url: string) (checksumAlgorithm: HashAlgorithm) =
try
use file = FileSystem.FileStreamReadShim url
let guid, alg =
match checksumAlgorithm with
| HashAlgorithm.Sha1 -> guidSha1, System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm
| HashAlgorithm.Sha256 -> guidSha2, System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm
let checkSum = alg.ComputeHash file
Some (guid, checkSum)
with _ -> None
//---------------------------------------------------------------------
// Portable PDB Writer
//---------------------------------------------------------------------
@ -153,7 +175,7 @@ let pdbGetCvDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvCh
}
let pdbMagicNumber= 0x4244504dL
let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) =
let pdbGetEmbeddedPdbDebugInfo (embeddedPdbChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) =
let iddPdbBuffer =
let buffer = Array.zeroCreate (sizeof<int32> + sizeof<int32> + int(stream.Length))
let (offset, size) = (0, sizeof<int32>) // Magic Number dword: 0x4244504dL
@ -164,33 +186,57 @@ let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int6
Buffer.BlockCopy(stream.ToArray(), 0, buffer, offset, size)
buffer
{ iddCharacteristics = 0 // Reserved
iddMajorVersion = 0 // VersionMajor should be 0
iddMajorVersion = 0x0100 // VersionMajor should be 0x0100
iddMinorVersion = 0x0100 // VersionMinor should be 0x0100
iddType = 17 // IMAGE_DEBUG_TYPE_EMBEDDEDPDB
iddTimestamp = 0
iddData = iddPdbBuffer // Path name to the pdb file when built
iddChunk = embeddedPDBChunk
iddChunk = embeddedPdbChunk
}
let pdbGetDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvChunk: BinaryChunk) (embeddedPDBChunk: BinaryChunk option) (uncompressedLength: int64) (stream: MemoryStream option) =
match stream, embeddedPDBChunk with
| None, _ | _, None -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk |]
| Some s, Some chunk -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk; pdbGetPdbDebugInfo chunk uncompressedLength s |]
let pdbChecksumDebugInfo timestamp (checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte[]) =
let iddBuffer =
let alg = Encoding.UTF8.GetBytes(algorithmName)
let buffer = Array.zeroCreate (alg.Length + 1 + checksum.Length)
Buffer.BlockCopy(alg, 0, buffer, 0, alg.Length)
Buffer.BlockCopy(checksum, 0, buffer, alg.Length + 1, checksum.Length)
buffer
{ iddCharacteristics = 0 // Reserved
iddMajorVersion = 1 // VersionMajor should be 1
iddMinorVersion = 0x0100 // VersionMinor should be 0x0100
iddType = 19 // IMAGE_DEBUG_TYPE_CHECKSUMPDB
iddTimestamp = timestamp
iddData = iddBuffer // Path name to the pdb file when built
iddChunk = checksumPdbChunk
}
// Document checksum algorithms
let guidSourceHashMD5 = System.Guid(0x406ea660u, 0x64cfus, 0x4c82us, 0xb6uy, 0xf0uy, 0x42uy, 0xd4uy, 0x81uy, 0x72uy, 0xa7uy, 0x99uy) //406ea660-64cf-4c82-b6f0-42d48172a799
let hashSizeOfMD5 = 16
let pdbGetPdbDebugDeterministicInfo (deterministicPdbChunk: BinaryChunk) =
{ iddCharacteristics = 0 // Reserved
iddMajorVersion = 0 // VersionMajor should be 0
iddMinorVersion = 0 // VersionMinor should be 00
iddType = 16 // IMAGE_DEBUG_TYPE_DETERMINISTIC
iddTimestamp = 0
iddData = Array.empty // No DATA
iddChunk = deterministicPdbChunk
}
// If the FIPS algorithm policy is enabled on the computer (e.g., for US government employees and contractors)
// then obtaining the MD5 implementation in BCL will throw.
// In this case, catch the failure, and not set a checksum.
let checkSum (url: string) =
try
use file = FileSystem.FileStreamReadShim url
use md5 = System.Security.Cryptography.MD5.Create()
let checkSum = md5.ComputeHash file
Some (guidSourceHashMD5, checkSum)
with _ -> None
let pdbGetDebugInfo (contentId: byte[]) (timestamp: int32) (filepath: string)
(cvChunk: BinaryChunk)
(embeddedPdbChunk: BinaryChunk option)
(deterministicPdbChunk: BinaryChunk)
(checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte [])
(uncompressedLength: int64) (stream: MemoryStream option)
(embeddedPdb: bool) (deterministic: bool) =
[| yield pdbGetCvDebugInfo contentId timestamp filepath cvChunk
yield pdbChecksumDebugInfo timestamp checksumPdbChunk algorithmName checksum
if embeddedPdb then
match stream, embeddedPdbChunk with
| None, _ | _, None -> ()
| Some s, Some chunk ->
yield pdbGetEmbeddedPdbDebugInfo chunk uncompressedLength s
if deterministic then
yield pdbGetPdbDebugDeterministicInfo deterministicPdbChunk
|]
//------------------------------------------------------------------------------
// PDB Writer. The function [WritePdbInfo] abstracts the
@ -219,7 +265,7 @@ let getRowCounts tableRowCounts =
tableRowCounts |> Seq.iter(fun x -> builder.Add x)
builder.MoveToImmutable()
let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) showTimes (info: PdbData) isDeterministic (pathMap: PathMap) =
let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) checksumAlgorithm showTimes (info: PdbData) (pathMap: PathMap) =
sortMethods showTimes info
let externalRowCounts = getRowCounts info.TableRowCounts
let docs =
@ -286,7 +332,7 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s
metadata.SetCapacity(TableIndex.Document, docLength)
for doc in docs do
let handle =
match checkSum doc.File with
match checkSum doc.File checksumAlgorithm with
| Some (hashAlg, checkSum) ->
let dbgInfo =
(serializeDocumentName doc.File,
@ -481,25 +527,28 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s
| None -> MetadataTokens.MethodDefinitionHandle 0
| Some x -> MetadataTokens.MethodDefinitionHandle x
let deterministicIdProvider isDeterministic : System.Func<IEnumerable<Blob>, BlobContentId> =
match isDeterministic with
| false -> null
| true ->
let convert (content: IEnumerable<Blob>) =
use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only
let hash = content
|> Seq.collect (fun c -> c.GetBytes().Array |> sha.ComputeHash)
|> Array.ofSeq |> sha.ComputeHash
BlobContentId.FromHash hash
System.Func<IEnumerable<Blob>, BlobContentId>( convert )
// Compute the contentId for the pdb. Always do it deterministically, since we have to compute the anyway.
// The contentId is the hash of the ID using whichever algorithm has been specified to the compiler
let mutable contentHash = Array.empty<byte>
let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, deterministicIdProvider isDeterministic)
let algorithmName, hashAlgorithm =
match checksumAlgorithm with
| HashAlgorithm.Sha1 -> "SHA1", System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm
| HashAlgorithm.Sha256 -> "SHA256", System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm
let idProvider: System.Func<IEnumerable<Blob>, BlobContentId> =
let convert (content: IEnumerable<Blob>) =
let contentBytes = content |> Seq.collect (fun c -> c.GetBytes()) |> Array.ofSeq
contentHash <- contentBytes |> hashAlgorithm.ComputeHash
BlobContentId.FromHash contentHash
System.Func<IEnumerable<Blob>, BlobContentId>(convert)
let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, idProvider)
let blobBuilder = new BlobBuilder()
let contentId= serializer.Serialize blobBuilder
let portablePdbStream = new MemoryStream()
blobBuilder.WriteContentTo portablePdbStream
reportTime showTimes "PDB: Created"
(portablePdbStream.Length, contentId, portablePdbStream)
(portablePdbStream.Length, contentId, portablePdbStream, algorithmName, contentHash)
let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) =
let compressedStream = new MemoryStream()
@ -507,17 +556,17 @@ let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobConten
stream.WriteTo compressionStream
(uncompressedLength, contentId, compressedStream)
let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk =
let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb =
try FileSystem.FileDelete fpdb with _ -> ()
use pdbFile = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite)
stream.WriteTo pdbFile
reportTime showTimes "PDB: Closed"
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None 0L None
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None deterministicPdbChunk checksumPdbChunk algName checksum 0L None embeddedPdb deterministicPdb
let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk =
let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb =
reportTime showTimes "PDB: Closed"
let fn = Path.GetFileName fpdb
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) uncompressedLength (Some stream)
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) deterministicPdbChunk checksumPdbChunk algName checksum uncompressedLength (Some stream) embeddedPdb deterministicPdb
#if !FX_NO_PDB_WRITER
//---------------------------------------------------------------------

Просмотреть файл

@ -4,7 +4,7 @@
module internal FSharp.Compiler.AbstractIL.ILPdbWriter
open Internal.Utilities
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.ErrorLogger
open FSharp.Compiler.Range
open System.Collections.Generic
@ -83,10 +83,14 @@ type idd =
iddData: byte[];
iddChunk: BinaryChunk }
val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream)
type HashAlgorithm =
| Sha1
| Sha256
val generatePortablePdb : embedAllSource: bool -> embedSourceList: string list -> sourceLink: string -> checksumAlgorithm: HashAlgorithm -> showTimes: bool -> info: PdbData -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream * string * byte[])
val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream)
val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[]
val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> pathMap:PathMap -> cvChunk:BinaryChunk -> idd[]
val embedPortablePdbInfo: uncompressedLength: int64 -> contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> cvChunk: BinaryChunk -> pdbChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[]
val writePortablePdbInfo: contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> pathMap: PathMap -> cvChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[]
#if !FX_NO_PDB_WRITER
val writePdbInfo : showTimes:bool -> f:string -> fpdb:string -> info:PdbData -> cvChunk:BinaryChunk -> idd[]

Просмотреть файл

@ -1,22 +1,50 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
open System
open System.Diagnostics
open System.IO
open System.Reflection
open System.Reflection.PortableExecutable
open System.Text.RegularExpressions
module AssemblyVersionCheck =
module AssemblyCheck =
let private versionZero = Version(0, 0, 0, 0)
let private versionOne = Version(1, 0, 0, 0)
let private commitHashPattern = new Regex(@"Commit Hash: (<developer build>)|([0-9a-fA-F]{40})", RegexOptions.Compiled)
let private devVersionPattern = new Regex(@"-(ci|dev)", RegexOptions.Compiled)
let verifyAssemblyVersions (binariesPath:string) =
let verifyEmbeddedPdb (filename:string) =
use fileStream = File.OpenRead(filename)
let reader = new PEReader(fileStream)
let mutable hasEmbeddedPdb = false
try
for entry in reader.ReadDebugDirectory() do
match entry.Type with
| DebugDirectoryEntryType.CodeView ->
let _ = reader.ReadCodeViewDebugDirectoryData(entry)
()
| DebugDirectoryEntryType.EmbeddedPortablePdb ->
let _ = reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry)
hasEmbeddedPdb <- true
()
| DebugDirectoryEntryType.PdbChecksum ->
let _ = reader.ReadPdbChecksumDebugDirectoryData(entry)
()
| _ -> ()
with | e -> printfn "Error validating assembly %s\nMessage: %s" filename (e.ToString())
hasEmbeddedPdb
let verifyAssemblies (binariesPath:string) =
let excludedAssemblies =
[ "FSharp.Data.TypeProviders.dll" ]
|> Set.ofList
let fsharpAssemblies =
[ "FSharp*.dll"
"fsc.exe"
@ -28,12 +56,17 @@ module AssemblyVersionCheck =
|> List.ofSeq
|> List.filter (fun p -> (Set.contains (Path.GetFileName(p)) excludedAssemblies) |> not)
let fsharpExecutingWithEmbeddedPdbs =
fsharpAssemblies
|> List.filter (fun p -> not (p.Contains(@"\Proto\") || p.Contains(@"\Bootstrap\") || p.Contains(@".resources.") || p.Contains(@"\FSharpSdk\") || p.Contains(@"\tmp\") || p.Contains(@"\obj\")))
// verify that all assemblies have a version number other than 0.0.0.0 or 1.0.0.0
let failedVersionCheck =
fsharpAssemblies
|> List.filter (fun a ->
let assemblyVersion = AssemblyName.GetAssemblyName(a).Version
assemblyVersion = versionZero || assemblyVersion = versionOne)
if failedVersionCheck.Length > 0 then
printfn "The following assemblies had a version of %A or %A" versionZero versionOne
printfn "%s\r\n" <| String.Join("\r\n", failedVersionCheck)
@ -43,27 +76,36 @@ module AssemblyVersionCheck =
// verify that all assemblies have a commit hash
let failedCommitHash =
fsharpAssemblies
|> List.filter (fun p -> not (p.Contains(@"\FSharpSdk\")))
|> List.filter (fun a ->
let fileProductVersion = FileVersionInfo.GetVersionInfo(a).ProductVersion
not (commitHashPattern.IsMatch(fileProductVersion) || devVersionPattern.IsMatch(fileProductVersion)))
if failedCommitHash.Length > 0 then
printfn "The following assemblies don't have a commit hash set"
printfn "%s\r\n" <| String.Join("\r\n", failedCommitHash)
else
printfn "All shipping assemblies had an appropriate commit hash."
// return code is the number of failures
failedVersionCheck.Length + failedCommitHash.Length
// verify that all assemblies have an embedded pdb
let failedVerifyEmbeddedPdb =
fsharpExecutingWithEmbeddedPdbs
|> List.filter (fun a -> not (verifyEmbeddedPdb a))
if failedVerifyEmbeddedPdb.Length > 0 then
printfn "The following assemblies don't have an embedded pdb"
printfn "%s\r\n" <| String.Join("\r\n", failedVerifyEmbeddedPdb)
else
printfn "All shipping assemblies had an embedded PDB."
// return code is the number of failures
failedVersionCheck.Length + failedCommitHash.Length + failedVerifyEmbeddedPdb.Length
[<EntryPoint>]
let main (argv:string array) =
if argv.Length <> 1 then
printfn "Usage: fsi.exe AssemblyVersionCheck.fsx -- path/to/binaries"
printfn "Usage: dotnet AssemblyCheck.dll -- path/to/binaries"
1
else
AssemblyVersionCheck.verifyAssemblyVersions argv.[0]
Environment.GetCommandLineArgs()
|> Seq.skipWhile ((<>) "--")
|> Seq.skip 1
|> Array.ofSeq
|> main
AssemblyCheck.verifyAssemblies argv.[0]

Просмотреть файл

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyCheck.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\fsharp\FSharp.Core\FSharp.Core.fsproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -8,6 +8,7 @@
<ItemGroup>
<Projects Include="fslex\fslex.fsproj" />
<Projects Include="fsyacc\fsyacc.fsproj" />
<Projects Include="AssemblyCheck\AssemblyCheck.fsproj" />
</ItemGroup>
<Target Name="Build">

Просмотреть файл

@ -17,6 +17,7 @@ open Internal.Utilities.Text
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILBinaryReader
open FSharp.Compiler.AbstractIL.ILPdbWriter
open FSharp.Compiler.AbstractIL.Internal
open FSharp.Compiler.AbstractIL.Internal.Library
open FSharp.Compiler.AbstractIL.Extensions.ILX
@ -2101,6 +2102,7 @@ type TcConfigBuilder =
mutable maxErrors: int
mutable abortOnError: bool (* intended for fsi scripts that should exit on first error *)
mutable baseAddress: int32 option
mutable checksumAlgorithm: HashAlgorithm
#if DEBUG
mutable showOptimizationData: bool
#endif
@ -2234,6 +2236,7 @@ type TcConfigBuilder =
maxErrors = 100
abortOnError = false
baseAddress = None
checksumAlgorithm = HashAlgorithm.Sha256
delaysign = false
publicsign = false
@ -2744,6 +2747,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
member x.flatErrors = data.flatErrors
member x.maxErrors = data.maxErrors
member x.baseAddress = data.baseAddress
member x.checksumAlgorithm = data.checksumAlgorithm
#if DEBUG
member x.showOptimizationData = data.showOptimizationData
#endif

Просмотреть файл

@ -10,6 +10,7 @@ open Internal.Utilities
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILBinaryReader
open FSharp.Compiler.AbstractIL.ILPdbWriter
open FSharp.Compiler.AbstractIL.Internal.Library
open FSharp.Compiler
open FSharp.Compiler.TypeChecker
@ -338,6 +339,7 @@ type TcConfigBuilder =
mutable maxErrors: int
mutable abortOnError: bool
mutable baseAddress: int32 option
mutable checksumAlgorithm: HashAlgorithm
#if DEBUG
mutable showOptimizationData: bool
#endif
@ -500,6 +502,7 @@ type TcConfig =
member maxErrors: int
member baseAddress: int32 option
member checksumAlgorithm: HashAlgorithm
#if DEBUG
member showOptimizationData: bool
#endif

Просмотреть файл

@ -9,6 +9,7 @@ open System
open FSharp.Compiler
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILPdbWriter
open FSharp.Compiler.AbstractIL.Internal.Library
open FSharp.Compiler.AbstractIL.Extensions.ILX
open FSharp.Compiler.AbstractIL.Diagnostics
@ -523,6 +524,7 @@ let tagFullPDBOnlyPortable = "{full|pdbonly|portable|embedded}"
let tagWarnList = "<warn;...>"
let tagSymbolList = "<symbol;...>"
let tagAddress = "<address>"
let tagAlgorithm = "{SHA1|SHA256}"
let tagInt = "<n>"
let tagPathMap = "<path=sourcePath;...>"
let tagNone = ""
@ -948,6 +950,16 @@ let advancedFlagsFsc tcConfigB =
OptionString (fun s -> tcConfigB.baseAddress <- Some(int32 s)), None,
Some (FSComp.SR.optsBaseaddress()))
yield CompilerOption
("checksumalgorithm", tagAlgorithm,
OptionString (fun s ->
tcConfigB.checksumAlgorithm <-
match s.ToUpperInvariant() with
| "SHA1" -> HashAlgorithm.Sha1
| "SHA256" -> HashAlgorithm.Sha256
| _ -> error(Error(FSComp.SR.optsUnknownChecksumAlgorithm s, rangeCmdArgs))), None,
Some (FSComp.SR.optsChecksumAlgorithm()))
yield noFrameworkFlag true tcConfigB
yield CompilerOption

Просмотреть файл

@ -880,6 +880,7 @@ optsUtf8output,"Output messages in UTF-8 encoding"
optsFullpaths,"Output messages with fully qualified paths"
optsLib,"Specify a directory for the include path which is used to resolve source files and assemblies (Short form: -I)"
optsBaseaddress,"Base address for the library to be built"
optsChecksumAlgorithm,"Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)"
optsNoframework,"Do not reference the default CLI assemblies by default"
optsStandalone,"Statically link the F# library and all referenced DLLs that depend on it into the assembly being generated"
optsStaticlink,"Statically link the given assembly and all referenced DLLs that depend on this assembly. Use an assembly name e.g. mylib, not a DLL name."
@ -902,6 +903,7 @@ optsHelpBannerLanguage,"- LANGUAGE -"
optsHelpBannerErrsAndWarns,"- ERRORS AND WARNINGS -"
1063,optsUnknownArgumentToTheTestSwitch,"Unknown --test argument: '%s'"
1064,optsUnknownPlatform,"Unrecognized platform '%s', valid values are 'x86', 'x64', 'Itanium', 'anycpu32bitpreferred', and 'anycpu'"
1065,optsUnknownChecksumAlgorithm,"Algorithm '%s' is not supported"
optsInternalNoDescription,"The command-line option '%s' is for test purposes only"
optsDCLONoDescription,"The command-line option '%s' has been deprecated"
optsDCLODeprecatedSuggestAlternative,"The command-line option '%s' has been deprecated. Use '%s' instead."

Просмотреть файл

@ -24,6 +24,7 @@ type public Fsc () as this =
let mutable baseAddress : string = null
let mutable capturedArguments : string list = [] // list of individual args, to pass to HostObject Compile()
let mutable capturedFilenames : string list = [] // list of individual source filenames, to pass to HostObject Compile()
let mutable checksumAlgorithm: string = null
let mutable codePage : string = null
let mutable commandLineArgs : ITaskItem list = []
let mutable debugSymbols = false
@ -135,7 +136,7 @@ type public Fsc () as this =
builder.AppendSwitch("--tailcalls-")
// PdbFile
builder.AppendSwitchIfNotNull("--pdb:", pdbFile)
// Platform
// Platform
builder.AppendSwitchIfNotNull("--platform:",
let ToUpperInvariant (s:string) = if s = null then null else s.ToUpperInvariant()
match ToUpperInvariant(platform), prefer32bit, ToUpperInvariant(targetType) with
@ -145,6 +146,13 @@ type public Fsc () as this =
| "X86", _, _ -> "x86"
| "X64", _, _ -> "x64"
| _ -> null)
// checksumAlgorithm
builder.AppendSwitchIfNotNull("--checksumalgorithm:",
let ToUpperInvariant (s:string) = if s = null then null else s.ToUpperInvariant()
match ToUpperInvariant(checksumAlgorithm) with
| "SHA1" -> "Sha1"
| "SHA256" -> "Sha256"
| _ -> null)
// Resources
if resources <> null then
for item in resources do
@ -258,6 +266,11 @@ type public Fsc () as this =
with get() = baseAddress
and set(s) = baseAddress <- s
// --checksumalgorithm
member fsc.ChecksumAlgorithm
with get() = checksumAlgorithm
and set(s) = checksumAlgorithm <- s
// --codepage <int>: Specify the codepage to use when opening source files
member fsc.CodePage
with get() = codePage

Просмотреть файл

@ -283,6 +283,7 @@ this file.
<!-- NOTE: ManifestResourceWithNoCulture and ManifestNonResxWithNoCultureOnDisk are generated by Mono targets files -->
<Fsc Condition="'%(_CoreCompileResourceInputs.WithCulture)' != 'true'"
BaseAddress="$(BaseAddress)"
ChecksumAlgorithm="$(PdbChecksumAlgorithm)"
CodePage="$(CodePage)"
DebugSymbols="$(DebugSymbols)"
DebugType="$(DebugType)"

Просмотреть файл

@ -251,15 +251,15 @@
<Compile Include="..\..\absil\ilread.fs">
<Link>AbsIL\ilread.fs</Link>
</Compile>
<Compile Include="..\..\absil\ilwrite.fsi">
<Link>AbsIL\ilwrite.fsi</Link>
</Compile>
<Compile Include="..\..\absil\ilwritepdb.fsi">
<Link>AbsIL\ilwritepdb.fsi</Link>
</Compile>
<Compile Include="..\..\absil\ilwritepdb.fs">
<Link>AbsIL\ilwritepdb.fs</Link>
</Compile>
<Compile Include="..\..\absil\ilwrite.fsi">
<Link>AbsIL\ilwrite.fsi</Link>
</Compile>
<Compile Include="..\..\absil\ilwrite.fs">
<Link>AbsIL\ilwrite.fs</Link>
</Compile>

Просмотреть файл

@ -49,15 +49,7 @@
<file src="FSharp.Compiler.Private\$Configuration$\netstandard2.0\FSharp.Compiler.Private.dll" target="lib\netcoreapp2.1" />
<file src="FSharp.Build\$Configuration$\netcoreapp2.1\FSharp.Build.dll" target="lib\netcoreapp2.1" />
<file src="FSharp.Compiler.Interactive.Settings\$Configuration$\netstandard2.0\FSharp.Compiler.Interactive.Settings.dll"
target="lib\netcoreapp2.1" />
<!-- symbols -->
<file src="fsc\$Configuration$\netcoreapp2.1\fsc.pdb" target="lib\netcoreapp2.1" />
<file src="fsi\$Configuration$\netcoreapp2.1\fsi.pdb" target="lib\netcoreapp2.1" />
<file src="FSharp.Core\$Configuration$\netstandard2.0\FSharp.Core.pdb" target="lib\netcoreapp2.1" />
<file src="FSharp.Compiler.Private\$Configuration$\netstandard2.0\FSharp.Compiler.Private.pdb" target="lib\netcoreapp2.1" />
<file src="FSharp.Build\$Configuration$\netcoreapp2.1\FSharp.Build.pdb" target="lib\netcoreapp2.1" />
<file src="FSharp.Compiler.Interactive.Settings\$Configuration$\netstandard2.0\FSharp.Compiler.Interactive.Settings.pdb"
target="lib\netcoreapp2.1" />
target="lib\netcoreapp2.1" />
<!-- additional files -->
<file src="fsc\$Configuration$\netcoreapp2.1\default.win32manifest" target="contentFiles\any\any" />
<file src="FSharp.Build\$Configuration$\netcoreapp2.1\Microsoft.FSharp.Targets" target="contentFiles\any\any" />
@ -69,9 +61,9 @@
<!-- resources -->
<file src="FSharp.Core\$Configuration$\netstandard2.0\**\FSharp.Core.resources.dll" target="lib\netcoreapp2.1" />
<file src="FSharp.Compiler.Private\$Configuration$\netstandard2.0\**\FSharp.Compiler.Private.resources.dll"
target="lib\netcoreapp2.1" />
target="lib\netcoreapp2.1" />
<file src="FSharp.Compiler.Interactive.Settings\$Configuration$\netstandard2.0\**\FSharp.Compiler.Interactive.Settings.resources.dll"
target="lib\netcoreapp2.1" />
target="lib\netcoreapp2.1" />
<file src="FSharp.Build\$Configuration$\netcoreapp2.1\**\FSharp.Build.resources.dll" target="lib\netcoreapp2.1" />
</files>
</package>

Просмотреть файл

@ -2138,6 +2138,7 @@ let main4 dynamicAssemblyCreator (Args (ctok, tcConfig, tcImports: TcImports, t
embedAllSource = tcConfig.embedAllSource
embedSourceList = tcConfig.embedSourceList
sourceLink = tcConfig.sourceLink
checksumAlgorithm = tcConfig.checksumAlgorithm
signer = GetStrongNameSigner signingInfo
dumpDebugInfo = tcConfig.dumpDebugInfo
pathMap = tcConfig.pathMap },

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">Není definovaný obor názvů {0}.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">Der Namespace "{0}" ist nicht definiert.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">El espacio de nombres "{0}" no está definido.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">L'espace de noms '{0}' n'est pas défini.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">Lo spazio dei nomi '{0}' non è definito.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">名前空間 '{0}' が定義されていません。</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">'{0}' 네임스페이스가 정의되지 않았습니다.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">Nie zdefiniowano przestrzeni nazw „{0}”.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">O namespace '{0}' não está definido.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">Пространство имен "{0}" не определено.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">'{0}' ad alanı tanımlı değil.</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">未定义命名空间“{0}”。</target>

Просмотреть файл

@ -27,6 +27,16 @@
<target state="new">Unexpected symbol '.' in member definition. Expected 'with', '=' or other token.</target>
<note />
</trans-unit>
<trans-unit id="optsChecksumAlgorithm">
<source>Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</source>
<target state="new">Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)</target>
<note />
</trans-unit>
<trans-unit id="optsUnknownChecksumAlgorithm">
<source>Algorithm '{0}' is not supported</source>
<target state="new">Algorithm '{0}' is not supported</target>
<note />
</trans-unit>
<trans-unit id="undefinedNameNamespace">
<source>The namespace '{0}' is not defined.</source>
<target state="translated">未定義命名空間 '{0}'。</target>

Просмотреть файл

@ -12495,7 +12495,7 @@ namespace ProviderImplementation.ProvidedTypes
let pdbOpt =
match portablePDB with
| true ->
let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic
let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData
if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream)
else Some (pdbStream)
| _ -> None

3
tests/fsharp/.gitignore поставляемый
Просмотреть файл

@ -13,4 +13,5 @@ Library1.dll
cd.tmp
*.err
*.vserr

Просмотреть файл

@ -32,6 +32,76 @@ module CompilerAssert =
let checker = FSharpChecker.Create()
let private config = TestFramework.initializeSuite ()
// Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler
#if !NETCOREAPP
#else
let projectFile = """
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup><Compile Include="Program.fs" /></ItemGroup>
<Target Name="WriteFrameworkReferences" AfterTargets="AfterBuild">
<WriteLinesToFile File="FrameworkReferences.txt" Lines="@(ReferencePath)" Overwrite="true" WriteOnlyWhenDifferent="true" />
</Target>
</Project>"""
let programFs = """
open System
[<EntryPoint>]
let main argv = 0"""
let getNetCoreAppReferences =
let mutable output = ""
let mutable errors = ""
let mutable cleanUp = true
let projectDirectory = Path.Combine(Path.GetTempPath(), "netcoreapp2.1", Path.GetRandomFileName())
try
try
Directory.CreateDirectory(projectDirectory) |> ignore
let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj")
let programFsFileName = Path.Combine(projectDirectory, "Program.fs")
let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt")
File.WriteAllText(projectFileName, projectFile)
File.WriteAllText(programFsFileName, programFs)
let pInfo = ProcessStartInfo ()
pInfo.FileName <- config.DotNetExe
pInfo.Arguments <- "build"
pInfo.WorkingDirectory <- projectDirectory
pInfo.RedirectStandardOutput <- true
pInfo.RedirectStandardError <- true
pInfo.UseShellExecute <- false
let p = Process.Start(pInfo)
p.WaitForExit()
output <- p.StandardOutput.ReadToEnd ()
errors <- p.StandardError.ReadToEnd ()
if not (String.IsNullOrWhiteSpace errors) then Assert.Fail errors
if p.ExitCode <> 0 then Assert.Fail(sprintf "Program exited with exit code %d" p.ExitCode)
File.ReadLines(frameworkReferencesFileName) |> Seq.toArray
with | e ->
cleanUp <- false
printfn "%s" output
printfn "%s" errors
raise (new Exception (sprintf "An error occured getting netcoreapp references: %A" e))
finally
if cleanUp then
try Directory.Delete(projectDirectory) with | _ -> ()
#endif
let private defaultProjectOptions =
{
ProjectFileName = "Z:\\test.fsproj"
@ -41,14 +111,7 @@ module CompilerAssert =
OtherOptions = [|"--preferreduilang:en-US";|]
#else
OtherOptions =
// Hack: Currently a hack to get the runtime assemblies for netcore in order to compile.
let assemblies =
typeof<obj>.Assembly.Location
|> Path.GetDirectoryName
|> Directory.EnumerateFiles
|> Seq.toArray
|> Array.filter (fun x -> x.ToLowerInvariant().Contains("system.") || x.ToLowerInvariant().EndsWith("netstandard.dll"))
|> Array.map (fun x -> sprintf "-r:%s" x)
let assemblies = getNetCoreAppReferences |> Array.map (fun x -> sprintf "-r:%s" x)
Array.append [|"--preferreduilang:en-US"; "--targetprofile:netcore"; "--noframework"|] assemblies
#endif
ReferencedProjects = [||]
@ -60,6 +123,7 @@ module CompilerAssert =
ExtraProjectInfo = None
Stamp = None
}
let private gate = obj ()
let private compile isExe source f =
@ -109,11 +173,15 @@ module CompilerAssert =
Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors)
let TypeCheckWithErrors (source: string) expectedTypeErrors =
let TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors =
lock gate <| fun () ->
let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously
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)
@ -136,11 +204,17 @@ module CompilerAssert =
Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg")
)
let TypeCheckWithErrors (source: string) expectedTypeErrors =
TypeCheckWithErrorsAndOptions [||] source expectedTypeErrors
let TypeCheckSingleErrorWithOptions options (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) =
TypeCheckWithErrorsAndOptions options source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |]
let TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) =
TypeCheckWithErrors (source: string) [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |]
TypeCheckWithErrors source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |]
let CompileExe (source: string) =
compile true source (fun (errors, _) ->
compile true source (fun (errors, _) ->
if errors.Length > 0 then
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors))
@ -215,3 +289,4 @@ module CompilerAssert =
||> Seq.iter2 (fun expectedErrorMessage errorMessage ->
Assert.AreEqual(expectedErrorMessage, errorMessage)
)

Просмотреть файл

@ -0,0 +1,45 @@
// 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
[<TestFixture>]
module MemberConstraints =
[<Test>]
let ``we can overload operators on a type and not add all the extra jazz such as inlining and the ^ operator.``() =
CompilerAssert.CompileExeAndRun
"""
type Foo(x : int) =
member this.Val = x
static member (-->) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val)
static member (-->) ((src : Foo), (target : int)) = new Foo(src.Val + target)
static member (+) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val)
static member (+) ((src : Foo), (target : int)) = new Foo(src.Val + target)
let x = Foo(3) --> 4
let y = Foo(3) --> Foo(4)
let x2 = Foo(3) + 4
let y2 = Foo(3) + Foo(4)
if x.Val <> 7 then exit 1
if y.Val <> 7 then exit 1
if x2.Val <> 7 then exit 1
if y2.Val <> 7 then exit 1
"""
[<Test>]
let ``Invalid member constraint with ErrorRanges``() = // Regression test for FSharp1.0:2262
CompilerAssert.TypeCheckSingleErrorWithOptions
[| "--test:ErrorRanges" |]
"""
let inline length (x: ^a) : int = (^a : (member Length : int with get, set) (x, ()))
"""
FSharpErrorSeverity.Error
697
(2, 42, 2, 75)
"Invalid constraint"

Просмотреть файл

@ -0,0 +1,109 @@
// 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
[<TestFixture>]
module PrimitiveConstraints =
[<Test>]
let ``Test primitive : constraints``() =
CompilerAssert.CompileExeAndRun
"""
#light
type Foo(x : int) =
member this.Value = x
override this.ToString() = "Foo"
type Bar(x : int) =
inherit Foo(-1)
member this.Value2 = x
override this.ToString() = "Bar"
let test1 (x : Foo) = x.Value
let test2 (x : Bar) = (x.Value, x.Value2)
let f = new Foo(128)
let b = new Bar(256)
if test1 f <> 128 then exit 1
if test2 b <> (-1, 256) then exit 1
"""
[<Test>]
let ``Test primitive :> constraints``() =
CompilerAssert.CompileExeAndRun
"""
#light
type Foo(x : int) =
member this.Value = x
override this.ToString() = "Foo"
type Bar(x : int) =
inherit Foo(-1)
member this.Value2 = x
override this.ToString() = "Bar"
type Ram(x : int) =
inherit Foo(10)
member this.ValueA = x
override this.ToString() = "Ram"
let test (x : Foo) = (x.Value, x.ToString())
let f = new Foo(128)
let b = new Bar(256)
let r = new Ram(314)
if test f <> (128, "Foo") then exit 1
if test b <> (-1, "Bar") then exit 1
if test r <> (10, "Ram") then exit 1
"""
[<Test>]
let ``Test primitive : null constraint``() =
CompilerAssert.CompileExeAndRun
"""
let inline isNull<'a when 'a : null> (x : 'a) =
match x with
| null -> "is null"
| _ -> (x :> obj).ToString()
let runTest =
// Wrapping in try block to work around FSB 1989
try
if isNull null <> "is null" then exit 1
if isNull "F#" <> "F#" then exit 1
true
with _ -> exit 1
if runTest <> true then exit 1
exit 0
"""
[<Test>]
/// Title: Type checking oddity
///
/// This suggestion was resolved as by design,
/// so the test makes sure, we're emitting error message about 'not being a valid object construction expression'
let ``Invalid object constructor``() = // Regression test for FSharp1.0:4189
CompilerAssert.TypeCheckWithErrorsAndOptions
[| "--test:ErrorRanges" |]
"""
type ImmutableStack<'a> private(items: 'a list) =
member this.Push item = ImmutableStack(item::items)
member this.Pop = match items with | [] -> failwith "No elements in stack" | x::xs -> x,ImmutableStack(xs)
// Notice type annotation is commented out, which results in an error
new(col (*: seq<'a>*)) = ImmutableStack(List.ofSeq col)
"""
[| FSharpErrorSeverity.Error, 41, (4, 29, 4, 56), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a>, private new : items:'a list -> ImmutableStack<'a>"
FSharpErrorSeverity.Error, 41, (5, 93, 5, 111), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a>, private new : items:'a list -> ImmutableStack<'a>"
FSharpErrorSeverity.Error, 41, (8, 30, 8, 60), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a> when 'b :> seq<'c>, private new : items:'a list -> ImmutableStack<'a>"
FSharpErrorSeverity.Error, 696, (8, 30, 8, 60), "This is not a valid object construction expression. Explicit object constructors must either call an alternate constructor or initialize all fields of the object and specify a call to a super class constructor." |]

Просмотреть файл

@ -0,0 +1,23 @@
// 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
[<TestFixture>]
module ``Errors assigning to mutable objects`` =
[<Test>]
let ``Assign to immutable error``() =
CompilerAssert.TypeCheckSingleError
"""
let x = 10
x <- 20
exit 0
"""
FSharpErrorSeverity.Error
27
(3, 1, 3, 8)
"This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable x = expression'."

Просмотреть файл

@ -0,0 +1,45 @@
// 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
[<TestFixture>]
module NameResolutionTests =
[<Test>]
let FieldNotInRecord () =
CompilerAssert.TypeCheckSingleError
"""
type A = { Hello:string; World:string }
type B = { Size:int; Height:int }
type C = { Wheels:int }
type D = { Size:int; Height:int; Walls:int }
type E = { Unknown:string }
type F = { Wallis:int; Size:int; Height:int; }
let r:F = { Size=3; Height=4; Wall=1 }
"""
FSharpErrorSeverity.Error
1129
(9, 31, 9, 35)
"The record type 'F' does not contain a label 'Wall'."
[<Test>]
let RecordFieldProposal () =
CompilerAssert.TypeCheckSingleError
"""
type A = { Hello:string; World:string }
type B = { Size:int; Height:int }
type C = { Wheels:int }
type D = { Size:int; Height:int; Walls:int }
type E = { Unknown:string }
type F = { Wallis:int; Size:int; Height:int; }
let r = { Size=3; Height=4; Wall=1 }
"""
FSharpErrorSeverity.Error
39
(9, 29, 9, 33)
"The record label 'Wall' is not defined."

Просмотреть файл

@ -0,0 +1,135 @@
// 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
[<TestFixture>]
module ``Type Mismatch`` =
[<Test>]
let ``return Instead Of return!``() =
CompilerAssert.TypeCheckSingleError
"""
let rec foo() = async { return foo() }
"""
FSharpErrorSeverity.Error
1
(2, 32, 2, 37)
"Type mismatch. Expecting a\n ''a' \nbut given a\n 'Async<'a>' \nThe types ''a' and 'Async<'a>' cannot be unified. Consider using 'return!' instead of 'return'."
[<Test>]
let ``yield Instead Of yield!``() =
CompilerAssert.TypeCheckSingleError
"""
type Foo() =
member this.Yield(x) = [x]
let rec f () = Foo() { yield f ()}
"""
FSharpErrorSeverity.Error
1
(5, 30, 5, 34)
"Type mismatch. Expecting a\n ''a' \nbut given a\n ''a list' \nThe types ''a' and ''a list' cannot be unified. Consider using 'yield!' instead of 'yield'."
[<Test>]
let ``Ref Cell Instead Of Not``() =
CompilerAssert.TypeCheckSingleError
"""
let x = true
if !x then
printfn "hello"
"""
FSharpErrorSeverity.Error
1
(3, 5, 3, 6)
"This expression was expected to have type\n 'bool ref' \nbut here has type\n 'bool' \r\nThe '!' operator is used to dereference a ref cell. Consider using 'not expr' here."
[<Test>]
let ``Ref Cell Instead Of Not 2``() =
CompilerAssert.TypeCheckSingleError
"""
let x = true
let y = !x
"""
FSharpErrorSeverity.Error
1
(3, 10, 3, 11)
"This expression was expected to have type\n ''a ref' \nbut here has type\n 'bool' \r\nThe '!' operator is used to dereference a ref cell. Consider using 'not expr' here."
[<Test>]
let ``Guard Has Wrong Type``() =
CompilerAssert.TypeCheckWithErrors
"""
let x = 1
match x with
| 1 when "s" -> true
| _ -> false
"""
[|
FSharpErrorSeverity.Error, 1, (4, 10, 4, 13), "A pattern match guard must be of type 'bool', but this 'when' expression is of type 'string'."
FSharpErrorSeverity.Warning, 20, (3, 1, 5, 13), "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'."
|]
[<Test>]
let ``Runtime Type Test In Pattern``() =
CompilerAssert.TypeCheckWithErrors
"""
open System.Collections.Generic
let orig = Dictionary<obj,obj>()
let c =
match orig with
| :? IDictionary<obj,obj> -> "yes"
| _ -> "no"
"""
[|
FSharpErrorSeverity.Warning, 67, (8, 5, 8, 28), "This type test or downcast will always hold"
FSharpErrorSeverity.Error, 193, (8, 5, 8, 28), "Type constraint mismatch. The type \n 'IDictionary<obj,obj>' \nis not compatible with type\n 'Dictionary<obj,obj>' \n"
|]
[<Test>]
let ``Runtime Type Test In Pattern 2``() =
CompilerAssert.TypeCheckWithErrors
"""
open System.Collections.Generic
let orig = Dictionary<obj,obj>()
let c =
match orig with
| :? IDictionary<obj,obj> as y -> "yes" + y.ToString()
| _ -> "no"
"""
[|
FSharpErrorSeverity.Warning, 67, (8, 5, 8, 28), "This type test or downcast will always hold"
FSharpErrorSeverity.Error, 193, (8, 5, 8, 28), "Type constraint mismatch. The type \n 'IDictionary<obj,obj>' \nis not compatible with type\n 'Dictionary<obj,obj>' \n"
|]
[<Test>]
let ``Override Errors``() =
CompilerAssert.TypeCheckWithErrors
"""
type Base() =
abstract member Member: int * string -> string
default x.Member (i, s) = s
type Derived1() =
inherit Base()
override x.Member() = 5
type Derived2() =
inherit Base()
override x.Member (i : int) = "Hello"
type Derived3() =
inherit Base()
override x.Member (s : string, i : int) = sprintf "Hello %s" s
"""
[|
FSharpErrorSeverity.Error, 856, (8, 16, 8, 22), "This override takes a different number of arguments to the corresponding abstract member. The following abstract members were found:\r\n abstract member Base.Member : int * string -> string"
FSharpErrorSeverity.Error, 856, (12, 16, 12, 22), "This override takes a different number of arguments to the corresponding abstract member. The following abstract members were found:\r\n abstract member Base.Member : int * string -> string"
FSharpErrorSeverity.Error, 1, (16, 24, 16, 34), "This expression was expected to have type\n 'int' \nbut here has type\n 'string' "
|]

Просмотреть файл

@ -0,0 +1,27 @@
// 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
[<TestFixture>]
module ``Unit generic abstract Type`` =
[<Test>]
let ``Unit can not be used as return type of abstract method paramete on return type``() =
CompilerAssert.TypeCheckSingleError
"""
type EDF<'S> =
abstract member Apply : int -> 'S
type SomeEDF () =
interface EDF<unit> with
member this.Apply d =
// [ERROR] The member 'Apply' does not have the correct type to override the corresponding abstract method.
()
"""
FSharpErrorSeverity.Error
17
(6, 21, 6, 26)
"The member 'Apply : int -> unit' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type."

Просмотреть файл

@ -0,0 +1,51 @@
// 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
[<TestFixture>]
module ``Upcast and Downcast`` =
[<Test>]
let ``Downcast Instead Of Upcast``() =
CompilerAssert.TypeCheckSingleError
"""
open System.Collections.Generic
let orig = Dictionary<obj,obj>() :> IDictionary<obj,obj>
let c = orig :> Dictionary<obj,obj>
"""
FSharpErrorSeverity.Error
193
(5, 9, 5, 36)
"Type constraint mismatch. The type \n 'IDictionary<obj,obj>' \nis not compatible with type\n 'Dictionary<obj,obj>' \n"
[<Test>]
let ``Upcast Instead Of Downcast``() =
CompilerAssert.TypeCheckWithErrors
"""
open System.Collections.Generic
let orig = Dictionary<obj,obj>()
let c = orig :?> IDictionary<obj,obj>
"""
[|
FSharpErrorSeverity.Warning, 67, (5, 9, 5, 38), "This type test or downcast will always hold"
FSharpErrorSeverity.Error, 3198, (5, 9, 5, 38), "The conversion from Dictionary<obj,obj> to IDictionary<obj,obj> is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator."
|]
[<Test>]
let ``Upcast Function Instead Of Downcast``() =
CompilerAssert.TypeCheckWithErrors
"""
open System.Collections.Generic
let orig = Dictionary<obj,obj>()
let c : IDictionary<obj,obj> = downcast orig
"""
[|
FSharpErrorSeverity.Warning, 67, (5, 32, 5, 45), "This type test or downcast will always hold"
FSharpErrorSeverity.Error, 3198, (5, 32, 5, 45), "The conversion from Dictionary<obj,obj> to IDictionary<obj,obj> is a compile-time safe upcast, not a downcast. Consider using 'upcast' instead of 'downcast'."
|]

Просмотреть файл

@ -0,0 +1,208 @@
// 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
[<TestFixture>]
module ``Warn Expression`` =
[<Test>]
let ``Warn If Expression Result Unused``() =
CompilerAssert.TypeCheckSingleError
"""
1 + 2
printfn "%d" 3
"""
FSharpErrorSeverity.Warning
20
(2, 1, 2, 6)
"The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'."
[<Test>]
let ``Warn If Possible Assignment``() =
CompilerAssert.TypeCheckSingleError
"""
let x = 10
let y = "hello"
let changeX() =
x = 20
y = "test"
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 11)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'."
[<Test>]
let ``Warn If Possible Assignment To Mutable``() =
CompilerAssert.TypeCheckSingleError
"""
let mutable x = 10
let y = "hello"
let changeX() =
x = 20
y = "test"
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 11)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'."
[<Test>]
let ``Warn If Possible dotnet Property Setter``() =
CompilerAssert.TypeCheckWithErrors
"""
open System
let z = System.Timers.Timer()
let y = "hello"
let changeProperty() =
z.Enabled = true
y = "test"
"""
[|
FSharpErrorSeverity.Warning, 760, (4, 9, 4, 30), "It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value"
FSharpErrorSeverity.Warning, 20, (8, 5, 8, 21), "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression'."
|]
[<Test>]
let ``Don't Warn If Property Without Setter``() =
CompilerAssert.TypeCheckSingleError
"""
type MyClass(property1 : int) =
member val Property2 = "" with get
let x = MyClass(1)
let y = "hello"
let changeProperty() =
x.Property2 = "22"
y = "test"
"""
FSharpErrorSeverity.Warning
20
(9, 5, 9, 23)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'."
[<Test>]
let ``Warn If Implicitly Discarded``() =
CompilerAssert.TypeCheckSingleError
"""
let x = 10
let y = 20
let changeX() =
y * x = 20
y = 30
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 15)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'."
[<Test>]
let ``Warn If Discarded In List``() =
CompilerAssert.TypeCheckSingleError
"""
let div _ _ = 1
let subView _ _ = [1; 2]
// elmish view
let view model dispatch =
[
yield! subView model dispatch
div [] []
]
"""
FSharpErrorSeverity.Warning
3221
(9, 8, 9, 17)
"This expression returns a value of type 'int' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'."
[<Test>]
let ``Warn If Discarded In List 2``() =
CompilerAssert.TypeCheckSingleError
"""
// stupid things to make the sample compile
let div _ _ = 1
let subView _ _ = [1; 2]
let y = 1
// elmish view
let view model dispatch =
[
div [] [
match y with
| 1 -> yield! subView model dispatch
| _ -> subView model dispatch
]
]
"""
FSharpErrorSeverity.Warning
3222
(13, 19, 13, 41)
"This expression returns a value of type 'int list' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'."
[<Test>]
let ``Warn If Discarded In List 3``() =
CompilerAssert.TypeCheckSingleError
"""
// stupid things to make the sample compile
let div _ _ = 1
let subView _ _ = true
let y = 1
// elmish view
let view model dispatch =
[
div [] [
match y with
| 1 -> ()
| _ -> subView model dispatch
]
]
"""
FSharpErrorSeverity.Warning
20
(13, 19, 13, 41)
"The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'."
[<Test>]
let ``Warn Only On Last Expression``() =
CompilerAssert.TypeCheckSingleError
"""
let mutable x = 0
while x < 1 do
printfn "unneeded"
x <- x + 1
true
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 9)
"The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'."
[<Test>]
let ``Warn If Possible Property Setter``() =
CompilerAssert.TypeCheckSingleError
"""
type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set
let x = MyClass(1)
let y = "hello"
let changeProperty() =
x.Property2 = "20"
y = "test"
"""
FSharpErrorSeverity.Warning
20
(10, 5, 10, 23)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression'."

Просмотреть файл

@ -27,45 +27,45 @@ let test () =
verifier.VerifyIL
[
""".method public static void test() cil managed
{
.maxstack 5
.locals init (valuetype [System.Private.CoreLib]System.Span`1<class [System.Private.CoreLib]System.Object> V_0,
int32 V_1,
valuetype [System.Private.CoreLib]System.Int32 V_2,
class [System.Private.CoreLib]System.Object& V_3)
IL_0000: call valuetype [System.Private.CoreLib]System.Span`1<!0> valuetype [System.Private.CoreLib]System.Span`1<class [System.Private.CoreLib]System.Object>::get_Empty()
IL_0005: stloc.0
IL_0006: ldc.i4.0
IL_0007: stloc.2
IL_0008: ldloca.s V_0
IL_000a: call instance int32 valuetype [System.Private.CoreLib]System.Span`1<class [System.Private.CoreLib]System.Object>::get_Length()
IL_000f: ldc.i4.1
IL_0010: sub
IL_0011: stloc.1
IL_0012: ldloc.1
IL_0013: ldloc.2
IL_0014: blt.s IL_0034
{
IL_0016: ldloca.s V_0
IL_0018: ldloc.2
IL_0019: call instance !0& valuetype [System.Private.CoreLib]System.Span`1<class [System.Private.CoreLib]System.Object>::get_Item(int32)
IL_001e: stloc.3
IL_001f: ldloc.3
IL_0020: ldobj [System.Private.CoreLib]System.Object
IL_0025: call void [System.Console]System.Console::WriteLine(object)
IL_002a: ldloc.2
IL_002b: ldc.i4.1
IL_002c: add
IL_002d: stloc.2
IL_002e: ldloc.2
IL_002f: ldloc.1
IL_0030: ldc.i4.1
IL_0031: add
IL_0032: bne.un.s IL_0016
.maxstack 5
.locals init (valuetype [System.Runtime]System.Span`1<object> V_0,
int32 V_1,
int32 V_2,
object& V_3)
IL_0000: call valuetype [System.Runtime]System.Span`1<!0> valuetype [System.Runtime]System.Span`1<object>::get_Empty()
IL_0005: stloc.0
IL_0006: ldc.i4.0
IL_0007: stloc.2
IL_0008: ldloca.s V_0
IL_000a: call instance int32 valuetype [System.Runtime]System.Span`1<object>::get_Length()
IL_000f: ldc.i4.1
IL_0010: sub
IL_0011: stloc.1
IL_0012: ldloc.1
IL_0013: ldloc.2
IL_0014: blt.s IL_0034
IL_0034: ret
} """
IL_0016: ldloca.s V_0
IL_0018: ldloc.2
IL_0019: call instance !0& valuetype [System.Runtime]System.Span`1<object>::get_Item(int32)
IL_001e: stloc.3
IL_001f: ldloc.3
IL_0020: ldobj [System.Runtime]System.Object
IL_0025: call void [System.Console]System.Console::WriteLine(object)
IL_002a: ldloc.2
IL_002b: ldc.i4.1
IL_002c: add
IL_002d: stloc.2
IL_002e: ldloc.2
IL_002f: ldloc.1
IL_0030: ldc.i4.1
IL_0031: add
IL_0032: bne.un.s IL_0016
IL_0034: ret
}"""
])
[<Test>]
@ -88,18 +88,18 @@ let test () =
[
""".method public static void test() cil managed
{
.maxstack 5
.locals init (valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<class [System.Private.CoreLib]System.Object> V_0,
.locals init (valuetype [System.Runtime]System.ReadOnlySpan`1<object> V_0,
int32 V_1,
valuetype [System.Private.CoreLib]System.Int32 V_2,
class [System.Private.CoreLib]System.Object& V_3)
IL_0000: call valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<!0> valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<class [System.Private.CoreLib]System.Object>::get_Empty()
int32 V_2,
object& V_3)
IL_0000: call valuetype [System.Runtime]System.ReadOnlySpan`1<!0> valuetype [System.Runtime]System.ReadOnlySpan`1<object>::get_Empty()
IL_0005: stloc.0
IL_0006: ldc.i4.0
IL_0007: stloc.2
IL_0008: ldloca.s V_0
IL_000a: call instance int32 valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<class [System.Private.CoreLib]System.Object>::get_Length()
IL_000a: call instance int32 valuetype [System.Runtime]System.ReadOnlySpan`1<object>::get_Length()
IL_000f: ldc.i4.1
IL_0010: sub
IL_0011: stloc.1
@ -109,10 +109,10 @@ let test () =
IL_0016: ldloca.s V_0
IL_0018: ldloc.2
IL_0019: call instance !0& modreq([System.Private.CoreLib]System.Runtime.InteropServices.InAttribute) valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<class [System.Private.CoreLib]System.Object>::get_Item(int32)
IL_0019: call instance !0& modreq([System.Runtime]System.Runtime.InteropServices.InAttribute) valuetype [System.Runtime]System.ReadOnlySpan`1<object>::get_Item(int32)
IL_001e: stloc.3
IL_001f: ldloc.3
IL_0020: ldobj [System.Private.CoreLib]System.Object
IL_0020: ldobj [System.Runtime]System.Object
IL_0025: call void [System.Console]System.Console::WriteLine(object)
IL_002a: ldloc.2
IL_002b: ldc.i4.1
@ -176,29 +176,29 @@ module Test =
[
""".method public static void test() cil managed
{
.maxstack 3
.locals init (valuetype System.Span`1<class [System.Private.CoreLib]System.Object> V_0,
class [System.Private.CoreLib]System.Collections.IEnumerator V_1,
.locals init (valuetype System.Span`1<object> V_0,
class [System.Runtime]System.Collections.IEnumerator V_1,
class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2,
class [System.Private.CoreLib]System.IDisposable V_3)
class [System.Runtime]System.IDisposable V_3)
IL_0000: ldc.i4.0
IL_0001: newarr [System.Private.CoreLib]System.Object
IL_0006: newobj instance void valuetype System.Span`1<class [System.Private.CoreLib]System.Object>::.ctor(!0[])
IL_0001: newarr [System.Runtime]System.Object
IL_0006: newobj instance void valuetype System.Span`1<object>::.ctor(!0[])
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: box valuetype System.Span`1<class [System.Private.CoreLib]System.Object>
IL_0012: unbox.any [System.Private.CoreLib]System.Collections.IEnumerable
IL_0017: callvirt instance class [System.Private.CoreLib]System.Collections.IEnumerator [System.Private.CoreLib]System.Collections.IEnumerable::GetEnumerator()
IL_000d: box valuetype System.Span`1<object>
IL_0012: unbox.any [System.Runtime]System.Collections.IEnumerable
IL_0017: callvirt instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator()
IL_001c: stloc.1
.try
{
IL_001d: ldloc.1
IL_001e: callvirt instance bool [System.Private.CoreLib]System.Collections.IEnumerator::MoveNext()
IL_001e: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext()
IL_0023: brfalse.s IL_0032
IL_0025: ldloc.1
IL_0026: callvirt instance object [System.Private.CoreLib]System.Collections.IEnumerator::get_Current()
IL_0026: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current()
IL_002b: call void [System.Console]System.Console::WriteLine(object)
IL_0030: br.s IL_001d
@ -206,24 +206,24 @@ module Test =
IL_0033: stloc.2
IL_0034: leave.s IL_004c
}
}
finally
{
IL_0036: ldloc.1
IL_0037: isinst [System.Private.CoreLib]System.IDisposable
IL_0037: isinst [System.Runtime]System.IDisposable
IL_003c: stloc.3
IL_003d: ldloc.3
IL_003e: brfalse.s IL_0049
IL_0040: ldloc.3
IL_0041: callvirt instance void [System.Private.CoreLib]System.IDisposable::Dispose()
IL_0041: callvirt instance void [System.Runtime]System.IDisposable::Dispose()
IL_0046: ldnull
IL_0047: pop
IL_0048: endfinally
IL_0049: ldnull
IL_004a: pop
IL_004b: endfinally
}
}
IL_004c: ldloc.2
IL_004d: pop
IL_004e: ret

Просмотреть файл

@ -0,0 +1,108 @@
// 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
[<TestFixture>]
module ``Warnings assigning to mutable and immutable objects`` =
[<Test>]
let ``Unused compare with immutable when assignment might be intended``() =
CompilerAssert.TypeCheckSingleError
"""
let x = 10
let y = "hello"
let changeX() =
x = 20
y = "test"
exit 0
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 11)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'."
[<Test>]
let ``Unused compare with mutable when assignment might be intended``() =
CompilerAssert.TypeCheckSingleError
"""
let mutable x = 10
let y = "hello"
let changeX() =
x = 20
y = "test"
exit 0
"""
FSharpErrorSeverity.Warning
20
(6, 5, 6, 11)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'."
[<Test>]
let ``Unused comparison of property in dotnet object when assignment might be intended``() =
CompilerAssert.TypeCheckSingleError
"""
open System
let z = new System.Timers.Timer()
let y = "hello"
let changeProperty() =
z.Enabled = true
y = "test"
exit 0
"""
FSharpErrorSeverity.Warning
20
(8, 5, 8, 21)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression'."
[<Test>]
let ``Unused comparison of property when assignment might be intended ``() =
CompilerAssert.TypeCheckSingleError
"""
type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set
let x = MyClass(1)
let y = "hello"
let changeProperty() =
x.Property2 = "20"
y = "test"
exit 0
"""
FSharpErrorSeverity.Warning
20
(10, 5, 10, 23)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression'."
[<Test>]
let ``Don't warn if assignment to property without setter ``() =
CompilerAssert.TypeCheckSingleError
"""
type MyClass(property1 : int) =
member val Property2 = "" with get
let x = MyClass(1)
let y = "hello"
let changeProperty() =
x.Property2 = "22"
y = "test"
exit 0
"""
FSharpErrorSeverity.Warning
20
(9, 5, 9, 23)
"The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'."

Просмотреть файл

@ -36,7 +36,15 @@
<Compile Include="Compiler\ErrorMessages\ConstructorTests.fs" />
<Compile Include="Compiler\ErrorMessages\AccessOfTypeAbbreviationTests.fs" />
<Compile Include="Compiler\ErrorMessages\ElseBranchHasWrongTypeTests.fs" />
<Compile Include="Compiler\ConstraintSolver\PrimitiveConstraints.fs" />
<Compile Include="Compiler\ConstraintSolver\MemberConstraints.fs" />
<Compile Include="Compiler\ErrorMessages\MissingElseBranch.fs" />
<Compile Include="Compiler\ErrorMessages\UnitGenericAbstactType.fs" />
<Compile Include="Compiler\ErrorMessages\NameResolutionTests.fs" />
<Compile Include="Compiler\ErrorMessages\TypeMismatchTests.fs" />
<Compile Include="Compiler\ErrorMessages\UpcastDowncastTests.fs" />
<Compile Include="Compiler\ErrorMessages\AssignmentErrorTests.fs" />
<Compile Include="Compiler\ErrorMessages\WarnExpressionTests.fs" />
<Compile Include="Compiler\SourceTextTests.fs" />
<Compile Include="Compiler\Language\AnonRecordTests.fs" />
<Compile Include="Compiler\Language\SpanOptimizationTests.fs" />

Просмотреть файл

@ -0,0 +1,168 @@
namespace FSharp.Libraries.UnitTests
open System
open NUnit.Framework
open FSharp.Compiler.UnitTests
[<TestFixture>]
module AsyncTests =
// Regression for FSHARP1.0:5969
// Async.StartChild: error when wait async is executed more than once
[<Test>]
let ``Execute Async multiple times``() =
CompilerAssert.CompileExeAndRun
"""
module M
let a = async {
let! a = Async.StartChild(
async {
do! Async.Sleep(1)
return 27
})
let! result = Async.Parallel [ a; a; a; a ]
return result
} |> Async.RunSynchronously
exit 0
"""
// Regression for FSHARP1.0:5970
// Async.StartChild: race in implementation of ResultCell in FSharp.Core
[<Test>]
let ``Joining StartChild``() =
CompilerAssert.CompileExeAndRun
"""
module M
let Join (a1: Async<'a>) (a2: Async<'b>) = async {
let! task1 = a1 |> Async.StartChild
let! task2 = a2 |> Async.StartChild
let! res1 = task1
let! res2 = task2
return (res1,res2) }
let r =
try
Async.RunSynchronously (Join (async { do! Async.Sleep(30)
failwith "fail"
return 3+3 })
(async { do! Async.Sleep(30)
return 2 + 2 } ))
with _ ->
(0,0)
exit 0
"""
// Regression test for FSHARP1.0:6086
[<Test>]
let ``Mailbox Async dot not StackOverflow``() =
CompilerAssert.CompileExeAndRun
"""
open Microsoft.FSharp.Control
type Color = Blue | Red | Yellow
let complement = function
| (Red, Yellow) | (Yellow, Red) -> Blue
| (Red, Blue) | (Blue, Red) -> Yellow
| (Yellow, Blue) | (Blue, Yellow) -> Red
| (Blue, Blue) -> Blue
| (Red, Red) -> Red
| (Yellow, Yellow) -> Yellow
type Message = Color * AsyncReplyChannel<Color option>
let chameleon (meetingPlace : MailboxProcessor<Message>) initial =
let rec loop c meets = async {
let replyMessage = meetingPlace.PostAndReply(fun reply -> c, reply)
match replyMessage with
| Some(newColor) -> return! loop newColor (meets + 1)
| None -> return meets
}
loop initial 0
let meetingPlace chams n = MailboxProcessor.Start(fun (processor : MailboxProcessor<Message>)->
let rec fadingLoop total =
async {
if total <> 0 then
let! (_, reply) = processor.Receive()
reply.Reply None
return! fadingLoop (total - 1)
else
printfn "Done"
}
let rec mainLoop curr =
async {
if (curr > 0) then
let! (color1, reply1) = processor.Receive()
let! (color2, reply2) = processor.Receive()
let newColor = complement (color1, color2)
reply1.Reply <| Some(newColor)
reply2.Reply <| Some(newColor)
return! mainLoop (curr - 1)
else
return! fadingLoop chams
}
mainLoop n
)
open System
open System.Diagnostics
let meetings = 100000
let colors = [Blue; Red; Yellow; Blue]
let mp = meetingPlace (colors.Length) meetings
let watch = Stopwatch.StartNew()
let meets =
colors
|> List.map (chameleon mp)
|> Async.Parallel
|> Async.RunSynchronously
watch.Stop()
for meet in meets do
printfn "%d" meet
printfn "Total: %d in %O" (Seq.sum meets) (watch.Elapsed)
exit 0
"""
// Regression for FSHARP1.0:5971
[<Test>]
let ``StartChild do not throw ObjectDisposedException``() =
CompilerAssert.CompileExeAndRun
"""
module M
let b = async {return 5} |> Async.StartChild
printfn "%A" (b |> Async.RunSynchronously |> Async.RunSynchronously)
exit 0
"""
[<Test>]
let ``StartChild test Trampoline HijackLimit``() =
CompilerAssert.CompileExeAndRun
"""
module M
let r =
async {
let! a = Async.StartChild(
async {
do! Async.Sleep(1)
return 5
}
)
let! _ = a
for __ in 1..10000 do // 10000 > bindHijackLimit
()
} |> Async.RunSynchronously
exit 0
"""

Просмотреть файл

@ -39,6 +39,7 @@
//<Expects status="success">section='- ADVANCED - ' ! option=fullpaths kind=OptionUnit</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=lib kind=OptionStringList</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=baseaddress kind=OptionString</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=checksumalgorithm kind=OptionString</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=noframework kind=OptionUnit</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=standalone kind=OptionUnit</Expects>
//<Expects status="success">section='- ADVANCED - ' ! option=staticlink kind=OptionString</Expects>

Просмотреть файл

@ -137,6 +137,10 @@ Copyright (c) Microsoft Corporation. All Rights Reserved.
Default - mscorlib
--baseaddress:<address> Base address for the library to be
built
--checksumalgorithm:{SHA1|SHA256} Specify algorithm for calculating
source file checksum stored in PDB.
Supported values are: SHA1 or SHA256
(default)
--noframework Do not reference the default CLI
assemblies by default
--standalone Statically link the F# library and

Просмотреть файл

@ -1,6 +0,0 @@
// #Regression #Conformance #TypeInference #TypeConstraints
// Regression test for FSharp1.0:2262
// We should emit an error, not ICE
//<Expects id="FS0697" span="(6,42-6,75)" status="error">Invalid constraint</Expects>
let inline length (x: ^a) : int = (^a : (member Length : int with get, set) (x, ()))

Просмотреть файл

@ -1,16 +0,0 @@
// #Regression #Conformance #TypeInference #TypeConstraints
// Regression test for FSharp1.0:4189
// Title: Type checking oddity
// This suggestion was resolved as by design,
// so the test makes sure, we're emitting error message about 'not being avalid object construction expression'
//<Expects status="error" span="(16,30-16,60)" id="FS0696">This is not a valid object construction expression\. Explicit object constructors must either call an alternate constructor or initialize all fields of the object and specify a call to a super class constructor\.$</Expects>
type ImmutableStack<'a> private(items: 'a list) =
member this.Push item = ImmutableStack(item::items)
member this.Pop = match items with | [] -> failwith "No elements in stack" | x::xs -> x,ImmutableStack(xs)
// Notice type annotation is commented out, which results in an error
new(col (*: seq<'a>*)) = ImmutableStack(List.ofSeq col)

Просмотреть файл

@ -1,24 +0,0 @@
// #Conformance #TypeInference #TypeConstraints
// Verify you can overload operators on a type and not add all the extra jazz
// such as inlining and the ^ operator.
type Foo(x : int) =
member this.Val = x
static member (-->) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val)
static member (-->) ((src : Foo), (target : int)) = new Foo(src.Val + target)
static member (+) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val)
static member (+) ((src : Foo), (target : int)) = new Foo(src.Val + target)
let x = Foo(3) --> 4
let y = Foo(3) --> Foo(4)
let x2 = Foo(3) + 4
let y2 = Foo(3) + Foo(4)
if x.Val <> 7 then exit 1
if y.Val <> 7 then exit 1
if x2.Val <> 7 then exit 1
if y2.Val <> 7 then exit 1
exit 0

Просмотреть файл

@ -1,26 +0,0 @@
// #Conformance #TypeInference #TypeConstraints
#light
// Test primitive constraints
// Test ':' constraints
type Foo(x : int) =
member this.Value = x
override this.ToString() = "Foo"
type Bar(x : int) =
inherit Foo(-1)
member this.Value2 = x
override this.ToString() = "Bar"
let test1 (x : Foo) = x.Value
let test2 (x : Bar) = (x.Value, x.Value2)
let f = new Foo(128)
let b = new Bar(256)
if test1 f <> 128 then exit 1
if test2 b <> (-1, 256) then exit 1
exit 0

Просмотреть файл

@ -1,33 +0,0 @@
// #Conformance #TypeInference #TypeConstraints
#light
// Test primitive constraints
// Test ':>' constraints
type Foo(x : int) =
member this.Value = x
override this.ToString() = "Foo"
type Bar(x : int) =
inherit Foo(-1)
member this.Value2 = x
override this.ToString() = "Bar"
type Ram(x : int) =
inherit Foo(10)
member this.ValueA = x
override this.ToString() = "Ram"
let test (x : Foo) = (x.Value, x.ToString())
let f = new Foo(128)
let b = new Bar(256)
let r = new Ram(314)
if test f <> (128, "Foo") then exit 1
if test b <> (-1, "Bar") then exit 1
if test r <> (10, "Ram") then exit 1
exit 0

Просмотреть файл

@ -1,23 +0,0 @@
// #Conformance #TypeInference #TypeConstraints
#light
// Test primitive constraints
// Test ': null' constraints
let inline isNull<'a when 'a : null> (x : 'a) =
match x with
| null -> "is null"
| _ -> (x :> obj).ToString()
let runTest =
// Wrapping in try block to work around FSB 1989
try
if isNull null <> "is null" then exit 1
if isNull "F#" <> "F#" then exit 1
true
with _ -> exit 1
if runTest <> true then exit 1
exit 0

Просмотреть файл

@ -1,10 +1,5 @@
SOURCE=E_NoImplicitDowncast01.fs SCFLAGS="--test:ErrorRanges --flaterrors" # E_NoImplicitDowncast01.fs
SOURCE=PrimConstraint01.fs # PrimConstraint01.fs
SOURCE=PrimConstraint02.fs # PrimConstraint02.fs
SOURCE=PrimConstraint03.fs # PrimConstraint03.fs
SOURCE=E_PrimConstraint04.fs SCFLAGS="--test:ErrorRanges" # E_PrimConstraint04.fs
SOURCE=E_TypeFuncDeclaredExplicit01.fs # E_TypeFuncDeclaredExplicit01.fs
SOURCE=ValueRestriction01.fs # ValueRestriction01.fs
@ -16,7 +11,4 @@
SOURCE=DelegateConstraint01.fs # DelegateConstraint01.fs
SOURCE=E_DelegateConstraint01.fs # E_DelegateConstraint01.fs
SOURCE=MemberConstraints01.fs # MemberConstraints01.fs
SOURCE=E_MemberConstraints01.fs SCFLAGS="--test:ErrorRanges" # E_MemberConstraints01.fs
SOURCE=ConstructorConstraint01.fs # ConstructorConstraint01.fs

Просмотреть файл

@ -1,13 +0,0 @@
// #ErrorMessages #NameResolution
//<Expects status="error" span="(11,31)" id="FS1129">The record type 'F' does not contain a label 'Wall'\.</Expects>
type A = { Hello:string; World:string }
type B = { Size:int; Height:int }
type C = { Wheels:int }
type D = { Size:int; Height:int; Walls:int }
type E = { Unknown:string }
type F = { Wallis:int; Size:int; Height:int; }
let r:F = { Size=3; Height=4; Wall=1 }
exit 0

Просмотреть файл

@ -1,6 +0,0 @@
// #ErrorMessages #NameResolution
//<Expects status="error" span="(4,36)" id="FS1126">'global' may only be used as the first name in a qualified path</Expects>
let x = global.System.String.Empty.global.System.String.Empty
exit 0

Просмотреть файл

@ -1,13 +0,0 @@
// #ErrorMessages #NameResolution
//<Expects status="error" span="(11,29)" id="FS0039">The record label 'Wall' is not defined\.</Expects>
type A = { Hello:string; World:string }
type B = { Size:int; Height:int }
type C = { Wheels:int }
type D = { Size:int; Height:int; Walls:int }
type E = { Unknown:string }
type F = { Wallis:int; Size:int; Height:int; }
let r = { Size=3; Height=4; Wall=1 }
exit 0

Просмотреть файл

@ -1,3 +0,0 @@
SOURCE=E_RecordFieldProposal.fs # E_RecordFieldProposal
SOURCE=E_GlobalQualifierAfterDot.fs # E_GlobalQualifierAfterDot
SOURCE=E_FieldNotInRecord.fs # E_FieldNotInRecord

Просмотреть файл

@ -1,9 +0,0 @@
// #ErrorMessages #UnitGenericAbstractType
//<Expects status="error" span="(7,21)" id="FS0017">The member 'Apply : int -> unit' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type\.</Expects>
type EDF<'S> =
abstract member Apply : int -> 'S
type SomeEDF () =
interface EDF<unit> with
member this.Apply d =
// [ERROR] The member 'Apply' does not have the correct type to override the corresponding abstract method.
()

Просмотреть файл

@ -1 +0,0 @@
SOURCE=E_UnitGenericAbstractType1.fs # E_UnitGenericAbstractType1

Просмотреть файл

@ -1,17 +0,0 @@
// #Regression #Libraries #Async
// Regression for FSHARP1.0:5969
// Async.StartChild: error when wait async is executed more than once
module M
let a = async {
let! a = Async.StartChild(
async {
do! Async.Sleep(500)
return 27
})
let! result = Async.Parallel [ a; a; a; a ]
return result
} |> Async.RunSynchronously
exit 0

Просмотреть файл

@ -1,25 +0,0 @@
// #Regression #Libraries #Async
// Regression for FSHARP1.0:5970
// Async.StartChild: race in implementation of ResultCell in FSharp.Core
module M
let Join (a1: Async<'a>) (a2: Async<'b>) = async {
let! task1 = a1 |> Async.StartChild
let! task2 = a2 |> Async.StartChild
let! res1 = task1
let! res2 = task2
return (res1,res2) }
let r =
try
Async.RunSynchronously (Join (async { do! Async.Sleep(30)
failwith "fail"
return 3+3 })
(async { do! Async.Sleep(30)
return 2 + 2 } ))
with _ ->
(0,0)
exit 0

Просмотреть файл

@ -1,78 +0,0 @@
// #Regression #Libraries #Async
// Regression test for FSHARP1.0:6086
// This is a bit of duplication because the same/similar test
// can also be found under the FSHARP suite. Yet, I like to have
// it here...
// The interesting thing about this test is that is used to throw
// an exception when executed on 64bit (FSharp.Core 2.0)
open Microsoft.FSharp.Control
type Color = Blue | Red | Yellow
let complement = function
| (Red, Yellow) | (Yellow, Red) -> Blue
| (Red, Blue) | (Blue, Red) -> Yellow
| (Yellow, Blue) | (Blue, Yellow) -> Red
| (Blue, Blue) -> Blue
| (Red, Red) -> Red
| (Yellow, Yellow) -> Yellow
type Message = Color * AsyncReplyChannel<Color option>
let chameleon (meetingPlace : MailboxProcessor<Message>) initial =
let rec loop c meets = async {
let replyMessage = meetingPlace.PostAndReply(fun reply -> c, reply)
match replyMessage with
| Some(newColor) -> return! loop newColor (meets + 1)
| None -> return meets
}
loop initial 0
let meetingPlace chams n = MailboxProcessor.Start(fun (processor : MailboxProcessor<Message>)->
let rec fadingLoop total =
async {
if total <> 0 then
let! (_, reply) = processor.Receive()
reply.Reply None
return! fadingLoop (total - 1)
else
printfn "Done"
}
let rec mainLoop curr =
async {
if (curr > 0) then
let! (color1, reply1) = processor.Receive()
let! (color2, reply2) = processor.Receive()
let newColor = complement (color1, color2)
reply1.Reply <| Some(newColor)
reply2.Reply <| Some(newColor)
return! mainLoop (curr - 1)
else
return! fadingLoop chams
}
mainLoop n
)
open System
open System.Diagnostics
[<EntryPoint>]
let main(args : string[]) =
printfn "CommandLine : %s" (String.concat ", " args)
let meetings = if args.Length > 0 then Int32.Parse(args.[0]) else 100000
let colors = [Blue; Red; Yellow; Blue]
let mp = meetingPlace (colors.Length) meetings
let watch = Stopwatch.StartNew()
let meets =
colors
|> List.map (chameleon mp)
|> Async.Parallel
|> Async.RunSynchronously
watch.Stop()
for meet in meets do
printfn "%d" meet
printfn "Total: %d in %O" (Seq.sum meets) (watch.Elapsed)
0

Просмотреть файл

@ -1,12 +0,0 @@
// #Regression #Libraries #Async
// Regression for FSHARP1.0:5971
// Async.StartChild: ObjectDisposedException
module M
let shortVersion(args: string []) =
let b = async {return 5} |> Async.StartChild
printfn "%A" (b |> Async.RunSynchronously |> Async.RunSynchronously)
(0)
exit 0

Просмотреть файл

@ -1,19 +0,0 @@
// #Regression #Libraries #Async
// Regression for FSHARP1.0:5972
// Async.StartChild: fails to install trampolines properly
module M
let r =
async {
let! a = Async.StartChild(
async {
do! Async.Sleep(500)
return 5
}
)
let! b = a
for i in 1..10000 do // 10000 > bindHijackLimit
()
} |> Async.RunSynchronously
exit 0

Просмотреть файл

@ -1,6 +0,0 @@
SOURCE=MailboxAsyncNoStackOverflow01.fs # MailboxAsyncNoStackOverflow01.fs
SOURCE=ExecuteAsyncMultipleTimes01.fs # ExecuteAsyncMultipleTimes01.fs
SOURCE=JoiningStartChild01.fs # JoiningStartChild01.fs
SOURCE=StartChildNoObjectDisposedException01.fs # StartChildNoObjectDisposedException01.fs
SOURCE=StartChildTestTrampolineHijackLimit01.fs # StartChildTestTrampolineHijackLimit01.fs

Просмотреть файл

@ -1,7 +0,0 @@
// #Warnings
//<Expects status="Error" span="(5,1)" id="FS0027">This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable x = expression'.</Expects>
let x = 10
x <- 20
exit 0

Просмотреть файл

@ -1,14 +0,0 @@
// #Warnings
//<Expects status="Warning" span="(11,5)" id="FS0020">The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'.</Expects>
type MyClass(property1 : int) =
member val Property2 = "" with get
let x = MyClass(1)
let y = "hello"
let changeProperty() =
x.Property2 = "22"
y = "test"
exit 0

Просмотреть файл

@ -1,9 +0,0 @@
// #Warnings
//<Expects status="Error" span="(7,9)" id="FS0193">Type constraint mismatch. The type</Expects>
open System.Collections.Generic
let orig = Dictionary<obj,obj>() :> IDictionary<obj,obj>
let c = orig :> Dictionary<obj,obj>
exit 0

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше