From 4e9850879a20e6334380e16b86a02a03fab0a50c Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Wed, 4 Dec 2019 12:34:20 -0800 Subject: [PATCH 1/8] Annotate System.IO.FileSystem for nullable --- .../Windows/Kernel32/Interop.ReplaceFile.cs | 5 +- .../IO/FileSystem.Attributes.Windows.cs | 13 ++--- .../FileSystem.DirectoryCreation.Windows.cs | 10 ++-- .../ref/System.IO.FileSystem.cs | 48 +++++++++---------- .../ref/System.IO.FileSystem.csproj | 1 + .../src/System.IO.FileSystem.csproj | 1 + .../src/System/IO/Directory.cs | 14 +++--- .../src/System/IO/DirectoryInfo.cs | 14 +++--- .../IO/Enumeration/FileSystemEnumerable.cs | 10 ++-- .../Enumeration/FileSystemEnumerator.Win32.cs | 2 +- .../FileSystemEnumerator.Windows.cs | 6 +-- .../IO/Enumeration/FileSystemEnumerator.cs | 6 +-- .../System/IO/Enumeration/FileSystemName.cs | 2 +- .../src/System/IO/File.cs | 32 ++++++------- .../src/System/IO/FileInfo.cs | 14 +++--- .../src/System/IO/FileSystem.Win32.cs | 2 +- .../src/System/IO/FileSystem.Windows.cs | 4 +- .../src/System/IO/FileSystemInfo.cs | 6 +-- .../src/System/IO/Iterator.cs | 9 ++-- .../src/System/IO/ReadLinesIterator.cs | 6 +-- .../Kernel32/Interop.GetFileAttributesEx.cs | 4 +- .../src/System/IO/PathInternal.Windows.cs | 2 +- .../src/System/IO/PathInternal.cs | 10 ++-- 23 files changed, 110 insertions(+), 111 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs index 4b9dd79d5e3ec4..8ab349f9217004 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Runtime.InteropServices; @@ -12,11 +13,11 @@ internal partial class Kernel32 { [DllImport(Libraries.Kernel32, EntryPoint = "ReplaceFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] private static extern bool ReplaceFilePrivate( - string replacedFileName, string replacementFileName, string backupFileName, + string replacedFileName, string replacementFileName, string? backupFileName, int dwReplaceFlags, IntPtr lpExclude, IntPtr lpReserved); internal static bool ReplaceFile( - string replacedFileName, string replacementFileName, string backupFileName, + string replacedFileName, string replacementFileName, string? backupFileName, int dwReplaceFlags, IntPtr lpExclude, IntPtr lpReserved) { replacedFileName = PathInternal.EnsureExtendedPrefixIfNeeded(replacedFileName); diff --git a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs index 26cefbc63af52b..430b264b8fcf02 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs @@ -2,13 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; -using System; -using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; -using System.IO; -using System.Text; #if MS_IO_REDIST namespace Microsoft.IO @@ -18,12 +15,12 @@ namespace System.IO { internal static partial class FileSystem { - public static bool DirectoryExists(string fullPath) + public static bool DirectoryExists(string? fullPath) { return DirectoryExists(fullPath, out int lastError); } - private static bool DirectoryExists(string path, out int lastError) + private static bool DirectoryExists(string? path, out int lastError) { Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = default; lastError = FillAttributeInfo(path, ref data, returnErrorOnNotFound: true); @@ -52,7 +49,7 @@ public static bool FileExists(string fullPath) /// The file path from which the file attribute information will be filled. /// A struct that will contain the attribute information. /// Return the error code for not found errors? - internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound) + internal static int FillAttributeInfo(string? path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound) { int errorCode = Interop.Errors.ERROR_SUCCESS; @@ -97,7 +94,7 @@ internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FI // cases that we know we don't want to retry on. Interop.Kernel32.WIN32_FIND_DATA findData = default; - using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData)) + using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path!, ref findData)) { if (handle.IsInvalid) { diff --git a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs index f127e3da5eeaf6..f0a6a9ce4dfe9d 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs @@ -2,13 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; -using System; +#nullable enable using System.Collections.Generic; -using System.Diagnostics; using System.Runtime.InteropServices; -using System.IO; -using System.Text; #if MS_IO_REDIST namespace Microsoft.IO @@ -18,7 +14,7 @@ namespace System.IO { internal static partial class FileSystem { - public static unsafe void CreateDirectory(string fullPath, byte[] securityDescriptor = null) + public static unsafe void CreateDirectory(string fullPath, byte[]? securityDescriptor = null) { // We can save a bunch of work if the directory we want to create already exists. This also // saves us in the case where sub paths are inaccessible (due to ERROR_ACCESS_DENIED) but the @@ -126,7 +122,7 @@ public static unsafe void CreateDirectory(string fullPath, byte[] securityDescri // Handle CreateDirectory("X:\\") when X: doesn't exist. Similarly for n/w paths. if ((count == 0) && !somepathexists) { - string root = Path.GetPathRoot(fullPath); + string? root = Path.GetPathRoot(fullPath); if (!DirectoryExists(root)) { diff --git a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs index 898efd3bde5af7..0388e9aa100bb9 100644 --- a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs +++ b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs @@ -24,7 +24,7 @@ public static void Delete(string path, bool recursive) { } public static System.Collections.Generic.IEnumerable EnumerateFileSystemEntries(string path, string searchPattern) { throw null; } public static System.Collections.Generic.IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; } public static System.Collections.Generic.IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; } - public static bool Exists(string path) { throw null; } + public static bool Exists(string? path) { throw null; } public static System.DateTime GetCreationTime(string path) { throw null; } public static System.DateTime GetCreationTimeUtc(string path) { throw null; } public static string GetCurrentDirectory() { throw null; } @@ -32,7 +32,7 @@ public static void Delete(string path, bool recursive) { } public static string[] GetDirectories(string path, string searchPattern) { throw null; } public static string[] GetDirectories(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; } public static string[] GetDirectories(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; } - public static string GetDirectoryRoot(string path) { throw null; } + public static string? GetDirectoryRoot(string path) { throw null; } public static string[] GetFiles(string path) { throw null; } public static string[] GetFiles(string path, string searchPattern) { throw null; } public static string[] GetFiles(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; } @@ -46,7 +46,7 @@ public static void Delete(string path, bool recursive) { } public static System.DateTime GetLastWriteTime(string path) { throw null; } public static System.DateTime GetLastWriteTimeUtc(string path) { throw null; } public static string[] GetLogicalDrives() { throw null; } - public static System.IO.DirectoryInfo GetParent(string path) { throw null; } + public static System.IO.DirectoryInfo? GetParent(string path) { throw null; } public static void Move(string sourceDirName, string destDirName) { } public static void SetCreationTime(string path, System.DateTime creationTime) { } public static void SetCreationTimeUtc(string path, System.DateTime creationTimeUtc) { } @@ -61,7 +61,7 @@ public sealed partial class DirectoryInfo : System.IO.FileSystemInfo public DirectoryInfo(string path) { } public override bool Exists { get { throw null; } } public override string Name { get { throw null; } } - public System.IO.DirectoryInfo Parent { get { throw null; } } + public System.IO.DirectoryInfo? Parent { get { throw null; } } public System.IO.DirectoryInfo Root { get { throw null; } } public void Create() { } public System.IO.DirectoryInfo CreateSubdirectory(string path) { throw null; } @@ -111,10 +111,10 @@ public static void AppendAllLines(string path, System.Collections.Generic.IEnume public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task AppendAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task AppendAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static void AppendAllText(string path, string contents) { } - public static void AppendAllText(string path, string contents, System.Text.Encoding encoding) { } - public static System.Threading.Tasks.Task AppendAllTextAsync(string path, string contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static System.Threading.Tasks.Task AppendAllTextAsync(string path, string contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static void AppendAllText(string path, string? contents) { } + public static void AppendAllText(string path, string? contents, System.Text.Encoding encoding) { } + public static System.Threading.Tasks.Task AppendAllTextAsync(string path, string? contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task AppendAllTextAsync(string path, string? contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.IO.StreamWriter AppendText(string path) { throw null; } public static void Copy(string sourceFileName, string destFileName) { } public static void Copy(string sourceFileName, string destFileName, bool overwrite) { } @@ -125,7 +125,7 @@ public static void Copy(string sourceFileName, string destFileName, bool overwri public static void Decrypt(string path) { } public static void Delete(string path) { } public static void Encrypt(string path) { } - public static bool Exists(string path) { throw null; } + public static bool Exists(string? path) { throw null; } public static System.IO.FileAttributes GetAttributes(string path) { throw null; } public static System.DateTime GetCreationTime(string path) { throw null; } public static System.DateTime GetCreationTimeUtc(string path) { throw null; } @@ -153,8 +153,8 @@ public static void Move(string sourceFileName, string destFileName, bool overwri public static System.Threading.Tasks.Task ReadAllTextAsync(string path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Collections.Generic.IEnumerable ReadLines(string path) { throw null; } public static System.Collections.Generic.IEnumerable ReadLines(string path, System.Text.Encoding encoding) { throw null; } - public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName) { } - public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) { } + public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName) { } + public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors) { } public static void SetAttributes(string path, System.IO.FileAttributes fileAttributes) { } public static void SetCreationTime(string path, System.DateTime creationTime) { } public static void SetCreationTimeUtc(string path, System.DateTime creationTimeUtc) { } @@ -170,16 +170,16 @@ public static void WriteAllLines(string path, string[] contents) { } public static void WriteAllLines(string path, string[] contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task WriteAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task WriteAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static void WriteAllText(string path, string contents) { } - public static void WriteAllText(string path, string contents, System.Text.Encoding encoding) { } - public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static void WriteAllText(string path, string? contents) { } + public static void WriteAllText(string path, string? contents, System.Text.Encoding encoding) { } + public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string? contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public sealed partial class FileInfo : System.IO.FileSystemInfo { public FileInfo(string fileName) { } - public System.IO.DirectoryInfo Directory { get { throw null; } } - public string DirectoryName { get { throw null; } } + public System.IO.DirectoryInfo? Directory { get { throw null; } } + public string? DirectoryName { get { throw null; } } public override bool Exists { get { throw null; } } public bool IsReadOnly { get { throw null; } set { } } public long Length { get { throw null; } } @@ -200,8 +200,8 @@ public void MoveTo(string destFileName, bool overwrite) { } public System.IO.FileStream OpenRead() { throw null; } public System.IO.StreamReader OpenText() { throw null; } public System.IO.FileStream OpenWrite() { throw null; } - public System.IO.FileInfo Replace(string destinationFileName, string destinationBackupFileName) { throw null; } - public System.IO.FileInfo Replace(string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) { throw null; } + public System.IO.FileInfo Replace(string destinationFileName, string? destinationBackupFileName) { throw null; } + public System.IO.FileInfo Replace(string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors) { throw null; } public override string ToString() { throw null; } } public abstract partial class FileSystemInfo : System.MarshalByRefObject, System.Runtime.Serialization.ISerializable @@ -266,9 +266,9 @@ public ref partial struct FileSystemEntry } public partial class FileSystemEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - public FileSystemEnumerable(string directory, System.IO.Enumeration.FileSystemEnumerable.FindTransform transform, System.IO.EnumerationOptions options = null) { } - public System.IO.Enumeration.FileSystemEnumerable.FindPredicate ShouldIncludePredicate { get { throw null; } set { } } - public System.IO.Enumeration.FileSystemEnumerable.FindPredicate ShouldRecursePredicate { get { throw null; } set { } } + public FileSystemEnumerable(string directory, System.IO.Enumeration.FileSystemEnumerable.FindTransform transform, System.IO.EnumerationOptions? options = null) { } + public System.IO.Enumeration.FileSystemEnumerable.FindPredicate? ShouldIncludePredicate { get { throw null; } set { } } + public System.IO.Enumeration.FileSystemEnumerable.FindPredicate? ShouldRecursePredicate { get { throw null; } set { } } public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public delegate bool FindPredicate(ref System.IO.Enumeration.FileSystemEntry entry); @@ -276,9 +276,9 @@ public FileSystemEnumerable(string directory, System.IO.Enumeration.FileSystemEn } public abstract partial class FileSystemEnumerator : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { - public FileSystemEnumerator(string directory, System.IO.EnumerationOptions options = null) { } + public FileSystemEnumerator(string directory, System.IO.EnumerationOptions? options = null) { } public TResult Current { get { throw null; } } - object System.Collections.IEnumerator.Current { get { throw null; } } + object? System.Collections.IEnumerator.Current { get { throw null; } } protected virtual bool ContinueOnError(int error) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } @@ -293,6 +293,6 @@ public static partial class FileSystemName { public static bool MatchesSimpleExpression(System.ReadOnlySpan expression, System.ReadOnlySpan name, bool ignoreCase = true) { throw null; } public static bool MatchesWin32Expression(System.ReadOnlySpan expression, System.ReadOnlySpan name, bool ignoreCase = true) { throw null; } - public static string TranslateWin32Expression(string expression) { throw null; } + public static string TranslateWin32Expression(string? expression) { throw null; } } } diff --git a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.csproj b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.csproj index 5d9776564b8a92..58940b1181b8a5 100644 --- a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.csproj +++ b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.csproj @@ -1,6 +1,7 @@ netcoreapp-Debug;netcoreapp-Release + enable diff --git a/src/libraries/System.IO.FileSystem/src/System.IO.FileSystem.csproj b/src/libraries/System.IO.FileSystem/src/System.IO.FileSystem.csproj index ea88c0dc1c1df4..95dca566081798 100644 --- a/src/libraries/System.IO.FileSystem/src/System.IO.FileSystem.csproj +++ b/src/libraries/System.IO.FileSystem/src/System.IO.FileSystem.csproj @@ -5,6 +5,7 @@ $(NoWarn);CS1573 true netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release + enable $(NoWarn);414 diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs index 433e7d6d462337..2127b25d0cd83f 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs @@ -19,7 +19,7 @@ namespace System.IO { public static partial class Directory { - public static DirectoryInfo GetParent(string path) + public static DirectoryInfo? GetParent(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -29,7 +29,7 @@ public static DirectoryInfo GetParent(string path) string fullPath = Path.GetFullPath(path); - string s = Path.GetDirectoryName(fullPath); + string? s = Path.GetDirectoryName(fullPath); if (s == null) return null; return new DirectoryInfo(s); @@ -50,7 +50,7 @@ public static DirectoryInfo CreateDirectory(string path) } // Tests if the given path refers to an existing DirectoryInfo on disk. - public static bool Exists(string path) + public static bool Exists(string? path) { try { @@ -221,13 +221,13 @@ public static IEnumerable EnumerateFileSystemEntries(string path, string public static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions) => InternalEnumeratePaths(path, searchPattern, SearchTarget.Both, enumerationOptions); - public static string GetDirectoryRoot(string path) + public static string? GetDirectoryRoot(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); string fullPath = Path.GetFullPath(path); - string root = Path.GetPathRoot(fullPath); + string? root = Path.GetPathRoot(fullPath); return root; } @@ -276,8 +276,8 @@ public static void Move(string sourceDirName, string destDirName) && string.Equals(sourcePath, destPath, fileSystemSensitivity)) throw new IOException(SR.IO_SourceDestMustBeDifferent); - string sourceRoot = Path.GetPathRoot(sourcePath); - string destinationRoot = Path.GetPathRoot(destPath); + string? sourceRoot = Path.GetPathRoot(sourcePath); + string? destinationRoot = Path.GetPathRoot(destPath); // Compare paths for the same, skip this step if we already know the paths are identical. if (!string.Equals(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase)) diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/DirectoryInfo.cs b/src/libraries/System.IO.FileSystem/src/System/IO/DirectoryInfo.cs index 8149ee8cbee65c..0ac36a73305a89 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/DirectoryInfo.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/DirectoryInfo.cs @@ -29,12 +29,12 @@ public DirectoryInfo(string path) isNormalized: true); } - internal DirectoryInfo(string originalPath, string fullPath = null, string fileName = null, bool isNormalized = false) + internal DirectoryInfo(string originalPath, string? fullPath = null, string? fileName = null, bool isNormalized = false) { Init(originalPath, fullPath, fileName, isNormalized); } - private void Init(string originalPath, string fullPath = null, string fileName = null, bool isNormalized = false) + private void Init(string originalPath, string? fullPath = null, string? fileName = null, bool isNormalized = false) { OriginalPath = originalPath ?? throw new ArgumentNullException(nameof(originalPath)); @@ -50,14 +50,14 @@ private void Init(string originalPath, string fullPath = null, string fileName = _isNormalized = isNormalized; } - public DirectoryInfo Parent + public DirectoryInfo? Parent { get { // FullPath might end in either "parent\child" or "parent\child\", and in either case we want // the parent of child, not the child. Trim off an ending directory separator if there is one, // but don't mangle the root. - string parentName = Path.GetDirectoryName(PathInternal.IsRoot(FullPath.AsSpan()) ? FullPath : Path.TrimEndingDirectorySeparator(FullPath)); + string? parentName = Path.GetDirectoryName(PathInternal.IsRoot(FullPath.AsSpan()) ? FullPath : Path.TrimEndingDirectorySeparator(FullPath)); return parentName != null ? new DirectoryInfo(parentName, isNormalized: true) : null; @@ -193,7 +193,7 @@ private IEnumerable InternalEnumerateInfos( }; } - public DirectoryInfo Root => new DirectoryInfo(Path.GetPathRoot(FullPath)); + public DirectoryInfo Root => new DirectoryInfo(Path.GetPathRoot(FullPath)!); public void MoveTo(string destDirName) { @@ -210,8 +210,8 @@ public void MoveTo(string destDirName) if (string.Equals(sourceWithSeparator, destinationWithSeparator, PathInternal.StringComparison)) throw new IOException(SR.IO_SourceDestMustBeDifferent); - string sourceRoot = Path.GetPathRoot(sourceWithSeparator); - string destinationRoot = Path.GetPathRoot(destinationWithSeparator); + string? sourceRoot = Path.GetPathRoot(sourceWithSeparator); + string? destinationRoot = Path.GetPathRoot(destinationWithSeparator); if (!string.Equals(sourceRoot, destinationRoot, PathInternal.StringComparison)) throw new IOException(SR.IO_SourceDestMustHaveSameRoot); diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs index f3601a033b1318..caecac2c07ad4a 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs @@ -18,17 +18,17 @@ namespace System.IO.Enumeration /// public class FileSystemEnumerable : IEnumerable { - private DelegateEnumerator _enumerator; + private DelegateEnumerator? _enumerator; private readonly FindTransform _transform; private readonly EnumerationOptions _options; private readonly string _directory; - public FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions options = null) + public FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions? options = null) : this(directory, transform, options, isNormalized: false) { } - internal FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions options, bool isNormalized) + internal FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions? options, bool isNormalized) { _directory = directory ?? throw new ArgumentNullException(nameof(directory)); _transform = transform ?? throw new ArgumentNullException(nameof(transform)); @@ -39,8 +39,8 @@ internal FileSystemEnumerable(string directory, FindTransform transform, Enumera _enumerator = new DelegateEnumerator(this, isNormalized); } - public FindPredicate ShouldIncludePredicate { get; set; } - public FindPredicate ShouldRecursePredicate { get; set; } + public FindPredicate? ShouldIncludePredicate { get; set; } + public FindPredicate? ShouldRecursePredicate { get; set; } public IEnumerator GetEnumerator() { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs index 2fa89c0b0efc5a..8784669c29d009 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs @@ -55,7 +55,7 @@ private unsafe bool GetData() } } - private unsafe IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan relativePath, string fullPath) + private unsafe IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan relativePath, string? fullPath) { (int status, IntPtr handle) = Interop.NtDll.CreateFile( relativePath, diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs index c347e1597a7e84..2172841878f3a9 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs @@ -32,14 +32,14 @@ public unsafe abstract partial class FileSystemEnumerator : CriticalFin private readonly object _lock = new object(); private Interop.NtDll.FILE_FULL_DIR_INFORMATION* _entry; - private TResult _current; + private TResult _current = default!; private IntPtr _buffer; private int _bufferLength; private IntPtr _directoryHandle; - private string _currentPath; + private string _currentPath = null!; // Initialized in Init() private bool _lastEntryFound; - private Queue<(IntPtr Handle, string Path)> _pending; + private Queue<(IntPtr Handle, string Path)>? _pending; private void Init() { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs index 80823511879642..26a980e04d4a6b 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs @@ -20,7 +20,7 @@ public unsafe abstract partial class FileSystemEnumerator : CriticalFin /// /// The directory to search in. /// Enumeration options to use. - public FileSystemEnumerator(string directory, EnumerationOptions options = null) + public FileSystemEnumerator(string directory, EnumerationOptions? options = null) : this(directory, isNormalized: false, options) { } @@ -31,7 +31,7 @@ public FileSystemEnumerator(string directory, EnumerationOptions options = null) /// The directory to search in. /// Whether the directory path is already normalized or not. /// Enumeration options to use. - internal FileSystemEnumerator(string directory, bool isNormalized, EnumerationOptions options = null) + internal FileSystemEnumerator(string directory, bool isNormalized, EnumerationOptions? options = null) { _originalRootDirectory = directory ?? throw new ArgumentNullException(nameof(directory)); @@ -72,7 +72,7 @@ protected virtual void OnDirectoryFinished(ReadOnlySpan directory) { } public TResult Current => _current; - object IEnumerator.Current => Current; + object? IEnumerator.Current => Current; private void DirectoryFinished() { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs index e4684dca98f9dc..e2d932f29e6bcf 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs @@ -32,7 +32,7 @@ public static class FileSystemName /// Change '*' and '?' to '<', '>' and '"' to match Win32 behavior. For compatibility, Windows /// changes some wildcards to provide a closer match to historical DOS 8.3 filename matching. /// - public static string TranslateWin32Expression(string expression) + public static string TranslateWin32Expression(string? expression) { if (string.IsNullOrEmpty(expression) || expression == "*" || expression == "*.*") return "*"; diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/File.cs b/src/libraries/System.IO.FileSystem/src/System/IO/File.cs index 93685a41e801b3..d2492ba8fe96cd 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/File.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/File.cs @@ -23,7 +23,7 @@ namespace System.IO public static class File { private const int MaxByteArrayLength = 0x7FFFFFC7; - private static Encoding s_UTF8NoBOM; + private static Encoding? s_UTF8NoBOM; internal const int DefaultBufferSize = 4096; @@ -114,7 +114,7 @@ public static void Delete(string path) // given by the specified path exists; otherwise, the result is // false. Note that if path describes a directory, // Exists will return true. - public static bool Exists(string path) + public static bool Exists(string? path) { try { @@ -297,7 +297,7 @@ private static string InternalReadAllText(string path, Encoding encoding) return sr.ReadToEnd(); } - public static void WriteAllText(string path, string contents) + public static void WriteAllText(string path, string? contents) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -310,7 +310,7 @@ public static void WriteAllText(string path, string contents) } } - public static void WriteAllText(string path, string contents, Encoding encoding) + public static void WriteAllText(string path, string? contents, Encoding encoding) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -362,7 +362,7 @@ public static byte[] ReadAllBytes(string path) #if !MS_IO_REDIST private static byte[] ReadAllBytesUnknownLength(FileStream fs) { - byte[] rentedArray = null; + byte[]? rentedArray = null; Span buffer = stackalloc byte[512]; try { @@ -456,7 +456,7 @@ private static string[] InternalReadAllLines(string path, Encoding encoding) Debug.Assert(encoding != null); Debug.Assert(path.Length != 0); - string line; + string? line; List lines = new List(); using (StreamReader sr = new StreamReader(path, encoding)) @@ -538,7 +538,7 @@ private static void InternalWriteAllLines(TextWriter writer, IEnumerable } } - public static void AppendAllText(string path, string contents) + public static void AppendAllText(string path, string? contents) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -551,7 +551,7 @@ public static void AppendAllText(string path, string contents) } } - public static void AppendAllText(string path, string contents, Encoding encoding) + public static void AppendAllText(string path, string? contents, Encoding encoding) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -592,12 +592,12 @@ public static void AppendAllLines(string path, IEnumerable contents, Enc InternalWriteAllLines(new StreamWriter(path, true, encoding), contents); } - public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName) + public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName) { Replace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors: false); } - public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) + public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors) { if (sourceFileName == null) throw new ArgumentNullException(nameof(sourceFileName)); @@ -701,7 +701,7 @@ private static async Task InternalReadAllTextAsync(string path, Encoding Debug.Assert(!string.IsNullOrEmpty(path)); Debug.Assert(encoding != null); - char[] buffer = null; + char[]? buffer = null; StreamReader sr = AsyncStreamReader(path, encoding); try { @@ -736,7 +736,7 @@ private static async Task InternalReadAllTextAsync(string path, Encoding public static Task WriteAllTextAsync(string path, string contents, CancellationToken cancellationToken = default(CancellationToken)) => WriteAllTextAsync(path, contents, UTF8NoBOM, cancellationToken); - public static Task WriteAllTextAsync(string path, string contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) + public static Task WriteAllTextAsync(string path, string? contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -919,7 +919,7 @@ private static async Task InternalReadAllLinesAsync(string path, Encod using (StreamReader sr = AsyncStreamReader(path, encoding)) { cancellationToken.ThrowIfCancellationRequested(); - string line; + string? line; List lines = new List(); while ((line = await sr.ReadLineAsync().ConfigureAwait(false)) != null) { @@ -972,7 +972,7 @@ private static async Task InternalWriteAllLinesAsync(TextWriter writer, IEnumera private static async Task InternalWriteAllTextAsync(StreamWriter sw, string contents, CancellationToken cancellationToken) { - char[] buffer = null; + char[]? buffer = null; try { buffer = ArrayPool.Shared.Rent(DefaultBufferSize); @@ -1003,10 +1003,10 @@ private static async Task InternalWriteAllTextAsync(StreamWriter sw, string cont } } - public static Task AppendAllTextAsync(string path, string contents, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AppendAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default(CancellationToken)) => AppendAllTextAsync(path, contents, UTF8NoBOM, cancellationToken); - public static Task AppendAllTextAsync(string path, string contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AppendAllTextAsync(string path, string? contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { if (path == null) throw new ArgumentNullException(nameof(path)); diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs index 5127f1da3d9093..dbd6bb2ddc1436 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs @@ -24,7 +24,7 @@ public FileInfo(string fileName) { } - internal FileInfo(string originalPath, string fullPath = null, string fileName = null, bool isNormalized = false) + internal FileInfo(string originalPath, string? fullPath = null, string? fileName = null, bool isNormalized = false) { // Want to throw the original argument name OriginalPath = originalPath ?? throw new ArgumentNullException(nameof(fileName)); @@ -48,13 +48,13 @@ public long Length } } - public string DirectoryName => Path.GetDirectoryName(FullPath); + public string? DirectoryName => Path.GetDirectoryName(FullPath); - public DirectoryInfo Directory + public DirectoryInfo? Directory { get { - string dirName = DirectoryName; + string? dirName = DirectoryName; if (dirName == null) return null; return new DirectoryInfo(dirName); @@ -140,7 +140,7 @@ public void MoveTo(string destFileName, bool overwrite) // These checks are in place to ensure Unix error throwing happens the same way // as it does on Windows.These checks can be removed if a solution to #2460 is // found that doesn't require validity checks before making an API call. - if (!new DirectoryInfo(Path.GetDirectoryName(FullName)).Exists) + if (!new DirectoryInfo(Path.GetDirectoryName(FullName)!).Exists) // TODO should assert or ... throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, FullName)); if (!Exists) @@ -156,10 +156,10 @@ public void MoveTo(string destFileName, bool overwrite) Invalidate(); } - public FileInfo Replace(string destinationFileName, string destinationBackupFileName) + public FileInfo Replace(string destinationFileName, string? destinationBackupFileName) => Replace(destinationFileName, destinationBackupFileName, ignoreMetadataErrors: false); - public FileInfo Replace(string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) + public FileInfo Replace(string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors) { if (destinationFileName == null) throw new ArgumentNullException(nameof(destinationFileName)); diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Win32.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Win32.cs index 95828b8fad47b1..57ed6731bec619 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Win32.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Win32.cs @@ -41,7 +41,7 @@ private static unsafe void ThrowExceptionEncryptDecryptFail(string fullPath) if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { // Check to see if the file system support the Encrypted File System (EFS) - string name = DriveInfoInternal.NormalizeDriveName(Path.GetPathRoot(fullPath)); + string name = DriveInfoInternal.NormalizeDriveName(Path.GetPathRoot(fullPath)!); using (DisableMediaInsertionPrompt.Create()) { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Windows.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Windows.cs index 8c6296952e507c..0cd337d050ed87 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Windows.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Windows.cs @@ -47,7 +47,7 @@ public static void CopyFile(string sourceFullPath, string destFullPath, bool ove } } - public static void ReplaceFile(string sourceFullPath, string destFullPath, string destBackupFullPath, bool ignoreMetadataErrors) + public static void ReplaceFile(string sourceFullPath, string destFullPath, string? destBackupFullPath, bool ignoreMetadataErrors) { int flags = ignoreMetadataErrors ? Interop.Kernel32.REPLACEFILE_IGNORE_MERGE_ERRORS : 0; @@ -234,7 +234,7 @@ private static bool IsNameSurrogateReparsePoint(ref Interop.Kernel32.WIN32_FIND_ private static void RemoveDirectoryRecursive(string fullPath, ref Interop.Kernel32.WIN32_FIND_DATA findData, bool topLevel) { int errorCode; - Exception exception = null; + Exception? exception = null; using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(Path.Join(fullPath, "*"), ref findData)) { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs index c6170ad92854bc..f7ee8c4010c9dd 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs @@ -15,10 +15,10 @@ namespace System.IO public abstract partial class FileSystemInfo : MarshalByRefObject, ISerializable { // FullPath and OriginalPath are documented fields - protected string FullPath; // fully qualified path of the file or directory - protected string OriginalPath; // path passed in by the user + protected string FullPath = null!; // fully qualified path of the file or directory + protected string OriginalPath = null!; // path passed in by the user - internal string _name; + internal string _name = null!; // Fields initiated in derived classes protected FileSystemInfo(SerializationInfo info, StreamingContext context) { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs index c39914e9b5c340..98ce3ee38182dd 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs @@ -5,6 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.IO { @@ -14,13 +15,15 @@ internal abstract class Iterator : IEnumerable, IEnumerator GetEnumerator() public abstract bool MoveNext(); - object IEnumerator.Current + object? IEnumerator.Current { get { return Current; } } diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/ReadLinesIterator.cs b/src/libraries/System.IO.FileSystem/src/System/IO/ReadLinesIterator.cs index 1de57d5278459c..96c9b70fccd670 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/ReadLinesIterator.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/ReadLinesIterator.cs @@ -85,17 +85,17 @@ protected override void Dispose(bool disposing) } finally { - _reader = null; + _reader = null!; base.Dispose(disposing); } } internal static ReadLinesIterator CreateIterator(string path, Encoding encoding) { - return CreateIterator(path, encoding, (StreamReader)null); + return CreateIterator(path, encoding, (StreamReader?)null); } - private static ReadLinesIterator CreateIterator(string path, Encoding encoding, StreamReader reader) + private static ReadLinesIterator CreateIterator(string path, Encoding encoding, StreamReader? reader) { return new ReadLinesIterator(path, encoding, reader ?? new StreamReader(path, encoding)); } diff --git a/src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs b/src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs index 8d2e754edbab55..aed8919cd03e93 100644 --- a/src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs +++ b/src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs @@ -14,9 +14,9 @@ internal static partial class Kernel32 /// WARNING: This method does not implicitly handle long paths. Use GetFileAttributesEx. /// [DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern bool GetFileAttributesExPrivate(string name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); + private static extern bool GetFileAttributesExPrivate(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); - internal static bool GetFileAttributesEx(string name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation) + internal static bool GetFileAttributesEx(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation) { name = PathInternal.EnsureExtendedPrefixIfNeeded(name); return GetFileAttributesExPrivate(name, fileInfoLevel, ref lpFileInformation); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs index 300d12655795a7..07e259869d61ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs @@ -335,7 +335,7 @@ internal static bool IsDirectorySeparator(char c) /// 3. Doesn't play nice with string logic /// 4. Isn't a cross-plat friendly concept/behavior /// - internal static string NormalizeDirectorySeparators(string path) + internal static string? NormalizeDirectorySeparators(string? path) { if (string.IsNullOrEmpty(path)) return path; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs index ba1570536b647d..12f6949636565c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs @@ -55,7 +55,7 @@ internal static int GetCommonPathLength(string first, string second, bool ignore /// /// Gets the count of common characters from the left optionally ignoring case /// - internal static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase) + internal static unsafe int EqualStartingCharacterCount(string? first, string? second, bool ignoreCase) { if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0; @@ -84,7 +84,7 @@ internal static unsafe int EqualStartingCharacterCount(string first, string seco /// /// Returns true if the two paths have the same root /// - internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType) + internal static bool AreRootsEqual(string? first, string? second, StringComparison comparisonType) { int firstRootLength = GetRootLength(first.AsSpan()); int secondRootLength = GetRootLength(second.AsSpan()); @@ -220,15 +220,15 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen /// /// Trims one trailing directory separator beyond the root of the path. /// - internal static string TrimEndingDirectorySeparator(string path) => + internal static string? TrimEndingDirectorySeparator(string? path) => EndsInDirectorySeparator(path) && !IsRoot(path.AsSpan()) ? - path.Substring(0, path.Length - 1) : + path!.Substring(0, path.Length - 1) : path; /// /// Returns true if the path ends in a directory separator. /// - internal static bool EndsInDirectorySeparator(string path) => + internal static bool EndsInDirectorySeparator(string? path) => !string.IsNullOrEmpty(path) && IsDirectorySeparator(path[path.Length - 1]); /// From 7e0e54868368a9aab82d2cb58a0755ca9be16a3d Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Thu, 5 Dec 2019 13:23:19 -0800 Subject: [PATCH 2/8] Applying feedback --- .../Common/src/System/IO/FileSystem.Attributes.Windows.cs | 4 ++++ .../src/System/IO/FileSystem.DirectoryCreation.Windows.cs | 5 +++++ .../System.IO.FileSystem/ref/System.IO.FileSystem.cs | 2 +- .../src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs | 2 +- src/libraries/System.IO.FileSystem/src/System/IO/File.cs | 2 +- .../System.Private.CoreLib/src/System/IO/PathInternal.cs | 2 ++ 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs index 430b264b8fcf02..977293e3fe89d5 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs @@ -4,8 +4,12 @@ #nullable enable using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; +using System.IO; +using System.Text; #if MS_IO_REDIST namespace Microsoft.IO diff --git a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs index f0a6a9ce4dfe9d..c97ec9f41b1e0e 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs @@ -3,8 +3,13 @@ // See the LICENSE file in the project root for more information. #nullable enable +using Microsoft.Win32.SafeHandles; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.InteropServices; +using System.IO; +using System.Text; #if MS_IO_REDIST namespace Microsoft.IO diff --git a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs index 0388e9aa100bb9..43f962c0e07460 100644 --- a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs +++ b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs @@ -173,7 +173,7 @@ public static void WriteAllLines(string path, string[] contents, System.Text.Enc public static void WriteAllText(string path, string? contents) { } public static void WriteAllText(string path, string? contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string? contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string? contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public sealed partial class FileInfo : System.IO.FileSystemInfo { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs index 8784669c29d009..2fa89c0b0efc5a 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs @@ -55,7 +55,7 @@ private unsafe bool GetData() } } - private unsafe IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan relativePath, string? fullPath) + private unsafe IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan relativePath, string fullPath) { (int status, IntPtr handle) = Interop.NtDll.CreateFile( relativePath, diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/File.cs b/src/libraries/System.IO.FileSystem/src/System/IO/File.cs index d2492ba8fe96cd..e1b19b2db599f7 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/File.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/File.cs @@ -733,7 +733,7 @@ private static async Task InternalReadAllTextAsync(string path, Encoding } } - public static Task WriteAllTextAsync(string path, string contents, CancellationToken cancellationToken = default(CancellationToken)) + public static Task WriteAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default(CancellationToken)) => WriteAllTextAsync(path, contents, UTF8NoBOM, cancellationToken); public static Task WriteAllTextAsync(string path, string? contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs index 12f6949636565c..4c804366a5e5eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace System.IO @@ -220,6 +221,7 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen /// /// Trims one trailing directory separator beyond the root of the path. /// + [return: NotNullIfNotNull("path")] internal static string? TrimEndingDirectorySeparator(string? path) => EndsInDirectorySeparator(path) && !IsRoot(path.AsSpan()) ? path!.Substring(0, path.Length - 1) : From 8164e2fdca4ddf15aff9e555418798db0b07c3a9 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Thu, 5 Dec 2019 17:47:51 -0800 Subject: [PATCH 3/8] Linux versions update --- .../Common/src/System/Text/ValueUtf8Converter.cs | 5 +++-- .../System.IO.FileSystem/System.IO.FileSystem.sln | 8 ++++---- .../IO/Enumeration/FileSystemEnumerator.Unix.cs | 10 +++++----- .../src/System/IO/FileSystem.Unix.cs | 11 ++++++----- .../src/System/IO/PathInternal.Unix.cs | 4 +++- .../src/System/IO/PathInternal.Windows.cs | 1 + 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/libraries/Common/src/System/Text/ValueUtf8Converter.cs b/src/libraries/Common/src/System/Text/ValueUtf8Converter.cs index 3a2ba294db3977..7d8aaae592b46a 100644 --- a/src/libraries/Common/src/System/Text/ValueUtf8Converter.cs +++ b/src/libraries/Common/src/System/Text/ValueUtf8Converter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; namespace System.Text @@ -13,7 +14,7 @@ namespace System.Text /// internal ref struct ValueUtf8Converter { - private byte[] _arrayToReturnToPool; + private byte[]? _arrayToReturnToPool; private Span _bytes; public ValueUtf8Converter(Span initialBuffer) @@ -40,7 +41,7 @@ public Span ConvertAndTerminateString(ReadOnlySpan value) public void Dispose() { - byte[] toReturn = _arrayToReturnToPool; + byte[]? toReturn = _arrayToReturnToPool; if (toReturn != null) { _arrayToReturnToPool = null; diff --git a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln index 42726a58fee0bb..a6ecaa9edd5f1f 100644 --- a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln +++ b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27213.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29504.125 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Tests", "tests\System.IO.FileSystem.Tests.csproj", "{F0D49126-6A1C-42D5-9428-4374C868BAF8}" ProjectSection(ProjectDependencies) = postProject @@ -30,8 +30,8 @@ Global {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU - {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU - {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU + {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.ActiveCfg = netcoreapp-Unix-Debug|Any CPU + {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.Build.0 = netcoreapp-Unix-Debug|Any CPU {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU {4B15C12E-B6AB-4B05-8ECA-C2E2AEA67482}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs index ba6f611a7a04f4..13d02bfef9d38d 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs @@ -20,18 +20,18 @@ public unsafe abstract partial class FileSystemEnumerator : CriticalFin private readonly object _lock = new object(); - private string _currentPath; + private string? _currentPath; private IntPtr _directoryHandle; private bool _lastEntryFound; - private Queue _pending; + private Queue? _pending; private Interop.Sys.DirectoryEntry _entry; - private TResult _current; + private TResult _current = default; // Used for creating full paths - private char[] _pathBuffer; + private char[]? _pathBuffer; // Used to get the raw entry data - private byte[] _entryBuffer; + private byte[]? _entryBuffer; private void Init() { diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs index 75f8f89eaa3eb3..eec902b6934eb7 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs @@ -84,7 +84,7 @@ private static void LinkOrCopyFile (string sourceFullPath, string destFullPath) { // The operation failed. Within reason, try to determine which path caused the problem // so we can throw a detailed exception. - string path = null; + string? path = null; bool isDirectory = false; if (errorInfo.Error == Interop.Error.ENOENT) { @@ -116,7 +116,7 @@ private static void LinkOrCopyFile (string sourceFullPath, string destFullPath) } - public static void ReplaceFile(string sourceFullPath, string destFullPath, string destBackupFullPath, bool ignoreMetadataErrors) + public static void ReplaceFile(string sourceFullPath, string destFullPath, string? destBackupFullPath, bool ignoreMetadataErrors) { if (destBackupFullPath != null) { @@ -223,7 +223,8 @@ public static void DeleteFile(string fullPath) { case Interop.Error.ENOENT: // In order to match Windows behavior - string directoryName = Path.GetDirectoryName(fullPath); + string? directoryName = Path.GetDirectoryName(fullPath); + Debug.Assert(directoryName != null); if (directoryName.Length > 0 && !Directory.Exists(directoryName)) { throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, true); @@ -307,7 +308,7 @@ public static void CreateDirectory(string fullPath) int count = stackDir.Count; if (count == 0 && !somepathexists) { - string root = Path.GetPathRoot(fullPath); + string? root = Path.GetPathRoot(fullPath); if (!DirectoryExists(root)) { throw Interop.GetExceptionForIoErrno(Interop.Error.ENOENT.Info(), fullPath, isDirectory: true); @@ -406,7 +407,7 @@ public static void RemoveDirectory(string fullPath, bool recursive) private static void RemoveDirectoryInternal(DirectoryInfo directory, bool recursive, bool throwOnTopLevelDirectoryNotFound) { - Exception firstException = null; + Exception? firstException = null; if ((directory.Attributes & FileAttributes.ReparsePoint) != 0) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Unix.cs index f9a018ae5e3174..4d652b6417f592 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Unix.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Text; using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; namespace System.IO { @@ -35,7 +36,8 @@ internal static bool IsDirectorySeparator(char c) /// /// Normalize separators in the given path. Compresses forward slash runs. /// - internal static string NormalizeDirectorySeparators(string path) + [return: NotNullIfNotNull("path")] + internal static string? NormalizeDirectorySeparators(string? path) { if (string.IsNullOrEmpty(path)) return path; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs index 07e259869d61ed..ae12bf79abfef2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs @@ -335,6 +335,7 @@ internal static bool IsDirectorySeparator(char c) /// 3. Doesn't play nice with string logic /// 4. Isn't a cross-plat friendly concept/behavior /// + [return: NotNullIfNotNull("path")] internal static string? NormalizeDirectorySeparators(string? path) { if (string.IsNullOrEmpty(path)) From a02ab7dce2e6430821d71e06683b2a07ad5a0c9d Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Thu, 5 Dec 2019 17:53:25 -0800 Subject: [PATCH 4/8] Reverting back unwanted change --- .../System.IO.FileSystem/System.IO.FileSystem.sln | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln index a6ecaa9edd5f1f..71fe9ddfb82487 100644 --- a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln +++ b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29504.125 +# Visual Studio Version 15 +VisualStudioVersion = 15.0.27213.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Tests", "tests\System.IO.FileSystem.Tests.csproj", "{F0D49126-6A1C-42D5-9428-4374C868BAF8}" ProjectSection(ProjectDependencies) = postProject @@ -30,8 +30,8 @@ Global {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU {F0D49126-6A1C-42D5-9428-4374C868BAF8}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU - {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.ActiveCfg = netcoreapp-Unix-Debug|Any CPU - {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.Build.0 = netcoreapp-Unix-Debug|Any CPU + {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU + {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU {1B528B61-14F9-4BFC-A79A-F0BDB3339150}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU {4B15C12E-B6AB-4B05-8ECA-C2E2AEA67482}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU From 9dc7838f16af521d83e8c782018b5aac80e92ff7 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Thu, 5 Dec 2019 19:01:14 -0800 Subject: [PATCH 5/8] More review updates --- src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln | 2 +- .../System.IO.FileSystem/ref/System.IO.FileSystem.cs | 2 +- src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs | 4 ++-- .../src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs | 2 +- .../src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs | 2 +- src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln index 71fe9ddfb82487..42726a58fee0bb 100644 --- a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln +++ b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 15 +# Visual Studio 15 VisualStudioVersion = 15.0.27213.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Tests", "tests\System.IO.FileSystem.Tests.csproj", "{F0D49126-6A1C-42D5-9428-4374C868BAF8}" diff --git a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs index 43f962c0e07460..74770914a9a217 100644 --- a/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs +++ b/src/libraries/System.IO.FileSystem/ref/System.IO.FileSystem.cs @@ -32,7 +32,7 @@ public static void Delete(string path, bool recursive) { } public static string[] GetDirectories(string path, string searchPattern) { throw null; } public static string[] GetDirectories(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; } public static string[] GetDirectories(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; } - public static string? GetDirectoryRoot(string path) { throw null; } + public static string GetDirectoryRoot(string path) { throw null; } public static string[] GetFiles(string path) { throw null; } public static string[] GetFiles(string path, string searchPattern) { throw null; } public static string[] GetFiles(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; } diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs index 2127b25d0cd83f..4f03714b2c5b57 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs @@ -221,13 +221,13 @@ public static IEnumerable EnumerateFileSystemEntries(string path, string public static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions) => InternalEnumeratePaths(path, searchPattern, SearchTarget.Both, enumerationOptions); - public static string? GetDirectoryRoot(string path) + public static string GetDirectoryRoot(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); string fullPath = Path.GetFullPath(path); - string? root = Path.GetPathRoot(fullPath); + string root = Path.GetPathRoot(fullPath)!; return root; } diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs index 13d02bfef9d38d..5880145802cdb9 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs @@ -26,7 +26,7 @@ public unsafe abstract partial class FileSystemEnumerator : CriticalFin private Queue? _pending; private Interop.Sys.DirectoryEntry _entry; - private TResult _current = default; + private TResult _current = default!; // Used for creating full paths private char[]? _pathBuffer; diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs index 2172841878f3a9..414c40e7c25a18 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs @@ -37,7 +37,7 @@ public unsafe abstract partial class FileSystemEnumerator : CriticalFin private IntPtr _buffer; private int _bufferLength; private IntPtr _directoryHandle; - private string _currentPath = null!; // Initialized in Init() + private string? _currentPath; private bool _lastEntryFound; private Queue<(IntPtr Handle, string Path)>? _pending; diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs b/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs index dbd6bb2ddc1436..ae0744a95aff29 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/FileInfo.cs @@ -140,7 +140,7 @@ public void MoveTo(string destFileName, bool overwrite) // These checks are in place to ensure Unix error throwing happens the same way // as it does on Windows.These checks can be removed if a solution to #2460 is // found that doesn't require validity checks before making an API call. - if (!new DirectoryInfo(Path.GetDirectoryName(FullName)!).Exists) // TODO should assert or ... + if (!new DirectoryInfo(Path.GetDirectoryName(FullName)!).Exists) throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, FullName)); if (!Exists) From 7b9d9fb8a1f58c60c84f0327f133fc216855b338 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Fri, 6 Dec 2019 10:19:39 -0800 Subject: [PATCH 6/8] Enabling nullabe for PathInternal.cs --- .../System.Private.CoreLib/src/System/IO/PathInternal.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs index 4c804366a5e5eb..fd3529067f71c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; From cee6c0c0a9303f4bb8e3016ea809d9c375f0ddc8 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Tue, 10 Dec 2019 14:34:55 -0800 Subject: [PATCH 7/8] Addressing feedback --- src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs index 98ce3ee38182dd..6db76890188804 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Iterator.cs @@ -23,7 +23,6 @@ public Iterator() _threadId = Environment.CurrentManagedThreadId; } - [MaybeNull] public TSource Current { get { return current; } From baff181e5270db819e4d8f9286d46f0e204e2f0b Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Tue, 10 Dec 2019 14:59:28 -0800 Subject: [PATCH 8/8] Update same annotation in Linq.Parallel --- .../src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs index 2b69371d8053cc..e0505bd1fe25c8 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs @@ -65,7 +65,6 @@ internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentE } // IEnumerator methods. - [MaybeNull] public T Current { get { return default!; } } object? IEnumerator.Current { get { return null; } } public bool MoveNext() { return false; }