|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Windows.Forms.Analyzers;
using System.Windows.Forms.CSharp.Analyzers.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using static System.Windows.Forms.Analyzers.ApplicationConfig;
namespace System.Windows.Forms.CSharp.Generators.ApplicationConfiguration;
internal static partial class ProjectFileReader
{
public static IncrementalValueProvider<(ApplicationConfig? ApplicationConfig, Diagnostic? Diagnostic)> ReadApplicationConfig(IncrementalValueProvider<AnalyzerConfigOptionsProvider> configOptionsProvider) =>
configOptionsProvider.Select(
(analyzerConfigOptions, cancellationToken) =>
{
if (!TryReadBool(analyzerConfigOptions, PropertyNameCSharp.EnableVisualStyles,
defaultValue: PropertyDefaultValue.EnableVisualStyles,
out bool enableVisualStyles, out Diagnostic? diagnostic)
|| !TryReadBool(analyzerConfigOptions, PropertyNameCSharp.UseCompatibleTextRendering,
defaultValue: PropertyDefaultValue.UseCompatibleTextRendering,
out bool useCompatibleTextRendering, out diagnostic)
|| !TryReadFont(analyzerConfigOptions, out FontDescriptor? font, out diagnostic)
|| !TryReadHighDpiMode(analyzerConfigOptions, out HighDpiMode highDpiMode, out diagnostic))
{
return ((ApplicationConfig?)null, diagnostic);
}
ApplicationConfig projectConfig = new(
EnableVisualStyles: enableVisualStyles,
DefaultFont: font?.ToString(),
HighDpiMode: highDpiMode,
UseCompatibleTextRendering: useCompatibleTextRendering);
return (projectConfig, null);
});
private static bool TryReadBool(AnalyzerConfigOptionsProvider configOptions, string propertyName, bool defaultValue, out bool value, out Diagnostic? diagnostic)
{
value = defaultValue;
diagnostic = null;
if (!configOptions.GetMSBuildProperty(propertyName, out string? rawValue) ||
rawValue == string.Empty)
{
// The property is either not defined explicitly, or the value is "". All good, use the default.
return true;
}
if (!bool.TryParse(rawValue, out value))
{
diagnostic = Diagnostic.Create(CSharpDiagnosticDescriptors.s_propertyCantBeSetToValue,
Location.None,
propertyName,
rawValue);
value = defaultValue;
return false;
}
return true;
}
private static bool TryReadFont(AnalyzerConfigOptionsProvider configOptions, out FontDescriptor? font, out Diagnostic? diagnostic)
{
font = null;
diagnostic = null;
if (!configOptions.GetMSBuildProperty(PropertyNameCSharp.DefaultFont, out string? rawValue) ||
rawValue == string.Empty)
{
// The property is either not defined explicitly, or the value is "". All good, use the default.
return true;
}
try
{
// In .NET runtime the font is validated via GDI+ to see whether it can be mapped to a valid font family.
// We don't have access to Font (though we can with some gymnastics) or FontConverter (at all), so our
// font validation logic is not as exhaustive as it is in .NET runtime.
// With that it is possible that the value is not a valid font (e.g. 'Style=Bold' or '11px'), and which
// will lead to runtime failures when we execute SetDefaultFont(new FontFamily('Style=Bold')).
font = FontConverter.ConvertFrom(rawValue!);
return true;
}
catch (Exception ex)
{
diagnostic = Diagnostic.Create(CSharpDiagnosticDescriptors.s_propertyCantBeSetToValueWithReason,
Location.None,
PropertyNameCSharp.DefaultFont,
rawValue,
ex.Message);
}
return false;
}
private static bool TryReadHighDpiMode(AnalyzerConfigOptionsProvider configOptions, out HighDpiMode highDpiMode, out Diagnostic? diagnostic)
{
highDpiMode = PropertyDefaultValue.DpiMode;
diagnostic = null;
if (!configOptions.GetMSBuildProperty(PropertyNameCSharp.HighDpiMode, out string? rawValue) ||
rawValue == string.Empty)
{
// The property is either not defined explicitly, or the value is "". All good, use the default.
return true;
}
if (!Enum.TryParse(rawValue, true, out highDpiMode) ||
!Enum.IsDefined(typeof(HighDpiMode), highDpiMode))
{
diagnostic = Diagnostic.Create(CSharpDiagnosticDescriptors.s_propertyCantBeSetToValue,
Location.None,
PropertyNameCSharp.HighDpiMode,
rawValue);
highDpiMode = PropertyDefaultValue.DpiMode;
return false;
}
return true;
}
}
|