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
2 changes: 1 addition & 1 deletion src/Common/src/System/Text/OSEncoding.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,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
34 changes: 17 additions & 17 deletions src/System.Console/ref/System.Console.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 // TODO: Ask for review
{
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
2 changes: 1 addition & 1 deletion src/System.Console/src/System/ConsoleCancelEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace System
{

public delegate void ConsoleCancelEventHandler(object sender, ConsoleCancelEventArgs e);
public delegate void ConsoleCancelEventHandler(object? sender, ConsoleCancelEventArgs e);

public sealed class ConsoleCancelEventArgs : EventArgs
{
Expand Down
2 changes: 1 addition & 1 deletion src/System.Console/src/System/ConsoleKeyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public ConsoleModifiers Modifiers
get { return _mods; }
}

public override bool Equals(object value)
public override bool Equals(object? value)
{
return value is ConsoleKeyInfo && Equals((ConsoleKeyInfo)value);
}
Expand Down
4 changes: 2 additions & 2 deletions src/System.Console/src/System/IO/SyncTextReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public override int ReadBlock(char[] buffer, int index, int count)
}
}

public override string ReadLine()
public override string? ReadLine()
{
lock (this)
{
Expand All @@ -91,7 +91,7 @@ public override string ReadToEnd()
// No explicit locking is needed, as they all just delegate
//

public override Task<string> ReadLineAsync()
public override Task<string?> ReadLineAsync()
{
return Task.FromResult(ReadLine());
}
Expand Down