diff --git a/src/core/IronPython/Hosting/Python.cs b/src/core/IronPython/Hosting/Python.cs index 32e666307..e91f3d622 100644 --- a/src/core/IronPython/Hosting/Python.cs +++ b/src/core/IronPython/Hosting/Python.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; @@ -198,11 +200,11 @@ public static class Python { /// /// /// - public static void ImportModule (this ScriptScope/*!*/ scope, string/*!*/ moduleName) { - ContractUtils.RequiresNotNull (scope, nameof(scope)); - ContractUtils.RequiresNotNull (moduleName, nameof(moduleName)); + public static void ImportModule(this ScriptScope/*!*/ scope, string/*!*/ moduleName) { + ContractUtils.RequiresNotNull(scope, nameof(scope)); + ContractUtils.RequiresNotNull(moduleName, nameof(moduleName)); - scope.SetVariable (moduleName, scope.Engine.ImportModule (moduleName)); + scope.SetVariable(moduleName, scope.Engine.ImportModule(moduleName)); } /// @@ -270,12 +272,12 @@ public static void CallTracing(this ScriptEngine/*!*/ engine, object traceFunc, /// /// The ScriptRuntimeSetup object can then be additional configured and used to create a ScriptRuntime. /// - public static ScriptRuntimeSetup/*!*/ CreateRuntimeSetup(IDictionary options) { + public static ScriptRuntimeSetup/*!*/ CreateRuntimeSetup(IDictionary? options) { ScriptRuntimeSetup setup = new ScriptRuntimeSetup(); setup.LanguageSetups.Add(CreateLanguageSetup(options)); if (options != null) { - object value; + object? value; if (options.TryGetValue("Debug", out value) && value is bool && (bool)value) { @@ -298,7 +300,7 @@ value is bool && /// The LanguageSetup object can be used with other LanguageSetup objects from other languages to /// configure a ScriptRuntimeSetup object. /// - public static LanguageSetup/*!*/ CreateLanguageSetup(IDictionary options) { + public static LanguageSetup/*!*/ CreateLanguageSetup(IDictionary? options) { var setup = new LanguageSetup( typeof(PythonContext).AssemblyQualifiedName, PythonContext.IronPythonDisplayName, @@ -360,7 +362,7 @@ public static string[] GetModuleFilenames(this ScriptEngine engine) { } private static PythonContext/*!*/ GetPythonContext(ScriptEngine/*!*/ engine) { - return HostingHelpers.GetLanguageContext(engine) as PythonContext; + return (PythonContext)HostingHelpers.GetLanguageContext(engine); } #endregion diff --git a/src/core/IronPython/Hosting/PythonCodeDomCodeGen.cs b/src/core/IronPython/Hosting/PythonCodeDomCodeGen.cs index 76c711b01..65455b9c6 100644 --- a/src/core/IronPython/Hosting/PythonCodeDomCodeGen.cs +++ b/src/core/IronPython/Hosting/PythonCodeDomCodeGen.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.CodeDom; using System.Collections.Generic; + using Microsoft.Scripting.Runtime; #if FEATURE_CODEDOM @@ -44,8 +47,7 @@ protected override void WriteSnippetStatement(CodeSnippetStatement s) { int indentLen = lastLine.Length; if (indentLen > _indents.Peek()) { _indents.Push(indentLen); - } - else { + } else { while (indentLen < _indents.Peek()) { _indents.Pop(); } @@ -94,4 +96,4 @@ private string IndentSnippetStatement(string block) { } } -#endif \ No newline at end of file +#endif diff --git a/src/core/IronPython/Hosting/PythonCommandLine.cs b/src/core/IronPython/Hosting/PythonCommandLine.cs index 2fc86f071..1c4b4c453 100644 --- a/src/core/IronPython/Hosting/PythonCommandLine.cs +++ b/src/core/IronPython/Hosting/PythonCommandLine.cs @@ -2,9 +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; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.MemoryMappedFiles; using System.Reflection; @@ -35,7 +37,7 @@ public class PythonCommandLine : CommandLine { public PythonCommandLine() { } - protected override string Logo => PythonContext.PythonOptions.Quiet ? null : GetLogoDisplay(); + protected override string? Logo => PythonContext.PythonOptions.Quiet ? null : GetLogoDisplay(); /// /// Returns the display look for IronPython. @@ -49,7 +51,7 @@ public static string GetLogoDisplay() { } private int GetEffectiveExitCode(SystemExitException/*!*/ e) { - object nonIntegerCode; + object? nonIntegerCode; int exitCode = e.GetExitCode(out nonIntegerCode); if (nonIntegerCode != null) { Console.WriteLine(nonIntegerCode.ToString(), Style.Error); @@ -121,8 +123,8 @@ protected override int Run() { int result = base.Run(); // Check if IRONPYTHONINSPECT was set during execution - string inspectLine = Environment.GetEnvironmentVariable("IRONPYTHONINSPECT"); - if (inspectLine != null && !Options.Introspection) + string? inspectLine = Environment.GetEnvironmentVariable("IRONPYTHONINSPECT"); + if (!string.IsNullOrEmpty(inspectLine) && !Options.Introspection) result = RunInteractiveLoop(); return result; @@ -139,8 +141,6 @@ protected override int RunInteractiveLoop() { #region Initialization protected override void Initialize() { - Debug.Assert(Language != null); - base.Initialize(); Console.Output = new OutputWriter(PythonContext, false); @@ -168,8 +168,8 @@ protected override void Initialize() { // Equivalent to -i command line option // Check if IRONPYTHONINSPECT was set before execution - string inspectLine = Environment.GetEnvironmentVariable("IRONPYTHONINSPECT"); - if (inspectLine != null) + string? inspectLine = Environment.GetEnvironmentVariable("IRONPYTHONINSPECT"); + if (!string.IsNullOrEmpty(inspectLine)) Options.Introspection = true; // If running in console mode (including with -c), the current working directory should be @@ -198,7 +198,7 @@ protected override void Initialize() { fullPath = Path.GetDirectoryName( Language.DomainManager.Platform.GetFullPath(Options.FileName) - ); + )!; } } @@ -224,8 +224,8 @@ protected override void Initialize() { private void InitializePath(ref int pathIndex) { // paths, environment vars if (!Options.IgnoreEnvironmentVariables) { - string path = Environment.GetEnvironmentVariable("IRONPYTHONPATH"); - if (path != null && path.Length > 0) { + string? path = Environment.GetEnvironmentVariable("IRONPYTHONPATH"); + if (!string.IsNullOrEmpty(path)) { string[] paths = path.Split(Path.PathSeparator); foreach (string p in paths) { PythonContext.InsertIntoPath(pathIndex++, p); @@ -236,7 +236,7 @@ private void InitializePath(ref int pathIndex) { private void InitializeEnvironmentVariables() { if (!Options.IgnoreEnvironmentVariables) { - string warnings = Environment.GetEnvironmentVariable("IRONPYTHONWARNINGS"); + string? warnings = Environment.GetEnvironmentVariable("IRONPYTHONWARNINGS"); object o = PythonContext.GetSystemStateValue("warnoptions"); if (o == null) { o = new PythonList(); @@ -254,13 +254,13 @@ private void InitializeEnvironmentVariables() { private void InitializeModules() { string executable = ""; - string prefix = null; + string? prefix = null; - Assembly entryAssembly = Assembly.GetEntryAssembly(); + Assembly? entryAssembly = Assembly.GetEntryAssembly(); // Can be null if called from unmanaged code (VS integration scenario) if (entryAssembly != null) { executable = entryAssembly.Location; - prefix = Path.GetDirectoryName(executable); + prefix = Path.GetDirectoryName(executable)!; var name = Path.GetFileNameWithoutExtension(executable); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -285,7 +285,7 @@ private void InitializeModules() { } if (prefix is not null) { - string pyvenv_prefix = null; + string? pyvenv_prefix = null; // look for pyvenv.cfg in the current folder and then the parent folder var path = Path.Combine(prefix, "pyvenv.cfg"); @@ -302,7 +302,9 @@ private void InitializeModules() { } break; } - path = Path.Combine(Path.GetDirectoryName(prefix), "pyvenv.cfg"); + var parent = Path.GetDirectoryName(prefix); + if (parent is null) break; + path = Path.Combine(parent, "pyvenv.cfg"); } prefix = pyvenv_prefix ?? prefix; @@ -317,8 +319,8 @@ private void InitializeModules() { // --- Local functions ------- - static bool FindRunner(string prefix, string name, string assembly, out string runner) { - runner = null; + static bool FindRunner([DisallowNull] string? prefix, string name, string assembly, [NotNullWhen(true)] out string? runner) { + runner = string.Empty; #if NET while (prefix != null) { runner = Path.Combine(prefix, name); @@ -339,7 +341,7 @@ static bool FindRunner(string prefix, string name, string assembly, out string r using var mmf = MemoryMappedFile.CreateFromFile(runner, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); using var accessor = mmf.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); - for (long i = accessor.Capacity - fsAssemblyPath.Length; i >= 0; i--) { // the path should be close to the end of the file + for (long i = accessor.Capacity - fsAssemblyPath.Length; i >= 0; i--) { // the path should be close to the end of the file if (accessor.ReadByte(i) != fsap0) continue; bool found = true; @@ -354,6 +356,7 @@ static bool FindRunner(string prefix, string name, string assembly, out string r } catch { } // if reading the file fails, it is not our runner } #endif + runner = null; return false; } @@ -458,8 +461,8 @@ private void RunStartup() { if (Options.IgnoreEnvironmentVariables) return; - string startup = Environment.GetEnvironmentVariable("IRONPYTHONSTARTUP"); - if (startup != null && startup.Length > 0) { + string? startup = Environment.GetEnvironmentVariable("IRONPYTHONSTARTUP"); + if (!string.IsNullOrEmpty(startup)) { if (Options.HandleExceptions) { try { ExecuteCommand(Engine.CreateScriptSourceFromFile(startup)); diff --git a/src/core/IronPython/Hosting/PythonConsoleOptions.cs b/src/core/IronPython/Hosting/PythonConsoleOptions.cs index b8b3dde7e..f279bb376 100644 --- a/src/core/IronPython/Hosting/PythonConsoleOptions.cs +++ b/src/core/IronPython/Hosting/PythonConsoleOptions.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 Microsoft.Scripting.Hosting.Shell; namespace IronPython.Hosting { @@ -12,7 +15,7 @@ public sealed class PythonConsoleOptions : ConsoleOptions { public bool SkipImportSite { get; set; } - public string ModuleToRun { get; set; } + public string? ModuleToRun { get; set; } /// /// Gets or sets a value indicating whether to skip the first line of the code to execute. diff --git a/src/core/IronPython/Hosting/PythonOptionsParser.cs b/src/core/IronPython/Hosting/PythonOptionsParser.cs index 1bd42ee80..277f0847a 100644 --- a/src/core/IronPython/Hosting/PythonOptionsParser.cs +++ b/src/core/IronPython/Hosting/PythonOptionsParser.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; using System.Diagnostics; @@ -16,7 +18,7 @@ namespace IronPython.Hosting { public sealed class PythonOptionsParser : OptionsParser { - private List _warningFilters; + private List? _warningFilters; public PythonOptionsParser() { } @@ -205,8 +207,8 @@ protected override void ParseArgument(string/*!*/ arg) { } } - protected override void HandleImplementationSpecificOption(string arg, string val) { - object frames; + protected override void HandleImplementationSpecificOption(string arg, string? val) { + object? frames; switch (arg) { case "NoFrames": if (LanguageSetup.Options.TryGetValue("Frames", out frames) && frames != ScriptingRuntimeHelpers.False) { diff --git a/src/core/IronPython/Hosting/PythonService.cs b/src/core/IronPython/Hosting/PythonService.cs index c790b9b8e..4a0d39ccc 100644 --- a/src/core/IronPython/Hosting/PythonService.cs +++ b/src/core/IronPython/Hosting/PythonService.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 + #if FEATURE_REMOTING using System.Runtime.Remoting; #else @@ -11,8 +13,10 @@ using System; using System.Collections.Generic; using System.Threading; + using IronPython.Runtime; using IronPython.Runtime.Operations; + using Microsoft.Scripting.Hosting; using Microsoft.Scripting.Hosting.Providers; using Microsoft.Scripting.Utils; @@ -27,7 +31,7 @@ namespace IronPython.Hosting { public sealed class PythonService : MarshalByRefObject { private readonly ScriptEngine/*!*/ _engine; private readonly PythonContext/*!*/ _context; - private ScriptScope _sys, _builtins, _clr; + private ScriptScope? _sys, _builtins, _clr; public PythonService(PythonContext/*!*/ context, ScriptEngine/*!*/ engine) { Assert.NotNull(context, engine); @@ -76,7 +80,7 @@ public PythonService(PythonContext/*!*/ context, ScriptEngine/*!*/ engine) { _context.PublishModule(name, module); module.__init__(name, docString); module.__dict__["__file__"] = filename; - + return HostingHelpers.CreateScriptScope(_engine, module.Scope); } @@ -109,7 +113,7 @@ public void DispatchCommand(Action command) { } #if FEATURE_REMOTING - public ObjectHandle GetSetCommandDispatcher(ObjectHandle dispatcher) { + public ObjectHandle? GetSetCommandDispatcher(ObjectHandle dispatcher) { var res = _context.GetSetCommandDispatcher((Action)dispatcher.Unwrap()); if (res != null) { return new ObjectHandle(res);