Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge release/dev17.13 to main #75672

Merged
merged 38 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c29c6dd
Update STJ
Cosifne Sep 18, 2024
f2ba7cf
Merged PR 43018: Flow public release dev17.10 to internal/release/dev…
Cosifne Sep 18, 2024
ea280d3
Merge remote-tracking branch 'dnceng/internal/release/dev17.10' into …
Cosifne Sep 18, 2024
154f8a3
Merged PR 43023: Update STJ in 17.10 branch
Cosifne Sep 18, 2024
44e2f0e
Merge remote-tracking branch 'azdo-dnceng-internal/internal/release/d…
mmitche Oct 10, 2024
7642cb7
Update NuGet.config
mmitche Oct 10, 2024
e36f075
Merge pull request #75471 from mmitche/merge-from-internal-17.10
mmitche Oct 11, 2024
e29d0b7
[release/dev17.10] Update dependencies from dotnet/arcade (#75252)
dotnet-maestro[bot] Oct 15, 2024
0a838b9
Add a HasSdkCodeStyleAnalyzers property to ProjectAttributes
JoeRobich Oct 16, 2024
180455c
Track unmapped AnalyzerReferences added by the project system.
JoeRobich Oct 16, 2024
03eccdd
Selectively treat some Host analyzers as Project analyzers.
JoeRobich Oct 16, 2024
e9f7c04
Allow the DiagnosticComputer to treat some Host analyzers as Project …
JoeRobich Oct 22, 2024
c23b6b5
Merge remote-tracking branch 'upstream/release/dev17.10' into merges/…
akhera99 Oct 22, 2024
6860d90
Merge pull request #75541 from dotnet/merges/release/dev17.10-to-rele…
dotnet-bot Oct 22, 2024
e60f8d9
Update dependencies from https://github.com/dotnet/arcade build 20241…
dotnet-maestro[bot] Oct 22, 2024
1198405
Added integration tests
JoeRobich Oct 23, 2024
7344695
PR feedback
JoeRobich Oct 24, 2024
dff04fe
Backport test skip from #75612
JoeRobich Oct 24, 2024
16f58fa
Merge pull request #75534 from dotnet/dev/jorobich/redirect-feature-a…
JoeRobich Oct 24, 2024
477a090
Merge pull request #75669 from dotnet/merges/release/dev17.12-to-rele…
dotnet-bot Oct 29, 2024
45769e3
Fix flow of CompilerGeneratedFilesOutputPath from CPS
tmat Oct 30, 2024
f2d0393
Merge remote-tracking branch 'upstream/release/dev17.10' into merges/…
akhera99 Oct 31, 2024
b06d089
Merge remote-tracking branch 'upstream/release/dev17.11' into merges/…
akhera99 Oct 31, 2024
f5c31b2
Merge pull request #75591 from dotnet/merges/release/dev17.10-to-rele…
dotnet-bot Nov 1, 2024
e8ea5e7
Merge pull request #75589 from dotnet/merges/release/dev17.11-to-rele…
dotnet-bot Nov 1, 2024
c339476
Merge pull request #75697 from dotnet/merges/release/dev17.11-to-rele…
dotnet-bot Nov 1, 2024
9dedafa
Merge pull request #75698 from dotnet/merges/release/dev17.12-to-rele…
dotnet-bot Nov 1, 2024
9589188
Merge pull request #75699 from dotnet/merges/release/dev17.12-to-rele…
dotnet-bot Nov 1, 2024
7123a54
Relative path
tmat Nov 1, 2024
82a6808
Update src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/CSharpCompi…
tmat Nov 1, 2024
4b30d25
Update src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/AdditionalP…
tmat Nov 1, 2024
be03640
Merge pull request #75674 from tmat/FixCompilerGeneratedFilesOutputPath
arunchndr Nov 1, 2024
ec87a60
Merge branch 'release/dev17.13' into main
jjonescz Nov 4, 2024
3922582
Unpin S.T.J
jjonescz Nov 4, 2024
4ffa80c
Add delay to RedirectFeaturesAnalyzers integration test
JoeRobich Nov 4, 2024
f83bc56
Reset FormattingOptions.IndentionSize between integration tests
JoeRobich Nov 5, 2024
6eff4e4
Ignore Build errors in RedirectFeaturesAnalyzers tests
JoeRobich Nov 5, 2024
c67ddcc
Use Warning as minimum severity in RedirectFeaturesAnalyzers
JoeRobich Nov 5, 2024
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
55 changes: 50 additions & 5 deletions eng/common/templates-official/steps/get-delegation-sas.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
parameters:
- name: federatedServiceConnection
type: string
- name: outputVariableName
type: string
- name: expiryInHours
type: number
default: 1
- name: base64Encode
type: boolean
default: false
- name: storageAccount
type: string
- name: container
type: string
- name: permissions
type: string
default: 'rl'

steps:
- template: /eng/common/core-templates/steps/get-delegation-sas.yml
parameters:
is1ESPipeline: true
- task: AzureCLI@2
displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}'
inputs:
azureSubscription: ${{ parameters.federatedServiceConnection }}
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
# Calculate the expiration of the SAS token and convert to UTC
$expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")

# Temporarily work around a helix issue where SAS tokens with / in them will cause incorrect downloads
# of correlation payloads. https://github.com/dotnet/dnceng/issues/3484
$sas = ""
do {
$sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to generate SAS token."
exit 1
}
} while($sas.IndexOf('/') -ne -1)

if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to generate SAS token."
exit 1
}

if ('${{ parameters.base64Encode }}' -eq 'true') {
$sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas))
}

${{ each parameter in parameters }}:
${{ parameter.key }}: ${{ parameter.value }}
Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value"
Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas"
55 changes: 50 additions & 5 deletions eng/common/templates/steps/get-delegation-sas.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
parameters:
- name: federatedServiceConnection
type: string
- name: outputVariableName
type: string
- name: expiryInHours
type: number
default: 1
- name: base64Encode
type: boolean
default: false
- name: storageAccount
type: string
- name: container
type: string
- name: permissions
type: string
default: 'rl'

steps:
- template: /eng/common/core-templates/steps/get-delegation-sas.yml
parameters:
is1ESPipeline: false
- task: AzureCLI@2
displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}'
inputs:
azureSubscription: ${{ parameters.federatedServiceConnection }}
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
# Calculate the expiration of the SAS token and convert to UTC
$expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")

# Temporarily work around a helix issue where SAS tokens with / in them will cause incorrect downloads
# of correlation payloads. https://github.com/dotnet/dnceng/issues/3484
$sas = ""
do {
$sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to generate SAS token."
exit 1
}
} while($sas.IndexOf('/') -ne -1)

if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to generate SAS token."
exit 1
}

if ('${{ parameters.base64Encode }}' -eq 'true') {
$sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas))
}

${{ each parameter in parameters }}:
${{ parameter.key }}: ${{ parameter.value }}
Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value"
Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas"
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,11 @@

CompilerGeneratedFilesOutputPath controls the location the files will be output to.
The compiler will not emit any generated files when the path is empty, and defaults to a /generated directory in $(IntermediateOutputPath) if $(IntermediateOutputPath) has a value.
A relative path is considered relative to the project directory.

EmitCompilerGeneratedFiles allows the user to control if anything is emitted by clearing the property when not true.
When EmitCompilerGeneratedFiles is true, we ensure that CompilerGeneatedFilesOutputPath has a value and issue a warning if not.

We will create CompilerGeneratedFilesOutputPath if it does not exist.
-->
<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2
Expand All @@ -31,19 +32,76 @@ public IEnumerable<StateSet> GetAllHostStateSets()

private HostAnalyzerStateSets GetOrCreateHostStateSets(Project project, ProjectAnalyzerStateSets projectStateSets)
{
var key = new HostAnalyzerStateSetKey(project.Language, project.Solution.SolutionState.Analyzers.HostAnalyzerReferences);
var hostStateSets = ImmutableInterlocked.GetOrAdd(ref _hostAnalyzerStateMap, key, CreateLanguageSpecificAnalyzerMap, project.Solution.SolutionState.Analyzers);
var key = new HostAnalyzerStateSetKey(project.Language, project.State.HasSdkCodeStyleAnalyzers, project.Solution.SolutionState.Analyzers.HostAnalyzerReferences);
// Some Host Analyzers may need to be treated as Project Analyzers so that they do not have access to the
// Host fallback options. These ids will be used when building up the Host and Project analyzer collections.
var referenceIdsToRedirect = GetReferenceIdsToRedirectAsProjectAnalyzers(project);
var hostStateSets = ImmutableInterlocked.GetOrAdd(ref _hostAnalyzerStateMap, key, CreateLanguageSpecificAnalyzerMap, (project.Solution.SolutionState.Analyzers, referenceIdsToRedirect));
return hostStateSets.WithExcludedAnalyzers(projectStateSets.SkippedAnalyzersInfo.SkippedAnalyzers);

static HostAnalyzerStateSets CreateLanguageSpecificAnalyzerMap(HostAnalyzerStateSetKey arg, HostDiagnosticAnalyzers hostAnalyzers)
static HostAnalyzerStateSets CreateLanguageSpecificAnalyzerMap(HostAnalyzerStateSetKey arg, (HostDiagnosticAnalyzers HostAnalyzers, ImmutableHashSet<object> ReferenceIdsToRedirect) state)
{
var language = arg.Language;
var analyzersPerReference = hostAnalyzers.GetOrCreateHostDiagnosticAnalyzersPerReference(language);
var analyzersPerReference = state.HostAnalyzers.GetOrCreateHostDiagnosticAnalyzersPerReference(language);

var analyzerMap = CreateStateSetMap(language, [], analyzersPerReference.Values, includeWorkspacePlaceholderAnalyzers: true);
var (hostAnalyzerCollection, projectAnalyzerCollection) = GetAnalyzerCollections(analyzersPerReference, state.ReferenceIdsToRedirect);
var analyzerMap = CreateStateSetMap(language, projectAnalyzerCollection, hostAnalyzerCollection, includeWorkspacePlaceholderAnalyzers: true);

return new HostAnalyzerStateSets(analyzerMap);
}

static (IEnumerable<ImmutableArray<DiagnosticAnalyzer>> HostAnalyzerCollection, IEnumerable<ImmutableArray<DiagnosticAnalyzer>> ProjectAnalyzerCollection) GetAnalyzerCollections(
ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>> analyzersPerReference,
ImmutableHashSet<object> referenceIdsToRedirectAsProjectAnalyzers)
{
if (referenceIdsToRedirectAsProjectAnalyzers.IsEmpty)
{
return (analyzersPerReference.Values, []);
}

var hostAnalyzerCollection = ArrayBuilder<ImmutableArray<DiagnosticAnalyzer>>.GetInstance();
var projectAnalyzerCollection = ArrayBuilder<ImmutableArray<DiagnosticAnalyzer>>.GetInstance();

foreach (var (referenceId, analyzers) in analyzersPerReference)
{
if (referenceIdsToRedirectAsProjectAnalyzers.Contains(referenceId))
{
projectAnalyzerCollection.Add(analyzers);
}
else
{
hostAnalyzerCollection.Add(analyzers);
}
}

return (hostAnalyzerCollection.ToImmutableAndFree(), projectAnalyzerCollection.ToImmutableAndFree());
}
}

private static ImmutableHashSet<object> GetReferenceIdsToRedirectAsProjectAnalyzers(Project project)
{
if (project.State.HasSdkCodeStyleAnalyzers)
{
// When a project uses CodeStyle analyzers added by the SDK, we remove them in favor of the
// Features analyzers. We need to then treat the Features analyzers as Project analyzers so
// they do not get access to the Host fallback options.
return GetFeaturesAnalyzerReferenceIds(project.Solution.SolutionState.Analyzers);
}

return [];

static ImmutableHashSet<object> GetFeaturesAnalyzerReferenceIds(HostDiagnosticAnalyzers hostAnalyzers)
{
var builder = ImmutableHashSet.CreateBuilder<object>();

foreach (var analyzerReference in hostAnalyzers.HostAnalyzerReferences)
{
if (analyzerReference.IsFeaturesAnalyzer())
builder.Add(analyzerReference.Id);
}

return builder.ToImmutable();
}
}

private sealed class HostAnalyzerStateSets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,23 +187,28 @@ private static ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateStateSetM

private readonly struct HostAnalyzerStateSetKey : IEquatable<HostAnalyzerStateSetKey>
{
public HostAnalyzerStateSetKey(string language, IReadOnlyList<AnalyzerReference> analyzerReferences)
public HostAnalyzerStateSetKey(string language, bool hasSdkCodeStyleAnalyzers, IReadOnlyList<AnalyzerReference> analyzerReferences)
{
Language = language;
HasSdkCodeStyleAnalyzers = hasSdkCodeStyleAnalyzers;
AnalyzerReferences = analyzerReferences;
}

public string Language { get; }
public bool HasSdkCodeStyleAnalyzers { get; }
public IReadOnlyList<AnalyzerReference> AnalyzerReferences { get; }

public bool Equals(HostAnalyzerStateSetKey other)
=> Language == other.Language && AnalyzerReferences == other.AnalyzerReferences;
=> Language == other.Language &&
HasSdkCodeStyleAnalyzers == other.HasSdkCodeStyleAnalyzers &&
AnalyzerReferences == other.AnalyzerReferences;

public override bool Equals(object? obj)
=> obj is HostAnalyzerStateSetKey key && Equals(key);

public override int GetHashCode()
=> Hash.Combine(Language.GetHashCode(), AnalyzerReferences.GetHashCode());
=> Hash.Combine(Language.GetHashCode(),
Hash.Combine(HasSdkCodeStyleAnalyzers.GetHashCode(), AnalyzerReferences.GetHashCode()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#nullable disable

using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -151,5 +152,29 @@ void TestLegacyProject()
Assert.Equal(expectedRunAnalyzers, environment.Workspace.CurrentSolution.Projects.Single().State.RunAnalyzers);
}
}

[WpfFact]
public async Task SetProperty_CompilerGeneratedFilesOutputPath_CPS()
{
using (var environment = new TestEnvironment())
using (var project = await CSharpHelpers.CreateCSharpCPSProjectAsync(environment, "Test"))
{
Assert.Null(environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);

// relative path is relative to the project dir:
project.SetProperty(BuildPropertyNames.CompilerGeneratedFilesOutputPath, "generated");
AssertEx.AreEqual(
Path.Combine(Path.GetDirectoryName(project.ProjectFilePath), "generated"),
environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);

var path = Path.Combine(TempRoot.Root, "generated");
project.SetProperty(BuildPropertyNames.CompilerGeneratedFilesOutputPath, path);
AssertEx.AreEqual(path, environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);

// empty path:
project.SetProperty(BuildPropertyNames.CompilerGeneratedFilesOutputPath, "");
Assert.Null(environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,27 @@ public async Task ChecksumAlgorithm_CPS()

cpsProject.SetOptions(ImmutableArray.Create("/checksumalgorithm:SHA1"));

var project = environment.Workspace.CurrentSolution.Projects.Single();
Assert.Equal(SourceHashAlgorithm.Sha1, environment.Workspace.CurrentSolution.Projects.Single().State.ChecksumAlgorithm);
}

[WpfFact]
public async Task CompilerGeneratedFilesOutputPath_CPS()
{
using var environment = new TestEnvironment();
using var cpsProject = await CSharpHelpers.CreateCSharpCPSProjectAsync(environment, "Test");

Assert.Null(environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);

var path = Path.Combine(TempRoot.Root, "generated");
cpsProject.SetOptions(["/generatedfilesout:" + path]);

AssertEx.AreEqual(path, environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);

// relative path is relative to the project dir:
cpsProject.SetOptions(["/generatedfilesout:gen2"]);
AssertEx.AreEqual(
Path.Combine(Path.GetDirectoryName(cpsProject.ProjectFilePath), "gen2"),
environment.Workspace.CurrentSolution.Projects.Single().CompilationOutputInfo.GeneratedFilesOutputDirectory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,33 +173,30 @@ public void SetProperty(string name, string? value)
}
else if (name == BuildPropertyNames.TargetRefPath)
{
// If we don't have a path, always set it to null
_projectSystemProject.OutputRefFilePath = GetAbsolutePath(value);
}
else if (name == BuildPropertyNames.CompilerGeneratedFilesOutputPath)
{
_projectSystemProject.GeneratedFilesOutputDirectory = GetAbsolutePath(value);
}

string? GetAbsolutePath(string? value)
{
if (string.IsNullOrEmpty(value))
{
_projectSystemProject.OutputRefFilePath = null;
return null;
}
else

if (PathUtilities.IsAbsolute(value))
{
// If we only have a non-rooted path, make it full. This is apparently working around cases
// where CPS pushes us a temporary path when they're loading. It's possible this hack
// can be removed now, but we still have tests asserting it.
if (!PathUtilities.IsAbsolute(value))
{
var rootDirectory = _projectSystemProject.FilePath != null
? Path.GetDirectoryName(_projectSystemProject.FilePath)
: Path.GetTempPath();

_projectSystemProject.OutputRefFilePath = Path.Combine(rootDirectory, value);
}
else
{
_projectSystemProject.OutputRefFilePath = value;
}
return value;
}
}
else if (name == BuildPropertyNames.CompilerGeneratedFilesOutputPath)
{
_projectSystemProject.GeneratedFilesOutputDirectory = string.IsNullOrWhiteSpace(value) ? null : value;

var rootDirectory = _projectSystemProject.FilePath != null
? Path.GetDirectoryName(_projectSystemProject.FilePath)
: Path.GetTempPath();

return Path.Combine(rootDirectory, value);
}
}

Expand Down
Loading
Loading