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
32 changes: 13 additions & 19 deletions src/roslyn/.github/skills/snap/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ Identify the three named branches (`main`, `release/insiders`, `release/stable`)

**Step B — Read versions and configs** from all three branches:
- Fetch `eng/Versions.props` from each branch to get the current version.
- For roslyn: VS version = `Major + 13`.`Minor` (e.g., Roslyn 5.6 → VS 18.6).
- For roslyn: read `<MajorVersion>` and `<MinorVersion>`. `<VsMajorVersion>` is derived as Roslyn `MajorVersion + 13`, and `<VsMinorVersion>` is derived from Roslyn `<MinorVersion>` (e.g., Roslyn 5.6 → VS 18.6).
- Razor versions are also in `eng/Versions.props` (same file as Roslyn's version), using `Razor`-prefixed property names. Razor has **two independent versions**:
- **Razor VSIX/Addin version**: use `<RazorVsixVersionPrefix>` directly (e.g., `18.8.1`). Tracks the Visual Studio version like the rest of the snap cascade. `<RazorAddinMajorVersion>` tracks the major.minor (e.g., `18.8`).
- **Razor VSIX/Addin version**: `<RazorVsixVersionPrefix>` and `<RazorAddinMajorVersion>` are derived from the shared `VsMajorVersion`/`VsMinorVersion` properties. They track the Visual Studio version like the rest of the snap cascade.
- **Razor SDK version**: read `<RazorMajorVersion>` and `<RazorMinorVersion>` (e.g., `10.4`). Tracks the **.NET SDK band** Razor ships into, **not** the VS version. The mapping is `.NET <Major>.0.<Band>xx SDK` <-> Razor `<Major>.<Band>` (e.g., `.NET 10.0.4xx SDK` <-> Razor `10.4`, `.NET 11.0.1xx SDK` <-> Razor `11.1`).
- Note: `src/Razor/Directory.Build.props` maps these `Razor`-prefixed properties to the standard MSBuild properties (`MajorVersion`, `MinorVersion`, etc.) for Razor projects. During a snap, only edit `eng/Versions.props` — the Razor props file should not need changes.
- Fetch `eng/config/PublishData.json` from each branch to get insertion config (`vsBranch`, `insertionCreateDraftPR`, `insertionTitlePrefix`).
Expand All @@ -91,7 +91,7 @@ Identify the three named branches (`main`, `release/insiders`, `release/stable`)
- Among those, locate the channel whose major matches the branch's current Razor `RazorMajorVersion`. If multiple channels of the same major are temporarily assigned (e.g., both `.NET 10.0.4xx SDK` and `.NET 10.0.5xx SDK`), pick the **lowest** band -- Razor is versioned to the lowest SDK band it ships into, since higher bands roll forward and can consume the same package.
- Apply the mapping `.NET <Major>.0.<Band>xx SDK` -> expected Razor `<Major>.<Band>`.
- If no matching SDK channel exists for that branch (common on `main` immediately after a previous snap, before the next SDK band channel has been created), record the branch as "no matching SDK channel -- Razor SDK version bump deferred".
- If the expected version differs from the branch's current `RazorMajorVersion.RazorMinorVersion`, flag it as a drift to fix (during snap, see Phase 2 step 5b; during follow-up, see Phase 3 step 3.9).
- If the expected version differs from the branch's current `RazorMajorVersion.RazorMinorVersion`, flag it as a drift to fix (during snap, see Phase 2 step 5; during follow-up, see Phase 3 step 3.9).

**Step C — Infer the snap cascade** from the discovered state:
- The snap version is whatever `main` currently targets (e.g., 18.6).
Expand Down Expand Up @@ -258,15 +258,11 @@ After gathering, present **all** planned actions in a numbered list for the user

3. **Update `PublishData.json` on `main`**: Set `insertionCreateDraftPR` to `true`. Until the snapped version's scheduled VS `main` → `rel/insiders` snap, main's insertions should be drafts to avoid merging into the wrong VS branch. This change goes in the same PR as the version bump.

4. **Update `Versions.props` on `main`**: Bump the minor version (e.g., 5.6.0 → 5.7.0) and reset `PreReleaseVersionLabel` to `1`.
4. **Update `Versions.props` on `main`**: Bump the Roslyn minor version (e.g., 5.6.0 → 5.7.0) and reset `PreReleaseVersionLabel` to `1`. This automatically advances `VsMajorVersion`/`VsMinorVersion` and the derived Razor VSIX/Addin and EditorConfig component versions. Do not edit those derived properties.

5. **Update Razor versions in `eng/Versions.props`** (roslyn only) -- Razor has two independent versions, both stored as `Razor`-prefixed properties in `eng/Versions.props`:

**5a. Razor VSIX/Addin version**: bump `<RazorVsixVersionPrefix>` and `<RazorAddinMajorVersion>` minor to track the new VS version (e.g., `18.7.1` -> `18.8.1`, `18.7` -> `18.8`). Always done as part of the snap.

**5b. Razor SDK version**: only update if the branch's SDK default-channel doesn't match the current `<RazorMajorVersion>.<RazorMinorVersion>`. Use the discovery from Phase 1 / Step B.1:
5. **Update the Razor SDK version in `eng/Versions.props`** (roslyn only): Only update if the branch's SDK default-channel doesn't match the current `<RazorMajorVersion>.<RazorMinorVersion>`. Use the discovery from Phase 1 / Step B.1:
- If `main` flows to `.NET <Major>.0.<Band>xx SDK` and `<Major>.<Band>` differs from the current `<RazorMajorVersion>.<RazorMinorVersion>` in `eng/Versions.props`, set `<RazorMajorVersion>` and `<RazorMinorVersion>` to match (e.g., `.NET 10.0.4xx SDK` -> `<RazorMajorVersion>10</RazorMajorVersion>`, `<RazorMinorVersion>4</RazorMinorVersion>`). Leave `<RazorPatchVersion>` as `0`.
- If no SDK channel matching Razor's current major exists on `main` yet (the next SDK band channel hasn't been created), **skip 5b** and add it to the post-VS-snap follow-up (step 3.9). Do **not** predict the next band -- only update when darc confirms the channel.
- If no SDK channel matching Razor's current major exists on `main` yet (the next SDK band channel hasn't been created), **skip this update** and add it to the post-VS-snap follow-up (step 3.9). Do **not** predict the next band -- only update when darc confirms the channel.

6. **Update SARIF files** (roslyn only): Replace old version string with new version in all `.sarif` files under `src/RoslynAnalyzers/` (search recursively).

Expand Down Expand Up @@ -517,16 +513,14 @@ Find them with `git ls-files 'src/RoslynAnalyzers/**/*.sarif'` or search via the

These SARIF files are generated and intentionally have no final newline. Perform a byte-preserving replacement: keep the existing encoding, BOM, line endings, and EOF state exactly. Do not deserialize/reserialize the JSON or append a newline. The correctness build regenerates these files and fails if any non-version bytes differ.

**Razor versions in `eng/Versions.props`**: Two independent sets of edits in the Razor PropertyGroups. Read the current file, perform both replacements in memory, then PUT the new content back via the GitHub API.
**Version properties in `eng/Versions.props`**: Update source properties and leave derived properties unchanged. Read the current file, perform the required replacements in memory, then PUT the new content back via the GitHub API.

- **5a. VSIX/Addin version** -- bump the VS version (always done):
- `<RazorVsixVersionPrefix>{oldMajor.Minor}.1</RazorVsixVersionPrefix>` -> `<RazorVsixVersionPrefix>{newMajor.Minor}.1</RazorVsixVersionPrefix>` (e.g., `18.7.1` -> `18.8.1`)
- `<RazorAddinMajorVersion>{oldMajor.Minor}</RazorAddinMajorVersion>` -> `<RazorAddinMajorVersion>{newMajor.Minor}</RazorAddinMajorVersion>` (e.g., `18.7` -> `18.8`)
- **5b. SDK RazorMajorVersion/RazorMinorVersion** -- only if the matching SDK channel exists on `main` and differs from the current value (see Phase 1 / Step B.1):
- **Roslyn/VS version** -- bump `<MinorVersion>` and reset `<PreReleaseVersionLabel>` to `1`. `VsMajorVersion`, `VsMinorVersion`, `RazorVsixVersionPrefix`, `RazorAddinMajorVersion`, `EditorConfigVersionPrefix`, and `EditorConfigAssemblyVersion` are derived and must not be edited during a snap. Verify that they evaluate to the new VS train after the Roslyn bump.
- **SDK RazorMajorVersion/RazorMinorVersion** -- only if the matching SDK channel exists on `main` and differs from the current value (see Phase 1 / Step B.1):
- `<RazorMajorVersion>{old}</RazorMajorVersion>` -> `<RazorMajorVersion>{newSdkMajor}</RazorMajorVersion>` (only changes when crossing .NET majors, e.g., 10 -> 11)
- `<RazorMinorVersion>{old}</RazorMinorVersion>` -> `<RazorMinorVersion>{newSdkBand}</RazorMinorVersion>` (e.g., `0` -> `4` when `main` flows to `.NET 10.0.4xx SDK`)
- Leave `<RazorPatchVersion>0</RazorPatchVersion>` and `<RazorPreReleaseVersionLabel>` untouched.
- If no matching SDK channel exists on `main` yet (the next SDK band hasn't been created), **omit 5b from this PR** and add it to the post-VS-snap follow-up (Step 3.9).
- If no matching SDK channel exists on `main` yet (the next SDK band hasn't been created), omit this update from the PR and add it to the post-VS-snap follow-up (Step 3.9).

#### 3.6 Update darc default channels and subscriptions

Expand Down Expand Up @@ -727,9 +721,9 @@ In the PR body/description, include a brief note such as `Auto-generated by snap

Also handle any pending SDK channel follow-ups (e.g., adding `main` to a newly created `.NET 10.0.Nxx SDK` channel).

**Deferred Razor SDK version bump** (roslyn only): If the Razor SDK version bump (Phase 2 step 5b) was deferred during the initial snap because no matching `.NET <Razor.RazorMajorVersion>.0.<Band>xx SDK` channel existed on `main` at the time, re-check now:
**Deferred Razor SDK version bump** (roslyn only): If the Razor SDK version bump (Phase 2 step 5) was deferred during the initial snap because no matching `.NET <Razor.RazorMajorVersion>.0.<Band>xx SDK` channel existed on `main` at the time, re-check now:
- Re-query darc default-channels for `main` (`darc get-default-channels --source-repo https://github.com/{owner}/{repo} --branch main`).
- If a `.NET <Major>.0.<Band>xx SDK` channel matching the current `<RazorMajorVersion>` is now present on `main` and `<Band>` differs from the current `<RazorMinorVersion>` in `eng/Versions.props`, include the `<RazorMajorVersion>`/`<RazorMinorVersion>` edit in this same post-VS-snap follow-up PR (using the same edit pattern as Step 3.5 / 5b).
- If a `.NET <Major>.0.<Band>xx SDK` channel matching the current `<RazorMajorVersion>` is now present on `main` and `<Band>` differs from the current `<RazorMinorVersion>` in `eng/Versions.props`, include the `<RazorMajorVersion>`/`<RazorMinorVersion>` edit in this same post-VS-snap follow-up PR (using the same edit pattern as Step 3.5).
- If still no matching SDK channel exists on `main`, leave Razor unchanged -- the bump waits for the next opportunity (i.e., when the channel is added).

Remind the user of the exact schedule-derived follow-up date when finishing the snap, and pick this step up when the user resumes this session.
Expand All @@ -744,7 +738,7 @@ After completing the snap, review whether any steps needed to be done differentl
|---------|---------|---------|
| Roslyn version | `Major.Minor.Patch` | `5.6.0` |
| VS version (from roslyn) | `(Major+13).(Minor)` | `18.6` |
| VS version (from razor RazorVsixVersionPrefix) | Same as RazorVsixVersionPrefix major.minor | `18.6` |
| Razor VSIX/Addin version | Derived from `VsMajorVersion.VsMinorVersion` | `18.6` |
| Razor SDK version | `<RazorMajorVersion>.<RazorMinorVersion>` from `eng/Versions.props` | `10.4` |
| Razor SDK <-> .NET SDK channel | `Razor X.Y` <-> `.NET X.0.Yxx SDK` | `Razor 10.4` <-> `.NET 10.0.4xx SDK` |
| Named branches | `main` → `release/insiders` → `release/stable` | cascade order |
Expand Down
18 changes: 16 additions & 2 deletions src/roslyn/eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,29 @@
<RazorAssemblyVersion>$(RazorMajorVersion).$(RazorMinorVersion).0.0</RazorAssemblyVersion>
</PropertyGroup>

<!-- Visual Studio train version (used to version VS components that ship out-of-band from Roslyn/Razor) -->
<PropertyGroup>
<VsMajorVersion>$([MSBuild]::Add($(MajorVersion), 13))</VsMajorVersion>
<VsMinorVersion>$(MinorVersion)</VsMinorVersion>
</PropertyGroup>

<!-- Razor tooling version -->
<PropertyGroup>
<RazorVsixVersionPrefix>18.12.1</RazorVsixVersionPrefix>
<RazorAddinMajorVersion>18.12</RazorAddinMajorVersion>
<RazorVsixPatchVersion>1</RazorVsixPatchVersion>
<RazorVsixVersionPrefix>$(VsMajorVersion).$(VsMinorVersion).$(RazorVsixPatchVersion)</RazorVsixVersionPrefix>
<RazorAddinMajorVersion>$(VsMajorVersion).$(VsMinorVersion)</RazorAddinMajorVersion>
<RazorAddinVersion>$(RazorAddinMajorVersion)</RazorAddinVersion>
<RazorAddinVersion Condition="'$(OfficialBuildId)' != ''">$(RazorAddinVersion).$(OfficialBuildId)</RazorAddinVersion>
<RazorAddinVersion Condition="'$(OfficialBuildId)' == ''">$(RazorAddinVersion).42424242.42</RazorAddinVersion>
</PropertyGroup>

<!-- EditorConfig components version -->
<PropertyGroup>
<EditorConfigPatchVersion>0</EditorConfigPatchVersion>
<EditorConfigVersionPrefix>$(VsMajorVersion).$(VsMinorVersion).$(EditorConfigPatchVersion)</EditorConfigVersionPrefix>
<EditorConfigAssemblyVersion>$(VsMajorVersion).$(VsMinorVersion).0.0</EditorConfigAssemblyVersion>
</PropertyGroup>

<!--
The maintenance-packages dependency versions need to be conditionally selected:
https://github.com/dotnet/sdk/issues/45155
Expand Down
5 changes: 4 additions & 1 deletion src/roslyn/src/Compilers/Server/VBCSCompiler/VBCSCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public static int Main(string[] args)
return CommonCompiler.Failed;
}

using var logger = new CompilerServerLogger($"VBCSCompiler {Process.GetCurrentProcess().Id}", options.LogFilePath);
var identifier = $"VBCSCompiler {Process.GetCurrentProcess().Id}";
using var logger = options.LogFilePath is null
? new CompilerServerLogger(identifier, StandardBuildEnvironment.Instance)
: new CompilerServerLogger(identifier, options.LogFilePath);

#if BOOTSTRAP
ExitingTraceListener.Install(logger);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,65 @@ public void Dispose()

public class StartupTests : VBCSCompilerServerTests
{
[Theory]
[InlineData(false)]
[InlineData(true)]
public void LoggingFromEnvironment(bool logToDirectory)
{
var directory = TempRoot.CreateDirectory();
var logPath = logToDirectory ? directory.Path : Path.Combine(directory.Path, "server.log");

RunServerWithLogging(logPath);

var logFile = Assert.Single(Directory.GetFiles(directory.Path));
if (logToDirectory)
{
Assert.StartsWith("server.", Path.GetFileName(logFile));
Assert.EndsWith(".log", logFile);
}
else
{
Assert.Equal(logPath, logFile);
}

var log = File.ReadAllText(logFile);
Assert.Contains("ID=VBCSCompiler ", log);
Assert.Contains("Keep alive timeout is: 1000 milliseconds.", log);
}

[Fact]
public void ExplicitLogFileOverridesEnvironment()
{
var directory = TempRoot.CreateDirectory();
var environmentLogPath = Path.Combine(directory.Path, "environment.log");
var explicitLogPath = Path.Combine(directory.Path, "explicit.log");

RunServerWithLogging(environmentLogPath, $@" -log:""{explicitLogPath}""");

Assert.False(File.Exists(environmentLogPath));
var log = File.ReadAllText(explicitLogPath);
Assert.Contains("ID=VBCSCompiler ", log);
Assert.Contains("Keep alive timeout is: 1000 milliseconds.", log);
}

private static void RunServerWithLogging(string environmentLogPath, string additionalArguments = "")
{
var filePath = typeof(VBCSCompiler).Assembly.Location;
var arguments = $"-pipename:{ServerUtil.GetPipeName()} -timeout:1{additionalArguments}";
if (BuildServerConnection.IsBuiltinToolRunningOnCoreClr)
{
arguments = RuntimeHostInfo.GetDotNetExecCommandLine(filePath, arguments);
filePath = RuntimeHostInfo.GetDotNetHostPath(StandardBuildEnvironment.Instance);
}

var result = ProcessUtilities.Run(filePath, arguments, additionalEnvironmentVars:
new Dictionary<string, string>
{
[CompilerServerLogger.EnvironmentVariableName] = environmentLogPath,
});
Assert.True(result.ExitCode == CommonCompiler.Succeeded, result.ToString());
}

[ConditionalFact(typeof(WindowsOnly))]
[WorkItem(217709, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/217709")]
public async Task ShadowCopyAnalyzerAssemblyLoaderMissingDirectory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.ReferenceHighlighting;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests.Logging;
using Roslyn.Test.Utilities;
using Roslyn.Text.Adornments;
using Roslyn.Utilities;
Expand Down Expand Up @@ -108,6 +110,36 @@ void M2()
AssertHighlightCount(results, expectedDefinitionCount: 1, expectedWrittenReferenceCount: 0, expectedReferenceCount: 3);
}

[Theory, CombinatorialData]
public async Task StreamedReferencesWithResultsAreNotReportedAsEmpty(bool mutatingLspWorkspace)
{
var markup =
"""
class C
{
void M()
{
{|caret:|}M();
}
}
""";
await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, CapabilitiesWithVSExtensions);
using var progress = BufferedProgress.Create<object>(null);
using var telemetry = RoslynTelemetry.SetCurrent(new RoslynTelemetry());
var sink = new TestTelemetryEventSink();
using var registration = RoslynTelemetry.Current.AddEventSink(sink);

var results = await RunFindAllReferencesAsync(
testLspServer,
testLspServer.GetLocations("caret").Single(),
progress);

Assert.NotEmpty(results);
Assert.DoesNotContain(
sink.PostedEvents,
telemetryEvent => telemetryEvent.Name == "vs/ide/vbcs/lsp/symbolrequest/emptyresult");
}

[Theory, CombinatorialData]
public async Task TestFindAllReferencesAsync_Class(bool mutatingLspWorkspace)
{
Expand Down
Loading
Loading