This commit is contained in:
Даниил Заикин
2026-06-17 20:44:53 +03:00
parent 9d153773c2
commit b133e7c656
1880 changed files with 244545 additions and 0 deletions
@@ -0,0 +1,28 @@
using System.Collections.Generic;
namespace QFSW.QC.Suggestors
{
public class BoolSuggestor : BasicCachedQcSuggestor<string>
{
private readonly string[] _values =
{
"true",
"false"
};
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.TargetType == typeof(bool);
}
protected override IQcSuggestion ItemToSuggestion(string value)
{
return new RawSuggestion(value);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
return _values;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d92f72d4245dd241a6011cd64ae3644
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC.Suggestors
{
public class CommandNameSuggestor : BasicCachedQcSuggestor<string>
{
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.HasTag<Tags.CommandNameTag>()
&& !string.IsNullOrWhiteSpace(context.Prompt);
}
protected override IQcSuggestion ItemToSuggestion(string commandName)
{
return new RawSuggestion(commandName);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
string incompleteCommandName =
context.Prompt
.SplitScopedFirst(' ')
.SplitFirst('<');
return QuantumConsoleProcessor.GetUniqueCommands()
.Select(command => command.CommandName);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c09d30aec8067b41af36708c7808282
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
namespace QFSW.QC.Suggestors
{
public class CommandSuggestion : IQcSuggestion
{
private readonly CommandData _command;
private readonly string[] _paramNames;
private readonly int _numOptionalParams;
private readonly Dictionary<string, Type[]> _genericSignatureCache = new Dictionary<string, Type[]>();
private readonly Dictionary<ParameterInfo, IQcSuggestorTag[]> _parameterTagsCache = new Dictionary<ParameterInfo, IQcSuggestorTag[]>();
private readonly StringBuilder _stringBuilder = new StringBuilder();
private struct ParsedCommandNameInfo
{
public string RawName;
public string CommandName;
public string GenericSignature;
public string[] GenericArgNames;
}
private ParsedCommandNameInfo _currentCommandNameCache;
public string FullSignature => _command.CommandSignature;
public string PrimarySignature => _command.CommandName;
public string SecondarySignature { get; }
public CommandData Command => _command;
public CommandSuggestion(CommandData command, int numOptionalParams = 0)
{
_command = command;
_paramNames = _command.ParameterSignature.Split(' ');
_numOptionalParams = numOptionalParams;
for (int i = _paramNames.Length - _numOptionalParams; i < _paramNames.Length; i++)
{
_paramNames[i] = $"[{_paramNames[i]}]";
}
SecondarySignature = $"{_command.GenericSignature} {string.Join(" ", _paramNames)}";
}
public bool MatchesPrompt(string prompt)
{
UpdateCurrentCache(prompt);
return _currentCommandNameCache.CommandName == _command.CommandName;
}
public string GetCompletion(string prompt)
{
return _command.CommandName;
}
public string GetCompletionTail(string prompt)
{
UpdateCurrentCache(prompt);
_stringBuilder.Clear();
int numParamsInPrompt = prompt
.SplitScoped(' ')
.Count(x => !string.IsNullOrWhiteSpace(x)) - 1;
// Can't be less than zero params in the prompt
numParamsInPrompt = Mathf.Max(numParamsInPrompt, 0);
int numParamsToPrint = _command.ParamCount - numParamsInPrompt;
if (prompt == _currentCommandNameCache.CommandName)
{
_stringBuilder.Append(_command.GenericSignature);
}
// Print out the params not in the prompt
for (int i = 0; i < numParamsToPrint; i++)
{
// Add a space only if there's no whitespace trail already
if (i > 0 || !prompt.EndsWith(" "))
{
_stringBuilder.Append(' ');
}
int paramIdx = i + numParamsInPrompt;
_stringBuilder.Append(_paramNames[paramIdx]);
}
return _stringBuilder.ToString();
}
public SuggestionContext? GetInnerSuggestionContext(SuggestionContext context)
{
UpdateCurrentCache(context.Prompt);
// We want to consider this a new prompt if we've hit whitespace and we're not in an incomplete scope
bool emptyPromptEnd = context.Prompt.EndsWith(" ") && context.Prompt.GetMaxScopeDepthAtEnd() == 0;
string[] promptParts = context.Prompt
.SplitScoped(' ')
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToArray();
int promptArgs = promptParts.Length - 1;
if (emptyPromptEnd)
{
promptArgs++;
}
if (promptArgs <= 0 || promptArgs > _command.ParamCount)
{
return null;
}
int paramIndex = promptArgs - 1;
SuggestionContext newContext = context;
newContext.Depth++;
newContext.TargetType = GetParameterType(paramIndex);
newContext.Tags = GetParameterTags(paramIndex);
newContext.Prompt = emptyPromptEnd
? string.Empty
: promptParts.LastOrDefault();
return newContext;
}
private void UpdateCurrentCache(string prompt)
{
string rawName = prompt.SplitScopedFirst(' ');
if (rawName != _currentCommandNameCache.RawName)
{
_currentCommandNameCache = ParseCommandNameInfo(rawName);
}
}
private ParsedCommandNameInfo ParseCommandNameInfo(string rawName)
{
string[] commandNameParts = rawName.Split(new[] { '<' }, 2);
ParsedCommandNameInfo info = new ParsedCommandNameInfo();
info.RawName = rawName;
info.CommandName = commandNameParts[0];
if (_command.IsGeneric)
{
info.GenericSignature = commandNameParts.Length > 1 ? $"<{commandNameParts[1]}" : "";
info.GenericArgNames = info.GenericSignature
.ReduceScope('<', '>')
.SplitScoped(',');
}
return info;
}
private Type[] ParseGenericTypes(ParsedCommandNameInfo commandNameInfo)
{
return commandNameInfo
.GenericArgNames
.Select(QuantumParser.ParseType)
.ToArray();
}
private Type[] GetParameterTypes(ParsedCommandNameInfo commandNameInfo)
{
// Return normal types if not generic
if (!_command.IsGeneric)
{
return _command.ParamTypes;
}
// Return cached if available
if (_genericSignatureCache.TryGetValue(commandNameInfo.GenericSignature, out Type[] paramTypes))
{
return paramTypes;
}
try
{
// Build types from generic types
Type[] genericTypes = ParseGenericTypes(_currentCommandNameCache);
paramTypes = _command.MakeGenericArguments(genericTypes);
}
catch
{
// Use normal types if unable to process generics
paramTypes = _command.ParamTypes;
}
return _genericSignatureCache[commandNameInfo.GenericSignature] = paramTypes;
}
private Type GetParameterType(int paramIndex)
{
Type[] paramTypes = GetParameterTypes(_currentCommandNameCache);
return paramTypes[paramIndex];
}
private IQcSuggestorTag[] GetParameterTags(int paramIndex)
{
ParameterInfo parameter = _command.MethodParamData[paramIndex];
if (_parameterTagsCache.TryGetValue(parameter, out IQcSuggestorTag[] tags))
{
return tags;
}
return _parameterTagsCache[parameter] =
parameter
.GetCustomAttributes<SuggestorTagAttribute>()
.SelectMany(x => x.GetSuggestorTags())
.ToArray();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a094f36512b47b429cba82b4de046c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,121 @@
using System.Collections.Generic;
using System.Linq;
using QFSW.QC.Utilities;
namespace QFSW.QC.Suggestors
{
public struct CollapsedCommand
{
public CommandData Command;
public int NumOptionalParams;
public CollapsedCommand(CommandData command)
{
Command = command;
NumOptionalParams = 0;
}
}
public class CommandSuggestor : BasicCachedQcSuggestor<CollapsedCommand>
{
private readonly Dictionary<string, List<CommandData>> _commandGroups = new Dictionary<string, List<CommandData>>();
private readonly Stack<CollapsedCommand> _commandCollector = new Stack<CollapsedCommand>();
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.Depth == 0;
}
protected override IQcSuggestion ItemToSuggestion(CollapsedCommand collapsedCommand)
{
return new CommandSuggestion(collapsedCommand.Command, collapsedCommand.NumOptionalParams);
}
protected override IEnumerable<CollapsedCommand> GetItems(SuggestionContext context, SuggestorOptions options)
{
string incompleteCommandName =
context.Prompt
.SplitScopedFirst(' ')
.SplitFirst('<');
IEnumerable<CommandData> commands = GetCommands(incompleteCommandName, options);
return options.CollapseOverloads
? CollapseCommands(commands)
: commands.Select(x => new CollapsedCommand(x));
}
public IEnumerable<CommandData> GetCommands(string incompleteCommandName, SuggestorOptions options)
{
if (string.IsNullOrWhiteSpace(incompleteCommandName))
{
return Enumerable.Empty<CommandData>();
}
return QuantumConsoleProcessor.GetAllCommands()
.Where(command => SuggestorUtilities.IsCompatible(incompleteCommandName, command.CommandName, options));
}
protected override bool IsMatch(SuggestionContext context, IQcSuggestion suggestion, SuggestorOptions options)
{
// Perform filtering in GetCommands
return true;
}
private IEnumerable<CollapsedCommand> CollapseCommands(IEnumerable<CommandData> commands)
{
// Reset the command groups but keep lists around for better memory performance
foreach (List<CommandData> commandGroup in _commandGroups.Values)
{
commandGroup.Clear();
}
// Allocate commands to their groups
foreach (CommandData command in commands)
{
if (!_commandGroups.TryGetValue(command.CommandName, out List<CommandData> commandGroup))
{
commandGroup = new List<CommandData>();
_commandGroups[command.CommandName] = commandGroup;
}
commandGroup.Add(command);
}
// For each group, iterate over commands from least to most parameters
// If the new candidate is the same as the previous candidate + 1 new parameter
// Then absorb the previous command as an optional argument, otherwise keep both
foreach (List<CommandData> commandGroup in _commandGroups.Values)
{
commandGroup.InsertionSortBy(x => x.ParamCount);
_commandCollector.Clear();
foreach (CommandData command in commandGroup)
{
CollapsedCommand newCandidate = new CollapsedCommand(command);
if (_commandCollector.Count > 0)
{
CollapsedCommand prevCandidate = _commandCollector.Peek();
CommandData newCommand = newCandidate.Command;
CommandData prevCommand = prevCandidate.Command;
if (newCommand.ParamCount == prevCommand.ParamCount + 1)
{
if (newCommand.ParameterSignature.StartsWith(prevCommand.ParameterSignature))
{
_commandCollector.Pop();
newCandidate.NumOptionalParams += 1 + prevCandidate.NumOptionalParams;
}
}
}
_commandCollector.Push(newCandidate);
}
foreach (CollapsedCommand collapsedCommand in _commandCollector)
{
yield return collapsedCommand;
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a81fd548b8f63a409ff49dd984e0847
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
using QFSW.QC.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;
namespace QFSW.QC.Suggestors
{
public class ComponentSuggestor : BasicCachedQcSuggestor<string>
{
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
Type targetType = context.TargetType;
return targetType != null
&& targetType.IsDerivedTypeOf(typeof(Component))
&& !targetType.IsGenericParameter;
}
protected override IQcSuggestion ItemToSuggestion(string name)
{
return new RawSuggestion(name, true);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
return Object.FindObjectsOfType(context.TargetType)
.Select(cmp => (Component) cmp)
.Select(cmp => cmp.gameObject.name);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9268967e70c604946bad8e88174c2db6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC.Suggestors
{
public class EnumSuggestor : BasicCachedQcSuggestor<string>
{
private readonly Dictionary<Type, string[]> _enumCaseCache = new Dictionary<Type, string[]>();
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
Type targetType = context.TargetType;
return targetType != null
&& targetType.IsEnum;
}
protected override IQcSuggestion ItemToSuggestion(string item)
{
return new RawSuggestion(item);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
return GetEnumCases(context.TargetType);
}
private string[] GetEnumCases(Type enumType)
{
if (_enumCaseCache.TryGetValue(enumType, out string[] cachedEnumCases))
{
return cachedEnumCases;
}
string[] enumCases =
enumType.GetEnumNames()
.Select(x => x.ToString())
.ToArray();
return _enumCaseCache[enumType] = enumCases;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4db269b19a4ec5f48b6e97ac1ef7c183
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFSW.QC.Suggestors
{
public class GameObjectSuggestor : BasicCachedQcSuggestor<string>
{
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.TargetType == typeof(GameObject);
}
protected override IQcSuggestion ItemToSuggestion(string name)
{
return new RawSuggestion(name, true);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
return Object.FindObjectsOfType<GameObject>()
.Select(obj => obj.name);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b03355cf0721c774fb78eb92d958d535
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace QFSW.QC.Suggestors
{
/// <summary>
/// Produces the available suggestions for the suggestion system.
/// </summary>
public class InlineSuggestor : IQcSuggestor
{
public IEnumerable<IQcSuggestion> GetSuggestions(SuggestionContext context, SuggestorOptions options)
{
foreach (Tags.InlineSuggestionsTag t in context.GetTags<Tags.InlineSuggestionsTag>())
{
foreach (string s in t.Suggestions)
{
yield return new RawSuggestion(s, singleLiteral: true);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fed3d8fbe2fe15b4680532bcd9ac9d78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC.Suggestors
{
public class MacroSuggestor : BasicCachedQcSuggestor<string>
{
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.Prompt.StartsWith("#");
}
protected override IQcSuggestion ItemToSuggestion(string macro)
{
return new RawSuggestion($"#{macro}");
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
return QuantumMacros.GetMacros()
.Select(x => x.Key);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76d43cae401d00140b4e5c5fd5bd17ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,15 @@
{
"name": "QFSW.QC.Suggestors",
"references": [
"QFSW.QC"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 786923d329e69bf40b3d855b3e56d0cc
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using QFSW.QC.Utilities;
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC.Suggestors
{
public class SceneNameSuggestor : BasicCachedQcSuggestor<string>
{
protected override bool CanProvideSuggestions(SuggestionContext context, SuggestorOptions options)
{
return context.HasTag<Tags.SceneNameTag>();
}
protected override IQcSuggestion ItemToSuggestion(string sceneName)
{
return new RawSuggestion(sceneName, true);
}
protected override IEnumerable<string> GetItems(SuggestionContext context, SuggestorOptions options)
{
if (context.GetTag<Tags.SceneNameTag>().LoadedOnly)
{
return SceneUtilities.GetLoadedScenes()
.Select(x => x.name);
}
return SceneUtilities.GetAllSceneNames();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9473b0454f2e70d4d80abe5e83c818dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: