Skip to content

Add nullable annotations to Http.Abstractions, Http.Features, Connections.Abstractions #18084

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

Closed
wants to merge 2 commits into from

Conversation

JamesNK
Copy link
Member

@JamesNK JamesNK commented Jan 2, 2020

Addresses #5680

Annotations on projects at the bottom of the dependency tree. Because I haven't converted the tests there may be some types that are not null but should be. Should discover those as more projects are annotated.

@@ -14,9 +15,9 @@ protected BaseHeaderParser(bool supportsMultipleValues)

protected abstract int GetParsedValueLength(StringSegment value, int startIndex, out T parsedValue);

public sealed override bool TryParseValue(StringSegment value, ref int index, out T parsedValue)
public sealed override bool TryParseValue(StringSegment value, ref int index, [MaybeNullWhen(false)]out T parsedValue)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like TryParseValue can return true even in cases where parsedValue is never set if SupportsMultipleValues is also true.

@@ -27,7 +28,7 @@ public bool SupportsMultipleValues
// pointing to the next non-whitespace character after a delimiter. E.g. if called with a start index of 0
// for string "value , second_value", then after the call completes, 'index' must point to 's', i.e. the first
// non-whitespace after the separator ','.
public abstract bool TryParseValue(StringSegment value, ref int index, out T parsedValue);
public abstract bool TryParseValue(StringSegment value, ref int index, [NotNullWhen(true)]out T parsedValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the type be marked nullable when using attributes like NotNullWhen?

Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you plan to handle microsoft.extensions.activatorutilities.sources?

@@ -31,12 +31,12 @@ public class CacheControlHeaderValue
// Cache-Control headers, only one instance of CacheControlHeaderValue is created (if all headers contain valid
// values, otherwise we may have multiple strings containing the invalid values).
private static readonly HttpHeaderParser<CacheControlHeaderValue> Parser
= new GenericHeaderParser<CacheControlHeaderValue>(true, GetCacheControlLength);
= new GenericHeaderParser<CacheControlHeaderValue>(true, GetCacheControlLength!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error	CS8622	Nullability of reference types in type of parameter 'parsedValue' of 'int CacheControlHeaderValue.GetCacheControlLength(StringSegment input, int startIndex, out CacheControlHeaderValue? parsedValue)' doesn't match the target delegate 'GenericHeaderParser<CacheControlHeaderValue>.GetParsedValueLengthDelegate'.	Microsoft.Net.Http.Headers	D:\github\AspNetCore\src\Http\Headers\src\CacheControlHeaderValue.cs	34	Active

This seems like something the tooling should be able to handle?

internal delegate int GetParsedValueLengthDelegate(StringSegment value, int startIndex, [MaybeNull]out T parsedValue);
int GetCacheControlLength(StringSegment input, int startIndex, out CacheControlHeaderValue? parsedValue)

Or is the issue that T is unconstrained and could be a value type?

@@ -605,7 +604,7 @@ private static bool TrySetTimeSpan(NameValueHeaderValue nameValue, ref TimeSpan?
{
Contract.Requires(nameValue != null);

if (nameValue.Value == null)
if (nameValue!.Value == null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning goes away if you remove Contract.Requires. These are redundant now and could be removed.

@@ -142,7 +143,7 @@ public StringSegment FileNameStar
else
{
string sizeString = value.GetValueOrDefault().ToString(CultureInfo.InvariantCulture);
_parameters.Add(new NameValueHeaderValue(SizeString, sizeString));
_parameters!.Add(new NameValueHeaderValue(SizeString, sizeString));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an actual bug. NameValueHeaderValue.Find allows _parameters to be null. new ContentDispositionHeaderValue("foo") { Size = 1 } throws

    System.NullReferenceException : Object reference not set to an instance of an object.
  Stack Trace: 
    ContentDispositionHeaderValue.set_Size(Nullable`1 value) line 146

The fix would be to use Parameters.Add instead.

@@ -41,15 +41,15 @@ internal static void SetQuality(IList<NameValueHeaderValue> parameters, double?
}
else
{
parameters.Add(new NameValueHeaderValue(QualityName, qualityString));
parameters!.Add(new NameValueHeaderValue(QualityName, qualityString));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue with Contract.Requires.

@@ -166,7 +167,7 @@ public virtual string ToString(object value)
{
Contract.Requires(value != null);

return value.ToString();
return value!.ToString()!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue with Contract.Requires.

@@ -205,7 +206,7 @@ public IList<NameValueHeaderValue> Parameters
/// </summary>
public double? Quality
{
get { return HeaderUtilities.GetQuality(_parameters); }
get { return HeaderUtilities.GetQuality(Parameters); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetQuality is wrong in this case, it works just fine if parameters is null, the Contract.Requires can be removed and paramters can be marked as nullable. There's no point in allocating an empty Paramaters collection just to search it for a property we know isn't there.


if (nameValueLength == 0)
{
// There may be a trailing ';'
return current - startIndex;
}

nameValueCollection.Add(parameter);
nameValueCollection!.Add(parameter!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Contract.Requires issue.

@@ -121,7 +121,7 @@ public override int GetHashCode()
return 0;
}

rangeCollection.Add(range);
rangeCollection!.Add(range!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contract.Requires

@rynowak rynowak added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jan 6, 2020
@@ -14,9 +15,9 @@ protected BaseHeaderParser(bool supportsMultipleValues)

protected abstract int GetParsedValueLength(StringSegment value, int startIndex, out T parsedValue);

public sealed override bool TryParseValue(StringSegment value, ref int index, out T parsedValue)
public sealed override bool TryParseValue(StringSegment value, ref int index, [MaybeNullWhen(false)]out T parsedValue)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public sealed override bool TryParseValue(StringSegment value, ref int index, [MaybeNullWhen(false)]out T parsedValue)
public sealed override bool TryParseValue(StringSegment value, ref int index, [MaybeNullWhen(false)] out T parsedValue)

nit: I prefer a space here, though I'm willing to be overruled

@rynowak
Copy link
Member

rynowak commented Jan 7, 2020

API review YO

@analogrelay
Copy link
Contributor

Sounds like there are some build issues with using nullable annotations here. @JamesNK you can check in with @dotnet/aspnet-build and see if we can figure this out?

@analogrelay analogrelay added this to the 5.0.0-preview2 milestone Feb 19, 2020
@wtgodbe
Copy link
Member

wtgodbe commented Feb 19, 2020

/azp run

@azure-pipelines
Copy link

Pull request contains merge conflicts.

@dougbu
Copy link
Contributor

dougbu commented Feb 20, 2020

Sounds like there are some build issues with using nullable annotations here.

@anurse something beyond the missing Contract.Requires(...) calls that @Tratcher mentioned? Could you be a bit more specific?

@analogrelay
Copy link
Contributor

analogrelay commented Feb 20, 2020

That's just what @JamesNK said in Triage ;).

@halter73 halter73 closed this Feb 24, 2020
@JamesNK
Copy link
Member Author

JamesNK commented Feb 24, 2020

No immediate plans to look at this. Can re-open when I have time in the future.

@dougbu dougbu deleted the jamesnk/nullable-httpabstractions branch May 18, 2020 19:44
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants