Skip to content
Open
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
146 changes: 146 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Copilot Instructions for PowerShell Editor Services

## Build & Test

Requires .NET SDK 8.0+. Use `dotnet` directly for building and testing — it's faster and
requires no extra tooling. The `Invoke-Build` script requires the `InvokeBuild` and `platyPS`
PowerShell modules (platyPS is `#Requires`'d at the top, so the whole script fails without it),
and is mainly needed to assemble the full PowerShell module for release.

```powershell
# Build (run both; Hosting depends on the core library)
dotnet publish src/PowerShellEditorServices/PowerShellEditorServices.csproj -f netstandard2.0
dotnet publish src/PowerShellEditorServices.Hosting/PowerShellEditorServices.Hosting.csproj -f net8.0

# Run all unit tests
dotnet test test/PowerShellEditorServices.Test/ --framework net8.0

# Run a single test by name
dotnet test test/PowerShellEditorServices.Test/ --framework net8.0 --filter "FullyQualifiedName~CompletesCommandInFile"

# Run tests by trait category
dotnet test test/PowerShellEditorServices.Test/ --framework net8.0 --filter "Category=Completions"

# Run E2E tests
dotnet test test/PowerShellEditorServices.Test.E2E/ --framework net8.0
```

For assembling the full module or running the complete CI suite (including Windows PowerShell
5.1 targets), use `Invoke-Build` with the `InvokeBuild` and `platyPS` modules installed:

```powershell
Invoke-Build Build # full build + module assembly + help generation
Invoke-Build TestPS74 # unit tests via build script
Invoke-Build TestE2EPwsh # E2E tests via build script
Invoke-Build Build -Configuration Release # required before PRs (enforces XML doc comments)
```

`src/PowerShellEditorServices.Hosting/BuildInfo.cs` is auto-generated by the build script and
git-ignored for changes. Do not edit it manually.

## Architecture

PowerShell Editor Services (PSES) is a **Language Server Protocol (LSP)** and **Debug Adapter
Protocol (DAP)** server for PowerShell, consumed by VS Code and other editors.

### Projects

- **`src/PowerShellEditorServices`** (`netstandard2.0`) — Core library containing all LSP/DAP
handlers, services, and the PowerShell execution engine. Namespace:
`Microsoft.PowerShell.EditorServices`.
- **`src/PowerShellEditorServices.Hosting`** (`net8.0`, `net462`) — Entry point layer that loads
PSES into a PowerShell process via `StartEditorServicesCommand`. Uses a custom
`AssemblyLoadContext` (`PsesLoadContext`) on .NET Core to isolate dependencies.
- **`module/PowerShellEditorServices/`** — The shipped PowerShell module. The build assembles
compiled binaries into `bin/Core/` (net8.0) and `bin/Desktop/` (net462). The module manifest
loads the appropriate DLL based on PowerShell edition.

### Key Services (registered in `PsesServiceCollectionExtensions`)

- **`PsesInternalHost`** — The central PowerShell execution host. Also implements
`IRunspaceContext` and `IInternalPowerShellExecutionService`.
- **`WorkspaceService`** — Manages open documents and workspace files.
- **`SymbolsService`** — Provides symbol navigation (go-to-definition, find references).
- **`AnalysisService`** — Integrates PSScriptAnalyzer for real-time diagnostics.
- **`ConfigurationService`** — Manages editor/client settings.
- **`ExtensionService`** — Supports the `$psEditor` API for editor extensions.

### LSP/DAP Handler Pattern

Handlers live under `Services/<Feature>/Handlers/` and follow a consistent pattern:

- Class name: `Pses<Feature>Handler`, marked `internal`
- Inherits from an OmniSharp base class (e.g., `CompletionHandlerBase`, `HoverHandlerBase`)
- Dependencies injected via constructor (`ILoggerFactory`, services)
- Overrides `CreateRegistrationOptions()` and `Handle()`
- Uses `LspUtils.PowerShellDocumentSelector` for document registration

### Server Setup

- `PsesLanguageServer` — Configures and runs the LSP server using OmniSharp
- `PsesDebugServer` — Configures and runs the DAP server
- Both use `Microsoft.Extensions.DependencyInjection` for service registration

## Conventions

### C# Style

- All files require the copyright header: `// Copyright (c) Microsoft Corporation.` /
`// Licensed under the MIT License.`
- `.editorconfig` enforces many rules as **errors**, including unused variables, async/threading
rules (`VSTHRD*`), and modern C# idioms (pattern matching, null checks, expression bodies).
- Roslynator analyzers are enabled for formatting and code quality.
- Use `Microsoft.Extensions.Logging` (`ILogger<T>` via `ILoggerFactory`) for all logging.

### Testing

- **Framework:** xUnit with `Xunit.SkippableFact` for conditionally skipped tests.
- **Host setup:** Use `PsesHostFactory.Create(loggerFactory)` to get an isolated
`PsesInternalHost` for testing. Tests implement `IAsyncLifetime` for async setup/teardown.
- **Traits:** Tests use `[Trait("Category", "...")]` for filtering (e.g., `"Completions"`,
`"Symbols"`).
- **Fixtures:** Test PowerShell scripts live in `test/PowerShellEditorServices.Test/Fixtures/`.
- **E2E tests** are in a separate project (`PowerShellEditorServices.Test.E2E`) and test the
full LSP client-server interaction.

### Multi-targeting

The core library targets `netstandard2.0` for compatibility with both .NET Core and .NET
Framework. The hosting project and tests dual-target `net8.0` and `net462` (Windows PowerShell
5.1). Non-Windows platforms skip `net462` targets.

## Pull Request Labels

Every pull request **must** be labeled before it is opened so it is triaged
correctly and lands in the right changelog section.

Each PR requires:

- **At least one `Area-*` label** describing the part of the codebase it touches
(e.g. `Area-Debugging`, `Area-Language Server`, `Area-Workspaces`,
`Area-Documentation`). This is used for triage and filtering.
- **Exactly one `Issue-*` label** describing the kind of change:
- `Issue-Bug` — a bug fix.
- `Issue-Enhancement` — a new feature or changed behavior.
- `Issue-Performance` — a performance improvement.

The `Issue-*` label is not optional: GitHub's auto-generated release notes use it
to pick the changelog category. See [`.github/release.yml`](./release.yml) for the
authoritative mapping (`Issue-Enhancement` → "Enhancements & Features ✨",
`Issue-Bug` → "Squashed Bugs 🐛"). Any PR **without** an `Issue-*` label falls
through the `"*"` catch-all into "Other Changes 🙏" and is silently
miscategorized, so always set one correctly.
Comment on lines +122 to +132

Additionally:

- Add the relevant **`OS-*` label** (`OS-Windows`, `OS-macOS`, `OS-Linux`) when a
change is platform-specific.
- Use the **`Ignore`** label only for changes that should be excluded from the
release notes entirely (e.g. pure CI, test, or docs chores the maintainers do
not want in the changelog). `.github/release.yml` excludes this label from the
changelog.

The full, authoritative set of labels drifts over time — do not hard-code it
here. List the current labels with `gh label list --repo PowerShell/PowerShellEditorServices`
or the repo's [Labels page](https://github.com/PowerShell/PowerShellEditorServices/labels)
and pick the closest matches.
Loading