Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: "Copilot Setup Steps"

# Allow testing of the setup steps from your repository's "Actions" tab.
on:
workflow_dispatch:

pull_request:
branches:
- master
paths:
- ".github/workflows/copilot-setup-steps.yml"

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
# See https://docs.github.com/en/copilot/customizing-copilot/customizing-the-development-environment-for-copilot-coding-agent
copilot-setup-steps:
runs-on: ubuntu-latest

permissions:
contents: read

# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 1000

- name: Bootstrap
if: success()
run: |-
$title = 'Import Build.psm1'
Write-Host "::group::$title"
Import-Module ./build.psm1 -Verbose -ErrorAction Stop
Write-LogGroupEnd -Title $title

$title = 'Switch to public feed'
Write-LogGroupStart -Title $title
Switch-PSNugetConfig -Source Public
Write-LogGroupEnd -Title $title

$title = 'Bootstrap'
Write-LogGroupStart -Title $title
Start-PSBootstrap -Scenario DotNet
Write-LogGroupEnd -Title $title

$title = 'Install .NET Tools'
Write-LogGroupStart -Title $title
Start-PSBootstrap -Scenario Tools
Write-LogGroupEnd -Title $title

$title = 'Sync Tags'
Write-LogGroupStart -Title $title
Sync-PSTags -AddRemoteIfMissing
Write-LogGroupEnd -Title $title

$title = 'Setup .NET environment variables'
Write-LogGroupStart -Title $title
Find-DotNet -SetDotnetRoot
Write-LogGroupEnd -Title $title
shell: pwsh
4 changes: 4 additions & 0 deletions .globalconfig
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,10 @@ dotnet_diagnostic.CA2016.severity = suggestion
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2021
dotnet_diagnostic.CA2021.severity = warning

# CA2022: Avoid inexact read with 'Stream.Read'
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022
dotnet_diagnostic.CA2022.severity = warning

# CA2100: Review SQL queries for security vulnerabilities
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100
dotnet_diagnostic.CA2100.severity = none
Expand Down
106 changes: 98 additions & 8 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2282,7 +2282,12 @@ function Start-PSBootstrap {
[switch]$BuildLinuxArm,
[switch]$Force,
[Parameter(Mandatory = $true)]
[ValidateSet("Package", "DotNet", "Both")]
# Package: Install dependencies for packaging tools (fpm, rpmbuild, WiX)
# DotNet: Install the .NET SDK
# Both: Package and DotNet scenarios
# Tools: Install .NET global tools (e.g., dotnet-format)
# All: Install all dependencies (packaging, .NET SDK, and tools)
[ValidateSet("Package", "DotNet", "Both", "Tools", "All")]
[string]$Scenario = "Package"
)

Expand Down Expand Up @@ -2402,15 +2407,15 @@ function Start-PSBootstrap {

# Install [fpm](https://github.com/jordansissel/fpm)
# Note: fpm is now only needed for DEB and macOS packages; RPM packages use rpmbuild directly
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') {
if ($Scenario -in 'All', 'Both', 'Package') {
# Install fpm on Debian-based systems, macOS, and Mariner (where DEB packages are built)
if (($environment.IsLinux -and ($environment.IsDebianFamily -or $environment.IsMariner)) -or $environment.IsMacOS) {
Install-GlobalGem -Sudo $sudo -GemName "dotenv" -GemVersion "2.8.1"
Install-GlobalGem -Sudo $sudo -GemName "ffi" -GemVersion "1.16.3"
Install-GlobalGem -Sudo $sudo -GemName "fpm" -GemVersion "1.15.1"
Install-GlobalGem -Sudo $sudo -GemName "rexml" -GemVersion "3.2.5"
}

# For RPM-based systems, ensure rpmbuild is available
if ($environment.IsLinux -and ($environment.IsRedHatFamily -or $environment.IsSUSEFamily -or $environment.IsMariner)) {
Write-Verbose -Verbose "Checking for rpmbuild..."
Expand All @@ -2422,7 +2427,7 @@ function Start-PSBootstrap {
}
}

if ($Scenario -eq 'DotNet' -or $Scenario -eq 'Both') {
if ($Scenario -in 'All', 'Both', 'DotNet') {

Write-Verbose -Verbose "Calling Find-Dotnet from Start-PSBootstrap"

Expand Down Expand Up @@ -2479,6 +2484,19 @@ function Start-PSBootstrap {
}
}

if ($Scenario -in 'All', 'Tools') {
Write-Log -message "Installing .NET global tools"

# Ensure dotnet is available
Find-Dotnet

# Install dotnet-format
Write-Verbose -Verbose "Installing dotnet-format global tool"
Start-NativeExecution {
dotnet tool install --global dotnet-format
}
}

if ($env:TF_BUILD) {
Write-Verbose -Verbose "--- Start - Capturing nuget sources"
dotnet nuget list source --format detailed
Expand Down Expand Up @@ -2646,6 +2664,63 @@ function Start-ResGen
}
}

function Add-PSEnvironmentPath {
<#
.SYNOPSIS
Adds a path to the process PATH and persists to GitHub Actions workflow if running in GitHub Actions
.PARAMETER Path
Path to add to PATH
.PARAMETER Prepend
If specified, prepends the path instead of appending
#>
param (
[Parameter(Mandatory)]
[string]$Path,

[switch]$Prepend
)

# Set in current process
if ($Prepend) {
$env:PATH = $Path + [IO.Path]::PathSeparator + $env:PATH
} else {
$env:PATH += [IO.Path]::PathSeparator + $Path
}

# Persist to GitHub Actions workflow if running in GitHub Actions
if ($env:GITHUB_ACTIONS -eq 'true') {
Write-Verbose -Verbose "Adding $Path to GITHUB_PATH"
Add-Content -Path $env:GITHUB_PATH -Value $Path
}
}

function Set-PSEnvironmentVariable {
<#
.SYNOPSIS
Sets an environment variable in the process and persists to GitHub Actions workflow if running in GitHub Actions
.PARAMETER Name
The name of the environment variable
.PARAMETER Value
The value of the environment variable
#>
param (
[Parameter(Mandatory)]
[string]$Name,

[Parameter(Mandatory)]
[string]$Value
)

# Set in current process
Set-Item -Path "env:$Name" -Value $Value

# Persist to GitHub Actions workflow if running in GitHub Actions
if ($env:GITHUB_ACTIONS -eq 'true') {
Write-Verbose -Verbose "Setting $Name in GITHUB_ENV"
Add-Content -Path $env:GITHUB_ENV -Value "$Name=$Value"
}
}

function Find-Dotnet {
param (
[switch] $SetDotnetRoot
Expand Down Expand Up @@ -2676,25 +2751,40 @@ function Find-Dotnet {
if ($dotnetCLIInstalledVersion -ne $chosenDotNetVersion) {
Write-Warning "The 'dotnet' in the current path can't find SDK version ${dotnetCLIRequiredVersion}, prepending $dotnetPath to PATH."
# Globally installed dotnet doesn't have the required SDK version, prepend the user local dotnet location
$env:PATH = $dotnetPath + [IO.Path]::PathSeparator + $env:PATH
Add-PSEnvironmentPath -Path $dotnetPath -Prepend

if ($SetDotnetRoot) {
Write-Verbose -Verbose "Setting DOTNET_ROOT to $dotnetPath"
$env:DOTNET_ROOT = $dotnetPath
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
} elseif ($SetDotnetRoot) {
Write-Verbose -Verbose "Expected dotnet version found, setting DOTNET_ROOT to $dotnetPath"
$env:DOTNET_ROOT = $dotnetPath
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
}
else {
Write-Warning "Could not find 'dotnet', appending $dotnetPath to PATH."
$env:PATH += [IO.Path]::PathSeparator + $dotnetPath
Add-PSEnvironmentPath -Path $dotnetPath

if ($SetDotnetRoot) {
Write-Verbose -Verbose "Setting DOTNET_ROOT to $dotnetPath"
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
}

if (-not (precheck 'dotnet' "Still could not find 'dotnet', restoring PATH.")) {
# Give up, restore original PATH. There is nothing to persist since we didn't make a change.
$env:PATH = $originalPath
}
elseif ($SetDotnetRoot) {
# If we found dotnet, also add the global tools path to PATH
# Add .NET global tools to PATH when setting up the environment
$dotnetToolsPath = Join-Path $dotnetPath "tools"
if (Test-Path $dotnetToolsPath) {
Write-Verbose -Verbose "Adding .NET tools path to PATH: $dotnetToolsPath"
Add-PSEnvironmentPath -Path $dotnetToolsPath
}
}
}

<#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4580,8 +4580,8 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext
return CommandCompletion.EmptyCompletionResult;
}

var lastAst = context.RelatedAsts[^1];
if (lastAst.Parent is UsingStatementAst usingStatement
var lastAst = context.RelatedAsts?[^1];
if (lastAst?.Parent is UsingStatementAst usingStatement
&& usingStatement.UsingStatementKind is UsingStatementKind.Module or UsingStatementKind.Assembly
&& lastAst.Extent.File is not null)
{
Expand Down
23 changes: 23 additions & 0 deletions test/powershell/Host/TabCompletion/BugFix.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,27 @@ Describe "Tab completion bug fix" -Tags "CI" {
$Runspace.Dispose()
}
}

It "Issue#26277 - [CompletionCompleters]::CompleteFilename('') should work" {
$testDir = Join-Path $TestDrive "TempTestDir"
$file1 = Join-Path $testDir "abc.ps1"
$file2 = Join-Path $testDir "def.py"

New-Item -ItemType Directory -Path $testDir > $null
New-Item -ItemType File -Path $file1 > $null
New-Item -ItemType File -Path $file2 > $null

try {
Push-Location -Path $testDir
$result = [System.Management.Automation.CompletionCompleters]::CompleteFilename("")
$result | Should -Not -Be $null
$result | Measure-Object | ForEach-Object -MemberName Count | Should -Be 2

$item1, $item2 = @($result)
$item1.ListItemText | Should -BeExactly 'abc.ps1'
$item2.ListItemText | Should -BeExactly 'def.py'
} finally {
Pop-Location
}
}
}