Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Nullability annotations for System.Console #41161

Merged
merged 12 commits into from
Sep 19, 2019
8 changes: 4 additions & 4 deletions src/Common/src/System/Text/EncodingHelper.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ internal static partial class EncodingHelper
{
/// <summary>Creates an encoding from the current environment.</summary>
/// <returns>The encoding, or null if it could not be determined.</returns>
internal static Encoding GetEncodingFromCharset()
internal static Encoding? GetEncodingFromCharset()
{
string charset = GetCharset();
string? charset = GetCharset();
if (charset != null)
{
try { return Encoding.GetEncoding(charset); }
Expand All @@ -31,10 +31,10 @@ internal static Encoding GetEncodingFromCharset()

/// <summary>Gets the current charset name from the environment.</summary>
/// <returns>The charset name if found; otherwise, null.</returns>
private static string GetCharset()
private static string? GetCharset()
{
// Find the first of the locale environment variables that's set.
string locale = null;
string? locale = null;
foreach (string envVar in s_localeEnvVars)
{
locale = Environment.GetEnvironmentVariable(envVar);
Expand Down
3 changes: 2 additions & 1 deletion src/Common/src/System/Text/OSEncoding.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.Text;
using System.Collections.Generic;
Expand All @@ -11,7 +12,7 @@ namespace System.Text
internal sealed class OSEncoding : Encoding
{
private readonly int _codePage;
private string _encodingName;
private string? _encodingName;

internal OSEncoding(int codePage) : base(codePage)
{
Expand Down
9 changes: 6 additions & 3 deletions src/Common/src/System/Text/StringOrCharArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace System.Text
/// </summary>
internal readonly struct StringOrCharArray : IEquatable<StringOrCharArray>
{
public readonly string String;
public readonly string? String;

public readonly char[] CharArray;
public readonly char[]? CharArray;
public readonly int CharArrayOffset;
public readonly int CharArrayCount;

Expand Down Expand Up @@ -56,7 +56,7 @@ public int Length
}
}

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return
obj is StringOrCharArray &&
Expand All @@ -75,6 +75,7 @@ public unsafe bool Equals(StringOrCharArray other)
{
return StringComparer.Ordinal.Equals(this.String, other.String);
}
Debug.Assert(other.CharArray != null);

// String vs CharArray
if (this.String.Length != other.CharArrayCount)
Expand All @@ -88,6 +89,7 @@ public unsafe bool Equals(StringOrCharArray other)

return true;
}
Debug.Assert(CharArray != null);

// CharArray vs CharArray
if (other.CharArray != null)
Expand All @@ -103,6 +105,7 @@ public unsafe bool Equals(StringOrCharArray other)

return true;
}
Debug.Assert(other.String != null);

// CharArray vs String
if (this.CharArrayCount != other.String.Length)
Expand Down
36 changes: 18 additions & 18 deletions src/System.Console/ref/System.Console.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static partial class Console
public static int WindowLeft { get { throw null; } set { } }
public static int WindowTop { get { throw null; } set { } }
public static int WindowWidth { get { throw null; } set { } }
public static event System.ConsoleCancelEventHandler CancelKeyPress { add { } remove { } }
public static event System.ConsoleCancelEventHandler? CancelKeyPress { add { } remove { } }
public static void Beep() { }
public static void Beep(int frequency, int duration) { }
public static void Clear() { }
Expand All @@ -51,7 +51,7 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth
public static int Read() { throw null; }
public static System.ConsoleKeyInfo ReadKey() { throw null; }
public static System.ConsoleKeyInfo ReadKey(bool intercept) { throw null; }
public static string ReadLine() { throw null; }
public static string? ReadLine() { throw null; }
public static void ResetColor() { }
public static void SetBufferSize(int width, int height) { }
public static void SetCursorPosition(int left, int top) { }
Expand All @@ -62,39 +62,39 @@ public static void SetWindowPosition(int left, int top) { }
public static void SetWindowSize(int width, int height) { }
public static void Write(bool value) { }
public static void Write(char value) { }
public static void Write(char[] buffer) { }
public static void Write(char[]? buffer) { }
public static void Write(char[] buffer, int index, int count) { }
public static void Write(decimal value) { }
public static void Write(double value) { }
public static void Write(int value) { }
public static void Write(long value) { }
public static void Write(object value) { }
public static void Write(object? value) { }
public static void Write(float value) { }
public static void Write(string value) { }
public static void Write(string format, object arg0) { }
public static void Write(string format, object arg0, object arg1) { }
public static void Write(string format, object arg0, object arg1, object arg2) { }
public static void Write(string format, params object[] arg) { }
public static void Write(string? value) { }
public static void Write(string format, object? arg0) { }
public static void Write(string format, object? arg0, object? arg1) { }
public static void Write(string format, object? arg0, object? arg1, object? arg2) { }
public static void Write(string format, params object?[]? arg) { }
[System.CLSCompliantAttribute(false)]
public static void Write(uint value) { }
[System.CLSCompliantAttribute(false)]
public static void Write(ulong value) { }
public static void WriteLine() { }
public static void WriteLine(bool value) { }
public static void WriteLine(char value) { }
public static void WriteLine(char[] buffer) { }
public static void WriteLine(char[]? buffer) { }
public static void WriteLine(char[] buffer, int index, int count) { }
public static void WriteLine(decimal value) { }
public static void WriteLine(double value) { }
public static void WriteLine(int value) { }
public static void WriteLine(long value) { }
public static void WriteLine(object value) { }
public static void WriteLine(object? value) { }
public static void WriteLine(float value) { }
public static void WriteLine(string value) { }
public static void WriteLine(string format, object arg0) { }
public static void WriteLine(string format, object arg0, object arg1) { }
public static void WriteLine(string format, object arg0, object arg1, object arg2) { }
public static void WriteLine(string format, params object[] arg) { }
public static void WriteLine(string? value) { }
public static void WriteLine(string format, object? arg0) { }
public static void WriteLine(string format, object? arg0, object? arg1) { }
public static void WriteLine(string format, object? arg0, object? arg1, object? arg2) { }
public static void WriteLine(string format, params object?[]? arg) { }
[System.CLSCompliantAttribute(false)]
public static void WriteLine(uint value) { }
[System.CLSCompliantAttribute(false)]
Expand All @@ -106,7 +106,7 @@ internal ConsoleCancelEventArgs() { }
public bool Cancel { get { throw null; } set { } }
public System.ConsoleSpecialKey SpecialKey { get { throw null; } }
}
public delegate void ConsoleCancelEventHandler(object sender, System.ConsoleCancelEventArgs e);
public delegate void ConsoleCancelEventHandler(object? sender, System.ConsoleCancelEventArgs e);
public enum ConsoleColor
{
Black = 0,
Expand Down Expand Up @@ -281,7 +281,7 @@ public readonly partial struct ConsoleKeyInfo
public char KeyChar { get { throw null; } }
public System.ConsoleModifiers Modifiers { get { throw null; } }
public bool Equals(System.ConsoleKeyInfo obj) { throw null; }
public override bool Equals(object value) { throw null; }
public override bool Equals(object? value) { throw null; }
public override int GetHashCode() { throw null; }
public static bool operator ==(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
public static bool operator !=(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
Expand Down
3 changes: 2 additions & 1 deletion src/System.Console/ref/System.Console.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configurations>netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release</Configurations>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Console.cs" />
Expand Down
3 changes: 2 additions & 1 deletion src/System.Console/src/System.Console.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>System.Console</RootNamespace>
<AssemblyName>System.Console</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release</Configurations>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="FxCopBaseline.cs" />
Expand Down
59 changes: 30 additions & 29 deletions src/System.Console/src/System/Console.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
Expand All @@ -22,17 +23,17 @@ public static class Console
private const int WriteBufferSize = 256;

private static object InternalSyncObject = new object(); // for synchronizing changing of Console's static fields
private static TextReader s_in;
private static TextWriter s_out, s_error;
private static Encoding s_inputEncoding;
private static Encoding s_outputEncoding;
private static TextReader? s_in;
private static TextWriter? s_out, s_error;
private static Encoding? s_inputEncoding;
private static Encoding? s_outputEncoding;
private static bool s_isOutTextWriterRedirected = false;
private static bool s_isErrorTextWriterRedirected = false;

private static ConsoleCancelEventHandler s_cancelCallbacks;
private static ConsolePal.ControlCHandlerRegistrar s_registrar;
private static ConsoleCancelEventHandler? s_cancelCallbacks;
private static ConsolePal.ControlCHandlerRegistrar? s_registrar;

internal static T EnsureInitialized<T>(ref T field, Func<T> initializer) where T : class =>
internal static T EnsureInitialized<T>([NotNull] ref T? field, Func<T> initializer) where T : class =>
LazyInitializer.EnsureInitialized(ref field, ref InternalSyncObject, initializer);

public static TextReader In => EnsureInitialized(ref s_in, () => ConsolePal.GetOrCreateReader());
Expand Down Expand Up @@ -81,12 +82,12 @@ public static Encoding OutputEncoding
// s_out reinitialize the console code page.
if (Volatile.Read(ref s_out) != null && !s_isOutTextWriterRedirected)
{
s_out.Flush();
s_out!.Flush();
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 correct, but a little unfortunate. @jcouv, our use of [NotNullIfNotNull] on Volatile.Read was intended to cover cases like this, but it falls short because it's only one directional: the compiler can know that the return value is not null if s_out is not null, but it can't then also infer that s_out is not null if the return value is not null.

Volatile.Write(ref s_out, null);
}
if (Volatile.Read(ref s_error) != null && !s_isErrorTextWriterRedirected)
{
s_error.Flush();
s_error!.Flush();
Volatile.Write(ref s_error, null);
}

Expand Down Expand Up @@ -136,9 +137,9 @@ private static TextWriter CreateOutputWriter(Stream outputStream)
});
}

private static StrongBox<bool> _isStdInRedirected;
private static StrongBox<bool> _isStdOutRedirected;
private static StrongBox<bool> _isStdErrRedirected;
private static StrongBox<bool>? _isStdInRedirected;
private static StrongBox<bool>? _isStdOutRedirected;
private static StrongBox<bool>? _isStdErrRedirected;

public static bool IsInputRedirected
{
Expand Down Expand Up @@ -326,7 +327,7 @@ public static void SetCursorPosition(int left, int top)
ConsolePal.SetCursorPosition(left, top);
}

public static event ConsoleCancelEventHandler CancelKeyPress
public static event ConsoleCancelEventHandler? CancelKeyPress
{
add
{
Expand Down Expand Up @@ -461,7 +462,7 @@ public static int Read()
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static string ReadLine()
public static string? ReadLine()
{
return In.ReadLine();
}
Expand All @@ -485,7 +486,7 @@ public static void WriteLine(char value)
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(char[] buffer)
public static void WriteLine(char[]? buffer)
{
Out.WriteLine(buffer);
}
Expand Down Expand Up @@ -541,37 +542,37 @@ public static void WriteLine(ulong value)
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(object value)
public static void WriteLine(object? value)
{
Out.WriteLine(value);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(string value)
public static void WriteLine(string? value)
{
Out.WriteLine(value);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(string format, object arg0)
public static void WriteLine(string format, object? arg0)
{
Out.WriteLine(format, arg0);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(string format, object arg0, object arg1)
public static void WriteLine(string format, object? arg0, object? arg1)
{
Out.WriteLine(format, arg0, arg1);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(string format, object arg0, object arg1, object arg2)
public static void WriteLine(string format, object? arg0, object? arg1, object? arg2)
{
Out.WriteLine(format, arg0, arg1, arg2);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(string format, params object[] arg)
public static void WriteLine(string format, params object?[]? arg)
{
if (arg == null) // avoid ArgumentNullException from String.Format
Out.WriteLine(format, null, null); // faster than Out.WriteLine(format, (Object)arg);
Expand All @@ -580,25 +581,25 @@ public static void WriteLine(string format, params object[] arg)
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(string format, object arg0)
public static void Write(string format, object? arg0)
{
Out.Write(format, arg0);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(string format, object arg0, object arg1)
public static void Write(string format, object? arg0, object? arg1)
{
Out.Write(format, arg0, arg1);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(string format, object arg0, object arg1, object arg2)
public static void Write(string format, object? arg0, object? arg1, object? arg2)
{
Out.Write(format, arg0, arg1, arg2);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(string format, params object[] arg)
public static void Write(string format, params object?[]? arg)
{
if (arg == null) // avoid ArgumentNullException from String.Format
Out.Write(format, null, null); // faster than Out.Write(format, (Object)arg);
Expand All @@ -619,7 +620,7 @@ public static void Write(char value)
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(char[] buffer)
public static void Write(char[]? buffer)
{
Out.Write(buffer);
}
Expand Down Expand Up @@ -675,20 +676,20 @@ public static void Write(ulong value)
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(object value)
public static void Write(object? value)
{
Out.Write(value);
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(string value)
public static void Write(string? value)
{
Out.Write(value);
}

internal static bool HandleBreakEvent(ConsoleSpecialKey controlKey)
{
ConsoleCancelEventHandler handler = s_cancelCallbacks;
ConsoleCancelEventHandler? handler = s_cancelCallbacks;
if (handler == null)
{
return false;
Expand Down
Loading