8000 Enable more nullable annotations in WebCmdlets (#19359) · PowerShell/PowerShell@543b20b · GitHub
[go: up one dir, main page]

Skip to content

Commit 543b20b

Browse files
authored
Enable more nullable annotations in WebCmdlets (#19359)
1 parent 3547aca commit 543b20b

14 files changed

+105
-74
lines changed

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
#nullable enable
5+
46
using System.Collections.Generic;
57
using System.Diagnostics;
8+
using System.Diagnostics.CodeAnalysis;
69
using System.IO;
710
using System.Management.Automation;
811
using System.Net.Http;
@@ -33,7 +36,7 @@ public BasicHtmlWebResponseObject(HttpResponseMessage response, CancellationToke
3336
/// <param name="response">The response.</param>
3437
/// <param name="contentStream">The content stream associated with the response.</param>
3538
/// <param name="cancellationToken">Cancellation token.</param>
36-
public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentStream, CancellationToken cancellationToken) : base(response, contentStream, cancellationToken)
39+
public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream? contentStream, CancellationToken cancellationToken) : base(response, contentStream, cancellationToken)
3740
{
3841
InitializeContent(cancellationToken);
3942
InitializeRawContent(response);
@@ -60,9 +63,9 @@ public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentSt
6063
/// Encoding of the response body from the <c>Content-Type</c> header,
6164
/// or <see langword="null"/> if the encoding could not be determined.
6265
/// </value>
63-
public Encoding Encoding { get; private set; }
66+
public Encoding? Encoding { get; private set; }
6467

65-
private WebCmdletElementCollection _inputFields;
68+
private WebCmdletElementCollection? _inputFields;
6669

6770
/// <summary>
6871
/// Gets the HTML input field elements parsed from <see cref="Content"/>.
@@ -87,7 +90,7 @@ public WebCmdletElementCollection InputFields
8790
}
8891
}
8992

90-
private WebCmdletElementCollection _links;
93+
private WebCmdletElementCollection? _links;
9194

9295
/// <summary>
9396
/// Gets the HTML a link elements parsed from <see cref="Content"/>.
@@ -112,7 +115,7 @@ public WebCmdletElementCollection Links
112115
}
113116
}
114117

115-
private WebCmdletElementCollection _images;
118+
private WebCmdletElementCollection? _images;
116119

117120
/// <summary>
118121
/// Gets the HTML img elements parsed from <see cref="Content"/>.
@@ -145,13 +148,14 @@ public WebCmdletElementCollection Images
145148
/// Reads the response content from the web response.
146149
/// </summary>
147150
/// <param name="cancellationToken">The cancellation token.</param>
151+
[MemberNotNull(nameof(Content))]
148152
protected void InitializeContent(CancellationToken cancellationToken)
149153
{
150-
string contentType = ContentHelper.GetContentType(BaseResponse);
154+
string? contentType = ContentHelper.GetContentType(BaseResponse);
151155
if (ContentHelper.IsText(contentType))
152156
{
153157
// Fill the Content buffer
154-
string characterSet = WebResponseHelper.GetCharacterSet(BaseResponse);
158+
string? characterSet = WebResponseHelper.GetCharacterSet(BaseResponse);
155159

156160
Content = StreamHelper.DecodeStream(RawContentStream, characterSet, out Encoding encoding, cancellationToken);
157161
Encoding = encoding;
@@ -204,7 +208,7 @@ private static void ParseAttributes(string outerHtml, PSObject elementObject)
204208
string name = nvMatches.Groups[1].Value;
205209

206210
// The value (if any) is captured by group #2, #3, or #4, depending on quoting or lack thereof
207-
string value = null;
211+
string? value = null;
208212
if (nvMatches.Groups[2].Success)
209213
{
210214
value = nvMatches.Groups[2].Value;

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
#nullable enable
5+
46
using System;
7+
using System.Diagnostics.CodeAnalysis;
58
using System.Management.Automation;
69
using System.Net.Http;
710
using System.Net.Http.Headers;
@@ -16,7 +19,7 @@ internal static class ContentHelper
1619
#region Internal Methods
1720

1821
// ContentType may not exist in response header. Return null if not.
19-
internal static string GetContentType(HttpResponseMessage response) => response.Content.Headers.ContentType?.MediaType;
22+
internal static string? GetContentType(HttpResponseMessage response) => response.Content.Headers.ContentType?.MediaType;
2023

2124
internal static Encoding GetDefaultEncoding() => Encoding.UTF8;
2225

@@ -35,7 +38,7 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response)
3538
HttpHeaders[] headerCollections =
3639
{
3740
response.Headers,
38-
response.Content?.Headers
41+
response.Content.Headers
3942
};
4043

4144
foreach (var headerCollection in headerCollections)
@@ -59,7 +62,7 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response)
5962
return raw;
6063
}
6164

62-
internal static bool IsJson(string contentType)
65+
internal static bool IsJson([NotNullWhen(true)] string? contentType)
6366
{
6467
if (string.IsNullOrEmpty(contentType))
6568
{
@@ -80,7 +83,7 @@ internal static bool IsJson(string contentType)
8083
return isJson;
8184
}
8285

83-
internal static bool IsText(string contentType)
86+
internal static bool IsText([NotNullWhen(true)] string? contentType)
8487
{
8588
if (string.IsNullOrEmpty(contentType))
8689
{
@@ -96,19 +99,18 @@ internal static bool IsText(string contentType)
9699
if (Platform.IsWindows && !isText)
97100
{
98101
// Media types registered with Windows as having a perceived type of text, are text
99-
using (RegistryKey contentTypeKey = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type\" + contentType))
102+
using (RegistryKey? contentTypeKey = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type\" + contentType))
100103
{
101104
if (contentTypeKey != null)
102105
{
103-
string extension = contentTypeKey.GetValue("Extension") as string;
104-
if (extension != null)
106+
if (contentTypeKey.GetValue("Extension") is string extension)
105107
{
106-
using (RegistryKey extensionKey = Registry.ClassesRoot.OpenSubKey(extension))
108+
using (RegistryKey? extensionKey = Registry.ClassesRoot.OpenSubKey(extension))
107109
{
108110
if (extensionKey != null)
109111
{
110-
string perceivedType = extensionKey.GetValue("PerceivedType") as string;
111-
isText = (perceivedType == "text");
112+
string? perceivedType = extensionKey.GetValue("PerceivedType") as string;
113+
isText = perceivedType == "text";
112114
}
113115
}
114116
}
@@ -119,7 +121,7 @@ internal static bool IsText(string contentType)
119121
return isText;
120122
}
121123

122-
internal static bool IsXml(string contentType)
124+
internal static bool IsXml([NotNullWhen(true)] string? contentType)
123125
{
124126
if (string.IsNullOrEmpty(contentType))
125127
{

src/Microsoft.PowerShell.Commands.Utility/command 2851 s/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
#nullable enable
5+
46
using System;
7+
using System.Diagnostics.CodeAnalysis;
58
using System.IO;
69
using System.Management.Automation;
710
using System.Net.Http;
@@ -56,13 +59,13 @@ public int MaximumFollowRelLink
5659
/// </summary>
5760
[Parameter]
5861
[Alias("RHV")]
59-
public string ResponseHeadersVariable { get; set; }
62+
public string? ResponseHeadersVariable { get; set; }
6063

6164
/// <summary>
6265
/// Gets or sets the variable name to use for storing the status code from the response.
6366
/// </summary>
6467
[Parameter]
65-
public string StatusCodeVariable { get; set; }
68+
public string? StatusCodeVariable { get; set; }
6669

6770
#endregion Parameters
6871

@@ -95,12 +98,12 @@ internal override void ProcessResponse(HttpResponseMessage response)
9598
RestReturnType returnType = CheckReturnType(response);
9699

97100
// Try to get the response encoding from the ContentType header.
98-
string charSet = WebResponseHelper.GetCharacterSet(response);
101+
string? characterSet = WebResponseHelper.GetCharacterSet(response);
99102

100-
string str = StreamHelper.DecodeStream(responseStream, charSet, out Encoding encoding, _cancelToken.Token);
103+
string str = StreamHelper.DecodeStream(responseStream, characterSet, out Encoding encoding, _cancelToken.Token);
101104

102-
object obj = null;
103-
Exception ex = null;
105+
object? obj = null;
106+
Exception? ex = null;
104107

105108
string encodingVerboseName;
106109
try
@@ -167,7 +170,7 @@ private static RestReturnType CheckReturnType(HttpResponseMessage response)
167170
ArgumentNullException.ThrowIfNull(response);
168171

169172
RestReturnType rt = RestReturnType.Detect;
170-
string contentType = ContentHelper.GetContentType(response);
173+
string? contentType = ContentHelper.GetContentType(response);
171174
if (string.IsNullOrEmpty(contentType))
172175
{
173176
rt = RestReturnType.Detect;
@@ -223,7 +226,7 @@ private bool TryProcessFeedStream(Stream responseStream)
223226
)
224227
{
225228
// This one will do reader.Read() internally
226-
XmlNode result = workingDocument.ReadNode(reader);
229+
XmlNode? result = workingDocument.ReadNode(reader);
227230
WriteObject(result);
228231
}
229232
else
@@ -262,7 +265,7 @@ private static XmlReaderSettings GetSecureXmlReaderSettings()
262265
return xrs;
263266
}
264267

265-
private static bool TryConvertToXml(string xml, out object doc, ref Exception exRef)
268+
private static bool TryConvertToXml(string xml, [NotNullWhen(true)] out object? doc, ref Exception? exRef)
266269
{
267270
try
268271
{
@@ -284,13 +287,12 @@ private static bool TryConvertToXml(string xml, out object doc, ref Exception ex
284287
return doc != null;
285288
}
286289

287-
private static bool TryConvertToJson(string json, out object obj, ref Exception exRef)
290+
private static bool TryConvertToJson(string json, [NotNullWhen(true)] out object? obj, ref Exception? exRef)
288291
{
289292
bool converted = false;
290293
try
291294
{
292-
ErrorRecord error;
293-
obj = JsonObject.ConvertFromJson(json, out error);
295+
obj = JsonObject.ConvertFromJson(json, out ErrorRecord error);
294296

295297
if (obj == null)
296298
{
@@ -340,7 +342,7 @@ public enum RestReturnType
340342
/// <summary>
341343
/// Json return type.
342344
/// </summary>
343-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
345+
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
344346
Json,
345347

346348
/// <summary>

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebResponseObject.Common.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
#nullable enable
5+
46
using System;
57
using System.Collections.Generic;
68
using System.Diagnostics.CodeAnalysis;
@@ -26,22 +28,22 @@ public class WebResponseObject
2628
/// <summary>
2729
/// Gets or protected sets the response body content.
2830
/// </summary>
29-
public byte[] Content { get; protected set; }
31+
public byte[]? Content { get; protected set; }
3032

3133
/// <summary>
3234
/// Gets the Headers property.
3335
/// </summary>
3436
public Dictionary<string, IEnumerable<string>> Headers => _headers ??= WebResponseHelper.GetHeadersDictionary(BaseResponse);
3537

36-
private Dictionary<string, IEnumerable<string>> _headers = null;
38+
private Dictionary<string, IEnumerable<string>>? _headers;
3739

3840
/// <summary>
3941
/// Gets or protected sets the full response content.
4042
/// </summary>
4143
/// <value>
4244
/// Full response content, including the HTTP status line, headers, and body.
4345
/// </value>
44-
public string RawContent { get; protected set; }
46+
public string? RawContent { get; protected set; }
4547

4648
/// <summary>
4749
/// Gets the length (in bytes) of <see cref="RawContentStream"/>.
@@ -56,7 +58,7 @@ public class WebResponseObject
5658
/// <summary>
5759
/// Gets the RelationLink property.
5860
/// </summary>
59-
public Dictionary<string, string> RelationLink { get; internal set; }
61+
public Dictionary<string, string>? RelationLink { get; internal set; }
6062

6163
/// <summary>
6264
/// Gets the response status code.
@@ -77,8 +79,7 @@ public class WebResponseObject
7779
/// </summary>
7880
/// <param name="response">The Http response.</param>
7981
/// <param name="cancellationToken">The cancellation token.</param>
80-
public WebResponseObject(HttpResponseMessage response, CancellationToken cancellationToken) : this(response, null, cancellationToken)
81-
{ }
82+
public WebResponseObject(HttpResponseMessage response, CancellationToken cancellationToken) : this(response, null, cancellationToken) { }
8283

8384
/// <summary>
8485
/// Initializes a new instance of the <see cref="WebResponseObject"/> class
@@ -87,7 +88,7 @@ public WebResponseObject(HttpResponseMessage response, CancellationToken cancell
8788
/// <param name="response">Http response.</param>
8889
/// <param name="contentStream">The http content stream.</param>
8990
/// <param name="cancellationToken">The cancellation token.</param>
90-
public WebResponseObject(HttpResponseMessage response, Stream contentStream, CancellationToken cancellationToken)
91+
public WebResponseObject(HttpResponseMessage response, Stream? contentStream, CancellationToken cancellationToken)
9192
{
9293
SetResponse(response, contentStream, cancellationToken);
9394
InitializeContent();
@@ -111,9 +112,9 @@ private void InitializeRawContent(HttpResponseMessage baseResponse)
111112
StringBuilder raw = ContentHelper.GetRawContentHeader(baseResponse);
112113

113114
// Use ASCII encoding for the RawContent visual view of the content.
114-
if (Content.Length > 0)
115+
if (Content?.Length > 0)
115116
{
116-
raw.Append(this.ToString());
117+
raw.Append(ToString());
117118
}
118119

119120
RawContent = raw.ToString();
@@ -125,26 +126,23 @@ private static bool IsPrintable(char c) => char.IsLetterOrDigit(c)
125126
|| char.IsSymbol(c)
126127
|| char.IsWhiteSpace(c);
127128

128-
private void SetResponse(HttpResponseMessage response, Stream contentStream, CancellationToken cancellationToken)
129+
[MemberNotNull(nameof(RawContentStream))]
130+
[MemberNotNull(nameof(BaseResponse))]
131+
private void SetResponse(HttpResponseMessage response, Stream? contentStream, CancellationToken cancellationToken)
129132
{
130133
ArgumentNullException.ThrowIfNull(response);
131134

132135
BaseResponse = response;
133136

134-
MemoryStream ms = contentStream as MemoryStream;
135-
if (ms is not null)
137+
if (contentStream is MemoryStream ms)
136138
{
137139
RawContentStream = ms;
138140
}
139141
else
140142
{
141-
Stream st = contentStream;
142-
if (contentStream is null)
143-
{
144-
st = StreamHelper.GetResponseStream(response, cancellationToken);
145-
}
143+
Stream st = contentStream ?? StreamHelper.GetResponseStream(response, cancellationToken);
146144

147-
long contentLength = response.Content.Headers.ContentLength.Value;
145+
long contentLength = response.Content.Headers.ContentLength.GetValueOrDefault();
148146
if (contentLength <= 0)
149147
{
150148
contentLength = StreamHelper.DefaultReadBuffer;
@@ -164,7 +162,12 @@ private void SetResponse(HttpResponseMessage response, Stream contentStream, Can
164162
/// <returns>The string representation of this web response.</returns>
165163
public sealed override string ToString()
166164
{
167-
char[] stringContent = System.Text.Encoding.ASCII.GetChars(Content);
165+
if (Content is null)
166+
{
167+
return string.Empty;
168+
}
169+
170+
char[] stringContent = Encoding.ASCII.GetChars(Content);
168171
for (int counter = 0; counter < stringContent.Length; counter++)
169172
{
170173
if (!IsPrintable(stringContent[counter]))

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/HttpKnownHeaderNames.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
#nullable enable
5+
46
using System;
57
using System.Collections.Generic;
68

0 commit comments

Comments
 (0)
0