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

[pull] master from unoplatform:master #140

Merged
merged 7 commits into from
Jan 29, 2024
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
2 changes: 1 addition & 1 deletion doc/articles/features/working-with-xaml-hot-reload.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Hot Reload is supported by Visual Studio for WinAppSDK and provides support in u
- Search for **.NET / C++ Hot Reload**
- Ensure that all three checkboxes are checked (_**Enable hot reload when debugging**_, _**Enable Hot Reload without debugging**_ and _**Apply Hot Reload on File Save**_)
- Hot Reload for WebAssembly is not supported when using the debugger. Start your app using `Ctrl+F5`.
- The output window in VS has an output named `Uno Platform` in its drop-down. Diagnostics messages from the VS integration appear there.
- The output window in VS has an output named `Uno Platform` in its drop-down. Diagnostics messages from the VS integration appear there. Changing the MSBuild build output verbosity in `Tools/Options/Projects and Solutions/Build And Run` controls the log level.
- When a file is reloaded, XAML parsing errors will appear in the application's logs, on device or in browser.
- If there are multiple versions of the Uno.WinUI Package present in the solution, the newest will be used, regardless of the started application
- The app does not update its XAML, because the port number in `RemoteControl.g.cs` is `0`.
Expand Down
13 changes: 8 additions & 5 deletions src/Uno.UI.RemoteControl.VS/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class EntryPoint : IDisposable
private Action<string>? _verboseAction;
private Action<string>? _warningAction;
private Action<string>? _errorAction;
private int _msBuildLogLevel;
private System.Diagnostics.Process? _process;

private int RemoteControlServerPort;
Expand Down Expand Up @@ -101,6 +102,8 @@ private void SetupOutputWindow()
{
var ow = _dte2.ToolWindows.OutputWindow;

_msBuildLogLevel = _dte2.GetMSBuildOutputVerbosity();

// Add a new pane to the Output window.
var owPane = ow
.OutputWindowPanes
Expand All @@ -116,35 +119,35 @@ private void SetupOutputWindow()

_debugAction = s =>
{
if (!_closing)
if (!_closing && _msBuildLogLevel >= 3 /* MSBuild Log Detailed */)
{
owPane.OutputString("[DEBUG] " + s + "\r\n");
}
};
_infoAction = s =>
{
if (!_closing)
if (!_closing && _msBuildLogLevel >= 2 /* MSBuild Log Normal */)
{
owPane.OutputString("[INFO] " + s + "\r\n");
}
};
_verboseAction = s =>
{
if (!_closing)
if (!_closing && _msBuildLogLevel >= 4 /* MSBuild Log Diagnostic */)
{
owPane.OutputString("[VERBOSE] " + s + "\r\n");
}
};
_warningAction = s =>
{
if (!_closing)
if (!_closing && _msBuildLogLevel >= 1 /* MSBuild Log Minimal */)
{
owPane.OutputString("[WARNING] " + s + "\r\n");
}
};
_errorAction = e =>
{
if (!_closing)
if (!_closing && _msBuildLogLevel >= 0 /* MSBuild Log Quiet */)
{
owPane.OutputString("[ERROR] " + e + "\r\n");
}
Expand Down
20 changes: 20 additions & 0 deletions src/Uno.UI.RemoteControl.VS/Helpers/DTEHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;

namespace Uno.UI.RemoteControl.VS.Helpers;

internal static class DTEHelper
{
public static int GetMSBuildOutputVerbosity(this DTE2 dte)
{
ThreadHelper.ThrowIfNotOnUIThread();
var properties = dte?.Properties["Environment", "ProjectsAndSolution"];
var logOutput = properties?.Item("MSBuildOutputVerbosity").Value is int log ? log : 0;
return logOutput;
}
}
6 changes: 2 additions & 4 deletions src/Uno.UI.RemoteControl.VS/IDEChannel/IDEChannelClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private async Task StartKeepaliveAsync()

private void ProcessDevServerMessage(object sender, IdeMessage devServerMessage)
{
_logger.Info($"IDE: IDEChannel message received {devServerMessage}");
_logger.Verbose($"IDE: IDEChannel message received {devServerMessage}");

if (devServerMessage is ForceHotReloadIdeMessage forceHotReloadMessage)
{
Expand All @@ -93,13 +93,11 @@ private void ProcessDevServerMessage(object sender, IdeMessage devServerMessage)
}
else if (devServerMessage is KeepAliveIdeMessage)
{
#if DEBUG
_logger.Verbose($"Keep alive from Dev Server");
#endif
}
else
{
_logger.Debug($"Unknown message type {devServerMessage?.GetType()} from DevServer");
_logger.Verbose($"Unknown message type {devServerMessage?.GetType()} from DevServer");
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Uno.UI.RemoteControl.VS/Uno.UI.RemoteControl.VS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="Helpers\DTEHelper.cs" />
<UpToDateCheckInput Remove="Helpers\ILogger.cs" />
<UpToDateCheckInput Remove="IdeChannel\IDEChannelClient.cs" />
</ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UI.RuntimeTests/Helpers/FeatureConfigurationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public static IDisposable UseTemplatePooling()
#if WINAPPSDK
return null;
#else
var originallyEnabled = FrameworkTemplatePool.IsPoolingEnabled;
FrameworkTemplatePool.IsPoolingEnabled = true;
var originallyEnabled = FrameworkTemplatePool.InternalIsPoolingEnabled;
FrameworkTemplatePool.InternalIsPoolingEnabled = true;
FrameworkTemplatePool.Instance.SetPlatformProvider(new MockProvider());
return Disposable.Create(() =>
{
FrameworkTemplatePool.IsPoolingEnabled = originallyEnabled;
FrameworkTemplatePool.InternalIsPoolingEnabled = originallyEnabled;
FrameworkTemplatePool.Instance.SetPlatformProvider(null);
});
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ public void When_Collection_Reset()
}

Assert.AreEqual(SUT.Items.Count, 5);
Assert.AreEqual(count, 5);
Assert.AreEqual(count, FrameworkTemplatePool.IsPoolingEnabled ? 5 : 8);
Assert.IsNotNull(SUT.ContainerFromItem("One"));
Assert.IsNotNull(SUT.ContainerFromItem("Four"));
Assert.IsNotNull(SUT.ContainerFromItem("Five"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,23 +803,23 @@ Style BuildContainerStyle() =>
Assert.AreEqual(0, containerCount);

SUT.ItemsSource = source;
Assert.AreEqual(3, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 3 : 4, count);
Assert.AreEqual(3, containerCount);
Assert.AreEqual(3, containerCount);

source.Add("4");
Assert.AreEqual(4, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 4 : 6, count);
Assert.AreEqual(4, containerCount);
Assert.AreEqual(4, containerCount);

source.Remove("1");
Assert.AreEqual(4, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 4 : 6, count);
Assert.AreEqual(4, containerCount);
Assert.AreEqual(4, containerCount);

source[0] = "5";
// Data template is not recreated because of pooling
Assert.AreEqual(4, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 4 : 8, count);
// The item container style is reapplied (not cached)
Assert.AreEqual(5, containerCount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,23 @@ public void When_ObservableCollection()

collection.Add(1);

Assert.AreEqual(1, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 1 : 2, count);

collection.Add(42);

Assert.AreEqual(2, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 2 : 4, count);

collection.Add(43);

Assert.AreEqual(3, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 3 : 6, count);

collection.RemoveAt(0);

Assert.AreEqual(3, count);
Assert.AreEqual(FrameworkTemplatePool.IsPoolingEnabled ? 3 : 6, count);

collection[0] = 44;

Assert.AreEqual(FeatureConfiguration.FrameworkTemplate.IsPoolingEnabled ? 3 : 4, count);
Assert.AreEqual(FeatureConfiguration.FrameworkTemplate.IsPoolingEnabled ? 3 : 8, count);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UI.Tests/Windows_UI_Xaml/Given_FrameworkTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ public void Init()
_previousPoolingEnabled = FrameworkTemplatePool.IsPoolingEnabled;
FrameworkTemplatePool.Instance.SetPlatformProvider(_mockProvider = new());

FrameworkTemplatePool.IsPoolingEnabled = true;
FrameworkTemplatePool.InternalIsPoolingEnabled = true;
}

[TestCleanup]
public void Cleanup()
{
FrameworkTemplatePool.IsPoolingEnabled = _previousPoolingEnabled;
FrameworkTemplatePool.InternalIsPoolingEnabled = _previousPoolingEnabled;
FrameworkTemplatePool.Instance.SetPlatformProvider(null);
FrameworkTemplatePool.Scavenge();
}
Expand Down
37 changes: 28 additions & 9 deletions src/Uno.UI/UI/Xaml/FrameworkTemplatePool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#else
using View = Microsoft.UI.Xaml.UIElement;
using ViewGroup = Microsoft.UI.Xaml.UIElement;
using System.Text;
using System.Runtime.CompilerServices;
#endif


Expand Down Expand Up @@ -87,6 +89,7 @@ public static class TraceProvider

private readonly Dictionary<FrameworkTemplate, List<TemplateEntry>> _pooledInstances = new Dictionary<FrameworkTemplate, List<TemplateEntry>>(FrameworkTemplate.FrameworkTemplateEqualityComparer.Default);
private IFrameworkTemplatePoolPlatformProvider _platformProvider = new FrameworkTemplatePoolDefaultPlatformProvider();
private static bool _isPoolingEnabled;

#if USE_HARD_REFERENCES
/// <summary>
Expand All @@ -112,12 +115,28 @@ public static class TraceProvider
/// Determines if the pooling is enabled. If false, all requested instances are new.
/// </summary>
/// <remarks>
/// Disabled by default on Android. See: https://github.com/unoplatform/uno/issues/13969
/// This feature is currently disabled and has no effect. See: https://github.com/unoplatform/uno/issues/13969
/// </remarks>
public static bool IsPoolingEnabled { get; set; }
#if !__ANDROID__
= true;
#endif
public static bool IsPoolingEnabled
{
// Pooling is forced disabled, see InternalIsPoolingEnabled.
get => false;
set
{
if (typeof(FrameworkTemplatePool).Log().IsEnabled(LogLevel.Warning))
{
typeof(FrameworkTemplatePool).Log().LogWarn($"Template pooling is disabled in this build of Uno Platform. See https://github.com/unoplatform/uno/issues/13969");
}
}
}

// Pooling is disabled until https://github.com/unoplatform/uno/issues/13969 is fixed, but we
// allow some runtime tests to use it.
internal static bool InternalIsPoolingEnabled
{
get => _isPoolingEnabled;
set => _isPoolingEnabled = value;
}

/// <summary>
/// Gets a value indicating whether the pool is currently recycling a template.
Expand Down Expand Up @@ -240,12 +259,12 @@ internal int GetPooledTemplatesCount()

if (this.Log().IsEnabled(Uno.Foundation.Logging.LogLevel.Debug))
{
this.Log().Debug($"Creating new template, id={GetTemplateDebugId(template)} IsPoolingEnabled:{IsPoolingEnabled}");
this.Log().Debug($"Creating new template, id={GetTemplateDebugId(template)} IsPoolingEnabled:{_isPoolingEnabled}");
}

instance = ((IFrameworkTemplateInternal)template).LoadContent();

if (IsPoolingEnabled && instance is IFrameworkElement)
if (_isPoolingEnabled && instance is IFrameworkElement)
{
DependencyObjectExtensions.RegisterParentChangedCallback((DependencyObject)instance, template, OnParentChanged);
}
Expand All @@ -268,7 +287,7 @@ internal int GetPooledTemplatesCount()
}

#if USE_HARD_REFERENCES
if (IsPoolingEnabled && instance is { })
if (_isPoolingEnabled && instance is { })
{
_activeInstances.Add(instance);
}
Expand Down Expand Up @@ -366,7 +385,7 @@ private void OnParentChanged(object instance, object? key, DependencyObjectParen

private void TryReuseTemplateRoot(object instance, object? key, object? newParent, bool shouldCleanUpTemplateRoot)
{
if (!IsPoolingEnabled)
if (!_isPoolingEnabled)
{
return;
}
Expand Down
Loading