-
-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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: