From 75bd654a940749405837e4b098a1a131b743fb40 Mon Sep 17 00:00:00 2001 From: Sinai <49360850+sinai-dev@users.noreply.github.com> Date: Fri, 22 Apr 2022 09:07:51 +1000 Subject: [PATCH] TypeCompleter: Allow generics, support shorthand names --- src/UI/Widgets/AutoComplete/TypeCompleter.cs | 71 ++++++++++++++++---- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/src/UI/Widgets/AutoComplete/TypeCompleter.cs b/src/UI/Widgets/AutoComplete/TypeCompleter.cs index 3b36faa..540b4bc 100644 --- a/src/UI/Widgets/AutoComplete/TypeCompleter.cs +++ b/src/UI/Widgets/AutoComplete/TypeCompleter.cs @@ -28,30 +28,52 @@ namespace UnityExplorer.UI.Widgets.AutoComplete public Type[] GenericConstraints { get; set; } public bool AllTypes { get; set; } - private readonly bool allowAbstract; - private readonly bool allowEnum; - public InputFieldRef InputField { get; } public bool AnchorToCaretPosition => false; - private readonly List suggestions = new(); - private readonly HashSet suggestedNames = new(); + readonly bool allowAbstract; + readonly bool allowEnum; + readonly bool allowGeneric; private HashSet allowedTypes; + private HashSet allAllowedTypes; + readonly List suggestions = new(); + readonly HashSet suggestedNames = new(); private string chosenSuggestion; bool ISuggestionProvider.AllowNavigation => false; - public TypeCompleter(Type baseType, InputFieldRef inputField) : this(baseType, inputField, true, true) { } + static readonly Dictionary shorthandToType = new() + { + { "object", typeof(object) }, + { "string", typeof(string) }, + { "bool", typeof(bool) }, + { "byte", typeof(byte) }, + { "sbyte", typeof(sbyte) }, + { "char", typeof(char) }, + { "decimal", typeof(decimal) }, + { "double", typeof(double) }, + { "float", typeof(float) }, + { "int", typeof(int) }, + { "uint", typeof(uint) }, + { "long", typeof(long) }, + { "ulong", typeof(ulong) }, + { "short", typeof(short) }, + { "ushort", typeof(ushort) }, + { "void", typeof(void) }, + }; - public TypeCompleter(Type baseType, InputFieldRef inputField, bool allowAbstract, bool allowEnum) + public TypeCompleter(Type baseType, InputFieldRef inputField) : this(baseType, inputField, true, true, true) { } + + public TypeCompleter(Type baseType, InputFieldRef inputField, bool allowAbstract, bool allowEnum, bool allowGeneric) { BaseType = baseType; InputField = inputField; this.allowAbstract = allowAbstract; this.allowEnum = allowEnum; + this.allowGeneric = allowGeneric; inputField.OnValueChanged += OnInputFieldChanged; @@ -62,10 +84,16 @@ namespace UnityExplorer.UI.Widgets.AutoComplete public void CacheTypes() { if (!AllTypes) - allowedTypes = ReflectionUtility.GetImplementationsOf(BaseType, allowAbstract, allowEnum, false); + allowedTypes = ReflectionUtility.GetImplementationsOf(BaseType, allowAbstract, allowGeneric, allowEnum); else + allowedTypes = GetAllAllowedTypes(); + } + + HashSet GetAllAllowedTypes() + { + if (allAllowedTypes == null) { - allowedTypes = new(); + allAllowedTypes = new(); foreach (KeyValuePair entry in ReflectionUtility.AllTypes) { // skip and classes @@ -76,9 +104,11 @@ namespace UnityExplorer.UI.Widgets.AutoComplete { continue; } - allowedTypes.Add(type); + allAllowedTypes.Add(type); } } + + return allAllowedTypes; } public void OnSuggestionClicked(Suggestion suggestion) @@ -110,24 +140,37 @@ namespace UnityExplorer.UI.Widgets.AutoComplete } } - private void GetSuggestions(string value) + private void GetSuggestions(string input) { suggestions.Clear(); suggestedNames.Clear(); - if (BaseType == null) + if (!AllTypes && BaseType == null) { ExplorerCore.LogWarning("Autocompleter Base type is null!"); return; } + // shorthand types all inherit from System.Object + if (AllTypes || BaseType == typeof(object)) + { + if (shorthandToType.TryGetValue(input, out Type shorthand)) + AddSuggestion(shorthand); + + foreach (KeyValuePair entry in shorthandToType) + { + if (entry.Key.StartsWith(input, StringComparison.InvariantCultureIgnoreCase)) + AddSuggestion(entry.Value); + } + } + // Check for exact match first - if (ReflectionUtility.GetTypeByName(value) is Type t && allowedTypes.Contains(t)) + if (ReflectionUtility.GetTypeByName(input) is Type t && allowedTypes.Contains(t)) AddSuggestion(t); foreach (Type entry in allowedTypes) { - if (entry.FullName.ContainsIgnoreCase(value)) + if (entry.FullName.ContainsIgnoreCase(input)) AddSuggestion(entry); } }