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

Fixes #3574. Enabling trim mode breaks program at runtime (v2 only) #3582

Merged
merged 32 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4733685
Add SelfContained project.
BDisp Jul 4, 2024
8523657
Fix WriteConsole having a wrong parameter type.
BDisp Jul 4, 2024
5ca07e1
Add SourceGenerationContext and fix Serialize/Deserialize.
BDisp Jul 4, 2024
62b151e
Add SourceGenerationContext.
BDisp Jul 4, 2024
7647de7
Fix compile warnings.
BDisp Jul 4, 2024
b704b30
Using JsonStringEnumConverter<T> for AOT compatible.
BDisp Jul 4, 2024
b4f83bc
Update project and solution.
BDisp Jul 4, 2024
e8aad38
Some adjustments and add comment.
BDisp Jul 5, 2024
594921b
Fixes Example.
BDisp Jul 5, 2024
edba130
With Debug use the csproj and with Release use the latest nuget package.
BDisp Jul 6, 2024
57cb98a
Add separated publish profiles for Debug and Release.
BDisp Jul 6, 2024
91cbb2b
Add README file to the SelContained project.
BDisp Jul 6, 2024
f72f484
Add link to the ./SelfContained/README.md file.
BDisp Jul 6, 2024
d944528
Add link to the ./CommunityToolkitExample/README.md file.
BDisp Jul 6, 2024
abf11bf
Fixed brooked links.
BDisp Jul 6, 2024
efcd6bc
Fix FSharpExample link.
BDisp Jul 6, 2024
ced6a89
Fixing more links.
BDisp Jul 6, 2024
d31f798
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
42ee95b
Fix FSharpExample using the simple example.
BDisp Jul 7, 2024
7a0374d
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
3fcd11b
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
b43abfd
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
e8508cf
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
c0d53d8
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
267da65
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 7, 2024
f974861
Resolving merge conflicts.
BDisp Jul 11, 2024
d8d491a
Resolving merge conflicts.
BDisp Jul 11, 2024
a22f661
Add version ranges.
BDisp Jul 11, 2024
6cc4d54
Fix version ranges.
BDisp Jul 11, 2024
bbce488
Remove JETBRAINS_ANNOTATIONS from project.
BDisp Jul 11, 2024
3b19567
Merge branch 'v2_develop' into v2_3574_self-contained-single-file
BDisp Jul 12, 2024
abdde3a
Remove Terminal.Gui.Analyzers.Internal project from the Terminal.Gui …
BDisp Jul 12, 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
87 changes: 87 additions & 0 deletions SelfContained/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// This is a simple example application for a self-contained single file.

using System.Diagnostics.CodeAnalysis;
using Terminal.Gui;

namespace SelfContained;

public static class Program
{
[RequiresUnreferencedCode ("Calls Terminal.Gui.Application.Run<T>(Func<Exception, Boolean>, ConsoleDriver)")]
private static void Main (string [] args)
{
Application.Run<ExampleWindow> ().Dispose ();

// Before the application exits, reset Terminal.Gui for clean shutdown
Application.Shutdown ();

Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
}
}

// Defines a top-level window with border and title
public class ExampleWindow : Window
{
public static string? UserName;

public ExampleWindow ()
{
Title = $"Example App ({Application.QuitKey} to quit)";

// Create input components and labels
var usernameLabel = new Label { Text = "Username:" };

var usernameText = new TextField
{
// Position text field adjacent to the label
X = Pos.Right (usernameLabel) + 1,

// Fill remaining horizontal space
Width = Dim.Fill ()
};

var passwordLabel = new Label
{
Text = "Password:", X = Pos.Left (usernameLabel), Y = Pos.Bottom (usernameLabel) + 1
};

var passwordText = new TextField
{
Secret = true,

// align with the text box above
X = Pos.Left (usernameText),
Y = Pos.Top (passwordLabel),
Width = Dim.Fill ()
};

// Create login button
var btnLogin = new Button
{
Text = "Login",
Y = Pos.Bottom (passwordLabel) + 1,

// center the login button horizontally
X = Pos.Center (),
IsDefault = true
};

// When login button is clicked display a message popup
btnLogin.Accept += (s, e) =>
{
if (usernameText.Text == "admin" && passwordText.Text == "password")
{
MessageBox.Query ("Logging In", "Login Successful", "Ok");
UserName = usernameText.Text;
Application.RequestStop ();
}
else
{
MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
}
};

// Add the views to the Window
Add (usernameLabel, usernameText, passwordLabel, passwordText, btnLogin);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\linux-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\osx-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup>
</Project>
20 changes: 20 additions & 0 deletions SelfContained/SelfContained.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>Link</TrimMode>
<PublishSingleFile>true</PublishSingleFile>
<InvariantGlobalization>true</InvariantGlobalization>
<DebugType>embedded</DebugType>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
<TrimmerRootAssembly Include="Terminal.Gui" />
</ItemGroup>

</Project>
12 changes: 11 additions & 1 deletion Terminal.Gui/Application/Application.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;

Expand Down Expand Up @@ -56,7 +57,7 @@ internal static List<CultureInfo> GetSupportedCultures ()
string assemblyLocation = AppDomain.CurrentDomain.BaseDirectory;

// Find the resource file name of the assembly
var resourceFilename = $"{Path.GetFileNameWithoutExtension (assembly.Location)}.resources.dll";
var resourceFilename = $"{Path.GetFileNameWithoutExtension (AppContext.BaseDirectory)}.resources.dll";

// Return all culture for which satellite folder found with culture code.
return culture.Where (
Expand Down Expand Up @@ -192,6 +193,8 @@ internal static void ResetState (bool ignoreDisposed = false)
/// <see cref="ConsoleDriver"/> to use. If neither <paramref name="driver"/> or <paramref name="driverName"/> are
/// specified the default driver for the platform will be used.
/// </param>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (driver, driverName); }

internal static bool _initialized;
Expand All @@ -206,6 +209,8 @@ internal static void ResetState (bool ignoreDisposed = false)
// Unit Tests - To initialize the app with a custom Toplevel, using the FakeDriver. calledViaRunT will be false, causing all state to be reset.
//
// calledViaRunT: If false (default) all state will be reset. If true the state will not be reset.
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
internal static void InternalInit (
ConsoleDriver driver = null,
string driverName = null,
Expand Down Expand Up @@ -318,6 +323,7 @@ internal static void InternalInit (

/// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
/// <returns></returns>
[RequiresUnreferencedCode ("AOT")]
public static List<Type> GetDriverTypes ()
{
// use reflection to get the list of drivers
Expand Down Expand Up @@ -660,6 +666,8 @@ internal static bool PositionCursor (View view)
/// </para>
/// </remarks>
/// <returns>The created <see cref="Toplevel"/> object. The caller is responsible for disposing this object.</returns>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static Toplevel Run (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null) { return Run<Toplevel> (errorHandler, driver); }

/// <summary>
Expand All @@ -683,6 +691,8 @@ internal static bool PositionCursor (View view)
/// <see langword="null"/> if <see cref="Init"/> has already been called.
/// </param>
/// <returns>The created T object. The caller is responsible for disposing this object.</returns>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static T Run<T> (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null)
where T : Toplevel, new()
{
Expand Down
6 changes: 3 additions & 3 deletions Terminal.Gui/Configuration/AttributeJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Terminal.Gui;

/// <summary>Json converter fro the <see cref="Attribute"/> class.</summary>
/// <summary>Json converter from the <see cref="Attribute"/> class.</summary>
internal class AttributeJsonConverter : JsonConverter<Attribute>
{
private static AttributeJsonConverter _instance;
Expand Down Expand Up @@ -57,11 +57,11 @@ public override Attribute Read (ref Utf8JsonReader reader, Type typeToConvert, J
switch (propertyName?.ToLower ())
{
case "foreground":
foreground = JsonSerializer.Deserialize<Color> (color, options);
foreground = JsonSerializer.Deserialize (color, _serializerContext.Color);

break;
case "background":
background = JsonSerializer.Deserialize<Color> (color, options);
background = JsonSerializer.Deserialize (color, _serializerContext.Color);

break;

Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public override ColorScheme Read (ref Utf8JsonReader reader, Type typeToConvert,

string propertyName = reader.GetString ();
reader.Read ();
var attribute = JsonSerializer.Deserialize<Attribute> (ref reader, options);
var attribute = JsonSerializer.Deserialize (ref reader, _serializerContext.Attribute);

switch (propertyName.ToLower ())
{
Expand Down
26 changes: 22 additions & 4 deletions Terminal.Gui/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,12 @@ public enum ConfigLocations
},

// Enables Key to be "Ctrl+Q" vs "Ctrl\u002BQ"
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
TypeInfoResolver = SourceGenerationContext.Default
};

internal static readonly SourceGenerationContext _serializerContext = new (_serializerOptions);

[SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
internal static StringBuilder _jsonErrors = new ();

Expand Down Expand Up @@ -150,6 +153,8 @@ public enum ConfigLocations
/// </summary>
public static SettingsScope? Settings
{
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
get
{
if (_settings is null)
Expand Down Expand Up @@ -181,6 +186,8 @@ public static SettingsScope? Settings
public static event EventHandler<ConfigurationManagerEventArgs>? Applied;

/// <summary>Applies the configuration settings to the running <see cref="Application"/> instance.</summary>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Apply ()
{
var settings = false;
Expand Down Expand Up @@ -222,7 +229,7 @@ public static string GetEmptyJson ()
var emptyScope = new SettingsScope ();
emptyScope.Clear ();

return JsonSerializer.Serialize (emptyScope, _serializerOptions);
return JsonSerializer.Serialize (emptyScope, typeof (SettingsScope), _serializerContext);
}

/// <summary>
Expand All @@ -235,6 +242,8 @@ public static string GetEmptyJson ()
/// If <see langword="true"/> the state of <see cref="ConfigurationManager"/> will be reset to the
/// defaults.
/// </param>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Load (bool reset = false)
{
Debug.WriteLine ("ConfigurationManager.Load()");
Expand Down Expand Up @@ -322,6 +331,8 @@ public static void PrintJsonErrors ()
/// <see langword="true"/>.
/// </summary>
/// <remarks></remarks>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Reset ()
{
Debug.WriteLine (@"ConfigurationManager.Reset()");
Expand Down Expand Up @@ -475,6 +486,8 @@ where destProp.CanWrite
/// make sure you copy the Theme definitions from the existing <c>Terminal.Gui.Resources.config.json</c> file.
/// </para>
/// </remarks>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
internal static void GetHardCodedDefaults ()
{
if (_allConfigProperties is null)
Expand All @@ -496,6 +509,7 @@ internal static void GetHardCodedDefaults ()
/// Initializes the internal state of ConfigurationManager. Nominally called once as part of application startup
/// to initialize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
/// </summary>
[RequiresUnreferencedCode ("AOT")]
internal static void Initialize ()
{
_allConfigProperties = new ();
Expand Down Expand Up @@ -585,16 +599,20 @@ from p in enumerable

/// <summary>Creates a JSON document with the configuration specified.</summary>
/// <returns></returns>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
internal static string ToJson ()
{
//Debug.WriteLine ("ConfigurationManager.ToJson()");

return JsonSerializer.Serialize (Settings!, _serializerOptions);
return JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);
}

[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
internal static Stream ToStream ()
{
string json = JsonSerializer.Serialize (Settings!, _serializerOptions);
string json = JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);

// turn it into a stream
var stream = new MemoryStream ();
Expand Down
6 changes: 3 additions & 3 deletions Terminal.Gui/Configuration/DictionaryJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ JsonSerializerOptions options
{
string key = reader.GetString ();
reader.Read ();
var value = JsonSerializer.Deserialize<T> (ref reader, options);
dictionary.Add (key, value);
var value = JsonSerializer.Deserialize (ref reader, typeof (T), _serializerContext);
dictionary.Add (key, (T)value);
}
}
else if (reader.TokenType == JsonTokenType.EndArray)
Expand All @@ -51,7 +51,7 @@ public override void Write (Utf8JsonWriter writer, Dictionary<string, T> value,

//writer.WriteString (item.Key, item.Key);
writer.WritePropertyName (item.Key);
JsonSerializer.Serialize (writer, item.Value, options);
JsonSerializer.Serialize (writer, item.Value, typeof (T), _serializerContext);
writer.WriteEndObject ();
}

Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Configuration/KeyCodeJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override KeyCode Read (ref Utf8JsonReader reader, Type typeToConvert, Jso
}

// The enum uses "D0..D9" for the number keys
if (Enum.TryParse (reader.GetString ().TrimStart ('D', 'd'), false, out key))
if (Enum.TryParse (reader.GetString ()!.TrimStart ('D', 'd'), false, out key))
{
break;
}
Expand Down
Loading
Loading