From a403258f251046bb4eafff9b6dc9e47af452d1fd Mon Sep 17 00:00:00 2001 From: Pavel Koneski Date: Fri, 1 May 2026 11:20:21 -0700 Subject: [PATCH] Enable nullable annotations in core of Scripting --- src/core/Microsoft.Scripting/ErrorSink.cs | 26 +-- .../Hosting/ExceptionOperations.cs | 11 +- .../Microsoft.Scripting.csproj | 1 + .../Runtime/DlrConfiguration.cs | 35 ++-- .../Runtime/DynamicOperations.Generated.cs | 46 ++--- .../Runtime/DynamicOperations.cs | 165 +++++++++--------- .../Runtime/InvariantContext.cs | 16 +- .../LanguageBoundTextContentProvider.cs | 6 +- .../Runtime/LanguageContext.cs | 72 ++++---- .../Microsoft.Scripting/Runtime/ScriptCode.cs | 6 +- .../Runtime/ScriptDomainManager.cs | 40 ++++- .../Runtime/TokenizerService.cs | 4 +- src/core/Microsoft.Scripting/SourceUnit.cs | 48 ++--- .../SyntaxErrorException.cs | 26 +-- .../Utils/AssemblyQualifiedTypeName.cs | 5 +- 15 files changed, 285 insertions(+), 222 deletions(-) diff --git a/src/core/Microsoft.Scripting/ErrorSink.cs b/src/core/Microsoft.Scripting/ErrorSink.cs index 78a71215..71c442b7 100644 --- a/src/core/Microsoft.Scripting/ErrorSink.cs +++ b/src/core/Microsoft.Scripting/ErrorSink.cs @@ -2,20 +2,26 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System.Threading; using Microsoft.Scripting.Utils; namespace Microsoft.Scripting { public class ErrorSink { - public static readonly ErrorSink/*!*/ Default = new(); + public static readonly ErrorSink Default = new(); - public static readonly ErrorSink/*!*/ Null = new NullErrorSink(); + public static readonly ErrorSink Null = new NullErrorSink(); protected ErrorSink() { } - public virtual void Add(SourceUnit source, string/*!*/ message, SourceSpan span, int errorCode, Severity severity) { + /// + /// Reports an error against a source unit. Use the + /// overload when no is available (e.g. remote execution). + /// + public virtual void Add(SourceUnit source, string message, SourceSpan span, int errorCode, Severity severity) { if (severity == Severity.FatalError || severity == Severity.Error) { throw new SyntaxErrorException(message, source, span, errorCode, severity); } @@ -25,7 +31,7 @@ public virtual void Add(SourceUnit source, string/*!*/ message, SourceSpan span, /// This overload will be called when a SourceUnit is not available. This can happen if the code is being executed remotely, /// since SourceUnit cannot be marshaled across AppDomains. /// - public virtual void Add(string message, string path, string code, string line, SourceSpan span, int errorCode, Severity severity) { + public virtual void Add(string message, string? path, string? code, string? line, SourceSpan span, int errorCode, Severity severity) { if (severity == Severity.FatalError || severity == Severity.Error) { throw new SyntaxErrorException(message, path, code, line, span, errorCode, severity); } @@ -34,12 +40,12 @@ public virtual void Add(string message, string path, string code, string line, S internal sealed class NullErrorSink : ErrorSink { - public override void Add(SourceUnit source, string/*!*/ message, SourceSpan span, int errorCode, Severity severity) { + public override void Add(SourceUnit source, string message, SourceSpan span, int errorCode, Severity severity) { } } public class ErrorCounter : ErrorSink { - private readonly ErrorSink/*!*/ _sink; + private readonly ErrorSink _sink; private int _fatalErrorCount; private int _errorCount; @@ -63,15 +69,15 @@ public bool AnyError { } } - public ErrorCounter() + public ErrorCounter() : this(ErrorSink.Null) { } - public ErrorCounter(ErrorSink/*!*/ sink) { + public ErrorCounter(ErrorSink sink) { ContractUtils.RequiresNotNull(sink, nameof(sink)); _sink = sink; } - + protected virtual void CountError(Severity severity) { if (severity == Severity.FatalError) Interlocked.Increment(ref _fatalErrorCount); else if (severity == Severity.Error) Interlocked.Increment(ref _errorCount); @@ -82,7 +88,7 @@ public void ClearCounters() { _warningCount = _errorCount = _fatalErrorCount = 0; } - public override void Add(SourceUnit source, string/*!*/ message, SourceSpan span, int errorCode, Severity severity) { + public override void Add(SourceUnit source, string message, SourceSpan span, int errorCode, Severity severity) { CountError(severity); _sink.Add(source, message, span, errorCode, severity); } diff --git a/src/core/Microsoft.Scripting/Hosting/ExceptionOperations.cs b/src/core/Microsoft.Scripting/Hosting/ExceptionOperations.cs index 9e185b27..a983adef 100644 --- a/src/core/Microsoft.Scripting/Hosting/ExceptionOperations.cs +++ b/src/core/Microsoft.Scripting/Hosting/ExceptionOperations.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Collections.Generic; @@ -46,7 +48,7 @@ public string FormatException(ObjectHandle exception) { var exceptionObj = exception.Unwrap() as Exception; ContractUtils.Requires(exceptionObj is not null, nameof(exception), "ObjectHandle must be to Exception object"); - return _context.FormatException(exceptionObj); + return _context.FormatException(exceptionObj!); } public void GetExceptionMessage(ObjectHandle exception, out string message, out string errorTypeName) { @@ -54,7 +56,7 @@ public void GetExceptionMessage(ObjectHandle exception, out string message, out var exceptionObj = exception.Unwrap() as Exception; ContractUtils.Requires(exceptionObj is not null, nameof(exception), "ObjectHandle must be to Exception object"); - _context.GetExceptionMessage(exceptionObj, out message, out errorTypeName); + _context.GetExceptionMessage(exceptionObj!, out message, out errorTypeName); } public bool HandleException(ObjectHandle exception) { @@ -69,12 +71,11 @@ public IList GetStackFrames(ObjectHandle exception) { var exceptionObj = exception.Unwrap() as Exception; ContractUtils.Requires(exceptionObj is not null, nameof(exception), "ObjectHandle must be to Exception object"); - return _context.GetStackFrames(exceptionObj); + return _context.GetStackFrames(exceptionObj!); } - // TODO: Figure out what is the right lifetime public override object InitializeLifetimeService() { - return null; + return base.InitializeLifetimeService(); } #endif } diff --git a/src/core/Microsoft.Scripting/Microsoft.Scripting.csproj b/src/core/Microsoft.Scripting/Microsoft.Scripting.csproj index a3b59efc..79cca8e1 100644 --- a/src/core/Microsoft.Scripting/Microsoft.Scripting.csproj +++ b/src/core/Microsoft.Scripting/Microsoft.Scripting.csproj @@ -7,6 +7,7 @@ True T:System.Diagnostics.CodeAnalysis.MaybeNullAttribute; + T:System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute; T:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute; T:System.Diagnostics.CodeAnalysis.NotNullAttribute; T:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute; diff --git a/src/core/Microsoft.Scripting/Runtime/DlrConfiguration.cs b/src/core/Microsoft.Scripting/Runtime/DlrConfiguration.cs index 93c81a83..7bf102c1 100644 --- a/src/core/Microsoft.Scripting/Runtime/DlrConfiguration.cs +++ b/src/core/Microsoft.Scripting/Runtime/DlrConfiguration.cs @@ -2,9 +2,12 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Threading; @@ -17,9 +20,9 @@ namespace Microsoft.Scripting.Runtime { /// internal sealed class LanguageConfiguration { private readonly IDictionary _options; - private LanguageContext _context; + private LanguageContext? _context; - public LanguageContext LanguageContext => _context; + public LanguageContext? LanguageContext => _context; public AssemblyQualifiedTypeName ProviderName { get; } @@ -41,32 +44,32 @@ internal LanguageContext LoadLanguageContext(ScriptDomainManager domainManager, // Let assembly load errors bubble out var assembly = domainManager.Platform.LoadAssembly(ProviderName.AssemblyName.FullName); - Type type = assembly.GetType(ProviderName.TypeName); + Type? type = assembly.GetType(ProviderName.TypeName); if (type is null) { throw new InvalidOperationException( String.Format( "Failed to load language '{0}': assembly '{1}' does not contain type '{2}'", - DisplayName, + DisplayName, #if FEATURE_FILESYSTEM assembly.Location, #else assembly.FullName, #endif - ProviderName.TypeName + ProviderName.TypeName )); } if (!type.IsSubclassOf(typeof(LanguageContext))) { throw new InvalidOperationException( - $"Failed to load language '{DisplayName}': type '{type}' is not a valid language provider because it does not inherit from LanguageContext"); + $"Failed to load language '{DisplayName}': type '{type}' is not a valid language provider because it does not inherit from LanguageContext"); } LanguageContext context; try { - context = (LanguageContext)Activator.CreateInstance(type, new object[] { domainManager, _options }); + context = (LanguageContext)Activator.CreateInstance(type, new object[] { domainManager, _options })!; } catch (TargetInvocationException e) { throw new TargetInvocationException( - $"Failed to load language '{DisplayName}': {e.InnerException.Message}", + $"Failed to load language '{DisplayName}': {e.InnerException?.Message}", e.InnerException ); } catch (Exception e) { @@ -131,8 +134,8 @@ public void AddLanguage(string languageTypeName, string displayName, IList names, IList fileExtensions, - IDictionary options, string paramName) { + internal void AddLanguage(string languageTypeName, string displayName, IList names, IList fileExtensions, + IDictionary options, string? paramName) { ContractUtils.Requires(!_frozen, "Configuration cannot be modified once the runtime is initialized"); ContractUtils.Requires( names.All(id => !String.IsNullOrEmpty(id) && !_languageNames.ContainsKey(id)), @@ -187,10 +190,10 @@ internal void Freeze() { _frozen = true; } - internal bool TryLoadLanguage(ScriptDomainManager manager, in AssemblyQualifiedTypeName providerName, out LanguageContext language) { + internal bool TryLoadLanguage(ScriptDomainManager manager, in AssemblyQualifiedTypeName providerName, [NotNullWhen(true)] out LanguageContext? language) { Assert.NotNull(manager); - if (_languageConfigurations.TryGetValue(providerName, out LanguageConfiguration config)) { + if (_languageConfigurations.TryGetValue(providerName, out LanguageConfiguration? config)) { language = LoadLanguageContext(manager, config); return true; } @@ -199,12 +202,12 @@ internal bool TryLoadLanguage(ScriptDomainManager manager, in AssemblyQualifiedT return false; } - internal bool TryLoadLanguage(ScriptDomainManager manager, string str, bool isExtension, out LanguageContext language) { + internal bool TryLoadLanguage(ScriptDomainManager manager, string str, bool isExtension, [NotNullWhen(true)] out LanguageContext? language) { Assert.NotNull(manager, str); var dict = isExtension ? _languageExtensions : _languageNames; - if (dict.TryGetValue(str, out LanguageConfiguration config)) { + if (dict.TryGetValue(str, out LanguageConfiguration? config)) { language = LoadLanguageContext(manager, config); return true; } @@ -222,7 +225,7 @@ private LanguageContext LoadLanguageContext(ScriptDomainManager manager, Languag // The check takes place after config.LoadLanguageContext is called to avoid calling user code while holding a lock. lock (_loadedProviderTypes) { Type type = language.GetType(); - if (_loadedProviderTypes.TryGetValue(type, out LanguageConfiguration existingConfig)) { + if (_loadedProviderTypes.TryGetValue(type, out LanguageConfiguration? existingConfig)) { throw new InvalidOperationException( $"Language implemented by type '{config.ProviderName}' has already been loaded using name '{existingConfig.ProviderName}'"); } @@ -289,7 +292,7 @@ public string[] GetFileExtensions() { return ArrayUtils.MakeArray(_languageExtensions.Keys); } - internal LanguageConfiguration GetLanguageConfig(LanguageContext context) { + internal LanguageConfiguration? GetLanguageConfig(LanguageContext context) { foreach (var config in _languageConfigurations.Values) { if (config.LanguageContext == context) { return config; diff --git a/src/core/Microsoft.Scripting/Runtime/DynamicOperations.Generated.cs b/src/core/Microsoft.Scripting/Runtime/DynamicOperations.Generated.cs index 499f23e6..dfc279a5 100644 --- a/src/core/Microsoft.Scripting/Runtime/DynamicOperations.Generated.cs +++ b/src/core/Microsoft.Scripting/Runtime/DynamicOperations.Generated.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + // // To regenerate code in this file run: // ir Languages/Ruby/Scripts/CodeGenerator.rb DynamicOperations.Generated.cs @@ -17,8 +19,8 @@ namespace Microsoft.Scripting.Runtime { public sealed partial class DynamicOperations { private const int /*$$*/PregeneratedInvokerCount = 14; - private Func GetInvoker(int paramCount) { - Func invoker; + private Func GetInvoker(int paramCount) { + Func? invoker; lock (_invokers) { if (!_invokers.TryGetValue(paramCount, out invoker)) { _invokers[paramCount] = invoker = GetPregeneratedInvoker(paramCount) ?? EmitInvoker(paramCount); @@ -28,7 +30,7 @@ private Func GetInv } [MethodImpl(MethodImplOptions.NoInlining)] - private Func EmitInvoker(int paramCount) { + private Func EmitInvoker(int paramCount) { #if !FEATURE_REFEMIT throw new NotSupportedException(); #else @@ -46,7 +48,7 @@ private Func EmitIn } var getOrCreateSiteFunc = new Func>>(GetOrCreateSite>).GetMethodInfo().GetGenericMethodDefinition(); - return Expression.Lambda>( + return Expression.Lambda>( Expression.Block( new[] { site }, Expression.Assign( @@ -56,7 +58,7 @@ private Func EmitIn Expression.Invoke( Expression.Field( site, - site.Type.GetField("Target") + site.Type.GetField("Target")! ), siteArgs ) @@ -66,89 +68,89 @@ private Func EmitIn #endif } - private static Func GetPregeneratedInvoker(int paramCount) { + private static Func? GetPregeneratedInvoker(int paramCount) { switch (paramCount) { #if GENERATOR def generate; $PregeneratedInvokerCount.times { |n| @n = n + 1; super }; end def n; @n; end - def objects; "object, " * @n; end + def objects; "object?, " * @n; end def args; (0..@n-1).map { |i| ", args[#{i}]" }.join; end #else case /*$n{*/0/*}*/: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target/*$args*/); }; #endif #region Generated case 1: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0]); }; case 2: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1]); }; case 3: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2]); }; case 4: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3]); }; case 5: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4]); }; case 6: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5]); }; case 7: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); }; case 8: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); }; case 9: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); }; case 10: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); }; case 11: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); }; case 12: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); }; case 13: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); }; case 14: return (ops, binder, target, args) => { - var site = ops.GetOrCreateSite>(binder); + var site = ops.GetOrCreateSite>(binder); return site.Target(site, target, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]); }; #endregion diff --git a/src/core/Microsoft.Scripting/Runtime/DynamicOperations.cs b/src/core/Microsoft.Scripting/Runtime/DynamicOperations.cs index 82abc9a3..cc4f119e 100644 --- a/src/core/Microsoft.Scripting/Runtime/DynamicOperations.cs +++ b/src/core/Microsoft.Scripting/Runtime/DynamicOperations.cs @@ -2,9 +2,12 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Linq.Expressions; using System.Reflection; @@ -54,43 +57,43 @@ public DynamicOperations(LanguageContext lc) { #region Basic Operations - private readonly Dictionary> _invokers = new(); + private readonly Dictionary> _invokers = new(); /// /// Calls the provided object with the given parameters and returns the result. - /// - /// The prefered way of calling objects is to convert the object to a strongly typed delegate + /// + /// The prefered way of calling objects is to convert the object to a strongly typed delegate /// using the ConvertTo methods and then invoking that delegate. /// - public object Invoke(object obj, params object[] parameters) { + public object? Invoke(object? obj, params object?[] parameters) { return GetInvoker(parameters.Length)(this, _lc.CreateInvokeBinder(new CallInfo(parameters.Length)), obj, parameters); } - + /// /// Invokes a member on the provided object with the given parameters and returns the result. /// - public object InvokeMember(object obj, string memberName, params object[] parameters) { + public object? InvokeMember(object? obj, string memberName, params object?[] parameters) { return InvokeMember(obj, memberName, false, parameters); } /// /// Invokes a member on the provided object with the given parameters and returns the result. /// - public object InvokeMember(object obj, string memberName, bool ignoreCase, params object[] parameters) { + public object? InvokeMember(object? obj, string memberName, bool ignoreCase, params object?[] parameters) { return GetInvoker(parameters.Length)(this, _lc.CreateCallBinder(memberName, ignoreCase, new CallInfo(parameters.Length)), obj, parameters); } /// /// Creates a new instance from the provided object using the given parameters, and returns the result. /// - public object CreateInstance(object obj, params object[] parameters) { + public object? CreateInstance(object? obj, params object?[] parameters) { return GetInvoker(parameters.Length)(this, _lc.CreateCreateBinder(new CallInfo(parameters.Length)), obj, parameters); } /// /// Gets the member name from the object obj. Throws an exception if the member does not exist or is write-only. /// - public object GetMember(object obj, string name) { + public object? GetMember(object? obj, string name) { return GetMember(obj, name, false); } @@ -98,36 +101,37 @@ public object GetMember(object obj, string name) { /// Gets the member name from the object obj and converts it to the type T. Throws an exception if the /// member does not exist, is write-only, or cannot be converted. /// - public T GetMember(object obj, string name) { + [return: MaybeNull] + public T GetMember(object? obj, string name) { return GetMember(obj, name, false); } /// - /// Gets the member name from the object obj. Returns true if the member is successfully retrieved and + /// Gets the member name from the object obj. Returns true if the member is successfully retrieved and /// stores the value in the value out param. /// - public bool TryGetMember(object obj, string name, out object value) { + public bool TryGetMember(object? obj, string name, out object? value) { return TryGetMember(obj, name, false, out value); } /// /// Returns true if the object has a member named name, false if the member does not exist. /// - public bool ContainsMember(object obj, string name) { + public bool ContainsMember(object? obj, string name) { return ContainsMember(obj, name, false); } /// /// Removes the member name from the object obj. /// - public void RemoveMember(object obj, string name) { + public void RemoveMember(object? obj, string name) { RemoveMember(obj, name, false); } /// /// Sets the member name on object obj to value. /// - public void SetMember(object obj, string name, object value) { + public void SetMember(object? obj, string name, object? value) { SetMember(obj, name, value, false); } @@ -135,15 +139,15 @@ public void SetMember(object obj, string name, object value) { /// Sets the member name on object obj to value. This overload can be used to avoid /// boxing and casting of strongly typed members. /// - public void SetMember(object obj, string name, T value) { + public void SetMember(object? obj, string name, T value) { SetMember(obj, name, value, false); } /// /// Gets the member name from the object obj. Throws an exception if the member does not exist or is write-only. /// - public object GetMember(object obj, string name, bool ignoreCase) { - CallSite> site = GetOrCreateSite(_lc.CreateGetMemberBinder(name, ignoreCase)); + public object? GetMember(object? obj, string name, bool ignoreCase) { + CallSite> site = GetOrCreateSite(_lc.CreateGetMemberBinder(name, ignoreCase)); return site.Target(site, obj); } @@ -151,17 +155,18 @@ public object GetMember(object obj, string name, bool ignoreCase) { /// Gets the member name from the object obj and converts it to the type T. The conversion will be explicit or implicit /// depending on what the langauge prefers. Throws an exception if the member does not exist, is write-only, or cannot be converted. /// - public T GetMember(object obj, string name, bool ignoreCase) { - CallSite> convertSite = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), null)); - CallSite> site = GetOrCreateSite(_lc.CreateGetMemberBinder(name, ignoreCase)); + [return: MaybeNull] + public T GetMember(object? obj, string name, bool ignoreCase) { + CallSite> convertSite = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), null)); + CallSite> site = GetOrCreateSite(_lc.CreateGetMemberBinder(name, ignoreCase)); return convertSite.Target(convertSite, site.Target(site, obj)); } /// - /// Gets the member name from the object obj. Returns true if the member is successfully retrieved and + /// Gets the member name from the object obj. Returns true if the member is successfully retrieved and /// stores the value in the value out param. /// - public bool TryGetMember(object obj, string name, bool ignoreCase, out object value) { + public bool TryGetMember(object? obj, string name, bool ignoreCase, out object? value) { try { value = GetMember(obj, name, ignoreCase); return true; @@ -174,7 +179,7 @@ public bool TryGetMember(object obj, string name, bool ignoreCase, out object va /// /// Returns true if the object has a member named name, false if the member does not exist. /// - public bool ContainsMember(object obj, string name, bool ignoreCase) { + public bool ContainsMember(object? obj, string name, bool ignoreCase) { return TryGetMember(obj, name, ignoreCase, out _); } @@ -182,16 +187,16 @@ public bool ContainsMember(object obj, string name, bool ignoreCase) { /// Removes the member name from the object obj. Returns true if the member was successfully removed /// or false if the member does not exist. /// - public void RemoveMember(object obj, string name, bool ignoreCase) { - CallSite> site = GetOrCreateActionSite(_lc.CreateDeleteMemberBinder(name, ignoreCase)); + public void RemoveMember(object? obj, string name, bool ignoreCase) { + CallSite> site = GetOrCreateActionSite(_lc.CreateDeleteMemberBinder(name, ignoreCase)); site.Target(site, obj); } /// /// Sets the member name on object obj to value. /// - public void SetMember(object obj, string name, object value, bool ignoreCase) { - CallSite> site = GetOrCreateSite(_lc.CreateSetMemberBinder(name, ignoreCase)); + public void SetMember(object? obj, string name, object? value, bool ignoreCase) { + CallSite> site = GetOrCreateSite(_lc.CreateSetMemberBinder(name, ignoreCase)); site.Target(site, obj, value); } @@ -199,8 +204,8 @@ public void SetMember(object obj, string name, object value, bool ignoreCase) { /// Sets the member name on object obj to value. This overload can be used to avoid /// boxing and casting of strongly typed members. /// - public void SetMember(object obj, string name, T value, bool ignoreCase) { - CallSite> site = GetOrCreateSite(_lc.CreateSetMemberBinder(name, ignoreCase)); + public void SetMember(object? obj, string name, T value, bool ignoreCase) { + CallSite> site = GetOrCreateSite(_lc.CreateSetMemberBinder(name, ignoreCase)); site.Target(site, obj, value); } @@ -208,18 +213,19 @@ public void SetMember(object obj, string name, T value, bool ignoreCase) { /// Converts the object obj to the type T. The conversion will be explicit or implicit /// depending on what the langauge prefers. /// - public T ConvertTo(object obj) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), null)); + [return: MaybeNull] + public T ConvertTo(object? obj) { + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), null)); return site.Target(site, obj); } - /// + /// /// Converts the object obj to the type type. The conversion will be explicit or implicit /// depending on what the langauge prefers. /// - public object ConvertTo(object obj, Type type) { + public object? ConvertTo(object? obj, Type type) { if (type.IsInterface || type.IsClass) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, null)); + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, null)); return site.Target(site, obj); } @@ -227,9 +233,9 @@ public object ConvertTo(object obj, Type type) { foreach (MethodInfo mi in typeof(DynamicOperations).GetDeclaredMethods("ConvertTo")) { if (mi.IsGenericMethod) { try { - return mi.MakeGenericMethod(type).Invoke(this, new object[] { obj }); + return mi.MakeGenericMethod(type).Invoke(this, new object?[] { obj }); } catch(TargetInvocationException tie) { - throw tie.InnerException; + throw tie.InnerException!; } } } @@ -239,28 +245,28 @@ public object ConvertTo(object obj, Type type) { /// /// Converts the object obj to the type T. Returns true if the value can be converted, false if it cannot. - /// + /// /// The conversion will be explicit or implicit depending on what the langauge prefers. /// - public bool TryConvertTo(object obj, out T result) { + public bool TryConvertTo(object? obj, [MaybeNull] out T result) { try { result = ConvertTo(obj); return true; } catch (ArgumentTypeException) { - result = default(T); + result = default; return false; } catch (InvalidCastException) { - result = default(T); + result = default; return false; } } /// /// Converts the object obj to the type type. Returns true if the value can be converted, false if it cannot. - /// + /// /// The conversion will be explicit or implicit depending on what the langauge prefers. /// - public bool TryConvertTo(object obj, Type type, out object result) { + public bool TryConvertTo(object? obj, Type type, out object? result) { try { result = ConvertTo(obj, type); return true; @@ -276,25 +282,26 @@ public bool TryConvertTo(object obj, Type type, out object result) { /// /// Convers the object obj to the type T including explicit conversions which may lose information. /// - public T ExplicitConvertTo(object obj) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), true)); + [return: MaybeNull] + public T ExplicitConvertTo(object? obj) { + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), true)); return site.Target(site, obj); } /// /// Converts the object obj to the type type including explicit conversions which may lose information. /// - public object ExplicitConvertTo(object obj, Type type) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, true)); + public object? ExplicitConvertTo(object? obj, Type type) { + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, true)); return site.Target(site, obj); } /// - /// Converts the object obj to the type type including explicit conversions which may lose information. - /// + /// Converts the object obj to the type type including explicit conversions which may lose information. + /// /// Returns true if the value can be converted, false if it cannot. /// - public bool TryExplicitConvertTo(object obj, Type type, out object result) { + public bool TryExplicitConvertTo(object? obj, Type type, out object? result) { try { result = ExplicitConvertTo(obj, type); return true; @@ -310,15 +317,15 @@ public bool TryExplicitConvertTo(object obj, Type type, out object result) { /// /// Converts the object obj to the type T. Returns true if the value can be converted, false if it cannot. /// - public bool TryExplicitConvertTo(object obj, out T result) { + public bool TryExplicitConvertTo(object? obj, [MaybeNull] out T result) { try { result = ExplicitConvertTo(obj); return true; } catch (ArgumentTypeException) { - result = default(T); + result = default; return false; } catch (InvalidCastException) { - result = default(T); + result = default; return false; } } @@ -326,25 +333,26 @@ public bool TryExplicitConvertTo(object obj, out T result) { /// /// Convers the object obj to the type T including implicit conversions. /// - public T ImplicitConvertTo(object obj) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), false)); + [return: MaybeNull] + public T ImplicitConvertTo(object? obj) { + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(typeof(T), false)); return site.Target(site, obj); } /// /// Converts the object obj to the type type including implicit conversions. /// - public object ImplicitConvertTo(object obj, Type type) { - CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, false)); + public object? ImplicitConvertTo(object? obj, Type type) { + CallSite> site = GetOrCreateSite(_lc.CreateConvertBinder(type, false)); return site.Target(site, obj); } /// - /// Converts the object obj to the type type including implicit conversions. - /// + /// Converts the object obj to the type type including implicit conversions. + /// /// Returns true if the value can be converted, false if it cannot. /// - public bool TryImplicitConvertTo(object obj, Type type, out object result) { + public bool TryImplicitConvertTo(object? obj, Type type, out object? result) { try { result = ImplicitConvertTo(obj, type); return true; @@ -360,15 +368,15 @@ public bool TryImplicitConvertTo(object obj, Type type, out object result) { /// /// Converts the object obj to the type T. Returns true if the value can be converted, false if it cannot. /// - public bool TryImplicitConvertTo(object obj, out T result) { + public bool TryImplicitConvertTo(object? obj, [MaybeNull] out T result) { try { result = ImplicitConvertTo(obj); return true; } catch (ArgumentTypeException) { - result = default(T); + result = default; return false; } catch (InvalidCastException) { - result = default(T); + result = default; return false; } } @@ -376,6 +384,7 @@ public bool TryImplicitConvertTo(object obj, out T result) { /// /// Performs a generic unary operation on the strongly typed target and returns the value as the specified type /// + [return: MaybeNull] public TResult DoOperation(ExpressionType operation, TTarget target) { var site = GetOrCreateSite(_lc.CreateUnaryOperationBinder(operation)); return site.Target(site, target); @@ -385,34 +394,35 @@ public TResult DoOperation(ExpressionType operation, TTarget t /// Peforms the generic binary operation on the specified strongly typed targets and returns /// the strongly typed result. /// + [return: MaybeNull] public TResult DoOperation(ExpressionType operation, TTarget target, TOther other) { var site = GetOrCreateSite(_lc.CreateBinaryOperationBinder(operation)); return site.Target(site, target, other); } - - public string GetDocumentation(object o) { + + public string GetDocumentation(object? o) { return _lc.GetDocumentation(o); } - public IList GetCallSignatures(object o) { + public IList GetCallSignatures(object? o) { return _lc.GetCallSignatures(o); } - public bool IsCallable(object o) { + public bool IsCallable(object? o) { return _lc.IsCallable(o); } - + /// /// Returns a list of strings which contain the known members of the object. /// - public IList GetMemberNames(object obj) { + public IList GetMemberNames(object? obj) { return _lc.GetMemberNames(obj); } /// /// Returns a string representation of the object in a language specific object display format. /// - public string Format(object obj) { + public string Format(object? obj) { return _lc.FormatObject(this, obj); } @@ -482,7 +492,7 @@ private T GetOrCreateSite(CallSiteBinder siteBinder, Func SiteKey sk = new SiteKey(typeof(T), siteBinder); lock (_sites) { - if (!_sites.TryGetValue(sk, out SiteKey old)) { + if (!_sites.TryGetValue(sk, out SiteKey? old)) { SitesCreated++; if (SitesCreated < 0) { // overflow, just reset back to zero... @@ -500,7 +510,7 @@ private T GetOrCreateSite(CallSiteBinder siteBinder, Func CleanupNoLock(); } - return (T)sk.Site; + return (T)sk.Site!; } /// @@ -524,7 +534,7 @@ private void CleanupNoLock() { return; } - List toRemove = null; + List? toRemove = null; foreach (SiteKey sk in _sites.Keys) { if (sk.HitCount < (avgUse - RemoveThreshold)) { toRemove ??= new List(); @@ -568,17 +578,14 @@ private sealed class SiteKey : IEquatable { // not used for equality, used for caching strategy public int HitCount; - public CallSite Site; + public CallSite? Site; public SiteKey(Type siteType, CallSiteBinder siteBinder) { - Debug.Assert(siteType is not null); - Debug.Assert(siteBinder is not null); - SiteBinder = siteBinder; _siteType = siteType; } - public override bool Equals(object obj) => Equals(obj as SiteKey); + public override bool Equals(object? obj) => Equals(obj as SiteKey); public override int GetHashCode() { return SiteBinder.GetHashCode() ^ _siteType.GetHashCode(); @@ -586,7 +593,7 @@ public override int GetHashCode() { #region IEquatable Members - public bool Equals(SiteKey other) { + public bool Equals(SiteKey? other) { if (other is null) return false; return other.SiteBinder.Equals(SiteBinder) && diff --git a/src/core/Microsoft.Scripting/Runtime/InvariantContext.cs b/src/core/Microsoft.Scripting/Runtime/InvariantContext.cs index 8065704b..7c374469 100644 --- a/src/core/Microsoft.Scripting/Runtime/InvariantContext.cs +++ b/src/core/Microsoft.Scripting/Runtime/InvariantContext.cs @@ -2,7 +2,10 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Scripting.Runtime { /// @@ -16,13 +19,14 @@ internal InvariantContext(ScriptDomainManager manager) public override bool CanCreateSourceCode => false; - public override ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink) { + public override ScriptCode? CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink) { // invariant language doesn't have a grammar: throw new NotSupportedException(); } + [return: MaybeNull] public override T ScopeGetVariable(Scope scope, string name) { - if (scope.Storage is ScopeStorage storage && storage.TryGetValue(name, false, out object res)) { + if (scope.Storage is ScopeStorage storage && storage.TryGetValue(name, false, out object? res)) { return Operations.ConvertTo(res); } @@ -34,8 +38,8 @@ public override T ScopeGetVariable(Scope scope, string name) { return base.ScopeGetVariable(scope, name); } - public override dynamic ScopeGetVariable(Scope scope, string name) { - if (scope.Storage is ScopeStorage storage && storage.TryGetValue(name, false, out object res)) { + public override dynamic? ScopeGetVariable(Scope scope, string name) { + if (scope.Storage is ScopeStorage storage && storage.TryGetValue(name, false, out object? res)) { return res; } @@ -47,7 +51,7 @@ public override dynamic ScopeGetVariable(Scope scope, string name) { return base.ScopeGetVariable(scope, name); } - public override void ScopeSetVariable(Scope scope, string name, object value) { + public override void ScopeSetVariable(Scope scope, string name, object? value) { if (scope.Storage is ScopeStorage storage) { storage.SetValue(name, false, value); return; @@ -61,7 +65,7 @@ public override void ScopeSetVariable(Scope scope, string name, object value) { base.ScopeSetVariable(scope, name, value); } - public override bool ScopeTryGetVariable(Scope scope, string name, out dynamic value) { + public override bool ScopeTryGetVariable(Scope scope, string name, out dynamic? value) { if (scope.Storage is ScopeStorage storage && storage.TryGetValue(name, false, out value)) { return true; } diff --git a/src/core/Microsoft.Scripting/Runtime/LanguageBoundTextContentProvider.cs b/src/core/Microsoft.Scripting/Runtime/LanguageBoundTextContentProvider.cs index b486c127..dd2ef425 100644 --- a/src/core/Microsoft.Scripting/Runtime/LanguageBoundTextContentProvider.cs +++ b/src/core/Microsoft.Scripting/Runtime/LanguageBoundTextContentProvider.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System.IO; using System.Text; @@ -16,9 +18,9 @@ internal sealed class LanguageBoundTextContentProvider : TextContentProvider { private readonly LanguageContext _context; private readonly StreamContentProvider _streamProvider; private readonly Encoding _defaultEncoding; - private readonly string _path; + private readonly string? _path; - public LanguageBoundTextContentProvider(LanguageContext context, StreamContentProvider streamProvider, Encoding defaultEncoding, string path) { + public LanguageBoundTextContentProvider(LanguageContext context, StreamContentProvider streamProvider, Encoding defaultEncoding, string? path) { Assert.NotNull(context, streamProvider, defaultEncoding); _context = context; _streamProvider = streamProvider; diff --git a/src/core/Microsoft.Scripting/Runtime/LanguageContext.cs b/src/core/Microsoft.Scripting/Runtime/LanguageContext.cs index a84ca370..c3d352c1 100644 --- a/src/core/Microsoft.Scripting/Runtime/LanguageContext.cs +++ b/src/core/Microsoft.Scripting/Runtime/LanguageContext.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.IO; using System.Linq.Expressions; @@ -18,7 +21,7 @@ namespace Microsoft.Scripting.Runtime { /// Provides language specific facilities which are typically called by the runtime. /// public abstract class LanguageContext { - private DynamicOperations _operations; + private DynamicOperations? _operations; protected LanguageContext(ScriptDomainManager domainManager) { ContractUtils.RequiresNotNull(domainManager, nameof(domainManager)); @@ -49,7 +52,7 @@ protected LanguageContext(ScriptDomainManager domainManager) { /// /// Gets the scope associated with a file, or null if none was available /// - public virtual Scope GetScope(string path) { + public virtual Scope? GetScope(string path) { return null; } @@ -65,7 +68,7 @@ public virtual Scope CreateScope() { /// /// Accesses to the ScriptScope will turn into get,set, and delete members against this dictionary /// - public virtual Scope CreateScope(IDictionary dictionary) { + public virtual Scope CreateScope(IDictionary dictionary) { return new Scope(dictionary); } @@ -81,7 +84,7 @@ public virtual Scope CreateScope(IDynamicMetaObjectProvider storage) { // TODO: remove public ScopeExtension EnsureScopeExtension(Scope scope) { ContractUtils.RequiresNotNull(scope, nameof(scope)); - ScopeExtension extension = scope.GetExtension(ContextId); + ScopeExtension? extension = scope.GetExtension(ContextId); if (extension is not null) return extension; @@ -108,7 +111,7 @@ public virtual ScopeExtension CreateScopeExtension(Scope scope) { /// types for that language. Typically this includes ScopeStorage and any other /// classes which the language themselves uses for backing of a Scope. /// - public virtual void ScopeSetVariable(Scope scope, string name, object value) { + public virtual void ScopeSetVariable(Scope scope, string name, object? value) { Operations.SetMember(scope, name, value); } @@ -121,7 +124,7 @@ public virtual void ScopeSetVariable(Scope scope, string name, object value) { /// types for that language. Typically this includes ScopeStorage and any other /// classes which the language themselves uses for backing of a Scope. /// - public virtual bool ScopeTryGetVariable(Scope scope, string name, out dynamic value) { + public virtual bool ScopeTryGetVariable(Scope scope, string name, out dynamic? value) { return Operations.TryGetMember(scope, name, out value); } @@ -134,6 +137,7 @@ public virtual bool ScopeTryGetVariable(Scope scope, string name, out dynamic va /// types for that language. Typically this includes ScopeStorage and any other /// classes which the language themselves uses for backing of a Scope. /// + [return: MaybeNull] public virtual T ScopeGetVariable(Scope scope, string name) { return Operations.GetMember(scope, name); } @@ -147,7 +151,7 @@ public virtual T ScopeGetVariable(Scope scope, string name) { /// types for that language. Typically this includes ScopeStorage and any other /// classes which the language themselves uses for backing of a Scope. /// - public virtual dynamic ScopeGetVariable(Scope scope, string name) { + public virtual dynamic? ScopeGetVariable(Scope scope, string name) { return Operations.GetMember(scope, name); } @@ -163,7 +167,7 @@ public virtual dynamic ScopeGetVariable(Scope scope, string name) { /// the path of the source unit if available /// The reader. /// An I/O error occurs. - public virtual SourceCodeReader GetSourceReader(Stream stream, Encoding defaultEncoding, string path) { + public virtual SourceCodeReader GetSourceReader(Stream stream, Encoding defaultEncoding, string? path) { ContractUtils.RequiresNotNull(stream, nameof(stream)); ContractUtils.RequiresNotNull(defaultEncoding, nameof(defaultEncoding)); ContractUtils.Requires(stream.CanRead && stream.CanSeek, nameof(stream), "The stream must support reading and seeking"); @@ -195,16 +199,16 @@ public virtual CompilerOptions GetCompilerOptions(Scope scope) { /// /// null on failure. /// Could also set the code properties and line/file mappings on the source unit. - public abstract ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink); + public abstract ScriptCode? CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink); - public virtual ScriptCode LoadCompiledCode(Delegate method, string path, string customData) { + public virtual ScriptCode? LoadCompiledCode(Delegate method, string path, string customData) { throw new NotSupportedException(); } public virtual int ExecuteProgram(SourceUnit program) { ContractUtils.RequiresNotNull(program, nameof(program)); - object returnValue = program.Execute(); + object? returnValue = program.Execute(); if (returnValue is null) { return 0; @@ -238,7 +242,7 @@ public virtual SourceUnit GenerateSourceCode(System.CodeDom.CodeObject codeDom, } #endif - public virtual TService GetService(params object[] args) where TService : class { + public virtual TService? GetService(params object?[] args) where TService : class { return null; } @@ -267,7 +271,7 @@ public SourceUnit CreateSnippet(string code, SourceCodeKind kind) { return CreateSnippet(code, null, kind); } - public SourceUnit CreateSnippet(string code, string id, SourceCodeKind kind) { + public SourceUnit CreateSnippet(string code, string? id, SourceCodeKind kind) { ContractUtils.RequiresNotNull(code, nameof(code)); return CreateSourceUnit(new SourceStringContentProvider(code), id, kind); @@ -297,7 +301,7 @@ public SourceUnit CreateFileUnit(string path, string content) { return CreateSourceUnit(provider, path, SourceCodeKind.File); } - public SourceUnit CreateSourceUnit(StreamContentProvider contentProvider, string path, Encoding encoding, SourceCodeKind kind) { + public SourceUnit CreateSourceUnit(StreamContentProvider contentProvider, string? path, Encoding encoding, SourceCodeKind kind) { ContractUtils.RequiresNotNull(contentProvider, nameof(contentProvider)); ContractUtils.RequiresNotNull(encoding, nameof(encoding)); ContractUtils.Requires(kind.IsValid(), nameof(kind)); @@ -306,7 +310,7 @@ public SourceUnit CreateSourceUnit(StreamContentProvider contentProvider, string return new SourceUnit(this, new LanguageBoundTextContentProvider(this, contentProvider, encoding, path), path, kind); } - public SourceUnit CreateSourceUnit(TextContentProvider contentProvider, string path, SourceCodeKind kind) { + public SourceUnit CreateSourceUnit(TextContentProvider contentProvider, string? path, SourceCodeKind kind) { ContractUtils.RequiresNotNull(contentProvider, nameof(contentProvider)); ContractUtils.Requires(kind.IsValid(), nameof(kind)); ContractUtils.Requires(CanCreateSourceCode); @@ -327,7 +331,7 @@ public virtual ErrorSink GetCompilerErrorSink() { #region Object Operations Support - internal static DynamicMetaObject ErrorMetaObject(Type resultType, DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + internal static DynamicMetaObject ErrorMetaObject(Type resultType, DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject? errorSuggestion) { return errorSuggestion ?? new DynamicMetaObject( Expression.Throw(Expression.New(typeof(NotImplementedException)), resultType), target.Restrictions.Merge(BindingRestrictions.Combine(args)) @@ -343,7 +347,7 @@ internal DefaultUnaryOperationBinder(ExpressionType operation) : base(operation) { } - public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, target, new[] { target }, errorSuggestion); } } @@ -357,7 +361,7 @@ internal DefaultBinaryOperationBinder(ExpressionType operation) : base(operation) { } - public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, target, new[] { target, arg }, errorSuggestion); } } @@ -367,7 +371,7 @@ internal DefaultConvertAction(Type type, bool @explicit) : base(type, @explicit) { } - public override DynamicMetaObject FallbackConvert(DynamicMetaObject self, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackConvert(DynamicMetaObject self, DynamicMetaObject? errorSuggestion) { if (Type.IsAssignableFrom(self.LimitType)) { return new DynamicMetaObject( Expression.Convert(self.Expression, Type), @@ -409,11 +413,11 @@ internal DefaultGetMemberAction(string name, bool ignoreCase) : base(name, ignoreCase) { } - public override DynamicMetaObject FallbackGetMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject self, DynamicMetaObject? errorSuggestion) { return errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New( - typeof(MissingMemberException).GetConstructor(new[] { typeof(string) }), + typeof(MissingMemberException).GetConstructor(new[] { typeof(string) })!, Expression.Constant($"unknown member: {Name}") ), typeof(object) @@ -434,7 +438,7 @@ internal DefaultSetMemberAction(string name, bool ignoreCase) : base(name, ignoreCase) { } - public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, self, new DynamicMetaObject[] { value }, errorSuggestion); } } @@ -448,7 +452,7 @@ internal DefaultDeleteMemberAction(string name, bool ignoreCase) : base(name, ignoreCase) { } - public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, self, DynamicMetaObject.EmptyMetaObjects, errorSuggestion); } } @@ -465,7 +469,7 @@ internal DefaultCallAction(LanguageContext context, string name, bool ignoreCase _context = context; } - public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, target, [target, ..args], errorSuggestion); } @@ -479,7 +483,7 @@ private static Expression[] GetArgs(DynamicMetaObject target, DynamicMetaObject[ return res; } - public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject? errorSuggestion) { return new DynamicMetaObject( DynamicExpression.Dynamic( _context.CreateInvokeBinder(CallInfo), @@ -500,7 +504,7 @@ internal DefaultInvokeAction(CallInfo callInfo) : base(callInfo) { } - public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, target, args, errorSuggestion); } } @@ -514,7 +518,7 @@ internal DefaultCreateAction(CallInfo callInfo) : base(callInfo) { } - public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject? errorSuggestion) { return ErrorMetaObject(ReturnType, target, args, errorSuggestion); } } @@ -529,7 +533,7 @@ public DynamicOperations Operations { Interlocked.CompareExchange(ref _operations, new DynamicOperations(this), null); } - return _operations; + return _operations!; } } #endregion @@ -540,7 +544,7 @@ public DynamicOperations Operations { /// Gets the member names associated with the object /// By default, only returns IDO names /// - public virtual IList GetMemberNames(object obj) { + public virtual IList GetMemberNames(object? obj) { if (obj is IDynamicMetaObjectProvider ido) { var mo = ido.GetMetaObject(Expression.Parameter(typeof(object), null)); return mo.GetDynamicMemberNames().ToReadOnlyCollection(); @@ -548,15 +552,15 @@ public virtual IList GetMemberNames(object obj) { return Array.Empty(); } - public virtual string GetDocumentation(object obj) { + public virtual string GetDocumentation(object? obj) { return string.Empty; } - public virtual IList GetCallSignatures(object obj) { + public virtual IList GetCallSignatures(object? obj) { return Array.Empty(); } - public virtual bool IsCallable(object obj) => obj is Delegate; + public virtual bool IsCallable(object? obj) => obj is Delegate; #endregion @@ -568,8 +572,8 @@ public virtual IList GetCallSignatures(object obj) { /// Dynamic sites container that could be used for any dynamic dispatches necessary for formatting. /// Object to format. /// A string representation of object. - public virtual string FormatObject(DynamicOperations operations, object obj) { - return obj is null ? "null" : obj.ToString(); + public virtual string FormatObject(DynamicOperations operations, object? obj) { + return obj?.ToString() ?? "null"; } public virtual void GetExceptionMessage(Exception exception, out string message, out string errorTypeName) { diff --git a/src/core/Microsoft.Scripting/Runtime/ScriptCode.cs b/src/core/Microsoft.Scripting/Runtime/ScriptCode.cs index 3fe75ed2..2e0f5c79 100644 --- a/src/core/Microsoft.Scripting/Runtime/ScriptCode.cs +++ b/src/core/Microsoft.Scripting/Runtime/ScriptCode.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; @@ -27,11 +29,11 @@ public virtual Scope CreateScope() { return SourceUnit.LanguageContext.CreateScope(); } - public virtual object Run() { + public virtual object? Run() { return Run(CreateScope()); } - public abstract object Run(Scope scope); + public abstract object? Run(Scope scope); public override string ToString() { return $"ScriptCode '{SourceUnit.Path}' from {LanguageContext.GetType().Name}"; diff --git a/src/core/Microsoft.Scripting/Runtime/ScriptDomainManager.cs b/src/core/Microsoft.Scripting/Runtime/ScriptDomainManager.cs index 1cd082da..373117a1 100644 --- a/src/core/Microsoft.Scripting/Runtime/ScriptDomainManager.cs +++ b/src/core/Microsoft.Scripting/Runtime/ScriptDomainManager.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Threading; @@ -51,40 +54,61 @@ internal ContextId GenerateContextId() { return new ContextId(Interlocked.Increment(ref _lastContextId)); } + /// + /// Loads (if necessary) and returns the registered under the + /// assembly-qualified name of . + /// + /// + /// A closed, loaded that must derive from + /// and have been registered via + /// . + /// + /// No language is registered for the given type. public LanguageContext GetLanguage(Type providerType) { ContractUtils.RequiresNotNull(providerType, nameof(providerType)); - return GetLanguageByTypeName(providerType.AssemblyQualifiedName); + return GetLanguageByTypeName(providerType.AssemblyQualifiedName!); } + /// + /// Loads (if necessary) and returns the registered under the + /// given assembly-qualified type name. + /// + /// + /// The assembly-qualified name of a type that derives from and + /// was registered via . + /// The name is parsed and the referenced assembly is loaded on first access; the resolved type must inherit from + /// or an is thrown during loading. + /// + /// No language is registered for the given type name. public LanguageContext GetLanguageByTypeName(string providerAssemblyQualifiedTypeName) { ContractUtils.RequiresNotNull(providerAssemblyQualifiedTypeName, nameof(providerAssemblyQualifiedTypeName)); var aqtn = AssemblyQualifiedTypeName.ParseArgument(providerAssemblyQualifiedTypeName, nameof(providerAssemblyQualifiedTypeName)); - if (!Configuration.TryLoadLanguage(this, aqtn, out LanguageContext language)) { + if (!Configuration.TryLoadLanguage(this, aqtn, out LanguageContext? language)) { throw Error.UnknownLanguageProviderType(); } return language; } - public bool TryGetLanguage(string languageName, out LanguageContext language) { + public bool TryGetLanguage(string languageName, [NotNullWhen(true)] out LanguageContext? language) { ContractUtils.RequiresNotNull(languageName, nameof(languageName)); return Configuration.TryLoadLanguage(this, languageName, false, out language); } public LanguageContext GetLanguageByName(string languageName) { - if (!TryGetLanguage(languageName, out LanguageContext language)) { + if (!TryGetLanguage(languageName, out LanguageContext? language)) { throw new ArgumentException($"Unknown language name: '{languageName}'"); } return language; } - public bool TryGetLanguageByFileExtension(string fileExtension, out LanguageContext language) { + public bool TryGetLanguageByFileExtension(string fileExtension, [NotNullWhen(true)] out LanguageContext? language) { ContractUtils.RequiresNotEmpty(fileExtension, nameof(fileExtension)); return Configuration.TryLoadLanguage(this, DlrConfiguration.NormalizeExtension(fileExtension), true, out language); } public LanguageContext GetLanguageByExtension(string fileExtension) { - if (!TryGetLanguageByFileExtension(fileExtension, out LanguageContext language)) { + if (!TryGetLanguageByFileExtension(fileExtension, out LanguageContext? language)) { throw new ArgumentException($"Unknown file extension: '{fileExtension}'"); } return language; @@ -103,7 +127,7 @@ public LanguageContext GetLanguageByExtension(string fileExtension) { /// get any assemblies which were loaded before the language was /// loaded. /// - public event EventHandler AssemblyLoaded; + public event EventHandler? AssemblyLoaded; public bool LoadAssembly(Assembly assembly) { ContractUtils.RequiresNotNull(assembly, nameof(assembly)); @@ -116,7 +140,7 @@ public bool LoadAssembly(Assembly assembly) { _loadedAssemblies.Add(assembly); } - EventHandler assmLoaded = AssemblyLoaded; + EventHandler? assmLoaded = AssemblyLoaded; assmLoaded?.Invoke(this, new AssemblyLoadedEventArgs(assembly)); return true; diff --git a/src/core/Microsoft.Scripting/Runtime/TokenizerService.cs b/src/core/Microsoft.Scripting/Runtime/TokenizerService.cs index f1ab98fc..2cae18e3 100644 --- a/src/core/Microsoft.Scripting/Runtime/TokenizerService.cs +++ b/src/core/Microsoft.Scripting/Runtime/TokenizerService.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System.Collections.Generic; using System.IO; @@ -12,7 +14,7 @@ public abstract class TokenizerService { protected TokenizerService() { } - public abstract void Initialize(object state, TextReader sourceReader, SourceUnit sourceUnit, SourceLocation initialLocation); + public abstract void Initialize(object? state, TextReader sourceReader, SourceUnit sourceUnit, SourceLocation initialLocation); /// /// The current internal state of the scanner. diff --git a/src/core/Microsoft.Scripting/SourceUnit.cs b/src/core/Microsoft.Scripting/SourceUnit.cs index d4655ced..7031fbd7 100644 --- a/src/core/Microsoft.Scripting/SourceUnit.cs +++ b/src/core/Microsoft.Scripting/SourceUnit.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System.Linq.Expressions; using System; @@ -21,14 +23,14 @@ public sealed class SourceUnit { // SourceUnit is serializable => updated parse result is transmitted // back to the host unless the unit is passed by-ref private ScriptCodeParseResult? _parseResult; - private KeyValuePair[] _lineMap; + private KeyValuePair[]? _lineMap; /// - /// Identification of the source unit. Assigned by the host. + /// Identification of the source unit. Assigned by the host. /// The format and semantics is host dependent (could be a path on file system or URL). /// Empty string for anonymous source units. /// - public string Path { get; } + public string? Path { get; } private string DebugString => Path ?? ""; @@ -36,7 +38,7 @@ public sealed class SourceUnit { public SourceCodeKind Kind { get; } - public SymbolDocumentInfo Document { + public SymbolDocumentInfo? Document { get { // _path is valid to be null. In that case we cannot create a valid SymbolDocumentInfo. return Path is null ? null : Expression.SymbolDocument(Path, _language.LanguageGuid, _language.VendorGuid); @@ -68,7 +70,7 @@ public ScriptCodeParseResult? CodeProperties { set { _parseResult = value; } } - public SourceUnit(LanguageContext context, TextContentProvider contentProvider, string path, SourceCodeKind kind) { + public SourceUnit(LanguageContext context, TextContentProvider contentProvider, string? path, SourceCodeKind kind) { Assert.NotNull(context, contentProvider); Debug.Assert(context.CanCreateSourceCode); @@ -84,7 +86,7 @@ public SourceCodeReader GetReader() { } /// - /// Reads specified range of lines (or less) from the source unit. + /// Reads specified range of lines (or less) from the source unit. /// Line numbers starts with 1. /// public string[] GetCodeLines(int start, int count) { @@ -96,7 +98,7 @@ public string[] GetCodeLines(int start, int count) { using (SourceCodeReader reader = GetReader()) { reader.SeekLine(start); while (count > 0) { - string line = reader.ReadLine(); + string? line = reader.ReadLine(); if (line is null) break; result.Add(line); count--; @@ -107,7 +109,7 @@ public string[] GetCodeLines(int start, int count) { } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] - public string GetCodeLine(int line) { + public string? GetCodeLine(int line) { string[] lines = GetCodeLines(line, 1); return (lines.Length > 0) ? lines[0] : null; } @@ -148,7 +150,7 @@ public bool HasLineMapping { } private static int BinarySearch(KeyValuePair[] array, int line) { - int match = Array.BinarySearch(array, new KeyValuePair(line, default(T)), new KeyComparer()); + int match = Array.BinarySearch(array, new KeyValuePair(line, default(T)!), new KeyComparer()); if (match < 0) { // If we couldn't find an exact match for this line number, get the nearest // matching line number less than this one @@ -180,19 +182,19 @@ public bool EmitDebugSymbols { } } - public ScriptCode Compile() { + public ScriptCode? Compile() { return Compile(ErrorSink.Default); } - public ScriptCode Compile(ErrorSink errorSink) { + public ScriptCode? Compile(ErrorSink errorSink) { return Compile(_language.GetCompilerOptions(), errorSink); } /// - /// Errors are reported to the specified sink. + /// Errors are reported to the specified sink. /// Returns null if the parser cannot compile the code due to error(s). /// - public ScriptCode Compile(CompilerOptions options, ErrorSink errorSink) { + public ScriptCode? Compile(CompilerOptions options, ErrorSink errorSink) { ContractUtils.RequiresNotNull(errorSink, nameof(errorSink)); ContractUtils.RequiresNotNull(options, nameof(options)); @@ -202,17 +204,17 @@ public ScriptCode Compile(CompilerOptions options, ErrorSink errorSink) { /// /// Executes against a specified scope. /// - public object Execute(Scope scope) { + public object? Execute(Scope scope) { return Execute(scope, ErrorSink.Default); } /// /// Executes against a specified scope and reports errors to the given error sink. /// - public object Execute(Scope scope, ErrorSink errorSink) { + public object? Execute(Scope scope, ErrorSink errorSink) { ContractUtils.RequiresNotNull(scope, nameof(scope)); - ScriptCode compiledCode = Compile(_language.GetCompilerOptions(scope), errorSink); + ScriptCode? compiledCode = Compile(_language.GetCompilerOptions(scope), errorSink); if (compiledCode is null) { throw new SyntaxErrorException(); @@ -224,22 +226,22 @@ public object Execute(Scope scope, ErrorSink errorSink) { /// /// Executes in a new scope created by the language. /// - public object Execute() { - return Compile().Run(); + public object? Execute() { + return Compile()?.Run(); } /// /// Executes in a new scope created by the language. /// - public object Execute(ErrorSink errorSink) { - return Compile(errorSink).Run(); + public object? Execute(ErrorSink errorSink) { + return Compile(errorSink)?.Run(); } /// /// Executes in a new scope created by the language. /// - public object Execute(CompilerOptions options, ErrorSink errorSink) { - return Compile(options, errorSink).Run(); + public object? Execute(CompilerOptions options, ErrorSink errorSink) { + return Compile(options, errorSink)?.Run(); } public int ExecuteProgram() { @@ -248,7 +250,7 @@ public int ExecuteProgram() { #endregion - public void SetLineMapping(KeyValuePair[] lineMap) { + public void SetLineMapping(KeyValuePair[]? lineMap) { _lineMap = (lineMap is null || lineMap.Length == 0) ? null : lineMap; } } diff --git a/src/core/Microsoft.Scripting/SyntaxErrorException.cs b/src/core/Microsoft.Scripting/SyntaxErrorException.cs index 32f29233..79c19030 100644 --- a/src/core/Microsoft.Scripting/SyntaxErrorException.cs +++ b/src/core/Microsoft.Scripting/SyntaxErrorException.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Runtime.Serialization; using System.Dynamic; @@ -14,9 +16,9 @@ namespace Microsoft.Scripting { public class SyntaxErrorException : Exception { private readonly SourceSpan _span; - private readonly string _sourceCode; - private readonly string _sourceLine; - private readonly string _sourcePath; + private readonly string? _sourceCode; + private readonly string? _sourceLine; + private readonly string? _sourcePath; private readonly Severity _severity; private readonly int _errorCode; @@ -29,7 +31,7 @@ public SyntaxErrorException(string message, Exception innerException) : base(message, innerException) { } - public SyntaxErrorException(string message, SourceUnit sourceUnit, SourceSpan span, int errorCode, Severity severity) + public SyntaxErrorException(string message, SourceUnit? sourceUnit, SourceSpan span, int errorCode, Severity severity) : base(message) { ContractUtils.RequiresNotNull(message, nameof(message)); @@ -47,7 +49,7 @@ public SyntaxErrorException(string message, SourceUnit sourceUnit, SourceSpan sp } } - public SyntaxErrorException(string message, string path, string code, string line, SourceSpan span, int errorCode, Severity severity) + public SyntaxErrorException(string message, string? path, string? code, string? line, SourceSpan span, int errorCode, Severity severity) : base(message) { ContractUtils.RequiresNotNull(message, nameof(message)); @@ -64,10 +66,10 @@ public SyntaxErrorException(string message, string path, string code, string lin protected SyntaxErrorException(SerializationInfo info, StreamingContext context) : base(info, context) { - _span = (SourceSpan)info.GetValue("Span", typeof(SourceSpan)); + _span = (SourceSpan)info.GetValue("Span", typeof(SourceSpan))!; _sourceCode = info.GetString("SourceCode"); _sourcePath = info.GetString("SourcePath"); - _severity = (Severity)info.GetValue("Severity", typeof(Severity)); + _severity = (Severity)info.GetValue("Severity", typeof(Severity))!; _errorCode = info.GetInt32("ErrorCode"); } @@ -91,11 +93,11 @@ public SourceSpan RawSpan { get { return _span; } } - public string SourceCode { + public string? SourceCode { get { return _sourceCode; } } - public string SourcePath { + public string? SourcePath { get { return _sourcePath; } } @@ -117,14 +119,14 @@ public int ErrorCode { // TODO: fix [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] - public string GetSymbolDocumentName() { + public string? GetSymbolDocumentName() { return _sourcePath; } // TODO: fix [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] - public string GetCodeLine() { + public string? GetCodeLine() { return _sourceLine; } } -} \ No newline at end of file +} diff --git a/src/core/Microsoft.Scripting/Utils/AssemblyQualifiedTypeName.cs b/src/core/Microsoft.Scripting/Utils/AssemblyQualifiedTypeName.cs index 739cd683..3087c83e 100644 --- a/src/core/Microsoft.Scripting/Utils/AssemblyQualifiedTypeName.cs +++ b/src/core/Microsoft.Scripting/Utils/AssemblyQualifiedTypeName.cs @@ -10,7 +10,7 @@ namespace Microsoft.Scripting.Utils { [Serializable] internal readonly struct AssemblyQualifiedTypeName : IEquatable { - public readonly string? TypeName; + public readonly string TypeName; public readonly AssemblyName AssemblyName; public AssemblyQualifiedTypeName(string typeName, AssemblyName assemblyName) { @@ -22,7 +22,8 @@ public AssemblyQualifiedTypeName(string typeName, AssemblyName assemblyName) { } public AssemblyQualifiedTypeName(Type type) { - TypeName = type.FullName; + TypeName = type.FullName + ?? throw new ArgumentException($"Type '{type}' does not have a full name and cannot be used to create an {nameof(AssemblyQualifiedTypeName)}"); AssemblyName = type.Assembly.GetName(); }