Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.
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
10 changes: 10 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,14 @@
</PackageReference>
</ItemGroup>

<!-- Needed for reverting back to pre-.NET 8 method of Host using the RID graph to determine assets
This is due to a change in how the RuntimeIdentifier graph was changed in .NET 8. Without this, any assets from
NuGet packages that are targeting win10-* won't get picked up and referenced prooperly. -->
<!-- https://learn.microsoft.com/en-us/dotnet/core/compatibility/deployment/8.0/rid-asset-list -->
<PropertyGroup>
<UseRidGraph>true</UseRidGraph>
</PropertyGroup>
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Runtime.Loader.UseRidGraph" Value="true" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion ToolingVersions.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE-CODE in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<TargetFramework>net6.0-windows10.0.22000.0</TargetFramework>
<TargetFramework>net8.0-windows10.0.22000.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/AzureExtension/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace DevHomeAzureExtension;

internal class Constants
internal sealed class Constants
{
#pragma warning disable SA1310 // Field names should not contain underscore
public const string DEV_HOME_APPLICATION_NAME = "DevHome";
Expand Down
6 changes: 3 additions & 3 deletions src/AzureExtension/DataManager/AzureDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ public AzureDataManager(string identifier, DataStoreOptions dataStoreOptions)
Log.Logger()?.ReportWarn(Name, InstanceName, "Failed setting DeveloperId change handler.", ex);
}

if (Instances.ContainsKey(InstanceName))
if (Instances.TryGetValue(InstanceName, out var instanceIdentifier))
{
// We should not have duplicate AzureDataManagers, as every client should have one,
// but the identifiers may not be unique if using partial Guids. Note in the log
// the duplicate as a warning and the existing unique name so we can see in the log what
// client created the duplicate in order to discern random chance / consistent pattern.
Log.Logger()?.ReportWarn(Name, InstanceName, $"Duplicate instance created for identifier {InstanceName}:{Instances[InstanceName]}.");
Log.Logger()?.ReportWarn(Name, InstanceName, $"Duplicate instance created for identifier {InstanceName}:{instanceIdentifier}.");
}
else
{
Expand Down Expand Up @@ -824,7 +824,7 @@ protected virtual void Dispose(bool disposing)
try
{
Log.Logger()?.ReportDebug(Name, InstanceName, "Disposing of all Disposable resources.");
if (Instances.ContainsKey(InstanceName) && Instances[InstanceName] == UniqueName)
if (Instances.TryGetValue(InstanceName, out var instanceName) && instanceName == UniqueName)
{
Instances.TryRemove(InstanceName, out _);
Log.Logger()?.ReportInfo(Name, InstanceName, $"Removed AzureDataManager: {UniqueName}.");
Expand Down
5 changes: 1 addition & 4 deletions src/AzureExtension/DataModel/DataObjects/Identity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,7 @@ public static Identity Get(DataStore? dataStore, long id)

public static Identity GetOrCreateIdentity(DataStore dataStore, IdentityRef? identityRef)
{
if (identityRef == null)
{
throw new ArgumentNullException(nameof(identityRef));
}
ArgumentNullException.ThrowIfNull(identityRef);

var newIdentity = CreateFromIdentityRef(identityRef);
return AddOrUpdateIdentity(dataStore, newIdentity);
Expand Down
4 changes: 3 additions & 1 deletion src/AzureExtension/DeveloperId/AuthenticationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public AuthenticationResult? AuthenticationResult

public static Guid TransferTenetId { get; } = new("f8cdef31-a31e-4b4a-93e4-5f571e91255a");

private static readonly string[] _capabilities = new string[1] { "cp1" };

public AuthenticationHelper()
{
MicrosoftEntraIdSettings = new AuthenticationSettings();
Expand All @@ -53,7 +55,7 @@ public void InitializePublicClientApplicationBuilder()
.WithAuthority(string.Format(CultureInfo.InvariantCulture, MicrosoftEntraIdSettings.Authority, MicrosoftEntraIdSettings.TenantId))
.WithRedirectUri(string.Format(CultureInfo.InvariantCulture, MicrosoftEntraIdSettings.RedirectURI, MicrosoftEntraIdSettings.ClientId))
.WithLogging(new MSALLogger(EventLogLevel.Warning), enablePiiLogging: false)
.WithClientCapabilities(new string[] { "cp1" });
.WithClientCapabilities(_capabilities);
Log.Logger()?.ReportInfo($"Created PublicClientApplicationBuilder");
}

Expand Down
3 changes: 1 addition & 2 deletions src/AzureExtension/Helpers/IconLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ public class IconLoader
public static string GetIconAsBase64(string filename)
{
Log.Logger()?.ReportDebug(nameof(IconLoader), $"Asking for icon: {filename}");
if (!Base64ImageRegistry.ContainsKey(filename))
if (!Base64ImageRegistry.TryAdd(filename, ConvertIconToDataString(filename)))
{
Base64ImageRegistry.Add(filename, ConvertIconToDataString(filename));
Log.Logger()?.ReportDebug(nameof(IconLoader), $"The icon {filename} was converted and is now stored.");
}

Expand Down
2 changes: 1 addition & 1 deletion src/AzureExtension/Helpers/TimeSpanHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace DevHomeAzureExtension.Helpers;

internal class TimeSpanHelper
internal sealed class TimeSpanHelper
{
public static string TimeSpanToDisplayString(TimeSpan timeSpan, Logger? log = null)
{
Expand Down
4 changes: 1 addition & 3 deletions src/AzureExtension/Notifications/NotificationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ public static void NotificationActivation(AppNotificationActivatedEventArgs args
{
Log.Logger()?.ReportInfo($"Notification Activated with args: {NotificationArgsToString(args)}");

if (args.Arguments.ContainsKey("htmlurl"))
if (args.Arguments.TryGetValue("htmlurl", out var urlString))
{
try
{
// Do not assume this string is a safe URL and blindly execute it; verify that it is
// in fact a valid Azure URL.
// TODO: Validate Azure URL
var urlString = args.Arguments["htmlurl"];

Log.Logger()?.ReportInfo($"Launching Uri: {urlString}");
var processStartInfo = new ProcessStartInfo
{
Expand Down
2 changes: 1 addition & 1 deletion src/AzureExtension/Providers/RepositoryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ IAsyncOperation<RepositoriesResult> IRepositoryProvider.GetRepositoriesAsync(IDe
Parallel.ForEach(theseOrganizations, options, organization =>
{
var projects = GetProjects(organization, azureDeveloperId);
if (projects.Any())
if (projects.Count != 0)
{
foreach (var project in projects)
{
Expand Down
6 changes: 3 additions & 3 deletions src/AzureExtension/Widgets/AzurePullRequestsWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

namespace DevHomeAzureExtension.Widgets;

internal class AzurePullRequestsWidget : AzureWidget
internal sealed class AzurePullRequestsWidget : AzureWidget
{
private readonly string sampleIconData = IconLoader.GetIconAsBase64("screenshot.png");

protected static readonly new string Name = nameof(AzurePullRequestsWidget);
private static readonly new string Name = nameof(AzurePullRequestsWidget);

private static readonly string DefaultSelectedView = "Mine";

Expand All @@ -35,7 +35,7 @@ public AzurePullRequestsWidget()

public override void CreateWidget(WidgetContext widgetContext, string state)
{
if (state.Any())
if (state.Length != 0)
{
ResetDataFromState(state);
}
Expand Down
6 changes: 3 additions & 3 deletions src/AzureExtension/Widgets/AzureQueryListWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

namespace DevHomeAzureExtension.Widgets;

internal class AzureQueryListWidget : AzureWidget
internal sealed class AzureQueryListWidget : AzureWidget
{
private readonly string sampleIconData = IconLoader.GetIconAsBase64("screenshot.png");

protected static readonly new string Name = nameof(AzureQueryListWidget);
private static readonly new string Name = nameof(AzureQueryListWidget);

// Widget Data
private string widgetTitle = string.Empty;
Expand All @@ -31,7 +31,7 @@ public AzureQueryListWidget()

public override void CreateWidget(WidgetContext widgetContext, string state)
{
if (state.Any())
if (state.Length != 0)
{
ResetDataFromState(state);
}
Expand Down
18 changes: 9 additions & 9 deletions src/AzureExtension/Widgets/AzureQueryTilesWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@

namespace DevHomeAzureExtension.Widgets;

internal class AzureQueryTilesWidget : AzureWidget
internal sealed class AzureQueryTilesWidget : AzureWidget
{
private readonly string sampleIconData = IconLoader.GetIconAsBase64("screenshot.png");

private readonly int maxNumLines = 3;
private readonly int maxNumColumns = 2;

// Widget data
protected static readonly new string Name = nameof(AzureQueryTilesWidget);
private static readonly new string Name = nameof(AzureQueryTilesWidget);
private readonly List<QueryTile> tiles = new();

// Creation and destruction methods
Expand All @@ -30,7 +30,7 @@ public AzureQueryTilesWidget()

public override void CreateWidget(WidgetContext widgetContext, string state)
{
if (state.Any())
if (state.Length != 0)
{
// Not newly created widget, recovering tiles from state
ResetNumberOfTilesFromData(state);
Expand All @@ -54,7 +54,7 @@ public override void DeleteWidget(string widgetId, string customState)
}

// Action handler methods
protected void HandleAddTile(WidgetActionInvokedArgs args)
private void HandleAddTile(WidgetActionInvokedArgs args)
{
Page = WidgetPageState.Loading;
UpdateWidget();
Expand All @@ -81,12 +81,12 @@ private string RemoveLastTileFromData(string data)
return dataObject.ToJsonString();
}

protected void HandleRemoveTile(WidgetActionInvokedArgs args)
private void HandleRemoveTile(WidgetActionInvokedArgs args)
{
Page = WidgetPageState.Loading;
UpdateWidget();

if (tiles.Any())
if (tiles.Count != 0)
{
tiles.RemoveAt(tiles.Count - 1);
}
Expand Down Expand Up @@ -152,7 +152,7 @@ protected override bool ValidateConfiguration(WidgetActionInvokedArgs actionInvo
UpdateWidget();

UpdateAllTiles(actionInvokedArgs.Data);
bool hasValidData = ValidateConfigurationData();
var hasValidData = ValidateConfigurationData();
if (hasValidData)
{
Page = WidgetPageState.Content;
Expand Down Expand Up @@ -313,7 +313,7 @@ private bool ValidateConfigurationData()
return false;
}

if (!tiles.Any())
if (tiles.Count == 0)
{
return false;
}
Expand Down Expand Up @@ -458,7 +458,7 @@ public override string GetConfiguration(string data)
{
{ "url", tiles[i].AzureUri.ToString() },
{ "title", tiles[i].Title },
{ "message", tiles[i].Message.Any() ? tiles[i].Message : null },
{ "message", tiles[i].Message.Length != 0 ? tiles[i].Message : null },
});
}

Expand Down
6 changes: 3 additions & 3 deletions src/AzureExtension/Widgets/AzureWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public override void CreateWidget(WidgetContext widgetContext, string state)

// If there is a state, it is being retrieved from the widget service, so
// this widget was pinned before.
if (state.Any())
if (state.Length != 0)
{
Pinned = true;
CanSave = true;
Expand Down Expand Up @@ -324,10 +324,10 @@ public virtual string GetData(WidgetPageState page)

protected string GetTemplateForPage(WidgetPageState page)
{
if (Template.ContainsKey(page))
if (Template.TryGetValue(page, out var azureTemplate))
{
Log.Logger()?.ReportDebug(Name, ShortId, $"Using cached template for {page}");
return Template[page];
return azureTemplate;
}

try
Expand Down
2 changes: 1 addition & 1 deletion src/AzureExtension/Widgets/WidgetImplFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace DevHomeAzureExtension.Widgets;

[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "Templated class")]
internal class WidgetImplFactory<T> : IWidgetImplFactory
internal sealed class WidgetImplFactory<T> : IWidgetImplFactory
where T : WidgetImpl, new()
{
public WidgetImpl Create(WidgetContext widgetContext, string state)
Expand Down
33 changes: 16 additions & 17 deletions src/AzureExtension/Widgets/WidgetProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ private void InitializeWidget(WidgetContext widgetContext, string state)
var widgetId = widgetContext.Id;
var widgetDefinitionId = widgetContext.DefinitionId;
Log.Logger()?.ReportDebug($"Calling Initialize for Widget Id: {widgetId} - {widgetDefinitionId}");
if (widgetDefinitionRegistry.ContainsKey(widgetDefinitionId))
if (widgetDefinitionRegistry.TryGetValue(widgetDefinitionId, out var widgetFactory))
{
if (!runningWidgets.ContainsKey(widgetId))
{
var factory = widgetDefinitionRegistry[widgetDefinitionId];
var widgetImpl = factory.Create(widgetContext, state);
var widgetImpl = widgetFactory.Create(widgetContext, state);
runningWidgets.Add(widgetId, widgetImpl);
}
else
Expand Down Expand Up @@ -92,37 +91,37 @@ public void Activate(WidgetContext widgetContext)
{
Log.Logger()?.ReportDebug($"Activate id: {widgetContext.Id} definitionId: {widgetContext.DefinitionId}");
var widgetId = widgetContext.Id;
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetImpl))
{
runningWidgets[widgetId].Activate(widgetContext);
widgetImpl.Activate(widgetContext);
}
else
{
// Called to activate a widget that we don't know about, which is unexpected. Try to recover by creating it.
Log.Logger()?.ReportWarn($"Found WidgetId that was not known: {widgetContext.Id}, attempting to recover by creating it.");
CreateWidget(widgetContext);
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetImplForUnknownWidget))
{
runningWidgets[widgetId].Activate(widgetContext);
widgetImplForUnknownWidget.Activate(widgetContext);
}
}
}

public void Deactivate(string widgetId)
{
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetToDeactivate))
{
Log.Logger()?.ReportDebug($"Deactivate id: {widgetId}");
runningWidgets[widgetId].Deactivate(widgetId);
widgetToDeactivate.Deactivate(widgetId);
}
}

public void DeleteWidget(string widgetId, string customState)
{
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetToDelete))
{
Log.Logger()?.ReportInfo($"DeleteWidget id: {widgetId}");
runningWidgets[widgetId].DeleteWidget(widgetId, customState);
widgetToDelete.DeleteWidget(widgetId, customState);
runningWidgets.Remove(widgetId);
}
}
Expand All @@ -132,9 +131,9 @@ public void OnActionInvoked(WidgetActionInvokedArgs actionInvokedArgs)
Log.Logger()?.ReportDebug($"OnActionInvoked id: {actionInvokedArgs.WidgetContext.Id} definitionId: {actionInvokedArgs.WidgetContext.DefinitionId}");
var widgetContext = actionInvokedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetToInvokeAnActionOn))
{
runningWidgets[widgetId].OnActionInvoked(actionInvokedArgs);
widgetToInvokeAnActionOn.OnActionInvoked(actionInvokedArgs);
}
}

Expand All @@ -143,9 +142,9 @@ public void OnCustomizationRequested(WidgetCustomizationRequestedArgs customizat
Log.Logger()?.ReportDebug($"OnCustomizationRequested id: {customizationRequestedArgs.WidgetContext.Id} definitionId: {customizationRequestedArgs.WidgetContext.DefinitionId}");
var widgetContext = customizationRequestedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetToCustomize))
{
runningWidgets[widgetId].OnCustomizationRequested(customizationRequestedArgs);
widgetToCustomize.OnCustomizationRequested(customizationRequestedArgs);
}
}

Expand All @@ -154,9 +153,9 @@ public void OnWidgetContextChanged(WidgetContextChangedArgs contextChangedArgs)
Log.Logger()?.ReportDebug($"OnWidgetContextChanged id: {contextChangedArgs.WidgetContext.Id} definitionId: {contextChangedArgs.WidgetContext.DefinitionId}");
var widgetContext = contextChangedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (runningWidgets.ContainsKey(widgetId))
if (runningWidgets.TryGetValue(widgetId, out var widgetWithAChangedContext))
{
runningWidgets[widgetId].OnWidgetContextChanged(contextChangedArgs);
widgetWithAChangedContext.OnWidgetContextChanged(contextChangedArgs);
}
}
}
2 changes: 1 addition & 1 deletion src/AzureExtension/Widgets/WidgetServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void Dispose()
}
}

private class Ole32
private sealed class Ole32
{
#pragma warning disable SA1310 // Field names should not contain underscore
// https://docs.microsoft.com/windows/win32/api/wtypesbase/ne-wtypesbase-clsctx
Expand Down
Loading