-
-
Notifications
You must be signed in to change notification settings - Fork 101
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
Support for nullable reference types #241
Comments
Any movement on this? |
This was harder than I thought, so I was focusing other issues. |
I have no idea to add nullability for that... class ReactiveProperty<T>
{
public T Value
{
get;
set;
}
public ReactiveProperty() : this(default)
{
}
public ReactiveProperty(T initialValue)
{
Value = initialValue;
}
} |
In My Opinion, There is no way to avoid big breaking changes. class ReactiveProperty<T>
{
public T Value { get; set; }
// public ReactiveProperty() : this(default){}
public ReactiveProperty(T initialValue)
{
Value = initialValue;
}
} usage //public ReactiveProperty<string> RName { get; } = new(); //compile error
public ReactiveProperty<string> RName { get; } = new(string.Empty);
public ReactiveProperty<string?> RName { get; } = new(default(string)); |
@soi013 |
I considered another way. How about using a partial Here is the Analyzer repository and nupkg that I made as a demo. https://github.com/soi013/ReactivePropertyAnalyzer/ This Analyzer also works with the current version of ReactiveProperty, and shows warnings where it is initialized with null. Partial Disabling nullable class ReactiveProperty<T>
{
public T Value { get; set; }
#nullable disable
public ReactiveProperty() : this(default){}
#nullable restore
public ReactiveProperty(T initialValue)
{
Value = initialValue;
}
} |
That's great!! |
I hadn't thought of that approach. It's very nice!! |
@soi013 I cloned the repository, and I tried it. It is really interesting. I just added a few lines to improve the analyzer. private void AnalyzeObjectCreationSyntax(SyntaxNodeAnalysisContext context)
{
if (context.Node is not ObjectCreationExpressionSyntax invocationExpr)
return;
if (invocationExpr.Type is not GenericNameSyntax geneSynatx)
return;
if (geneSynatx.Identifier.ValueText is not nameof(ReactiveProperty) or nameof(ReadOnlyReactivePropertySlim))
return;
var typeGenerigArg = geneSynatx.TypeArgumentList.Arguments.FirstOrDefault();
if (typeGenerigArg == null)
return;
var symbolGeneric = context.SemanticModel.GetSymbolInfo(typeGenerigArg).Symbol as INamedTypeSymbol;
if (symbolGeneric == null) return;
if (symbolGeneric.IsValueType != false) return;
if (typeGenerigArg is NullableTypeSyntax) return; // add
var arguments = invocationExpr.ArgumentList?.Arguments;
if (arguments?.Count != 0)
return;
var diagnostic = Diagnostic.Create(Rule, invocationExpr.GetLocation(), invocationExpr.ToString());
context.ReportDiagnostic(diagnostic);
}
private void AnalyzeImplicitObjectCreationSyntax(SyntaxNodeAnalysisContext context)
{
if (context.Node is not ImplicitObjectCreationExpressionSyntax invocationExpr)
return;
var typeSymbol = context.SemanticModel.GetTypeInfo(invocationExpr, context.CancellationToken).Type;
if (typeSymbol?.Name is not nameof(ReactiveProperty) or nameof(ReadOnlyReactivePropertySlim))
return;
var symbolGeneric = (typeSymbol as INamedTypeSymbol)?.TypeArguments.FirstOrDefault();
if (symbolGeneric?.IsValueType != false)
return;
if (symbolGeneric.NullableAnnotation == NullableAnnotation.Annotated) return; // add
var arguments = invocationExpr.ArgumentList?.Arguments;
if (arguments?.Count != 0)
return;
var diagnostic = Diagnostic.Create(Rule, invocationExpr.GetLocation(), invocationExpr.ToString());
context.ReportDiagnostic(diagnostic);
} I succeeded detecting nullability. I will work for supporting nullablity for ReactiveProperty. But it is still too hard. 😓 |
LGTM! But how to analyze of var source1 = new ReactiveProperty<string>("initialValue");
var roName1 = source1.ToReadOnlyReactiveProperty<string>(); //.Value is not null
var source2 = new ReactiveProperty<string>("initialValue", mode: ReactivePropertyMode.None);
var roNameNull = source2.ToReadOnlyReactiveProperty<string>(); //.Value is null
var roName2 = source2.ToReadOnlyReactiveProperty<string>("initialValue"); //.Value is not null |
😥 |
I also have not... |
This task is not interesting for me. So, please expect delay for this. |
@runceel any update on this one? Is it still low on your priority list? |
@gmkado I had added nullable annotations for minimum necessary usecases. If you are facing warnings of nullable reference. Please let me know. |
Hi @runceel , thanks for responding. Should the following interactive script give me compiler warnings? #r "nuget: ReactiveProperty, 9.1.2"
#nullable enable
using Reactive.Bindings;
public class Foo
{
public IReadOnlyReactiveProperty<string> Bar => _bar;
private readonly ReactivePropertySlim<string> _bar = new(); // <-- should this complain?
}
var x = new Foo();
x.Bar.Value.Contains("uh oh"); |
@gmkado |
@runceel I've never worked with CodeAnalyzer's before, but could you add a similar rule to the invocation of Alternatively, if you wanted to phase out the default constructor you could mark it as |
Thank you for your opinion. And I don't want to add I expect that the C# compiler will be improved in the future to detect more nullable warnings correctly. |
Are you referring to this? If so, is there any harm in adding the analyzer that catches this scenario? It may not catch 100% of null references, but it would definitely help catch most of them. Or are there more corner cases that you ran into that aren't in this thread? |
Yes, it is.
I am not inclined to implement this as I would originally want the C# compiler to detect it. If someone can make a PR for this, I can merge it and publish it to NuGet. |
Analyzer
The text was updated successfully, but these errors were encountered: