mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 01:27:13 +02:00
* [Dependency] source generator No more reflection, no more codegen at runtime Also various changes to Roslyn helpers to make this easier to write. Requires all types with dependencies to be partial and not have readonly dependency fields. An analyzer enforces this at warning level, the previous injection strategies have remained in the code *for now* as a fallback. No fallback is available for [field: Dependency] properties, due to a Roslyn bug. Code Fixes exist. We love Roslyn * Apply dependencies generator changes to all code * Release notes * Preprocessor got hands * Handle nullable dependencies These are bad but gotta deal with it. * Apply suggestions from code review Co-authored-by: Moony <moony@hellomouse.net> * Fine, let's not use collection expressions --------- Co-authored-by: Moony <moony@hellomouse.net>
280 lines
8.5 KiB
C#
280 lines
8.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Localization;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Shared.Configuration
|
|
{
|
|
public static class CVarCommandUtil
|
|
{
|
|
/// <summary>
|
|
/// Parses a string into an object of the given type.
|
|
/// </summary>
|
|
/// <exception cref="FormatException">Thrown if the string could not be parsed into the given type.</exception>
|
|
/// <exception cref="NotSupportedException">Thrown if the type is not supported.</exception>
|
|
public static object ParseObject(Type type, string input)
|
|
{
|
|
if (type == typeof(bool))
|
|
{
|
|
if (bool.TryParse(input, out var val))
|
|
return val;
|
|
|
|
if (Parse.TryInt32(input, out var intVal))
|
|
{
|
|
if (intVal == 0) return false;
|
|
if (intVal == 1) return true;
|
|
}
|
|
|
|
throw new FormatException($"Could not parse bool value: {input}");
|
|
}
|
|
|
|
if (type == typeof(string))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
if (type == typeof(int))
|
|
{
|
|
return Parse.Int32(input);
|
|
}
|
|
|
|
if (type == typeof(float))
|
|
{
|
|
return Parse.Float(input);
|
|
}
|
|
|
|
if (type == typeof(long))
|
|
{
|
|
return long.Parse(input);
|
|
}
|
|
|
|
if (type == typeof(ushort))
|
|
{
|
|
return ushort.Parse(input);
|
|
}
|
|
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
internal static IEnumerable<CompletionOption> GetCVarCompletionOptions(IConfigurationManager cfg)
|
|
{
|
|
return cfg.GetRegisteredCVars()
|
|
.Select(c => new CompletionOption(c, GetCVarValueHint(cfg, c)));
|
|
}
|
|
|
|
private static string GetCVarValueHint(IConfigurationManager cfg, string cVar)
|
|
{
|
|
var flags = cfg.GetCVarFlags(cVar);
|
|
if ((flags & CVar.CONFIDENTIAL) != 0)
|
|
return Loc.GetString("cmd-cvar-value-hidden");
|
|
|
|
var value = cfg.GetCVar<object>(cVar).ToString() ?? "";
|
|
if (value.Length > 50)
|
|
value = $"{value[..51]}…";
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
|
internal sealed partial class CVarCommand : LocalizedCommands
|
|
{
|
|
[Dependency] private IConfigurationManager _cfg = default!;
|
|
|
|
public override string Command => "cvar";
|
|
|
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-invalid-args"));
|
|
return;
|
|
}
|
|
|
|
var name = args[0];
|
|
|
|
if (name == "?")
|
|
{
|
|
var cvars = _cfg.GetRegisteredCVars().OrderBy(c => c);
|
|
shell.WriteLine(string.Join("\n", cvars));
|
|
return;
|
|
}
|
|
|
|
if (!_cfg.IsCVarRegistered(name))
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-not-registered", ("cvar", name)));
|
|
return;
|
|
}
|
|
|
|
if (args.Length == 1)
|
|
{
|
|
// Read CVar
|
|
var value = _cfg.GetCVar<object>(name);
|
|
shell.WriteLine(value.ToString()!);
|
|
}
|
|
else
|
|
{
|
|
// Write CVar
|
|
var value = args[1];
|
|
var type = _cfg.GetCVarType(name);
|
|
try
|
|
{
|
|
var parsed = CVarCommandUtil.ParseObject(type, value);
|
|
_cfg.SetCVar(name, parsed);
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-parse-error", ("type", type)));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
var helpQuestion = Loc.GetString("cmd-cvar-compl-list");
|
|
|
|
return CompletionResult.FromHintOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.Union(new[] { new CompletionOption("?", helpQuestion) })
|
|
.OrderBy(c => c.Value),
|
|
Loc.GetString("cmd-cvar-arg-name"));
|
|
}
|
|
|
|
var cvar = args[0];
|
|
if (!_cfg.IsCVarRegistered(cvar))
|
|
return CompletionResult.Empty;
|
|
|
|
var type = _cfg.GetCVarType(cvar);
|
|
return CompletionResult.FromHint($"<{type.Name}>");
|
|
}
|
|
}
|
|
|
|
internal sealed partial class CVarSubsCommand : LocalizedCommands
|
|
{
|
|
[Dependency] private IConfigurationManager _cfg = default!;
|
|
|
|
public override string Command => "cvar_subs";
|
|
|
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length < 1)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar_subs-invalid-args"));
|
|
return;
|
|
}
|
|
|
|
var name = args[0];
|
|
var subs = ((ConfigurationManager)_cfg).GetSubs(name);
|
|
|
|
foreach (var @delegate in subs)
|
|
{
|
|
shell.WriteLine(ShowDelegateInfo(@delegate));
|
|
}
|
|
}
|
|
|
|
private static string ShowDelegateInfo(Delegate del)
|
|
{
|
|
return $"{del}: {del.Method} -> {del.Target}";
|
|
}
|
|
|
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromHintOptions(
|
|
_cfg.GetRegisteredCVars()
|
|
.Select(c => new CompletionOption(c))
|
|
.OrderBy(c => c.Value),
|
|
Loc.GetString("cmd-cvar_subs-arg-name"));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
internal sealed partial class ConfigMarkRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_mark";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-invalid-arg-number-error"));
|
|
return;
|
|
}
|
|
|
|
_cfg.MarkForRollback(args[0]);
|
|
}
|
|
|
|
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.OrderBy(c => c.Value));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
internal sealed partial class ConfigUnmarkRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_unmark";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-invalid-arg-number-error"));
|
|
return;
|
|
}
|
|
|
|
_cfg.UnmarkForRollback(args[0]);
|
|
}
|
|
|
|
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.OrderBy(c => c.Value));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
|
|
internal sealed partial class ConfigApplyRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_apply";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
_cfg.ApplyRollback();
|
|
}
|
|
}
|
|
}
|