diff --git a/.travis.yml b/.travis.yml index 1356e9224..92a455a3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,13 @@ language: cpp git: depth: 1000 -os: - - linux - - osx -sudo: required -dist: trusty -osx_image: xcode8.3 +matrix: + include: + - os: linux + dist: trusty + sudo: required + - os: osx + osx_image: xcode9.4 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then @@ -26,4 +27,4 @@ install: script: - ulimit -n 4096 - - powershell -File scripts/travis.ps1 + - pwsh -File scripts/travis.ps1 diff --git a/PowerShellEditorServices.Common.props b/PowerShellEditorServices.Common.props index 4a66d2acc..751a5f07e 100644 --- a/PowerShellEditorServices.Common.props +++ b/PowerShellEditorServices.Common.props @@ -1,6 +1,6 @@ - 1.8.2 + 2.0.0 Microsoft © Microsoft Corporation. All rights reserved. PowerShell;editor;development;language;debugging @@ -9,6 +9,5 @@ git https://github.com/PowerShell/PowerShellEditorServices portable - 1.0.3 diff --git a/PowerShellEditorServices.build.ps1 b/PowerShellEditorServices.build.ps1 index bb3ee01ad..40eb60edc 100644 --- a/PowerShellEditorServices.build.ps1 +++ b/PowerShellEditorServices.build.ps1 @@ -18,16 +18,158 @@ param( $script:IsCIBuild = $env:APPVEYOR -ne $null $script:IsUnix = $PSVersionTable.PSEdition -and $PSVersionTable.PSEdition -eq "Core" -and !$IsWindows -$script:TargetFrameworksParam = "/p:TargetFrameworks=\`"$(if (!$script:IsUnix) { "net451;" })netstandard1.6\`"" -$script:SaveModuleSupportsAllowPrerelease = (Get-Command Save-Module).Parameters.ContainsKey("AllowPrerelease") +$script:TargetPlatform = "netstandard2.0" +$script:TargetFrameworksParam = "/p:TargetFrameworks=`"$script:TargetPlatform`"" +$script:RequiredSdkVersion = "2.1.402" +$script:NugetApiUriBase = 'https://www.nuget.org/api/v2/package' +$script:ModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices/bin/" +$script:VSCodeModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices.VSCode/bin/" +$script:WindowsPowerShellFrameworkTarget = 'net461' +$script:NetFrameworkPlatformId = 'win' +$script:NetCoreTestingFrameworkVersion = '2.1.4' + +$script:PSCoreModulePath = $null + +$script:TestRuntime = @{ + 'Core' = 'netcoreapp2.1' + 'Desktop' = 'net461' +} + +<# +Declarative specification of binary assets produced +in the build that need to be binplaced in the module. +Schema is: +{ + : { + : [ + + ] + } +} +#> +$script:RequiredBuildAssets = @{ + $script:ModuleBinPath = @{ + 'PowerShellEditorServices' = @( + 'publish/Serilog.dll', + 'publish/Serilog.Sinks.Async.dll', + 'publish/Serilog.Sinks.Console.dll', + 'publish/Serilog.Sinks.File.dll', + 'Microsoft.PowerShell.EditorServices.dll', + 'Microsoft.PowerShell.EditorServices.pdb' + ) + + 'PowerShellEditorServices.Host' = @( + 'publish/UnixConsoleEcho.dll', + 'publish/runtimes/osx-64/native/libdisablekeyecho.dylib', + 'publish/runtimes/linux-64/native/libdisablekeyecho.so', + 'publish/Newtonsoft.Json.dll', + 'Microsoft.PowerShell.EditorServices.Host.dll', + 'Microsoft.PowerShell.EditorServices.Host.pdb' + ) + + 'PowerShellEditorServices.Protocol' = @( + 'Microsoft.PowerShell.EditorServices.Protocol.dll', + 'Microsoft.PowerShell.EditorServices.Protocol.pdb' + ) + } + + $script:VSCodeModuleBinPath = @{ + 'PowerShellEditorServices.VSCode' = @( + 'Microsoft.PowerShell.EditorServices.VSCode.dll', + 'Microsoft.PowerShell.EditorServices.VSCode.pdb' + ) + } +} + +<# +Declares the binary shims we need to make the netstandard DLLs hook into .NET Framework. +Schema is: +{ + : [{ + 'PackageName': , + 'PackageVersion': , + 'TargetRuntime': , + 'DllName'?: + }] +} +#> +$script:RequiredNugetBinaries = @{ + 'Desktop' = @( + @{ PackageName = 'System.Security.Principal.Windows'; PackageVersion = '4.5.0'; TargetRuntime = 'net461' }, + @{ PackageName = 'System.Security.AccessControl'; PackageVersion = '4.5.0'; TargetRuntime = 'net461' }, + @{ PackageName = 'System.IO.Pipes.AccessControl'; PackageVersion = '4.5.1'; TargetRuntime = 'net461' } + ) + + '6.0' = @( + @{ PackageName = 'System.Security.Principal.Windows'; PackageVersion = '4.5.0'; TargetRuntime = 'netcoreapp2.0' }, + @{ PackageName = 'System.Security.AccessControl'; PackageVersion = '4.5.0'; TargetRuntime = 'netcoreapp2.0' }, + @{ PackageName = 'System.IO.Pipes.AccessControl'; PackageVersion = '4.5.1'; TargetRuntime = 'netstandard2.0' } + ) +} if ($PSVersionTable.PSEdition -ne "Core") { Add-Type -Assembly System.IO.Compression.FileSystem } -task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, TestPowerShellApi, PackageNuGet { +function Restore-NugetAsmForRuntime { + param( + [ValidateNotNull()][string]$PackageName, + [ValidateNotNull()][string]$PackageVersion, + [string]$DllName, + [string]$DestinationPath, + [string]$TargetPlatform = $script:NetFrameworkPlatformId, + [string]$TargetRuntime = $script:WindowsPowerShellFrameworkTarget + ) + + $tmpDir = [System.IO.Path]::GetTempPath() + + if (-not $DllName) { + $DllName = "$PackageName.dll" + } + + if ($DestinationPath -eq $null) { + $DestinationPath = Join-Path $tmpDir $DllName + } elseif (Test-Path $DestinationPath -PathType Container) { + $DestinationPath = Join-Path $DestinationPath $DllName + } - $requiredSdkVersion = "2.0.0" + $packageDirPath = Join-Path $tmpDir "$PackageName.$PackageVersion" + if (-not (Test-Path $packageDirPath)) { + $guid = New-Guid + $tmpNupkgPath = Join-Path $tmpDir "$guid.zip" + if (Test-Path $tmpNupkgPath) { + Remove-Item -Force $tmpNupkgPath + } + + try { + $packageUri = "$script:NugetApiUriBase/$PackageName/$PackageVersion" + Invoke-WebRequest -Uri $packageUri -OutFile $tmpNupkgPath + Expand-Archive -Path $tmpNupkgPath -DestinationPath $packageDirPath + } finally { + Remove-Item -Force $tmpNupkgPath -ErrorAction SilentlyContinue + } + } + + $internalPath = [System.IO.Path]::Combine($packageDirPath, 'runtimes', $TargetPlatform, 'lib', $TargetRuntime, $DllName) + + Copy-Item -Path $internalPath -Destination $DestinationPath -Force + + return $DestinationPath +} + +function Invoke-WithCreateDefaultHook { + param([scriptblock]$ScriptBlock) + + try + { + $env:PSES_TEST_USE_CREATE_DEFAULT = 1 + & $ScriptBlock + } finally { + Remove-Item env:PSES_TEST_USE_CREATE_DEFAULT + } +} + +task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, PackageNuGet { $dotnetPath = "$PSScriptRoot/.dotnet" $dotnetExePath = if ($script:IsUnix) { "$dotnetPath/dotnet" } else { "$dotnetPath/dotnet.exe" } @@ -48,7 +190,7 @@ task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, TestP # dotnet --version can return a semver that System.Version can't handle # e.g.: 2.1.300-preview-01. The replace operator is used to remove any build suffix. $version = (& $dotnetExePath --version) -replace '[+-].*$','' - if ([version]$version -ge [version]$requiredSdkVersion) { + if ([version]$version -ge [version]$script:RequiredSdkVersion) { $script:dotnetExe = $dotnetExePath } else { @@ -63,21 +205,21 @@ task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, TestP if ($script:dotnetExe -eq $null) { - Write-Host "`n### Installing .NET CLI $requiredSdkVersion...`n" -ForegroundColor Green + Write-Host "`n### Installing .NET CLI $script:RequiredSdkVersion...`n" -ForegroundColor Green # The install script is platform-specific $installScriptExt = if ($script:IsUnix) { "sh" } else { "ps1" } # Download the official installation script and run it $installScriptPath = "$([System.IO.Path]::GetTempPath())dotnet-install.$installScriptExt" - Invoke-WebRequest "https://raw.githubusercontent.com/dotnet/cli/v2.0.0/scripts/obtain/dotnet-install.$installScriptExt" -OutFile $installScriptPath + Invoke-WebRequest "https://raw.githubusercontent.com/dotnet/cli/v$script:RequiredSdkVersion/scripts/obtain/dotnet-install.$installScriptExt" -OutFile $installScriptPath $env:DOTNET_INSTALL_DIR = "$PSScriptRoot/.dotnet" if (!$script:IsUnix) { - & $installScriptPath -Version $requiredSdkVersion -InstallDir "$env:DOTNET_INSTALL_DIR" + & $installScriptPath -Version $script:RequiredSdkVersion -InstallDir "$env:DOTNET_INSTALL_DIR" } else { - & /bin/bash $installScriptPath -Version $requiredSdkVersion -InstallDir "$env:DOTNET_INSTALL_DIR" + & /bin/bash $installScriptPath -Version $script:RequiredSdkVersion -InstallDir "$env:DOTNET_INSTALL_DIR" $env:PATH = $dotnetExeDir + [System.IO.Path]::PathSeparator + $env:PATH } @@ -98,6 +240,7 @@ task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, TestP } task Clean { + exec { & $script:dotnetExe restore } exec { & $script:dotnetExe clean } Remove-Item $PSScriptRoot\module\PowerShellEditorServices\bin -Recurse -Force -ErrorAction Ignore Remove-Item $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin -Recurse -Force -ErrorAction Ignore @@ -128,30 +271,10 @@ task GetProductVersion -Before PackageNuGet, PackageModule, UploadArtifacts { Write-Host "`n### Product Version: $script:FullVersion`n" -ForegroundColor Green } -function BuildForPowerShellVersion($version) { - Write-Host -ForegroundColor Green "`n### Testing API usage for PowerShell $version...`n" - exec { & $script:dotnetExe build -f net451 .\src\PowerShellEditorServices\PowerShellEditorServices.csproj /p:PowerShellVersion=$version } -} - -task TestPowerShellApi -If { !$script:IsUnix } { - BuildForPowerShellVersion v3 - BuildForPowerShellVersion v4 - BuildForPowerShellVersion v5r1 - - # Do a final restore to put everything back to normal - exec { & $script:dotnetExe restore .\src\PowerShellEditorServices\PowerShellEditorServices.csproj } -} - task Build { - exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices.Host\PowerShellEditorServices.Host.csproj -f netstandard1.6 } - if (!$script:IsUnix) { - exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices.Host\PowerShellEditorServices.Host.csproj -f net451 } - } + exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices\PowerShellEditorServices.csproj -f $script:TargetPlatform } + exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices.Host\PowerShellEditorServices.Host.csproj -f $script:TargetPlatform } exec { & $script:dotnetExe build -c $Configuration .\src\PowerShellEditorServices.VSCode\PowerShellEditorServices.VSCode.csproj $script:TargetFrameworksParam } - exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices\PowerShellEditorServices.csproj -f netstandard1.6 } - Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\UnixConsoleEcho.dll -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 - Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\runtimes\osx-64\native\libdisablekeyecho.dylib -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 - Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\runtimes\linux-64\native\libdisablekeyecho.so -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 } function UploadTestLogs { @@ -172,24 +295,42 @@ function UploadTestLogs { } } -task Test TestServer,TestProtocol,TestHost +task Test TestServer,TestProtocol -task TestServer -If { !$script:IsUnix } { +task TestServer { Set-Location .\test\PowerShellEditorServices.Test\ - exec { & $script:dotnetExe build -c $Configuration -f net452 } - exec { & $script:dotnetExe xunit -configuration $Configuration -framework net452 -verbose -nobuild } + + if (-not $script:IsUnix) { + exec { & $script:dotnetExe xunit -f $script:TestRuntime.Desktop } + } + + Invoke-WithCreateDefaultHook -NewModulePath $script:PSCoreModulePath { + exec { & $script:dotnetExe xunit -f $script:TestRuntime.Core --fx-version $script:NetCoreTestingFrameworkVersion } + } } -task TestProtocol -If { !$script:IsUnix } { +task TestProtocol { Set-Location .\test\PowerShellEditorServices.Test.Protocol\ - exec { & $script:dotnetExe build -c $Configuration -f net452 } - exec { & $script:dotnetExe xunit -configuration $Configuration -framework net452 -verbose -nobuild } + + if (-not $script:IsUnix) { + exec { & $script:dotnetExe xunit -f $script:TestRuntime.Desktop } + } + + Invoke-WithCreateDefaultHook { + exec { & $script:dotnetExe xunit -f $script:TestRuntime.Core --fx-version $script:NetCoreTestingFrameworkVersion } + } } -task TestHost -If { !$script:IsUnix } { +task TestHost { Set-Location .\test\PowerShellEditorServices.Test.Host\ - exec { & $script:dotnetExe build -c $Configuration -f net452 } - exec { & $script:dotnetExe xunit -configuration $Configuration -framework net452 -verbose -nobuild } + + if (-not $script:IsUnix) { + exec { & $script:dotnetExe build -f $script:TestRuntime.Desktop } + exec { & $script:dotnetExe test -f $script:TestRuntime.Desktop } + } + + exec { & $script:dotnetExe build -c $Configuration -f $script:TestRuntime.Core } + exec { & $script:dotnetExe test -f $script:TestRuntime.Core } } task CITest ?Test, { @@ -202,51 +343,40 @@ task CITest ?Test, { } task LayoutModule -After Build { - # Lay out the PowerShellEditorServices module's binaries - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices\bin\ -Type Directory | Out-Null - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop -Type Directory | Out-Null - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices\bin\Core -Type Directory | Out-Null - - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\Serilog*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\* -Filter Microsoft.PowerShell.EditorServices*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\UnixConsoleEcho.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\libdisablekeyecho.* -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\publish\runtimes\win\lib\netstandard1.3\* -Filter System.IO.Pipes*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - - if (!$script:IsUnix) { - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\net451\Serilog*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop - - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\net451\* -Filter Microsoft.PowerShell.EditorServices*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\net451\Newtonsoft.Json.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\net451\UnixConsoleEcho.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\net451\publish\System.Runtime.InteropServices.RuntimeInformation.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - } - # Copy Third Party Notices.txt to module folder Copy-Item -Force -Path "$PSScriptRoot\Third Party Notices.txt" -Destination $PSScriptRoot\module\PowerShellEditorServices - # Lay out the PowerShellEditorServices.VSCode module's binaries - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\ -Type Directory | Out-Null - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Desktop -Type Directory | Out-Null - New-Item -Force $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Core -Type Directory | Out-Null - - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.VSCode\bin\$Configuration\netstandard1.6\* -Filter Microsoft.PowerShell.EditorServices.VSCode*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Core\ - if (!$script:IsUnix) { - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.VSCode\bin\$Configuration\net451\* -Filter Microsoft.PowerShell.EditorServices.VSCode*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Desktop\ + # Lay out the PowerShellEditorServices module's binaries + # For each binplace destination + foreach ($destDir in $script:RequiredBuildAssets.Keys) { + # Create the destination dir + $null = New-Item -Force $destDir -Type Directory + + # For each PSES subproject + foreach ($projectName in $script:RequiredBuildAssets[$destDir].Keys) { + # Get the project build dir path + $basePath = [System.IO.Path]::Combine($PSScriptRoot, 'src', $projectName, 'bin', $Configuration, $script:TargetPlatform) + + # For each asset in the subproject + foreach ($bin in $script:RequiredBuildAssets[$destDir][$projectName]) { + # Get the asset path + $binPath = Join-Path $basePath $bin + + # Binplace the asset + Copy-Item -Force -Verbose $binPath $destDir + } + } } - if ($Configuration -eq "Debug") { - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.VSCode\bin\$Configuration\netstandard1.6\Microsoft.PowerShell.EditorServices.VSCode.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\Microsoft.PowerShell.EditorServices.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\Microsoft.PowerShell.EditorServices.Host.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Protocol\bin\$Configuration\netstandard1.6\Microsoft.PowerShell.EditorServices.Protocol.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ + # Get and place the shim bins for net461 + foreach ($binDestinationDir in $script:RequiredNugetBinaries.Keys) { + $binDestPath = Join-Path $script:ModuleBinPath $binDestinationDir + if (-not (Test-Path $binDestPath)) { + New-Item -Path $binDestPath -ItemType Directory + } - if (!$script:IsUnix) { - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.VSCode\bin\$Configuration\net451\Microsoft.PowerShell.EditorServices.VSCode.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices.VSCode\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\net451\Microsoft.PowerShell.EditorServices.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\net451\Microsoft.PowerShell.EditorServices.Host.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ - Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Protocol\bin\$Configuration\net451\Microsoft.PowerShell.EditorServices.Protocol.pdb -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Desktop\ + foreach ($packageDetails in $script:RequiredNugetBinaries[$binDestinationDir]) { + Restore-NugetAsmForRuntime -DestinationPath $binDestPath @packageDetails } } } @@ -264,6 +394,7 @@ task RestorePsesModules -After Build { Name = $name MinimumVersion = $_.Value.MinimumVersion MaximumVersion = $_.Value.MaximumVersion + AllowPrerelease = $_.Value.AllowPrerelease Repository = if ($_.Value.Repository) { $_.Value.Repository } else { $DefaultModuleRepository } Path = $submodulePath } @@ -273,11 +404,6 @@ task RestorePsesModules -After Build { throw "EditorServices module listed without name in '$ModulesJsonPath'" } - if ($script:SaveModuleSupportsAllowPrerelease) - { - $body += @{ AllowPrerelease = $_.Value.AllowPrerelease } - } - $moduleInfos.Add($name, $body) } @@ -296,16 +422,12 @@ task RestorePsesModules -After Build { Name = $moduleName MinimumVersion = $moduleInstallDetails.MinimumVersion MaximumVersion = $moduleInstallDetails.MaximumVersion + AllowPrerelease = $moduleInstallDetails.AllowPrerelease Repository = if ($moduleInstallDetails.Repository) { $moduleInstallDetails.Repository } else { $DefaultModuleRepository } Path = $submodulePath } - if ($script:SaveModuleSupportsAllowPrerelease) - { - $splatParameters += @{ AllowPrerelease = $moduleInstallDetails.AllowPrerelease } - } - - Write-Host "`tInstalling module: ${moduleName}" + Write-Host "`tInstalling module: ${moduleName} with arguments $(ConvertTo-Json $splatParameters)" Save-Module @splatParameters } @@ -341,4 +463,4 @@ task UploadArtifacts -If ($script:IsCIBuild) { } # The default task is to run the entire CI build -task . GetProductVersion, Clean, Build, TestPowerShellApi, CITest, BuildCmdletHelp, PackageNuGet, PackageModule, UploadArtifacts +task . GetProductVersion, Clean, Build, CITest, BuildCmdletHelp, PackageNuGet, PackageModule, UploadArtifacts diff --git a/module/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.psm1 b/module/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.psm1 index f5d53be4c..e7b34e076 100644 --- a/module/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.psm1 +++ b/module/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.psm1 @@ -3,12 +3,7 @@ # Licensed under the MIT license. See LICENSE file in the project root for full license information. # -if (!$PSVersionTable.PSEdition -or $PSVersionTable.PSEdition -eq "Desktop") { - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/Microsoft.PowerShell.EditorServices.VSCode.dll" -} -else { - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Core/Microsoft.PowerShell.EditorServices.VSCode.dll" -} +Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Microsoft.PowerShell.EditorServices.VSCode.dll" if ($psEditor -is [Microsoft.PowerShell.EditorServices.Extensions.EditorObject]) { [Microsoft.PowerShell.EditorServices.VSCode.ComponentRegistration]::Register($psEditor.Components) diff --git a/module/PowerShellEditorServices/PowerShellEditorServices.psm1 b/module/PowerShellEditorServices/PowerShellEditorServices.psm1 index 956287f2b..af7b1f87b 100644 --- a/module/PowerShellEditorServices/PowerShellEditorServices.psm1 +++ b/module/PowerShellEditorServices/PowerShellEditorServices.psm1 @@ -3,16 +3,21 @@ # Licensed under the MIT license. See LICENSE file in the project root for full license information. # -if (!$PSVersionTable.PSEdition -or $PSVersionTable.PSEdition -eq "Desktop") { - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/Microsoft.PowerShell.EditorServices.dll" - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/Microsoft.PowerShell.EditorServices.Host.dll" -} -else { - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Core/Microsoft.PowerShell.EditorServices.dll" - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Core/Microsoft.PowerShell.EditorServices.Protocol.dll" - Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Core/Microsoft.PowerShell.EditorServices.Host.dll" +# Need to load pipe handling shim assemblies in Windows PowerShell and PSCore 6.0 because they don't have WCP +if ($PSEdition -eq 'Desktop') { + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/System.IO.Pipes.AccessControl.dll" + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/System.Security.AccessControl.dll" + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Desktop/System.Security.Principal.Windows.dll" +} elseif ($PSVersionTable.PSVersion -ge '6.0' -and $PSVersionTable.PSVersion -lt '6.1' -and $IsWindows) { + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/6.0/System.IO.Pipes.AccessControl.dll" + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/6.0/System.Security.AccessControl.dll" + Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/6.0/System.Security.Principal.Windows.dll" } +Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Microsoft.PowerShell.EditorServices.dll" +Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Microsoft.PowerShell.EditorServices.Host.dll" +Microsoft.PowerShell.Utility\Add-Type -Path "$PSScriptRoot/bin/Microsoft.PowerShell.EditorServices.Protocol.dll" + function Start-EditorServicesHost { [CmdletBinding()] param( diff --git a/scripts/download.sh b/scripts/download.sh index 90310662d..476027b0e 100755 --- a/scripts/download.sh +++ b/scripts/download.sh @@ -1,153 +1,3 @@ #!/usr/bin/env bash -# Let's quit on interrupt of subcommands -trap ' - trap - INT # restore default INT handler - echo "Interrupted" - kill -s INT "$$" -' INT - -get_url() { - fork=$2 - release=v6.0.0-beta.1 - echo "https://github.com/$fork/PowerShell/releases/download/$release/$1" -} - -fork="PowerShell" -# Get OS specific asset ID and package name -case "$OSTYPE" in - linux*) - source /etc/os-release - # Install curl and wget to download package - case "$ID" in - centos*) - if ! hash curl 2>/dev/null; then - echo "curl not found, installing..." - sudo yum install -y curl - fi - - package=powershell-6.0.0_beta.1-1.el7.centos.x86_64.rpm - ;; - ubuntu) - if ! hash curl 2>/dev/null; then - echo "curl not found, installing..." - sudo apt-get install -y curl - fi - - case "$VERSION_ID" in - 14.04) - package=powershell_6.0.0-beta.1-1ubuntu1.14.04.1_amd64.deb - ;; - 16.04) - package=powershell_6.0.0-beta.1-1ubuntu1.16.04.1_amd64.deb - ;; - *) - echo "Ubuntu $VERSION_ID is not supported!" >&2 - exit 2 - esac - ;; - opensuse) - if ! hash curl 2>/dev/null; then - echo "curl not found, installing..." - sudo zypper install -y curl - fi - - - case "$VERSION_ID" in - 42.1) - # TODO during next release remove fork and fix package name - fork=TravisEz13 - package=powershell-6.0.0_beta.1-1.suse.42.1.x86_64.rpm - ;; - *) - echo "OpenSUSE $VERSION_ID is not supported!" >&2 - exit 2 - esac - ;; - *) - echo "$NAME is not supported!" >&2 - exit 2 - esac - ;; - darwin*) - # We don't check for curl as macOS should have a system version - package=powershell-6.0.0-beta.1-osx.10.12-x64.pkg - ;; - *) - echo "$OSTYPE is not supported!" >&2 - exit 2 - ;; -esac - -curl -L -o "$package" $(get_url "$package" "$fork") - -if [[ ! -r "$package" ]]; then - echo "ERROR: $package failed to download! Aborting..." >&2 - exit 1 -fi - -# Installs PowerShell package -case "$OSTYPE" in - linux*) - source /etc/os-release - # Install dependencies - echo "Installing PowerShell with sudo..." - case "$ID" in - centos) - # yum automatically resolves dependencies for local packages - sudo yum install "./$package" - ;; - ubuntu) - # dpkg does not automatically resolve dependencies, but spouts ugly errors - sudo dpkg -i "./$package" &> /dev/null - # Resolve dependencies - sudo apt-get install -f - ;; - opensuse) - # Install the Microsoft public key so that zypper trusts the package - sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc - # zypper automatically resolves dependencies for local packages - sudo zypper --non-interactive install "./$package" &> /dev/null - ;; - *) - esac - ;; - darwin*) - patched=0 - if hash brew 2>/dev/null; then - brew update - if [[ ! -d $(brew --prefix openssl) ]]; then - echo "Installing OpenSSL with brew..." - if ! brew install openssl; then - echo "ERROR: OpenSSL failed to install! Crypto functions will not work..." >&2 - # Don't abort because it is not fatal - elif ! brew install curl --with-openssl; then - echo "ERROR: curl failed to build against OpenSSL; SSL functions will not work..." >&2 - # Still not fatal - else - # OpenSSL installation succeeded; reme mber to patch System.Net.Http after PowerShell installation - patched=1 - fi - fi - - else - echo "ERROR: brew not found! OpenSSL may not be available..." >&2 - # Don't abort because it is not fatal - fi - - echo "Installing $package with sudo ..." - sudo installer -pkg "./$package" -target / - if [[ $patched -eq 1 ]]; then - echo "Patching System.Net.Http for libcurl and OpenSSL..." - find /usr/local/microsoft/powershell -name System.Net.Http.Native.dylib | xargs sudo install_name_tool -change /usr/lib/libcurl.4.dylib /usr/local/opt/curl/lib/libcurl.4.dylib - fi - ;; -esac - -powershell -noprofile -c '"Congratulations! PowerShell is installed at $PSHOME"' -success=$? - -if [[ "$success" != 0 ]]; then - echo "ERROR: PowerShell failed to install!" >&2 - exit "$success" -fi \ No newline at end of file +bash <(curl -s https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.sh) diff --git a/scripts/travis.ps1 b/scripts/travis.ps1 index 51dd4859f..abcb12fe2 100644 --- a/scripts/travis.ps1 +++ b/scripts/travis.ps1 @@ -1,11 +1,4 @@ -Get-Module PowerShellGet,PackageManagement | Remove-Module -Force -Verbose -powershell -Command { Install-Module -Name PowershellGet -MinimumVersion 1.6 -Scope CurrentUser -force -confirm:$false -verbose } -powershell -Command { Install-Module -Name PackageManagement -MinimumVersion 1.1.7.0 -Scope CurrentUser -Force -Confirm:$false -Verbose } -Import-Module -Name PowerShellGet -MinimumVersion 1.6 -Force -Import-Module -Name PackageManagement -MinimumVersion 1.1.7.0 -Force -Install-PackageProvider -Name NuGet -Force | Out-Null -Import-PackageProvider NuGet -Force | Out-Null -Set-PSRepository -Name PSGallery -InstallationPolicy Trusted | Out-Null +$ErrorActionPreference = 'Stop' # Install InvokeBuild Install-Module InvokeBuild -MaximumVersion 5.1.0 -Scope CurrentUser -Force diff --git a/src/PowerShellEditorServices.Host/EditorServicesHost.cs b/src/PowerShellEditorServices.Host/EditorServicesHost.cs index 12b287e20..3a88ee15c 100644 --- a/src/PowerShellEditorServices.Host/EditorServicesHost.cs +++ b/src/PowerShellEditorServices.Host/EditorServicesHost.cs @@ -19,6 +19,7 @@ using System.Management.Automation.Runspaces; using System.Reflection; using System.Threading.Tasks; +using System.Runtime.InteropServices; namespace Microsoft.PowerShell.EditorServices.Host { @@ -118,9 +119,7 @@ public EditorServicesHost( #endif // Catch unhandled exceptions for logging purposes -#if !CoreCLR AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; -#endif } #endregion @@ -139,21 +138,12 @@ public void StartLogging(string logFilePath, LogLevel logLevel) .AddLogFile(logFilePath) .Build(); -#if CoreCLR FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(this.GetType().GetTypeInfo().Assembly.Location); - // TODO #278: Need the correct dependency package for this to work correctly - //string osVersionString = RuntimeInformation.OSDescription; - //string processArchitecture = RuntimeInformation.ProcessArchitecture == Architecture.X64 ? "64-bit" : "32-bit"; - //string osArchitecture = RuntimeInformation.OSArchitecture == Architecture.X64 ? "64-bit" : "32-bit"; -#else - FileVersionInfo fileVersionInfo = - FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location); - string osVersionString = Environment.OSVersion.VersionString; - string processArchitecture = Environment.Is64BitProcess ? "64-bit" : "32-bit"; - string osArchitecture = Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit"; -#endif + string osVersionString = RuntimeInformation.OSDescription; + string processArchitecture = RuntimeInformation.ProcessArchitecture == Architecture.X64 ? "64-bit" : "32-bit"; + string osArchitecture = RuntimeInformation.OSArchitecture == Architecture.X64 ? "64-bit" : "32-bit"; string newLine = Environment.NewLine; @@ -165,14 +155,10 @@ public void StartLogging(string logFilePath, LogLevel logLevel) $" Name: {this.hostDetails.Name}" + newLine + $" ProfileId: {this.hostDetails.ProfileId}" + newLine + $" Version: {this.hostDetails.Version}" + newLine + -#if !CoreCLR $" Arch: {processArchitecture}" + newLine + newLine + " Operating system details:" + newLine + newLine + $" Version: {osVersionString}" + newLine + $" Arch: {osArchitecture}")); -#else - "")); -#endif } /// @@ -231,7 +217,7 @@ private async void OnLanguageServiceClientConnect( await this.editorSession.PowerShellContext.ImportCommandsModule( Path.Combine( Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location), - @"..\..\Commands")); + @"..\Commands")); this.languageServer.Start(); @@ -441,19 +427,13 @@ private void ProtocolEndpoint_UnhandledException(object sender, Exception e) this.serverCompletedTask.SetException(e); } -#if !CoreCLR private void CurrentDomain_UnhandledException( object sender, UnhandledExceptionEventArgs e) { // Log the exception - this.logger.Write( - LogLevel.Error, - string.Format( - "FATAL UNHANDLED EXCEPTION:\r\n\r\n{0}", - e.ExceptionObject.ToString())); + this.logger.Write(LogLevel.Error, $"FATAL UNHANDLED EXCEPTION: {e.ExceptionObject}"); } -#endif private IServerListener CreateServiceListener(MessageProtocolType protocol, EditorServiceTransportConfig config) { switch (config.TransportType) diff --git a/src/PowerShellEditorServices.Host/PowerShellEditorServices.Host.csproj b/src/PowerShellEditorServices.Host/PowerShellEditorServices.Host.csproj index 1874e2c20..309bf484a 100644 --- a/src/PowerShellEditorServices.Host/PowerShellEditorServices.Host.csproj +++ b/src/PowerShellEditorServices.Host/PowerShellEditorServices.Host.csproj @@ -4,30 +4,19 @@ PowerShell Editor Services Host Process Provides a process for hosting the PowerShell Editor Services library exposed by a JSON message protocol. - netstandard1.6;net451 + netstandard2.0 Microsoft.PowerShell.EditorServices.Host + + + - - - 10.0.3 - - - 6.0.0-alpha13 - - - - - $(DefineConstants);CoreCLR - - - - - - diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs index 3fd6d5b5e..8a40b6a1b 100644 --- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs +++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs @@ -69,24 +69,7 @@ public static async Task Connect( PipeDirection.InOut, PipeOptions.Asynchronous); -#if CoreCLR await pipeClient.ConnectAsync(); -#else - while (!pipeClient.IsConnected) - { - try - { - // Wait for 500 milliseconds so that we don't tie up the thread - pipeClient.Connect(500); - } - catch (TimeoutException) - { - // Connect timed out, wait and try again - await Task.Delay(1000); - continue; - } - } -#endif var clientChannel = new NamedPipeClientChannel(pipeClient, logger); clientChannel.Start(messageProtocolType); diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs index 44d6acb75..84a1de4f4 100644 --- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs +++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs @@ -106,14 +106,7 @@ private void ListenForConnection() { try { -#if CoreCLR await this.pipeServer.WaitForConnectionAsync(); -#else - await Task.Factory.FromAsync( - this.pipeServer.BeginWaitForConnection, - this.pipeServer.EndWaitForConnection, null); -#endif - await this.pipeServer.FlushAsync(); this.OnClientConnect( diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs index 119f42110..95318d860 100644 --- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs +++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs @@ -27,11 +27,15 @@ public StdioServerChannel(ILogger logger) protected override void Initialize(IMessageSerializer messageSerializer) { -#if !CoreCLR - // Ensure that the console is using UTF-8 encoding - System.Console.InputEncoding = Encoding.UTF8; - System.Console.OutputEncoding = Encoding.UTF8; -#endif + if (System.Console.InputEncoding != Encoding.UTF8) + { + System.Console.InputEncoding = Encoding.UTF8; + } + + if (System.Console.OutputEncoding != Encoding.UTF8) + { + System.Console.OutputEncoding = Encoding.UTF8; + } // Open the standard input/output streams this.inputStream = System.Console.OpenStandardInput(); diff --git a/src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj b/src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj index f8cd4cf73..5d663043d 100644 --- a/src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj +++ b/src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj @@ -3,25 +3,19 @@ PowerShell Editor Services Host Protocol Library Provides message types and client/server APIs for the PowerShell Editor Services JSON protocol. - netstandard1.6;net451; + netstandard2.0 Microsoft.PowerShell.EditorServices.Protocol + - - - - - - - - - $(DefineConstants);CoreCLR - - - - + + + diff --git a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs index 72662fbf7..d2331345a 100644 --- a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs +++ b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs @@ -289,21 +289,16 @@ protected async Task HandleLaunchRequest( { workingDir = null; Logger.Write( - LogLevel.Error, + LogLevel.Error, $"The specified 'cwd' path is invalid: '{launchParams.Cwd}'. Error: {ex.Message}"); } } - // If we have no working dir by this point and we are running in a temp console, + // If we have no working dir by this point and we are running in a temp console, // pick some reasonable default. if (string.IsNullOrEmpty(workingDir) && launchParams.CreateTemporaryIntegratedConsole) { -#if CoreCLR - //TODO: RKH 2018-06-26 .NET standard 2.0 has added Environment.CurrentDirectory - let's use it. - workingDir = AppContext.BaseDirectory; -#else workingDir = Environment.CurrentDirectory; -#endif } // At this point, we will either have a working dir that should be set to cwd in diff --git a/src/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.csproj b/src/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.csproj index 930922fb1..c50e535ea 100644 --- a/src/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.csproj +++ b/src/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.csproj @@ -4,12 +4,12 @@ PowerShell Editor Services, Visual Studio Code Extensions Provides added functionality to PowerShell Editor Services for the Visual Studio Code editor. - netstandard1.6;net451 + netstandard2.0 Microsoft.PowerShell.EditorServices.VSCode - + 1591,1573,1572 bin\$(TargetFramework)\$(Configuration)\Microsoft.PowerShell.EditorServices.VSCode.xml @@ -20,12 +20,4 @@ - - $(DefineConstants);CoreCLR - - - - - - diff --git a/src/PowerShellEditorServices/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Analysis/AnalysisService.cs index 0d9763b9e..e65cc7c24 100644 --- a/src/PowerShellEditorServices/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Analysis/AnalysisService.cs @@ -547,7 +547,12 @@ private static RunspacePool CreatePssaRunspacePool(out PSModuleInfo pssaModuleIn } // Create a base session state with PSScriptAnalyzer loaded - InitialSessionState sessionState = InitialSessionState.CreateDefault2(); + InitialSessionState sessionState; + if (Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1") { + sessionState = InitialSessionState.CreateDefault(); + } else { + sessionState = InitialSessionState.CreateDefault2(); + } sessionState.ImportPSModule(new [] { pssaModuleInfo.ModuleBase }); // RunspacePool takes care of queuing commands for us so we do not diff --git a/src/PowerShellEditorServices/Console/ConsoleProxy.cs b/src/PowerShellEditorServices/Console/ConsoleProxy.cs index bd7488169..3956f6df9 100644 --- a/src/PowerShellEditorServices/Console/ConsoleProxy.cs +++ b/src/PowerShellEditorServices/Console/ConsoleProxy.cs @@ -20,8 +20,6 @@ internal static class ConsoleProxy static ConsoleProxy() { - // Maybe we should just include the RuntimeInformation package for FullCLR? -#if CoreCLR if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { s_consoleProxy = new WindowsConsoleOperations(); @@ -29,9 +27,6 @@ static ConsoleProxy() } s_consoleProxy = new UnixConsoleOperations(); -#else - s_consoleProxy = new WindowsConsoleOperations(); -#endif } public static Task ReadKeyAsync(CancellationToken cancellationToken) => diff --git a/src/PowerShellEditorServices/Language/AstOperations.cs b/src/PowerShellEditorServices/Language/AstOperations.cs index e90be6bb4..2dd364cf5 100644 --- a/src/PowerShellEditorServices/Language/AstOperations.cs +++ b/src/PowerShellEditorServices/Language/AstOperations.cs @@ -65,17 +65,9 @@ static public async Task GetCompletions( { var type = scriptAst.Extent.StartScriptPosition.GetType(); var method = -#if CoreCLR type.GetMethod( "CloneWithNewOffset", BindingFlags.Instance | BindingFlags.NonPublic); -#else - type.GetMethod( - "CloneWithNewOffset", - BindingFlags.Instance | BindingFlags.NonPublic, - null, - new[] { typeof(int) }, null); -#endif IScriptPosition cursorPosition = (IScriptPosition)method.Invoke( diff --git a/src/PowerShellEditorServices/Language/CompletionResults.cs b/src/PowerShellEditorServices/Language/CompletionResults.cs index b41394146..fc8d2eb00 100644 --- a/src/PowerShellEditorServices/Language/CompletionResults.cs +++ b/src/PowerShellEditorServices/Language/CompletionResults.cs @@ -305,10 +305,8 @@ private static CompletionType ConvertCompletionResultType( case CompletionResultType.Type: return CompletionType.Type; -#if !PowerShellv3 case CompletionResultType.Keyword: return CompletionType.Keyword; -#endif case CompletionResultType.ProviderContainer: return CompletionType.Folder; diff --git a/src/PowerShellEditorServices/Language/FindSymbolsVisitor2.cs b/src/PowerShellEditorServices/Language/FindSymbolsVisitor2.cs index 41efffa00..5247f3f03 100644 --- a/src/PowerShellEditorServices/Language/FindSymbolsVisitor2.cs +++ b/src/PowerShellEditorServices/Language/FindSymbolsVisitor2.cs @@ -8,18 +8,16 @@ namespace Microsoft.PowerShell.EditorServices { -#if PowerShellv5 - // TODO: Restore this when we figure out how to support multiple // PS versions in the new PSES-as-a-module world (issue #276) ///// - ///// The visitor used to find all the symbols (function and class defs) in the AST. + ///// The visitor used to find all the symbols (function and class defs) in the AST. ///// ///// ///// Requires PowerShell v5 or higher ///// - ///// + ///// //internal class FindSymbolsVisitor2 : AstVisitor2 //{ // private FindSymbolsVisitor findSymbolsVisitor; @@ -38,10 +36,10 @@ namespace Microsoft.PowerShell.EditorServices // } // /// - // /// Adds each function defintion as a + // /// Adds each function defintion as a // /// // /// A functionDefinitionAst object in the script's AST - // /// A decision to stop searching if the right symbol was found, + // /// A decision to stop searching if the right symbol was found, // /// or a decision to continue if it wasn't found // public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) // { @@ -52,7 +50,7 @@ namespace Microsoft.PowerShell.EditorServices // /// Checks to see if this variable expression is the symbol we are looking for. // /// // /// A VariableExpressionAst object in the script's AST - // /// A descion to stop searching if the right symbol was found, + // /// A descion to stop searching if the right symbol was found, // /// or a decision to continue if it wasn't found // public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst) // { @@ -78,6 +76,5 @@ namespace Microsoft.PowerShell.EditorServices // return AstVisitAction.Continue; // } //} -#endif } diff --git a/src/PowerShellEditorServices/PowerShellEditorServices.csproj b/src/PowerShellEditorServices/PowerShellEditorServices.csproj index 1fbf922e9..359fddefa 100644 --- a/src/PowerShellEditorServices/PowerShellEditorServices.csproj +++ b/src/PowerShellEditorServices/PowerShellEditorServices.csproj @@ -3,74 +3,23 @@ PowerShell Editor Services Provides common PowerShell editor capabilities as a .NET library. - netstandard1.6;net451 + netstandard2.0 Microsoft.PowerShell.EditorServices - $(PackageTargetFallback);dnxcore50;portable-net45+win8 - - - - - - - - - $(DefineConstants);PowerShellv3 - $(DefineConstants);PowerShellv4 - $(DefineConstants);PowerShellv5r1;PowerShellv5 - $(DefineConstants);PowerShellv5r2;PowerShellv5 - - - + 1591,1573,1572 bin\$(TargetFramework)\$(Configuration)\Microsoft.PowerShell.EditorServices.xml - - - - - - - - - - - - - - - - - - - - 6.0.0-alpha13 - - - - - - - - - - - - - + + - - - $(DefineConstants);CoreCLR - - $(DefineConstants);RELEASE diff --git a/src/PowerShellEditorServices/Session/InvocationEventQueue.cs b/src/PowerShellEditorServices/Session/InvocationEventQueue.cs index 77d85bf23..89184e930 100644 --- a/src/PowerShellEditorServices/Session/InvocationEventQueue.cs +++ b/src/PowerShellEditorServices/Session/InvocationEventQueue.cs @@ -225,6 +225,11 @@ private void OnInvokerUnsubscribed(object sender, PSEventUnsubscribedEventArgs e CreateInvocationSubscriber(); } + private void OnInvokerUnsubscribed(object sender, PSEventArgs e) + { + CreateInvocationSubscriber(); + } + private void SetSubscriberExecutionThreadWithReflection(PSEventSubscriber subscriber) { // We need to create the PowerShell object in the same thread so we can get a nested diff --git a/src/PowerShellEditorServices/Session/PSReadLinePromptContext.cs b/src/PowerShellEditorServices/Session/PSReadLinePromptContext.cs index c0707d026..23c312fef 100644 --- a/src/PowerShellEditorServices/Session/PSReadLinePromptContext.cs +++ b/src/PowerShellEditorServices/Session/PSReadLinePromptContext.cs @@ -67,7 +67,6 @@ internal PSReadLinePromptContext( _consoleReadLine = new ConsoleReadLine(powerShellContext); _readLineProxy = readLineProxy; -#if CoreCLR if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return; @@ -77,7 +76,6 @@ internal PSReadLinePromptContext( intercept => ConsoleProxy.UnixReadKey( intercept, _readLineCancellationSource.Token)); -#endif } internal static bool TryGetPSReadLineProxy( diff --git a/src/PowerShellEditorServices/Session/PowerShell3Operations.cs b/src/PowerShellEditorServices/Session/PowerShell3Operations.cs deleted file mode 100644 index eb6cf0252..000000000 --- a/src/PowerShellEditorServices/Session/PowerShell3Operations.cs +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Management.Automation; -using System.Management.Automation.Host; -using System.Management.Automation.Runspaces; - -namespace Microsoft.PowerShell.EditorServices.Session -{ - internal class PowerShell3Operations : IVersionSpecificOperations - { - public void ConfigureDebugger(Runspace runspace) - { - // The debugger has no SetDebugMode in PowerShell v3. - } - - public void PauseDebugger(Runspace runspace) - { - // The debugger cannot be paused in PowerShell v3. - throw new NotSupportedException("Debugger cannot be paused in PowerShell v3"); - } - - public IEnumerable ExecuteCommandInDebugger( - PowerShellContext powerShellContext, - Runspace currentRunspace, - PSCommand psCommand, - bool sendOutputToHost, - out DebuggerResumeAction? debuggerResumeAction) - { - IEnumerable executionResult = null; - - using (var nestedPipeline = currentRunspace.CreateNestedPipeline()) - { - foreach (var command in psCommand.Commands) - { - nestedPipeline.Commands.Add(command); - } - - var results = nestedPipeline.Invoke(); - - if (typeof(TResult) != typeof(PSObject)) - { - executionResult = - results - .Select(pso => pso.BaseObject) - .Cast(); - } - else - { - executionResult = results.Cast(); - } - } - - // Write the output to the host if necessary - if (sendOutputToHost) - { - foreach (var line in executionResult) - { - powerShellContext.WriteOutput(line.ToString(), true); - } - } - - // No DebuggerResumeAction result for PowerShell v3 - debuggerResumeAction = null; - - return executionResult; - } - - public void StopCommandInDebugger(PowerShellContext powerShellContext) - { - } - - public bool IsDebuggerStopped(PromptNest promptNest, Runspace runspace) - { - return promptNest.IsInDebugger; - } - - public void ExitNestedPrompt(PSHost host) - { - try - { - host.ExitNestedPrompt(); - } - // FlowControlException is not accessible in PSv3 - catch (Exception) - { - } - } - } -} - diff --git a/src/PowerShellEditorServices/Session/PowerShell4Operations.cs b/src/PowerShellEditorServices/Session/PowerShell4Operations.cs deleted file mode 100644 index d9060ed2f..000000000 --- a/src/PowerShellEditorServices/Session/PowerShell4Operations.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Management.Automation; -using System.Management.Automation.Host; -using System.Management.Automation.Runspaces; - -namespace Microsoft.PowerShell.EditorServices.Session -{ - internal class PowerShell4Operations : IVersionSpecificOperations - { - public void ConfigureDebugger(Runspace runspace) - { -#if !PowerShellv3 - if (runspace.Debugger != null) - { - runspace.Debugger.SetDebugMode(DebugModes.LocalScript | DebugModes.RemoteScript); - } -#endif - } - - public virtual void PauseDebugger(Runspace runspace) - { - // The debugger cannot be paused in PowerShell v4. - throw new NotSupportedException("Debugger cannot be paused in PowerShell v4"); - } - - public IEnumerable ExecuteCommandInDebugger( - PowerShellContext powerShellContext, - Runspace currentRunspace, - PSCommand psCommand, - bool sendOutputToHost, - out DebuggerResumeAction? debuggerResumeAction) - { - debuggerResumeAction = null; - PSDataCollection outputCollection = new PSDataCollection(); - -#if !PowerShellv3 - if (sendOutputToHost) - { - outputCollection.DataAdded += - (obj, e) => - { - for (int i = e.Index; i < outputCollection.Count; i++) - { - powerShellContext.WriteOutput( - outputCollection[i].ToString(), - true); - } - }; - } - - DebuggerCommandResults commandResults = - currentRunspace.Debugger.ProcessCommand( - psCommand, - outputCollection); - - // Pass along the debugger's resume action if the user's - // command caused one to be returned - debuggerResumeAction = commandResults.ResumeAction; -#endif - - IEnumerable results = null; - if (typeof(TResult) != typeof(PSObject)) - { - results = - outputCollection - .Select(pso => pso.BaseObject) - .Cast(); - } - else - { - results = outputCollection.Cast(); - } - - return results; - } - - public void StopCommandInDebugger(PowerShellContext powerShellContext) - { -#if !PowerShellv3 - powerShellContext.CurrentRunspace.Runspace.Debugger.StopProcessCommand(); -#endif - } - - public virtual bool IsDebuggerStopped(PromptNest promptNest, Runspace runspace) - { - return promptNest.IsInDebugger; - } - - public void ExitNestedPrompt(PSHost host) - { -#if !PowerShellv3 - try - { - host.ExitNestedPrompt(); - } - catch (FlowControlException) - { - } -#else - throw new NotSupportedException(); -#endif - } - } -} - diff --git a/src/PowerShellEditorServices/Session/PowerShell5Operations.cs b/src/PowerShellEditorServices/Session/PowerShell5Operations.cs index e27c3b14e..e91c0edc8 100644 --- a/src/PowerShellEditorServices/Session/PowerShell5Operations.cs +++ b/src/PowerShellEditorServices/Session/PowerShell5Operations.cs @@ -3,30 +3,100 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Host; using System.Management.Automation.Runspaces; namespace Microsoft.PowerShell.EditorServices.Session { - internal class PowerShell5Operations : PowerShell4Operations + internal class PowerShell5Operations : IVersionSpecificOperations { - public override void PauseDebugger(Runspace runspace) + public void ConfigureDebugger(Runspace runspace) + { + if (runspace.Debugger != null) + { + runspace.Debugger.SetDebugMode(DebugModes.LocalScript | DebugModes.RemoteScript); + } + } + + public virtual void PauseDebugger(Runspace runspace) { -#if !PowerShellv3 && !PowerShellv4 if (runspace.Debugger != null) { runspace.Debugger.SetDebuggerStepMode(true); } -#endif } - public override bool IsDebuggerStopped(PromptNest promptNest, Runspace runspace) + public virtual bool IsDebuggerStopped(PromptNest promptNest, Runspace runspace) + { + return runspace.Debugger.InBreakpoint || (promptNest.IsRemote && promptNest.IsInDebugger); + } + + public IEnumerable ExecuteCommandInDebugger( + PowerShellContext powerShellContext, + Runspace currentRunspace, + PSCommand psCommand, + bool sendOutputToHost, + out DebuggerResumeAction? debuggerResumeAction) + { + debuggerResumeAction = null; + PSDataCollection outputCollection = new PSDataCollection(); + + if (sendOutputToHost) + { + outputCollection.DataAdded += + (obj, e) => + { + for (int i = e.Index; i < outputCollection.Count; i++) + { + powerShellContext.WriteOutput( + outputCollection[i].ToString(), + true); + } + }; + } + + DebuggerCommandResults commandResults = + currentRunspace.Debugger.ProcessCommand( + psCommand, + outputCollection); + + // Pass along the debugger's resume action if the user's + // command caused one to be returned + debuggerResumeAction = commandResults.ResumeAction; + + IEnumerable results = null; + if (typeof(TResult) != typeof(PSObject)) + { + results = + outputCollection + .Select(pso => pso.BaseObject) + .Cast(); + } + else + { + results = outputCollection.Cast(); + } + + return results; + } + + public void StopCommandInDebugger(PowerShellContext powerShellContext) { -#if !PowerShellv3 && !PowerShellv4 - return runspace.Debugger.InBreakpoint || - (promptNest.IsRemote && promptNest.IsInDebugger); -#else - throw new System.NotSupportedException(); -#endif + powerShellContext.CurrentRunspace.Runspace.Debugger.StopProcessCommand(); + } + + public void ExitNestedPrompt(PSHost host) + { + try + { + host.ExitNestedPrompt(); + } + catch (FlowControlException) + { + } } } } diff --git a/src/PowerShellEditorServices/Session/PowerShellContext.cs b/src/PowerShellEditorServices/Session/PowerShellContext.cs index 3d7c557f2..170cd0d20 100644 --- a/src/PowerShellEditorServices/Session/PowerShellContext.cs +++ b/src/PowerShellEditorServices/Session/PowerShellContext.cs @@ -166,12 +166,14 @@ public static Runspace CreateRunspace( /// public static Runspace CreateRunspace(PSHost psHost) { - var initialSessionState = InitialSessionState.CreateDefault2(); + InitialSessionState initialSessionState; + if (Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1") { + initialSessionState = InitialSessionState.CreateDefault(); + } else { + initialSessionState = InitialSessionState.CreateDefault2(); + } Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState); -#if !CoreCLR - runspace.ApartmentState = ApartmentState.STA; -#endif runspace.ThreadOptions = PSThreadOptions.ReuseThread; runspace.Open(); @@ -246,14 +248,6 @@ public void Initialize( { this.versionSpecificOperations = new PowerShell5Operations(); } - else if (powerShellVersion.Major == 4) - { - this.versionSpecificOperations = new PowerShell4Operations(); - } - else if (powerShellVersion.Major == 3) - { - this.versionSpecificOperations = new PowerShell3Operations(); - } else { throw new NotSupportedException( @@ -1015,44 +1009,11 @@ internal async Task InvokeReadLineAsync(bool isCommandLine, Cancellation internal static TResult ExecuteScriptAndGetItem(string scriptToExecute, Runspace runspace, TResult defaultValue = default(TResult)) { - Pipeline pipeline = null; - - try - { - if (runspace.RunspaceAvailability == RunspaceAvailability.AvailableForNestedCommand) - { - pipeline = runspace.CreateNestedPipeline(scriptToExecute, false); - } - else - { - pipeline = runspace.CreatePipeline(scriptToExecute, false); - } - - Collection results = pipeline.Invoke(); - - if (results.Count == 0 || results.FirstOrDefault() == null) - { - return defaultValue; - } - - if (typeof(TResult) != typeof(PSObject)) - { - return results - .Select(pso => pso.BaseObject) - .OfType() - .FirstOrDefault(); - } - else - { - return - results - .OfType() - .FirstOrDefault(); - } - } - finally + using (PowerShell pwsh = PowerShell.Create()) { - pipeline.Dispose(); + pwsh.Runspace = runspace; + IEnumerable results = pwsh.AddScript(scriptToExecute).Invoke(); + return results.DefaultIfEmpty(defaultValue).First(); } } @@ -1969,20 +1930,18 @@ private SessionDetails GetSessionDetailsInDebugger() private SessionDetails GetSessionDetailsInNestedPipeline() { - using (var pipeline = this.CurrentRunspace.Runspace.CreateNestedPipeline()) - { - return this.GetSessionDetails( - command => + // We don't need to check what thread we're on here. If it's a local + // nested pipeline then we will already be on the correct thread, and + // non-debugger nested pipelines aren't supported in remote runspaces. + return this.GetSessionDetails( + command => + { + using (var localPwsh = PowerShell.Create(RunspaceMode.CurrentRunspace)) { - pipeline.Commands.Clear(); - pipeline.Commands.Add(command.Commands[0]); - - return - pipeline - .Invoke() - .FirstOrDefault(); - }); - } + localPwsh.Commands = command; + return localPwsh.Invoke().FirstOrDefault(); + } + }); } private void SetProfileVariableInCurrentRunspace(ProfilePaths profilePaths) diff --git a/src/PowerShellEditorServices/Workspace/ScriptFile.cs b/src/PowerShellEditorServices/Workspace/ScriptFile.cs index fc290cff0..a738143ab 100644 --- a/src/PowerShellEditorServices/Workspace/ScriptFile.cs +++ b/src/PowerShellEditorServices/Workspace/ScriptFile.cs @@ -114,7 +114,7 @@ public Token[] ScriptTokens } /// - /// Gets the array of filepaths dot sourced in this ScriptFile + /// Gets the array of filepaths dot sourced in this ScriptFile /// public string[] ReferencedFiles { @@ -208,7 +208,7 @@ public static IEnumerable GetLines(string text) } /// - /// Deterines whether the supplied path indicates the file is an "untitled:Unitled-X" + /// Deterines whether the supplied path indicates the file is an "untitled:Unitled-X" /// which has not been saved to file. /// /// The path to check. @@ -549,10 +549,9 @@ private void ParseFileContents() try { -#if PowerShellv5r2 // This overload appeared with Windows 10 Update 1 - if (this.powerShellVersion.Major >= 5 && - this.powerShellVersion.Build >= 10586) + if (this.powerShellVersion.Major > 5 || + (this.powerShellVersion.Major == 5 && this.powerShellVersion.Build >= 10586)) { // Include the file path so that module relative // paths are evaluated correctly @@ -571,13 +570,6 @@ private void ParseFileContents() out this.scriptTokens, out parseErrors); } -#else - this.ScriptAst = - Parser.ParseInput( - this.Contents, - out this.scriptTokens, - out parseErrors); -#endif } catch (RuntimeException ex) { diff --git a/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs b/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs index a07e79501..7a2ccd197 100644 --- a/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs +++ b/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs @@ -7,6 +7,7 @@ using Microsoft.PowerShell.EditorServices.Protocol.DebugAdapter; using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol; using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using System; using System.IO; @@ -20,17 +21,13 @@ public class DebugAdapterTests : ServerTestsBase, IAsyncLifetime private ILogger logger; private DebugAdapterClient debugAdapterClient; private string DebugScriptPath = - Path.GetFullPath(@"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1"); + Path.GetFullPath(TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/DebugTest.ps1")); public async Task InitializeAsync() { string testLogPath = Path.Combine( -#if CoreCLR AppContext.BaseDirectory, -#else - AppDomain.CurrentDomain.BaseDirectory, -#endif "logs", this.GetType().Name, Guid.NewGuid().ToString().Substring(0, 8)); diff --git a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs index 155e28382..8b83525bc 100644 --- a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs +++ b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs @@ -11,6 +11,7 @@ using Microsoft.PowerShell.EditorServices.Protocol.Messages; using Microsoft.PowerShell.EditorServices.Protocol.Server; using Microsoft.PowerShell.EditorServices.Session; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using System; using System.IO; @@ -29,11 +30,7 @@ public async Task InitializeAsync() { string testLogPath = Path.Combine( -#if CoreCLR AppContext.BaseDirectory, -#else - AppDomain.CurrentDomain.BaseDirectory, -#endif "logs", this.GetType().Name, Guid.NewGuid().ToString().Substring(0, 8)); @@ -77,7 +74,7 @@ public async Task DisposeAsync() public async Task ServiceReturnsSyntaxErrors() { // Send the 'didOpen' event - await this.SendOpenFileEvent("TestFiles\\SimpleSyntaxError.ps1", false); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/SimpleSyntaxError.ps1"), false); // Wait for the diagnostic event PublishDiagnosticsNotification diagnostics = @@ -90,11 +87,11 @@ await this.WaitForEvent( string.IsNullOrEmpty(diagnostics.Diagnostics[0].Message)); } - [Fact(Skip = "Skipping until Script Analyzer integration is added back")] + [Fact] public async Task ServiceReturnsSemanticMarkers() { // Send the 'didOpen' event - await this.SendOpenFileEvent("TestFiles\\SimpleSemanticError.ps1", false); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/SimpleSemanticError.ps1"), false); // Wait for the diagnostic event PublishDiagnosticsNotification diagnostics = @@ -110,7 +107,7 @@ await this.WaitForEvent( public async Task ServiceReturnsNoErrorsForUsingRelativeModulePaths() { // Send the 'didOpen' event - await this.SendOpenFileEvent("TestFiles\\Module.psm1", false); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/Module.psm1"), false); // Wait for the diagnostic event PublishDiagnosticsNotification diagnostics = @@ -124,7 +121,7 @@ await this.WaitForEvent( [Fact] public async Task ServiceCompletesFunctionName() { - await this.SendOpenFileEvent("TestFiles\\CompleteFunctionName.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1")); CompletionItem[] completions = await this.SendRequest( @@ -133,7 +130,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\CompleteFunctionName.ps1", + Uri = TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1"), }, Position = new Position { @@ -151,7 +148,7 @@ await this.SendRequest( [Fact] public async Task CompletesDetailOnVariableSuggestion() { - await this.SendOpenFileEvent("TestFiles\\CompleteFunctionName.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1")); CompletionItem[] completions = await this.SendRequest( @@ -160,7 +157,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\CompleteFunctionName.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1") }, Position = new Position { @@ -181,7 +178,7 @@ await this.SendRequest( [Fact(Skip = "Skipped until variable documentation gathering is added back.")] public async Task CompletesDetailOnVariableDocSuggestion() { - await this.SendOpenFileEvent("TestFiles\\CompleteFunctionName.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1")); await this.SendRequest( CompletionRequest.Type, @@ -189,7 +186,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\CompleteFunctionName.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1") }, Position = new Position { @@ -223,7 +220,7 @@ await this.SendRequest( [Fact] public async Task CompletesDetailOnCommandSuggestion() { - await this.SendOpenFileEvent("TestFiles\\CompleteFunctionName.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1")); CompletionItem[] completions = await this.SendRequest( @@ -232,7 +229,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\CompleteFunctionName.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/CompleteFunctionName.ps1") }, Position = new Position { @@ -263,7 +260,7 @@ await this.SendRequest( [Fact] public async Task FindsReferencesOfVariable() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -272,7 +269,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -295,7 +292,7 @@ await this.SendRequest( [Fact] public async Task FindsNoReferencesOfEmptyLine() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -304,7 +301,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -320,7 +317,7 @@ await this.SendRequest( [Fact] public async Task FindsReferencesOnFunctionDefinition() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -329,7 +326,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -352,7 +349,7 @@ await this.SendRequest( [Fact] public async Task FindsReferencesOnCommand() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -361,7 +358,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -384,7 +381,7 @@ await this.SendRequest( [Fact] public async Task FindsDefinitionOfCommand() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -393,7 +390,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1", + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1"), }, Position = new Position { @@ -411,7 +408,7 @@ await this.SendRequest( [Fact] public async Task FindsNoDefinitionOfBuiltinCommand() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -420,7 +417,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -436,7 +433,7 @@ await this.SendRequest( [Fact] public async Task FindsDefintionOfVariable() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -445,7 +442,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -465,7 +462,7 @@ await this.SendRequest( [Fact] public async Task FindsDefinitionOfVariableInOtherFile() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -474,7 +471,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -495,7 +492,7 @@ await this.SendRequest( [Fact] public async Task FindDefinitionOfVariableWithSpecialChars() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); Location[] locations = await this.SendRequest( @@ -504,7 +501,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -525,7 +522,7 @@ await this.SendRequest( [Fact] public async Task FindsOccurencesOnFunctionDefinition() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); DocumentHighlight[] highlights = await this.SendRequest( @@ -534,7 +531,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -548,10 +545,10 @@ await this.SendRequest( Assert.Equal(2, highlights[1].Range.Start.Line); } - [Fact(Skip = "This test hangs in VSTS for some reason...")] + [Fact] public async Task GetsParameterHintsOnCommand() { - await this.SendOpenFileEvent("TestFiles\\FindReferences.ps1"); + await this.SendOpenFileEvent(TestUtilities.NormalizePath("TestFiles/FindReferences.ps1")); SignatureHelp signatureHelp = await this.SendRequest( @@ -560,7 +557,7 @@ await this.SendRequest( { TextDocument = new TextDocumentIdentifier { - Uri = "TestFiles\\FindReferences.ps1" + Uri = TestUtilities.NormalizePath("TestFiles/FindReferences.ps1") }, Position = new Position { @@ -603,9 +600,9 @@ public async Task ServiceExpandsAliases() string expandedText = await this.SendRequest( ExpandAliasRequest.Type, - "gci\r\npwd"); + TestUtilities.NormalizeNewlines("gci\npwd")); - Assert.Equal("Get-ChildItem\r\nGet-Location", expandedText); + Assert.Equal(TestUtilities.NormalizeNewlines("Get-ChildItem\nGet-Location"), expandedText); } [Fact] @@ -757,7 +754,7 @@ public async Task ServiceLoadsProfilesOnDemand() string testProfilePath = Path.Combine( Path.GetFullPath( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Profile\"), + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Profile/")), profileName); string currentUserCurrentHostPath = diff --git a/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj b/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj index b25a612c4..c183c3da3 100644 --- a/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj +++ b/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj @@ -1,42 +1,35 @@  - - netcoreapp2.0;net452 + netcoreapp2.1;net461 Microsoft.PowerShell.EditorServices.Test.Host - PreserveNewest - + - - - - 6.0.0-alpha13 - - - - - - - + $(DefineConstants);CoreCLR - - - - - - + + + + + + + + + + + diff --git a/test/PowerShellEditorServices.Test.Host/ServerTestsBase.cs b/test/PowerShellEditorServices.Test.Host/ServerTestsBase.cs index f8eef1062..c126be90a 100644 --- a/test/PowerShellEditorServices.Test.Host/ServerTestsBase.cs +++ b/test/PowerShellEditorServices.Test.Host/ServerTestsBase.cs @@ -4,6 +4,7 @@ // using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using Newtonsoft.Json.Linq; using System; @@ -11,6 +12,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -34,19 +36,15 @@ protected async Task> LaunchService( string logPath, bool waitForDebugger = false) { - string modulePath = Path.GetFullPath(@"..\..\..\..\..\module"); - string scriptPath = Path.GetFullPath(Path.Combine(modulePath, @"PowerShellEditorServices\Start-EditorServices.ps1")); + string modulePath = Path.GetFullPath(TestUtilities.NormalizePath("../../../../../module")); + string scriptPath = Path.GetFullPath(Path.Combine(modulePath, "PowerShellEditorServices", "Start-EditorServices.ps1")); if (!File.Exists(scriptPath)) { throw new IOException(String.Format("Bad start script path: '{0}'", scriptPath)); } -#if CoreCLR Assembly assembly = this.GetType().GetTypeInfo().Assembly; -#else - Assembly assembly = this.GetType().Assembly; -#endif string assemblyPath = new Uri(assembly.CodeBase).LocalPath; FileVersionInfo fileVersionInfo = @@ -98,7 +96,7 @@ protected async Task> LaunchService( { StartInfo = new ProcessStartInfo { - FileName = "powershell.exe", + FileName = GetPwshExeName(), Arguments = string.Join(" ", args), CreateNoWindow = true, UseShellExecute = false, @@ -305,5 +303,14 @@ protected async Task>> WaitForRequest - - netcoreapp2.0;net452 + netcoreapp2.1;net461 Microsoft.PowerShell.EditorServices.Test.Protocol - + + + + + + + - - - - 10.0.3 - - - 6.0.0-alpha13 - - - + + + + - - + $(DefineConstants);CoreCLR - - - - - - diff --git a/test/PowerShellEditorServices.Test.Protocol/Server/OutputDebouncerTests.cs b/test/PowerShellEditorServices.Test.Protocol/Server/OutputDebouncerTests.cs index 50aad110e..9e3db950f 100644 --- a/test/PowerShellEditorServices.Test.Protocol/Server/OutputDebouncerTests.cs +++ b/test/PowerShellEditorServices.Test.Protocol/Server/OutputDebouncerTests.cs @@ -6,6 +6,7 @@ using Microsoft.PowerShell.EditorServices.Protocol.DebugAdapter; using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol; using Microsoft.PowerShell.EditorServices.Protocol.Server; +using Microsoft.PowerShell.EditorServices.Test.Shared; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -39,7 +40,7 @@ public async Task OutputDebouncerAggregatesOutputEvents() // Assert that there's only one event with the expected string Assert.Equal(1, messageSender.OutputEvents.Count); Assert.Equal( - "This is a test\r\nAnother line", + TestUtilities.NormalizeNewlines("This is a test\nAnother line"), messageSender.OutputEvents[0].Output); // Wait for the next output to be flushed @@ -48,7 +49,7 @@ public async Task OutputDebouncerAggregatesOutputEvents() // Assert that there's only one event with the expected string Assert.Equal(2, messageSender.OutputEvents.Count); Assert.Equal( - "Another test line\r\nfor great justice", + TestUtilities.NormalizeNewlines("Another test line\nfor great justice"), messageSender.OutputEvents[1].Output); } @@ -76,8 +77,8 @@ public async Task OutputDebouncerDoesNotDuplicateOutput() // Ensure that the two events start with the correct lines Assert.Equal(2, messageSender.OutputEvents.Count); - Assert.Equal("Output 1", messageSender.OutputEvents[0].Output.Split('\r')[0]); - Assert.Equal("Output 26", messageSender.OutputEvents[1].Output.Split('\r')[0]); + Assert.Equal("Output 1", messageSender.OutputEvents[0].Output.Split('\n')[0].Trim('\r')); + Assert.Equal("Output 26", messageSender.OutputEvents[1].Output.Split('\n')[0].Trim('\r')); } private static Task SendOutput( diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteAttributeValue.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteAttributeValue.cs index 1b5319ac2..43bf5bc86 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteAttributeValue.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteAttributeValue.cs @@ -7,10 +7,10 @@ namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { public class CompleteAttributeValue { - public static readonly ScriptRegion SourceDetails = + public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Completion\CompletionExamples.psm1", + File = TestUtilities.NormalizePath("Completion/CompletionExamples.psm1"), StartLineNumber = 16, StartColumnNumber = 38 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs index 3177dcbd5..5b03f9183 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs @@ -3,24 +3,31 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using Microsoft.PowerShell.EditorServices; namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { public class CompleteCommandFromModule { - public static readonly ScriptRegion SourceDetails = + private static readonly string[] s_getRandomParamSets = { + "Get-Random [[-Maximum] ] [-SetSeed ] [-Minimum ] []", + "Get-Random [-InputObject] [-SetSeed ] [-Count ] []" + }; + + public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Completion\CompletionExamples.psm1", + File = TestUtilities.NormalizePath("Completion/CompletionExamples.psm1"), StartLineNumber = 13, - StartColumnNumber = 11 + StartColumnNumber = 8 }; public static readonly CompletionDetails ExpectedCompletion = CompletionDetails.Create( - "Install-Module", + "Get-Random", CompletionType.Command, - "Install-Module"); + string.Join(Environment.NewLine + Environment.NewLine, s_getRandomParamSets) + ); } } diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandInFile.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandInFile.cs index 3c201cd9d..93bfb739d 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandInFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandInFile.cs @@ -9,10 +9,10 @@ namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { public class CompleteCommandInFile { - public static readonly ScriptRegion SourceDetails = + public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Completion\CompletionExamples.psm1", + File = TestUtilities.NormalizePath("Completion/CompletionExamples.psm1"), StartLineNumber = 8, StartColumnNumber = 7 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteFilePath.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteFilePath.cs index 4bc71b8bc..1d2a77863 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteFilePath.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteFilePath.cs @@ -13,12 +13,12 @@ namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { public class CompleteFilePath { - public static readonly ScriptRegion SourceDetails = + public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Completion\CompletionExamples.psm1", + File = TestUtilities.NormalizePath("Completion/CompletionExamples.psm1"), StartLineNumber = 19, - StartColumnNumber = 25 + StartColumnNumber = 15 }; public static readonly BufferRange ExpectedRange = diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteVariableInFile.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteVariableInFile.cs index 9a728fa69..3a7bd4b40 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteVariableInFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteVariableInFile.cs @@ -9,10 +9,10 @@ namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { public class CompleteVariableInFile { - public static readonly ScriptRegion SourceDetails = + public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Completion\CompletionExamples.psm1", + File = TestUtilities.NormalizePath("Completion/CompletionExamples.psm1"), StartLineNumber = 10, StartColumnNumber = 9 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1 b/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1 index f34690cca..ee3dd9098 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1 +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1 @@ -10,10 +10,10 @@ Get-So $testVar Import-Module PowerShellGet -Install-Mo +Get-Rand function Test-Completion { param([Parameter(Mandatory, Value)]) } -Get-ChildItem c:\Program +Get-ChildItem / diff --git a/test/PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1 b/test/PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1 index 7398d8c01..fc6896990 100644 --- a/test/PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1 @@ -18,4 +18,4 @@ function Test-Variables { Write-Output "Done" } -Test-Variables \ No newline at end of file +Test-Variables diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs index 164d5798c..387e8e58b 100644 --- a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs +++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs @@ -10,7 +10,7 @@ public class FindsFunctionDefinition public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 3, StartColumnNumber = 12 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInDotSourceReference.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInDotSourceReference.cs index bba3f2b27..e8fb1f3b5 100644 --- a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInDotSourceReference.cs +++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInDotSourceReference.cs @@ -12,7 +12,7 @@ public class FindsFunctionDefinitionInDotSourceReference public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\FileWithReferences.ps1", + File = TestUtilities.NormalizePath("References/FileWithReferences.ps1"), StartLineNumber = 3, StartColumnNumber = 6 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInWorkspace.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInWorkspace.cs index b32a6159f..1c48cfefe 100644 --- a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInWorkspace.cs +++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinitionInWorkspace.cs @@ -12,7 +12,7 @@ public class FindsFunctionDefinitionInWorkspace public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\ReferenceFileD.ps1", + File = TestUtilities.NormalizePath("References/ReferenceFileD.ps1"), StartLineNumber = 1, StartColumnNumber = 2 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs index 6dab3ddad..1c785be21 100644 --- a/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs +++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs @@ -16,7 +16,7 @@ public class FindsVariableDefinition public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 8, StartColumnNumber = 3 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs index 62fc82716..7b3c368b7 100644 --- a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs +++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs @@ -10,7 +10,7 @@ public class FindOccurrencesOnParameter public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 1, StartColumnNumber = 31 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs index 2b8258410..72c2adf95 100644 --- a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs +++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs @@ -12,7 +12,7 @@ public class FindsOccurrencesOnFunction public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 1, StartColumnNumber = 17 }; diff --git a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs index fcb4e88f0..797d93bd1 100644 --- a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs +++ b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs @@ -12,7 +12,7 @@ public class FindsParameterSetsOnCommand public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"ParameterHints\ParamHints.ps1", + File = TestUtilities.NormalizePath("ParameterHints/ParamHints.ps1"), StartLineNumber = 1, StartColumnNumber = 14 }; diff --git a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs index 920530ec3..e7d40489e 100644 --- a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs +++ b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs @@ -10,7 +10,7 @@ public class FindsParameterSetsOnCommandWithSpaces public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"ParameterHints\ParamHints.ps1", + File = TestUtilities.NormalizePath("ParameterHints/ParamHints.ps1"), StartLineNumber = 9, StartColumnNumber = 31 }; diff --git a/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj b/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj index cee19e4f2..84bf41ab8 100644 --- a/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj +++ b/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj @@ -1,22 +1,15 @@  - 0.9.0-beta - netstandard1.6;net452 + netstandard2.0 Microsoft.PowerShell.EditorServices.Test.Shared - - + - - - $(DefineConstants);CoreCLR + + true + true - - - - - diff --git a/test/PowerShellEditorServices.Test.Shared/References/FileWithReferences.ps1 b/test/PowerShellEditorServices.Test.Shared/References/FileWithReferences.ps1 index fb39070e8..7a4e4cfe6 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/FileWithReferences.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/References/FileWithReferences.ps1 @@ -1,3 +1,3 @@ -. .\SimpleFile.ps1 +. ./SimpleFile.ps1 My-Function "test" diff --git a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnBuiltInCommandWithAlias.cs b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnBuiltInCommandWithAlias.cs index 2a22b13f2..c06e2452c 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnBuiltInCommandWithAlias.cs +++ b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnBuiltInCommandWithAlias.cs @@ -10,7 +10,7 @@ public class FindsReferencesOnBuiltInCommandWithAlias public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 14, StartColumnNumber = 3 }; @@ -20,7 +20,7 @@ public class FindsReferencesOnBuiltInAlias public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 15, StartColumnNumber = 2 }; diff --git a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunction.cs b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunction.cs index 6a53d69f2..28c3249fd 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunction.cs +++ b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunction.cs @@ -10,7 +10,7 @@ public class FindsReferencesOnFunction public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 3, StartColumnNumber = 8 }; diff --git a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunctionMultiFileDotSource.cs b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunctionMultiFileDotSource.cs index 5624edf02..872df6ff1 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunctionMultiFileDotSource.cs +++ b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnFunctionMultiFileDotSource.cs @@ -12,7 +12,7 @@ public class FindsReferencesOnFunctionMultiFileDotSourceFileB public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\ReferenceFileB.ps1", + File = TestUtilities.NormalizePath("References/ReferenceFileB.ps1"), StartLineNumber = 5, StartColumnNumber = 8 }; @@ -22,7 +22,7 @@ public class FindsReferencesOnFunctionMultiFileDotSourceFileC public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\ReferenceFileC.ps1", + File = TestUtilities.NormalizePath("References/ReferenceFileC.ps1"), StartLineNumber = 4, StartColumnNumber = 10 }; diff --git a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesonVariable.cs b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesonVariable.cs index b5ae61af4..1860e56d9 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesonVariable.cs +++ b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesonVariable.cs @@ -12,7 +12,7 @@ public class FindsReferencesOnVariable public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"References\SimpleFile.ps1", + File = TestUtilities.NormalizePath("References/SimpleFile.ps1"), StartLineNumber = 10, StartColumnNumber = 17 }; diff --git a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileA.ps1 b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileA.ps1 index a43f59fb2..31ef35600 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileA.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileA.ps1 @@ -1,9 +1,9 @@ . .\ReferenceFileA.ps1 -. .\ReferenceFileB.ps1 +. ./ReferenceFileB.ps1 . .\ReferenceFileC.ps1 function My-Function ($myInput) { My-Function $myInput } -Get-ChildItem \ No newline at end of file +Get-ChildItem diff --git a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileB.ps1 b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileB.ps1 index add70c1d6..20a1fc5c8 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileB.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileB.ps1 @@ -1,5 +1,5 @@ -. .\ReferenceFileC.ps1 +. ./ReferenceFileC.ps1 Get-ChildItem -My-Function "testb" \ No newline at end of file +My-Function "testb" diff --git a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileC.ps1 b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileC.ps1 index e17fd096f..6e1ee3131 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileC.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/References/ReferenceFileC.ps1 @@ -1,4 +1,4 @@ -. .\ReferenceFileA.ps1 +. ./ReferenceFileA.ps1 Get-ChildItem -My-Function "testc" \ No newline at end of file +My-Function "testc" diff --git a/test/PowerShellEditorServices.Test.Shared/References/SimpleFile.ps1 b/test/PowerShellEditorServices.Test.Shared/References/SimpleFile.ps1 index 7e9022cf2..527045b1e 100644 --- a/test/PowerShellEditorServices.Test.Shared/References/SimpleFile.ps1 +++ b/test/PowerShellEditorServices.Test.Shared/References/SimpleFile.ps1 @@ -12,9 +12,7 @@ My-Function $things Write-Output "Hello World"; Get-ChildItem -ls gci dir -LS Write-Host -Get-ChildItem \ No newline at end of file +Get-ChildItem diff --git a/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForBuiltInCommand.cs b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForBuiltInCommand.cs index c3526938b..d46206bcb 100644 --- a/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForBuiltInCommand.cs +++ b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForBuiltInCommand.cs @@ -10,7 +10,7 @@ public class FindsDetailsForBuiltInCommand public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"SymbolDetails\SymbolDetails.ps1", + File = TestUtilities.NormalizePath("SymbolDetails/SymbolDetails.ps1"), StartLineNumber = 1, StartColumnNumber = 10 }; diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInMultiSymbolFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInMultiSymbolFile.cs index 7f3dc68e8..ab3ce87b3 100644 --- a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInMultiSymbolFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInMultiSymbolFile.cs @@ -9,7 +9,7 @@ public class FindSymbolsInMultiSymbolFile { public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Symbols\MultipleSymbols.ps1" + File = TestUtilities.NormalizePath("Symbols/MultipleSymbols.ps1") }; } } diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNoSymbolsFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNoSymbolsFile.cs index cf1692030..c8c814ca0 100644 --- a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNoSymbolsFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNoSymbolsFile.cs @@ -9,7 +9,7 @@ public class FindSymbolsInNoSymbolsFile { public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Symbols\NoSymbols.ps1" + File = TestUtilities.NormalizePath("Symbols/NoSymbols.ps1") }; } } diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPSDFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPSDFile.cs index 8d96f49d6..6343b79cc 100644 --- a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPSDFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPSDFile.cs @@ -10,7 +10,7 @@ public class FindSymbolsInPSDFile public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Symbols\PowerShellDataFile.psd1" + File = TestUtilities.NormalizePath("Symbols/PowerShellDataFile.psd1") }; } } diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPesterFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPesterFile.cs index cebcae3aa..19a7c6519 100644 --- a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPesterFile.cs +++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInPesterFile.cs @@ -10,7 +10,7 @@ public class FindSymbolsInPesterFile public static readonly ScriptRegion SourceDetails = new ScriptRegion { - File = @"Symbols\PesterFile.tests.ps1" + File = TestUtilities.NormalizePath("Symbols/PesterFile.tests.ps1") }; } } diff --git a/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs b/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs new file mode 100644 index 000000000..dd6cc1211 --- /dev/null +++ b/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs @@ -0,0 +1,90 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Microsoft.PowerShell.EditorServices.Test.Shared +{ + /// + /// Convenience class to simplify cross-platform testing + /// + public static class TestUtilities + { + private static readonly char[] s_unixPathSeparators = new [] { '/' }; + + private static readonly char[] s_unixNewlines = new [] { '\n' }; + + /// + /// Takes a UNIX-style path and converts it to the path appropriate to the platform. + /// + /// A forward-slash separated path. + /// A path with directories separated by the appropriate separator. + public static string NormalizePath(string unixPath) + { + if (unixPath == null) + { + return unixPath; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return unixPath.Replace('/', Path.DirectorySeparatorChar); + } + + return unixPath; + } + + /// + /// Take a string with UNIX newlines and replaces them with platform-appropriate newlines. + /// + /// The string with UNIX-style newlines. + /// The platform-newline-normalized string. + public static string NormalizeNewlines(string unixString) + { + if (unixString == null) + { + return unixString; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return String.Join(Environment.NewLine, unixString.Split(s_unixNewlines)); + } + + return unixString; + } + + /// + /// Platform-normalize a string -- takes a UNIX-style string and gives it platform-appropriate newlines and path separators. + /// + /// The string to normalize for the platform, given with UNIX-specific separators. + /// The same string but separated by platform-appropriate directory and newline separators. + public static string PlatformNormalize(string unixString) + { + return NormalizeNewlines(NormalizePath(unixString)); + } + + /// + /// Not for use in production -- convenience code for debugging tests. + /// + public static void AWAIT_DEBUGGER_HERE( + [CallerMemberName] string callerName = null, + [CallerFilePath] string callerPath = null, + [CallerLineNumber] int callerLine = -1) + { + if (Debugger.IsAttached) + { + return; + } + + System.Console.WriteLine(); + System.Console.WriteLine("===== AWAITING DEBUGGER ====="); + System.Console.WriteLine($" PID: {Process.GetCurrentProcess().Id}"); + System.Console.WriteLine($" Waiting at {callerPath} line {callerLine} ({callerName})"); + System.Console.WriteLine(" PRESS ANY KEY TO CONTINUE"); + System.Console.WriteLine("============================="); + System.Console.ReadKey(); + } + } +} diff --git a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs index ac88caaf8..1c8e28b70 100644 --- a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs @@ -5,6 +5,7 @@ using Microsoft.PowerShell.EditorServices.Debugging; using Microsoft.PowerShell.EditorServices.Utility; +using Microsoft.PowerShell.EditorServices.Test.Shared; using System; using System.Collections.Generic; using System.Linq; @@ -41,11 +42,11 @@ public DebugServiceTests() // Load the test debug file this.debugScriptFile = this.workspace.GetFile( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1"); + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1")); this.variableScriptFile = this.workspace.GetFile( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\VariableTest.ps1"); + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1")); this.debugService = new DebugService(this.powerShellContext, logger); this.debugService.DebuggerStopped += debugService_DebuggerStopped; @@ -55,7 +56,7 @@ public DebugServiceTests() // Load the test debug file this.debugScriptFile = this.workspace.GetFile( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1"); + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/DebugTest.ps1")); } async void powerShellContext_SessionStateChanged(object sender, SessionStateChangedEventArgs e) @@ -108,7 +109,7 @@ public async Task DebuggerAcceptsScriptArgs(string[] args) // it should not escape already escaped chars. ScriptFile debugWithParamsFile = this.workspace.GetFile( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\Debug` With Params `[Test].ps1"); + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/Debug` With Params `[Test].ps1")); await this.debugService.SetLineBreakpoints( debugWithParamsFile, @@ -638,7 +639,7 @@ await this.debugService.SetLineBreakpoints( // Test set of global scope int variable (not strongly typed) VariableScope globalScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName); string newGlobalIntValue = "4242"; - string setGlobalIntValue = await debugService.SetVariable(globalScope.Id, "$MaximumAliasCount", newGlobalIntValue); + string setGlobalIntValue = await debugService.SetVariable(globalScope.Id, "$MaximumHistoryCount", newGlobalIntValue); Assert.Equal(newGlobalIntValue, setGlobalIntValue); // The above just tests that the debug service returns the correct new value string. @@ -664,7 +665,7 @@ await this.debugService.SetLineBreakpoints( // Test set of global scope int variable (not strongly typed) globalScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName); variables = debugService.GetVariables(globalScope.Id); - var intGlobalVar = variables.FirstOrDefault(v => v.Name == "$MaximumAliasCount"); + var intGlobalVar = variables.FirstOrDefault(v => v.Name == "$MaximumHistoryCount"); Assert.Equal(newGlobalIntValue, intGlobalVar.ValueString); // Abort execution of the script @@ -789,17 +790,26 @@ await this.debugService.SetLineBreakpoints( VariableDetailsBase[] variables = debugService.GetVariables(stackFrames[0].LocalVariables.Id); - var var = variables.FirstOrDefault(v => v.Name == "$assocArrVar"); + VariableDetailsBase var = variables.FirstOrDefault(v => v.Name == "$assocArrVar"); Assert.NotNull(var); Assert.Equal("[Hashtable: 2]", var.ValueString); Assert.True(var.IsExpandable); - var childVars = debugService.GetVariables(var.Id); + VariableDetailsBase[] childVars = debugService.GetVariables(var.Id); Assert.Equal(9, childVars.Length); Assert.Equal("[0]", childVars[0].Name); - Assert.Equal("[secondChild, 42]", childVars[0].ValueString); Assert.Equal("[1]", childVars[1].Name); - Assert.Equal("[firstChild, \"Child\"]", childVars[1].ValueString); + + var childVarStrs = new HashSet(childVars.Select(v => v.ValueString)); + var expectedVars = new [] { + "[firstChild, \"Child\"]", + "[secondChild, 42]" + }; + + foreach (string expectedVar in expectedVars) + { + Assert.Contains(expectedVar, childVarStrs); + } // Abort execution of the script this.powerShellContext.AbortExecution(); @@ -824,17 +834,17 @@ await this.debugService.SetLineBreakpoints( VariableDetailsBase[] variables = debugService.GetVariables(stackFrames[0].LocalVariables.Id); - var var = variables.FirstOrDefault(v => v.Name == "$psObjVar"); - Assert.NotNull(var); - Assert.Equal("@{Age=75; Name=John}", var.ValueString); - Assert.True(var.IsExpandable); + var psObjVar = variables.FirstOrDefault(v => v.Name == "$psObjVar"); + Assert.NotNull(psObjVar); + Assert.True("@{Age=75; Name=John}".Equals(psObjVar.ValueString) || "@{Name=John; Age=75}".Equals(psObjVar.ValueString)); + Assert.True(psObjVar.IsExpandable); - var childVars = debugService.GetVariables(var.Id); - Assert.Equal(2, childVars.Length); - Assert.Equal("Age", childVars[0].Name); - Assert.Equal("75", childVars[0].ValueString); - Assert.Equal("Name", childVars[1].Name); - Assert.Equal("\"John\"", childVars[1].ValueString); + IDictionary childVars = debugService.GetVariables(psObjVar.Id).ToDictionary(v => v.Name, v => v.ValueString); + Assert.Equal(2, childVars.Count); + Assert.Contains("Age", childVars.Keys); + Assert.Contains("Name", childVars.Keys); + Assert.Equal(childVars["Age"], "75"); + Assert.Equal(childVars["Name"], "\"John\""); // Abort execution of the script this.powerShellContext.AbortExecution(); @@ -875,9 +885,15 @@ await this.debugService.SetLineBreakpoints( this.powerShellContext.AbortExecution(); } +// TODO: Make this test cross platform by using the PowerShell process +// (the only process we can guarantee cross-platform) +#if CoreCLR + [Fact(Skip = "Need to use the PowerShell process in a cross-platform way for this test to work")] +#else // Verifies fix for issue #86, $proc = Get-Process foo displays just the // ETS property set and not all process properties. [Fact] +#endif public async Task DebuggerVariableProcessObjDisplaysCorrectly() { await this.debugService.SetLineBreakpoints( @@ -906,7 +922,7 @@ await this.debugService.SetLineBreakpoints( // Abort execution of the script this.powerShellContext.AbortExecution(); - } + } public async Task AssertDebuggerPaused() { diff --git a/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs b/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs index e56656a91..435d16ecb 100644 --- a/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs @@ -5,6 +5,7 @@ using Microsoft.PowerShell.EditorServices.Components; using Microsoft.PowerShell.EditorServices.Extensions; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using System; using System.Collections.Generic; @@ -38,7 +39,8 @@ public async Task InitializeAsync() { var logger = Logging.NullLogger; this.powerShellContext = PowerShellContextFactory.Create(logger); - await this.powerShellContext.ImportCommandsModule(@"..\..\..\..\..\module\PowerShellEditorServices\Commands"); + await this.powerShellContext.ImportCommandsModule( + TestUtilities.NormalizePath("../../../../../module/PowerShellEditorServices/Commands")); this.extensionService = new ExtensionService(this.powerShellContext); this.editorOperations = new TestEditorOperations(); @@ -51,7 +53,7 @@ await this.extensionService.Initialize( this.editorOperations, new ComponentRegistry()); - var filePath = @"c:\Test\Test.ps1"; + var filePath = TestUtilities.NormalizePath("c:/Test/Test.ps1"); this.currentFile = new ScriptFile(filePath, filePath, "This is a test file", new Version("5.0")); this.commandContext = new EditorContext( @@ -71,7 +73,7 @@ public Task DisposeAsync() public async Task CanRegisterAndInvokeCommandWithCmdletName() { await extensionService.PowerShellContext.ExecuteScriptString( - "function Invoke-Extension { $global:extensionValue = 5 }\r\n" + + TestUtilities.NormalizeNewlines("function Invoke-Extension { $global:extensionValue = 5 }\n") + "Register-EditorCommand -Name \"test.function\" -DisplayName \"Function extension\" -Function \"Invoke-Extension\""); // Wait for the add event @@ -110,10 +112,10 @@ await extensionService.PowerShellContext.ExecuteScriptString( public async Task CanUpdateRegisteredCommand() { // Register a command and then update it - await extensionService.PowerShellContext.ExecuteScriptString( - "function Invoke-Extension { Write-Output \"Extension output!\" }\r\n" + - "Register-EditorCommand -Name \"test.function\" -DisplayName \"Function extension\" -Function \"Invoke-Extension\"\r\n" + - "Register-EditorCommand -Name \"test.function\" -DisplayName \"Updated Function extension\" -Function \"Invoke-Extension\""); + await extensionService.PowerShellContext.ExecuteScriptString(TestUtilities.NormalizeNewlines( + "function Invoke-Extension { Write-Output \"Extension output!\" }\n" + + "Register-EditorCommand -Name \"test.function\" -DisplayName \"Function extension\" -Function \"Invoke-Extension\"\n" + + "Register-EditorCommand -Name \"test.function\" -DisplayName \"Updated Function extension\" -Function \"Invoke-Extension\"")); // Wait for the add and update events await this.AssertExtensionEvent(EventType.Add, "test.function"); diff --git a/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs b/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs index 1e19a544a..075fc4e79 100644 --- a/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs @@ -16,6 +16,8 @@ using System.Threading.Tasks; using Xunit; using Microsoft.PowerShell.EditorServices.Utility; +using Microsoft.PowerShell.EditorServices.Test.Shared; +using System.Runtime.InteropServices; namespace Microsoft.PowerShell.EditorServices.Test.Language { @@ -24,7 +26,8 @@ public class LanguageServiceTests : IDisposable private Workspace workspace; private LanguageService languageService; private PowerShellContext powerShellContext; - private const string baseSharedScriptPath = @"..\..\..\..\PowerShellEditorServices.Test.Shared\"; + private static readonly string s_baseSharedScriptPath = + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/"); public LanguageServiceTests() { @@ -52,7 +55,7 @@ await this.GetCompletionResults( completionResults.Completions[0]); } - [Fact(Skip = "This test does not run correctly on AppVeyor, need to investigate.")] + [Fact] public async Task LanguageServiceCompletesCommandFromModule() { CompletionResults completionResults = @@ -99,9 +102,14 @@ await this.GetCompletionResults( CompleteFilePath.SourceDetails); Assert.NotEqual(0, completionResults.Completions.Length); - Assert.Equal( - CompleteFilePath.ExpectedRange, - completionResults.ReplacedRange); + // TODO: Since this is a path completion, this test will need to be + // platform specific. Probably something like: + // - Windows: C:\Program + // - macOS: /User + // - Linux: /hom + //Assert.Equal( + // CompleteFilePath.ExpectedRange, + // completionResults.ReplacedRange); } [Fact] @@ -166,7 +174,7 @@ await this.GetDefinition( FindsFunctionDefinitionInWorkspace.SourceDetails, new Workspace(this.powerShellContext.LocalPowerShellVersion.Version, Logging.NullLogger) { - WorkspacePath = Path.Combine(baseSharedScriptPath, @"References") + WorkspacePath = Path.Combine(s_baseSharedScriptPath, @"References") }); var definition = definitionResult.FoundDefinition; Assert.EndsWith("ReferenceFileE.ps1", definition.FilePath); @@ -217,9 +225,10 @@ public async Task LanguageServiceFindsReferencesOnCommandWithAlias() await this.GetReferences( FindsReferencesOnBuiltInCommandWithAlias.SourceDetails); - Assert.Equal(6, refsResult.FoundReferences.Count()); - Assert.Equal("Get-ChildItem", refsResult.FoundReferences.Last().SymbolName); - Assert.Equal("ls", refsResult.FoundReferences.ToArray()[1].SymbolName); + SymbolReference[] foundRefs = refsResult.FoundReferences.ToArray(); + Assert.Equal(4, foundRefs.Length); + Assert.Equal("gci", foundRefs[1].SymbolName); + Assert.Equal("Get-ChildItem", foundRefs[foundRefs.Length - 1].SymbolName); } [Fact] @@ -229,10 +238,9 @@ public async Task LanguageServiceFindsReferencesOnAlias() await this.GetReferences( FindsReferencesOnBuiltInCommandWithAlias.SourceDetails); - Assert.Equal(6, refsResult.FoundReferences.Count()); + Assert.Equal(4, refsResult.FoundReferences.Count()); + Assert.Equal("dir", refsResult.FoundReferences.ToArray()[2].SymbolName); Assert.Equal("Get-ChildItem", refsResult.FoundReferences.Last().SymbolName); - Assert.Equal("gci", refsResult.FoundReferences.ToArray()[2].SymbolName); - Assert.Equal("LS", refsResult.FoundReferences.ToArray()[4].SymbolName); } [Fact] @@ -329,7 +337,7 @@ private ScriptFile GetScriptFile(ScriptRegion scriptRegion) { string resolvedPath = Path.Combine( - baseSharedScriptPath, + s_baseSharedScriptPath, scriptRegion.File); return diff --git a/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj b/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj index 7e16604a0..383baffae 100644 --- a/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj +++ b/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj @@ -1,37 +1,33 @@  - - netcoreapp2.0;net452 + netcoreapp2.1;net461 Microsoft.PowerShell.EditorServices.Test - + + true + true + - - - - 6.0.0-alpha13 - - - - + + - - - $(DefineConstants);CoreCLR - - - - - - - + + + + + + + + - + + $(DefineConstants);CoreCLR + diff --git a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs index ef07ae730..dcb0e738a 100644 --- a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs +++ b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs @@ -4,6 +4,7 @@ // using Microsoft.PowerShell.EditorServices.Session; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using System; using System.Collections.Generic; @@ -20,8 +21,8 @@ public class PowerShellContextTests : IDisposable private PowerShellContext powerShellContext; private AsyncQueue stateChangeQueue; - private const string DebugTestFilePath = - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1"; + private static readonly string s_debugTestFilePath = + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Debugging/DebugTest.ps1"); public static readonly HostDetails TestHostDetails = new HostDetails( @@ -36,9 +37,9 @@ public class PowerShellContextTests : IDisposable new ProfilePaths( TestHostDetails.ProfileId, Path.GetFullPath( - @"..\..\..\..\PowerShellEditorServices.Test.Shared\Profile"), + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Profile")), Path.GetFullPath( - @"..\..\..\..\PowerShellEditorServices.Test.Shared")); + TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared"))); public PowerShellContextTests() { @@ -104,7 +105,7 @@ public async Task CanAbortExecution() Task.Run( async () => { - var unusedTask = this.powerShellContext.ExecuteScriptWithArgs(DebugTestFilePath); + var unusedTask = this.powerShellContext.ExecuteScriptWithArgs(s_debugTestFilePath); await Task.Delay(50); this.powerShellContext.AbortExecution(); }); diff --git a/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs b/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs index 2045f6fd5..272c2f533 100644 --- a/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs +++ b/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs @@ -4,6 +4,7 @@ // using Microsoft.PowerShell.EditorServices; +using Microsoft.PowerShell.EditorServices.Test.Shared; using System; using System.IO; using System.Linq; @@ -13,7 +14,12 @@ namespace PSLanguageService.Test { public class ScriptFileChangeTests { - private static readonly Version PowerShellVersion = new Version("5.0"); + +#if CoreCLR + private static readonly Version PowerShellVersion = new Version(6, 1); +#else + private static readonly Version PowerShellVersion = new Version(5, 1); +#endif [Fact] public void CanApplySingleLineInsert() @@ -67,15 +73,15 @@ public void CanApplySingleLineDelete() public void CanApplyMultiLineInsert() { this.AssertFileChange( - "first\r\nsecond\r\nfifth", - "first\r\nsecond\r\nthird\r\nfourth\r\nfifth", + TestUtilities.NormalizeNewlines("first\nsecond\nfifth"), + TestUtilities.NormalizeNewlines("first\nsecond\nthird\nfourth\nfifth"), new FileChange { Line = 3, EndLine = 3, Offset = 1, EndOffset = 1, - InsertString = "third\r\nfourth\r\n" + InsertString = TestUtilities.NormalizeNewlines("third\nfourth\n") }); } @@ -83,15 +89,15 @@ public void CanApplyMultiLineInsert() public void CanApplyMultiLineReplace() { this.AssertFileChange( - "first\r\nsecoXX\r\nXXfth", - "first\r\nsecond\r\nthird\r\nfourth\r\nfifth", + TestUtilities.NormalizeNewlines("first\nsecoXX\nXXfth"), + TestUtilities.NormalizeNewlines("first\nsecond\nthird\nfourth\nfifth"), new FileChange { Line = 2, EndLine = 3, Offset = 5, EndOffset = 3, - InsertString = "nd\r\nthird\r\nfourth\r\nfi" + InsertString = TestUtilities.NormalizeNewlines("nd\nthird\nfourth\nfi") }); } @@ -99,15 +105,15 @@ public void CanApplyMultiLineReplace() public void CanApplyMultiLineReplaceWithRemovedLines() { this.AssertFileChange( - "first\r\nsecoXX\r\nREMOVE\r\nTHESE\r\nLINES\r\nXXfth", - "first\r\nsecond\r\nthird\r\nfourth\r\nfifth", + TestUtilities.NormalizeNewlines("first\nsecoXX\nREMOVE\nTHESE\nLINES\nXXfth"), + TestUtilities.NormalizeNewlines("first\nsecond\nthird\nfourth\nfifth"), new FileChange { Line = 2, EndLine = 6, Offset = 5, EndOffset = 3, - InsertString = "nd\r\nthird\r\nfourth\r\nfi" + InsertString = TestUtilities.NormalizeNewlines("nd\nthird\nfourth\nfi") }); } @@ -115,8 +121,8 @@ public void CanApplyMultiLineReplaceWithRemovedLines() public void CanApplyMultiLineDelete() { this.AssertFileChange( - "first\r\nsecond\r\nREMOVE\r\nTHESE\r\nLINES\r\nthird", - "first\r\nsecond\r\nthird", + TestUtilities.NormalizeNewlines("first\nsecond\nREMOVE\nTHESE\nLINES\nthird"), + TestUtilities.NormalizeNewlines("first\nsecond\nthird"), new FileChange { Line = 3, @@ -130,16 +136,16 @@ public void CanApplyMultiLineDelete() [Fact] public void FindsDotSourcedFiles() { - string exampleScriptContents = - @". .\athing.ps1"+"\r\n"+ - @". .\somefile.ps1"+"\r\n" + - @". .\somefile.ps1"+"\r\n" + - @"Do-Stuff $uri"+"\r\n" + - @". simpleps.ps1"; + string exampleScriptContents = TestUtilities.PlatformNormalize( + ". ./athing.ps1\n"+ + ". ./somefile.ps1\n"+ + ". ./somefile.ps1\n"+ + "Do-Stuff $uri\n"+ + ". simpleps.ps1"); using (StringReader stringReader = new StringReader(exampleScriptContents)) { - ScriptFile scriptFile = + ScriptFile scriptFile = new ScriptFile( "DotSourceTestFile.ps1", "DotSourceTestFile.ps1", @@ -148,7 +154,7 @@ public void FindsDotSourcedFiles() Assert.Equal(3, scriptFile.ReferencedFiles.Length); System.Console.Write("a" + scriptFile.ReferencedFiles[0]); - Assert.Equal(@".\athing.ps1", scriptFile.ReferencedFiles[0]); + Assert.Equal(TestUtilities.NormalizePath("./athing.ps1"), scriptFile.ReferencedFiles[0]); } } @@ -160,8 +166,8 @@ public void ThrowsExceptionWithEditOutsideOfRange() () => { this.AssertFileChange( - "first\r\nsecond\r\nREMOVE\r\nTHESE\r\nLINES\r\nthird", - "first\r\nsecond\r\nthird", + TestUtilities.NormalizeNewlines("first\nsecond\nREMOVE\nTHESE\nLINES\nthird"), + TestUtilities.NormalizeNewlines("first\nsecond\nthird"), new FileChange { Line = 3, @@ -178,7 +184,7 @@ internal static ScriptFile CreateScriptFile(string initialString) using (StringReader stringReader = new StringReader(initialString)) { // Create an in-memory file from the StringReader - ScriptFile fileToChange = + ScriptFile fileToChange = new ScriptFile( "TestFile.ps1", "TestFile.ps1", @@ -207,17 +213,17 @@ public class ScriptFileGetLinesTests { private ScriptFile scriptFile; - private const string TestString = "Line One\r\nLine Two\r\nLine Three\r\nLine Four\r\nLine Five"; + private static readonly string TestString = TestUtilities.NormalizeNewlines("Line One\nLine Two\nLine Three\nLine Four\nLine Five"); private readonly string[] TestStringLines = TestString.Split( - new string[] { "\r\n" }, + new string[] { Environment.NewLine }, StringSplitOptions.None); public ScriptFileGetLinesTests() { this.scriptFile = ScriptFileChangeTests.CreateScriptFile( - "Line One\r\nLine Two\r\nLine Three\r\nLine Four\r\nLine Five\r\n"); + TestUtilities.NormalizeNewlines("Line One\nLine Two\nLine Three\nLine Four\nLine Five\n")); } [Fact] diff --git a/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs b/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs index d40e59511..6322d9c3e 100644 --- a/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs +++ b/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using Xunit; @@ -17,31 +18,34 @@ public class WorkspaceTests [Fact] public void CanResolveWorkspaceRelativePath() { - string workspacePath = @"c:\Test\Workspace\"; - string testPathInside = @"c:\Test\Workspace\SubFolder\FilePath.ps1"; - string testPathOutside = @"c:\Test\PeerPath\FilePath.ps1"; - string testPathAnotherDrive = @"z:\TryAndFindMe\FilePath.ps1"; + string workspacePath = TestUtilities.NormalizePath("c:/Test/Workspace/"); + string testPathInside = TestUtilities.NormalizePath("c:/Test/Workspace/SubFolder/FilePath.ps1"); + string testPathOutside = TestUtilities.NormalizePath("c:/Test/PeerPath/FilePath.ps1"); + string testPathAnotherDrive = TestUtilities.NormalizePath("z:/TryAndFindMe/FilePath.ps1"); Workspace workspace = new Workspace(PowerShellVersion, Logging.NullLogger); // Test without a workspace path Assert.Equal(testPathOutside, workspace.GetRelativePath(testPathOutside)); + string expectedInsidePath = TestUtilities.NormalizePath("SubFolder/FilePath.ps1"); + string expectedOutsidePath = TestUtilities.NormalizePath("../PeerPath/FilePath.ps1"); + // Test with a workspace path workspace.WorkspacePath = workspacePath; - Assert.Equal(@"SubFolder\FilePath.ps1", workspace.GetRelativePath(testPathInside)); - Assert.Equal(@"..\PeerPath\FilePath.ps1", workspace.GetRelativePath(testPathOutside)); + Assert.Equal(expectedInsidePath, workspace.GetRelativePath(testPathInside)); + Assert.Equal(expectedOutsidePath, workspace.GetRelativePath(testPathOutside)); Assert.Equal(testPathAnotherDrive, workspace.GetRelativePath(testPathAnotherDrive)); } [Fact] public void CanDetermineIsPathInMemory() { - var tempDir = Environment.GetEnvironmentVariable("TEMP"); - var shortDirPath = Path.Combine(tempDir, "GitHub", "PowerShellEditorServices"); - var shortFilePath = Path.Combine(shortDirPath, "foo.ps1"); - var shortUriForm = "git:/c%3A/Users/Keith/GitHub/dahlbyk/posh-git/src/PoshGitTypes.ps1?%7B%22path%22%3A%22c%3A%5C%5CUsers%5C%5CKeith%5C%5CGitHub%5C%5Cdahlbyk%5C%5Cposh-git%5C%5Csrc%5C%5CPoshGitTypes.ps1%22%2C%22ref%22%3A%22~%22%7D"; - var longUriForm = "gitlens-git:c%3A%5CUsers%5CKeith%5CGitHub%5Cdahlbyk%5Cposh-git%5Csrc%5CPoshGitTypes%3Ae0022701.ps1?%7B%22fileName%22%3A%22src%2FPoshGitTypes.ps1%22%2C%22repoPath%22%3A%22c%3A%2FUsers%2FKeith%2FGitHub%2Fdahlbyk%2Fposh-git%22%2C%22sha%22%3A%22e0022701fa12e0bc22d0458673d6443c942b974a%22%7D"; + string tempDir = Path.GetTempPath(); + string shortDirPath = Path.Combine(tempDir, "GitHub", "PowerShellEditorServices"); + string shortFilePath = Path.Combine(shortDirPath, "foo.ps1"); + string shortUriForm = "git:/c%3A/Users/Keith/GitHub/dahlbyk/posh-git/src/PoshGitTypes.ps1?%7B%22path%22%3A%22c%3A%5C%5CUsers%5C%5CKeith%5C%5CGitHub%5C%5Cdahlbyk%5C%5Cposh-git%5C%5Csrc%5C%5CPoshGitTypes.ps1%22%2C%22ref%22%3A%22~%22%7D"; + string longUriForm = "gitlens-git:c%3A%5CUsers%5CKeith%5CGitHub%5Cdahlbyk%5Cposh-git%5Csrc%5CPoshGitTypes%3Ae0022701.ps1?%7B%22fileName%22%3A%22src%2FPoshGitTypes.ps1%22%2C%22repoPath%22%3A%22c%3A%2FUsers%2FKeith%2FGitHub%2Fdahlbyk%2Fposh-git%22%2C%22sha%22%3A%22e0022701fa12e0bc22d0458673d6443c942b974a%22%7D"; var testCases = new[] { // Test short file absolute paths @@ -52,7 +56,7 @@ public void CanDetermineIsPathInMemory() // Test short file relative paths - not sure we'll ever get these but just in case new { IsInMemory = false, Path = "foo.ps1" }, - new { IsInMemory = false, Path = ".." + Path.DirectorySeparatorChar + "foo.ps1" }, + new { IsInMemory = false, Path = Path.Combine(new [] { "..", "foo.ps1" }) }, // Test short non-file paths new { IsInMemory = true, Path = "untitled:untitled-1" }, diff --git a/test/PowerShellEditorServices.Test/Utility/AsyncDebouncerTests.cs b/test/PowerShellEditorServices.Test/Utility/AsyncDebouncerTests.cs index c87d2e43b..443dc1ba1 100644 --- a/test/PowerShellEditorServices.Test/Utility/AsyncDebouncerTests.cs +++ b/test/PowerShellEditorServices.Test/Utility/AsyncDebouncerTests.cs @@ -14,7 +14,7 @@ namespace Microsoft.PowerShell.EditorServices.Test.Utility { public class AsyncDebouncerTests { - [Fact(Skip = "TODO: This test fails in the new build system, need to investigate!")] + [Fact(Skip = "AsyncDebouncer not flushing within the interval")] public async Task AsyncDebouncerFlushesAfterInterval() { TestAsyncDebouncer debouncer = new TestAsyncDebouncer(); @@ -31,7 +31,7 @@ public async Task AsyncDebouncerFlushesAfterInterval() Assert.Equal(new List { 1, 2, 3 }, debouncer.FlushedBuffer); Assert.True( - debouncer.TimeToFlush > + debouncer.TimeToFlush > TimeSpan.FromMilliseconds(TestAsyncDebouncer.Interval), "Debouncer flushed before interval lapsed."); @@ -40,7 +40,7 @@ public async Task AsyncDebouncerFlushesAfterInterval() Assert.Equal(new List { 4, 5, 6 }, debouncer.FlushedBuffer); } - [Fact(Skip = "TODO: This test fails in the new build system, need to investigate!")] + [Fact] public async Task AsyncDebouncerRestartsAfterInvoke() { TestAsyncRestartDebouncer debouncer = new TestAsyncRestartDebouncer(); diff --git a/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs b/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs index cdb2e2237..ca0558a54 100644 --- a/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs +++ b/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using Microsoft.PowerShell.EditorServices.Test.Shared; using Microsoft.PowerShell.EditorServices.Utility; using System; using System.IO; @@ -128,7 +129,7 @@ private string ReadLogContents() { return string.Join( - "\r\n", + Environment.NewLine, File.ReadAllLines( logFilePath, Encoding.UTF8));