Skip to content
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1,122 changes: 563 additions & 559 deletions .editorconfig

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
<!-- MAUI version varies by target framework -->
<PropertyGroup>
<MauiVersion Condition="$(TargetFramework.StartsWith('net10'))">10.0.90</MauiVersion>
<MauiVersion Condition="$(TargetFramework.StartsWith('net11'))">11.0.0-preview.6.26360.8</MauiVersion>
<MauiVersion Condition="$(TargetFramework.StartsWith('net11'))">11.0.0-preview.7.26406.9</MauiVersion>
</PropertyGroup>

<PropertyGroup>
<!-- StyleSharp.Analyzers, PerformanceSharp.Analyzers and SecuritySharp.Analyzers ship from the
same release pipeline and always share a version. -->
<RoslynCommonAnalyzersVersion>3.39.2</RoslynCommonAnalyzersVersion>
<RoslynCommonAnalyzersVersion>3.45.0</RoslynCommonAnalyzersVersion>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -55,7 +55,8 @@

<!-- Dependencies -->
<PackageVersion Include="Splat" Version="21.0.0"/>
<PackageVersion Include="ReactiveUI.Primitives" Version="7.1.1"/>
<PackageVersion Include="ReactiveUI.Primitives" Version="7.2.0"/>
<PackageVersion Include="ReactiveUI.Primitives.Reactive" Version="7.2.0"/>
<PackageVersion Include="System.Reactive" Version="7.0.0"/>

<!-- Build Tools -->
Expand Down
19 changes: 5 additions & 14 deletions src/ReactiveUI.Binding.Analyzer/Analyzers/AnalyzerHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,9 @@ internal static class AnalyzerHelpers
/// <param name="methodSymbol">The method symbol to check.</param>
/// <returns>true if the method is from our generated extension class.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsBindingExtensionMethod(IMethodSymbol methodSymbol)
{
var containingType = methodSymbol.ContainingType;
if (containingType is null)
{
return false;
}

var name = containingType.Name;
return name is SourceGenerators.Constants.GeneratedExtensionClassName
internal static bool IsBindingExtensionMethod(IMethodSymbol methodSymbol) =>
methodSymbol.ContainingType?.Name is SourceGenerators.Constants.GeneratedExtensionClassName
or SourceGenerators.Constants.StubExtensionClassName;
}

/// <summary>Checks if an expression is an inline lambda (not a variable reference or method call).</summary>
/// <param name="expression">The expression to check.</param>
Expand Down Expand Up @@ -125,7 +116,7 @@ internal static bool LacksObservableMechanism(
out INamedTypeSymbol? sourceType)
{
sourceType = ExtractFirstTypeArgument(methodSymbol);
return sourceType is null ? false : !TypeAnalyzer.HasObservableMechanism(sourceType, compilation);
return sourceType is not null && !TypeAnalyzer.HasObservableMechanism(sourceType, compilation);
}

/// <summary>
Expand All @@ -145,7 +136,7 @@ internal static bool LacksBeforeChangeSupport(
{
mechanism = string.Empty;
receiverType = ExtractFirstTypeArgument(methodSymbol);
return receiverType is null ? false : !HasBeforeChangeSupport(receiverType, compilation, out mechanism);
return receiverType is not null && !HasBeforeChangeSupport(receiverType, compilation, out mechanism);
}

/// <summary>
Expand All @@ -171,7 +162,7 @@ internal static bool ImplementsDataErrorInfo(

var dataErrorInfo =
compilation.GetTypeByMetadataName(SourceGenerators.Constants.INotifyDataErrorInfoMetadataName);
return dataErrorInfo is null ? false : ImplementsInterface(sourceType, dataErrorInfo);
return dataErrorInfo is not null && ImplementsInterface(sourceType, dataErrorInfo);
}

/// <summary>Determines whether a type implements a specific interface.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal static void AnalyzeInvocation(in OperationAnalysisContext context)
var arguments = invocationOp.Arguments;

// Check RXUIBIND001: Non-inline lambda
CheckNonInlineLambda(context, arguments, methodName);
CheckNonInlineLambda(context, arguments);

// Check RXUIBIND003: Private/protected member access
CheckPrivateMember(context, arguments);
Expand Down Expand Up @@ -95,11 +95,9 @@ internal static void AnalyzeInvocation(in OperationAnalysisContext context)
/// <summary>Checks for RXUIBIND001: Expression arguments that are not inline lambdas.</summary>
/// <param name="context">The operation analysis context.</param>
/// <param name="arguments">The invocation arguments to inspect.</param>
/// <param name="methodName">The name of the method being invoked.</param>
internal static void CheckNonInlineLambda(
in OperationAnalysisContext context,
ImmutableArray<IArgumentOperation> arguments,
string methodName)
ImmutableArray<IArgumentOperation> arguments)
{
// Find the Expression<Func<...>> arguments
for (var i = 0; i < arguments.Length; i++)
Expand Down Expand Up @@ -458,22 +456,13 @@ internal static void WalkForUnsupportedSegments(
}

/// <summary>Extracts the body expression from a lambda expression syntax node.</summary>
/// <remarks>Only <see cref="SimpleLambdaExpressionSyntax"/> and <see cref="ParenthesizedLambdaExpressionSyntax"/> exist in Roslyn's C# syntax model.</remarks>
/// <param name="lambda">The lambda expression syntax node to extract the body from.</param>
/// <returns>
/// The body as an <see cref="ExpressionSyntax"/>, or <c>null</c> if the lambda body is a block statement.
/// </returns>
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
internal static ExpressionSyntax? GetLambdaBody(LambdaExpressionSyntax lambda)
{
if (lambda is SimpleLambdaExpressionSyntax simple)
{
return simple.Body as ExpressionSyntax;
}

var parenthesized = (ParenthesizedLambdaExpressionSyntax)lambda;
return parenthesized.Body as ExpressionSyntax;
}
internal static ExpressionSyntax? GetLambdaBody(LambdaExpressionSyntax lambda) =>
lambda.Body as ExpressionSyntax;

/// <summary>Determines whether a non-empty constant <c>toEvent</c> argument was explicitly supplied.</summary>
/// <param name="arguments">The invocation arguments to inspect.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
</ItemGroup>

<ItemGroup>
<Using Include="ReactiveUI.Primitives.Disposables"/>
<Using Include="System"/>
<Using Include="System.ComponentModel"/>
<Using Include="System.Diagnostics"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ public enum BooleanToVisibilityHints
Inverse = 1 << 1,

/// <summary>Use the Hidden value rather than Collapsed (MAUI only; ignored on WinUI where Hidden is not available).</summary>
UseHidden = 1 << 2
UseHidden = 1 << 2,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;
using Splat.Builder;

#if REACTIVE_SHIM
Expand All @@ -22,6 +23,7 @@ public static class MauiBindingBuilderExtensions
/// observation (on Windows) and Visibility converters.
/// </summary>
/// <returns>The builder instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IReactiveUIBindingBuilder WithMaui() =>
((IReactiveUIBindingBuilder)builder).WithMaui();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang

var dependencyProperty = dependencyPropertyFetcher();
var token = depSender.RegisterPropertyChangedCallback(dependencyProperty, handler);
return new ActionDisposable<(DependencyObject sender, DependencyProperty property, long token)>(
return Scope.Create<(DependencyObject Sender, DependencyProperty Property, long Token)>(
(depSender, dependencyProperty, token),
static state => state.sender.UnregisterPropertyChangedCallback(state.property, state.token));
static state => state.Sender.UnregisterPropertyChangedCallback(state.Property, state.Token));
});
}

Expand Down
1 change: 1 addition & 0 deletions src/ReactiveUI.Binding.Maui/ReactiveUI.Binding.Maui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
</ItemGroup>

<ItemGroup>
<Using Include="ReactiveUI.Primitives.Disposables"/>
<Using Include="System"/>
<Using Include="System.ComponentModel"/>
<Using Include="System.Diagnostics"/>
Expand Down
48 changes: 0 additions & 48 deletions src/ReactiveUI.Binding.Platform.Shared/ActionDisposable{TState}.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ namespace ReactiveUI.Binding.Observables;
/// An observable whose subscription logic is supplied as a delegate, for the platform observers that
/// hook an event on subscribe and hand back the unhook as the subscription.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequence.</typeparam>
/// <remarks>
/// Each platform assembly compiles its own internal copy, so this stays off the public surface of every
/// package and out of the seam: it names no scheduler and no notification type.
/// </remarks>
/// <typeparam name="T">The type of the elements in the sequence.</typeparam>
internal sealed class AnonymousObservable<T> : IObservable<T>
{
/// <summary>Produces the subscription for an observer, returning the resource that tears it down.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
<!-- The shifted counterparts of the lean leaf's imports: the same shared files, recompiled here
under the ReactiveUI.Binding.Reactive.* namespaces. -->
<ItemGroup>
<Using Include="ReactiveUI.Primitives.Reactive"/>
<Using Include="ReactiveUI.Primitives.Reactive.Advanced"/>
<Using Include="ReactiveUI.Primitives.Reactive.Signals"/>
<Using Include="ReactiveUI.Primitives.Disposables"/>
<Using Include="ReactiveUI.Binding.Reactive.Builder"/>
<Using Include="ReactiveUI.Binding.Reactive.Expressions"/>
<Using Include="ReactiveUI.Binding.Reactive.Fallback"/>
Expand All @@ -34,7 +38,7 @@

<ItemGroup>
<PackageReference Include="Splat"/>
<PackageReference Include="System.Reactive"/>
<PackageReference Include="ReactiveUI.Primitives.Reactive"/>
</ItemGroup>

<!-- The runtime library is useless on its own: every API it exposes is a stub that throws unless the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace ReactiveUI.Binding;
/// object-based shim (<see cref="TryConvertTyped(object?, object?, out object?)"/>), allowing the dispatch
/// layer to avoid reflection.
/// </remarks>
[DebuggerDisplay("{FromType.Name,nq} -> {ToType.Name,nq} converter")]
public abstract class BindingTypeConverter<TFrom, TTo> : IBindingTypeConverter<TFrom, TTo>
{
/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;

#if REACTIVE_SHIM
namespace ReactiveUI.Binding.Reactive;
#else
namespace ReactiveUI.Binding;
#endif

/// <summary>Converts <see cref="byte"/> to a nullable <see cref="byte"/>.</summary>
[DebuggerDisplay("byte -> byte? (affinity {Affinity})")]
public sealed class ByteToNullableByteTypeConverter : IBindingTypeConverter<byte, byte?>
{
/// <summary>The affinity returned by <see cref="GetAffinityForObjects"/> indicating a strong match.</summary>
Expand All @@ -21,6 +24,7 @@ public sealed class ByteToNullableByteTypeConverter : IBindingTypeConverter<byte
public Type ToType => typeof(byte?);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetAffinityForObjects() => Affinity;

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;

#if REACTIVE_SHIM
namespace ReactiveUI.Binding.Reactive;
#else
namespace ReactiveUI.Binding;
#endif

/// <summary>Converts <see cref="decimal"/> to a nullable <see cref="decimal"/>.</summary>
[DebuggerDisplay("decimal -> decimal? (affinity {Affinity})")]
public sealed class DecimalToNullableDecimalTypeConverter : IBindingTypeConverter<decimal, decimal?>
{
/// <summary>The affinity returned by <see cref="GetAffinityForObjects"/> indicating a strong match.</summary>
Expand All @@ -21,6 +24,7 @@ public sealed class DecimalToNullableDecimalTypeConverter : IBindingTypeConverte
public Type ToType => typeof(decimal?);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetAffinityForObjects() => Affinity;

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;

#if REACTIVE_SHIM
namespace ReactiveUI.Binding.Reactive;
#else
namespace ReactiveUI.Binding;
#endif

/// <summary>Converts <see cref="double"/> to a nullable <see cref="double"/>.</summary>
[DebuggerDisplay("double -> double? (affinity {Affinity})")]
public sealed class DoubleToNullableDoubleTypeConverter : IBindingTypeConverter<double, double?>
{
/// <summary>The affinity returned by <see cref="GetAffinityForObjects"/> indicating a strong match.</summary>
Expand All @@ -21,6 +24,7 @@ public sealed class DoubleToNullableDoubleTypeConverter : IBindingTypeConverter<
public Type ToType => typeof(double?);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetAffinityForObjects() => Affinity;

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;

#if REACTIVE_SHIM
namespace ReactiveUI.Binding.Reactive;
#else
Expand All @@ -19,6 +21,7 @@ namespace ReactiveUI.Binding;
/// Example: Convert an enum value to bool by comparing with a specific enum member.
/// </para>
/// </remarks>
[DebuggerDisplay("{FromType.Name,nq} -> {ToType.Name,nq} by equality with the conversion hint")]
public sealed class EqualityTypeConverter : IBindingTypeConverter
{
/// <inheritdoc/>
Expand All @@ -28,6 +31,7 @@ public sealed class EqualityTypeConverter : IBindingTypeConverter
public Type ToType => typeof(bool);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetAffinityForObjects() => 1;

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;

#if REACTIVE_SHIM
namespace ReactiveUI.Binding.Reactive;
#else
namespace ReactiveUI.Binding;
#endif

/// <summary>Converts <see cref="int"/> to a nullable <see cref="int"/>.</summary>
[DebuggerDisplay("int -> int? (affinity {Affinity})")]
public sealed class IntegerToNullableIntegerTypeConverter : IBindingTypeConverter<int, int?>
{
/// <summary>The affinity returned by <see cref="GetAffinityForObjects"/> indicating a strong match.</summary>
Expand All @@ -21,6 +24,7 @@ public sealed class IntegerToNullableIntegerTypeConverter : IBindingTypeConverte
public Type ToType => typeof(int?);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetAffinityForObjects() => Affinity;

/// <inheritdoc/>
Expand Down
Loading
Loading