diff --git a/src/OneScript.Core/Types/ITypeManager.cs b/src/OneScript.Core/Types/ITypeManager.cs index 01f69ab34..79b21490a 100644 --- a/src/OneScript.Core/Types/ITypeManager.cs +++ b/src/OneScript.Core/Types/ITypeManager.cs @@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Collections.Generic; namespace OneScript.Types { @@ -25,5 +26,8 @@ public interface ITypeManager bool IsKnownType(Type type); bool IsKnownType(string typeName); + + IReadOnlyList RegisteredTypes(); + } } \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Reflector.cs b/src/OneScript.StandardLibrary/Reflector.cs index fdb6e3ac3..1f610d5eb 100644 --- a/src/OneScript.StandardLibrary/Reflector.cs +++ b/src/OneScript.StandardLibrary/Reflector.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Reflection; +using OneScript.Commons; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Execution; @@ -30,6 +31,13 @@ namespace OneScript.StandardLibrary [ContextClass("Рефлектор","Reflector")] public class ReflectorContext : AutoContext { + private readonly ITypeManager _typeManager; + + private ReflectorContext(ITypeManager typeManager) + { + _typeManager = typeManager; + } + /// /// Вызывает метод по его имени. /// @@ -478,10 +486,54 @@ public static Type ReflectContext(Type clrType) .Build(); } + /// + /// Возвращает все известные типы + /// + /// Структура - Условия поиска. Ключ - имя колонки, значение - искомое значение + /// + /// ТаблицаЗначений: + /// * Имя - Строка - Имя типа + /// * Значение - Тип - Тип + /// * Примитивный - Булево - Это примитивный тип + /// * Пользовательский - Булево - Это пользовательский типа + /// * Коллекция - Булево - Это коллекция + /// + [ContextMethod("ИзвестныеТипы", "KnownTypes")] + public ValueTable KnownTypes(StructureImpl filter = default) + { + var result = new ValueTable(); + + var nameColumn = result.Columns.Add("Имя", TypeDescription.StringType()); + var valueColumn = result.Columns.Add("Значение", new TypeDescription(new List() { new BslTypeValue(BasicTypes.Type) })); + var primitiveColumn = result.Columns.Add("Примитивный", TypeDescription.BooleanType()); + var userColumn = result.Columns.Add("Пользовательский", TypeDescription.BooleanType()); + var collectionColumn = result.Columns.Add("Коллекция", TypeDescription.BooleanType()); + + _typeManager.RegisteredTypes().ForEach(descriptor => + { + var row = result.Add(); + + row.Set(nameColumn, ValueFactory.Create(descriptor.ToString())); + row.Set(valueColumn, new BslTypeValue(descriptor)); + row.Set(primitiveColumn, ValueFactory.Create(descriptor.ImplementingClass.IsSubclassOf(typeof(BslPrimitiveValue)))); + row.Set(userColumn, ValueFactory.Create(descriptor.ImplementingClass == typeof(AttachedScriptsFactory))); + row.Set(collectionColumn, ValueFactory.Create( + descriptor.ImplementingClass.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionContext<>)) + )); + }); + + if (filter != default) + { + result = result.Copy(filter); + } + + return result; + } + [ScriptConstructor] - public static IRuntimeContextInstance CreateNew() + public static ReflectorContext CreateNew(TypeActivationContext context) { - return new ReflectorContext(); + return new ReflectorContext(context.TypeManager); } } } diff --git a/src/ScriptEngine/Machine/DefaultTypeManager.cs b/src/ScriptEngine/Machine/DefaultTypeManager.cs index 3be4bd521..985ad9170 100644 --- a/src/ScriptEngine/Machine/DefaultTypeManager.cs +++ b/src/ScriptEngine/Machine/DefaultTypeManager.cs @@ -143,6 +143,11 @@ public bool IsKnownType(string typeName) return _knownTypes.Any(x => x.Name.ToUpperInvariant() == nameToUpper); } + public IReadOnlyList RegisteredTypes() + { + return _knownTypes; + } + public Type NewInstanceHandler { get diff --git a/tests/reflector.os b/tests/reflector.os index beb8820c7..b5a07ca6f 100644 --- a/tests/reflector.os +++ b/tests/reflector.os @@ -41,6 +41,11 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьРефлексиюДля_ЭтотОбъект"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПустыеАннотации"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПриватныеПоля"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский"); Возврат ВсеТесты; КонецФункции @@ -215,7 +220,7 @@ ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Пример); юТест.ПроверитьРавенство(Строка(ТипЗнч(ТаблицаМетодов)), "ТаблицаЗначений", "ТаблицаМетодов"); - юТест.ПроверитьРавенство(6, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()"); + юТест.ПроверитьРавенство(7, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()"); Метод0 = ТаблицаМетодов.Найти("ВызватьМетод", "Имя"); юТест.ПроверитьНеРавенство(Неопределено, Метод0, "Метод0"); @@ -667,4 +672,157 @@ юТест.ПроверитьНеравенство(0, ТаблицаМетодов.Количество()); юТест.ПроверитьНеравенство(0, ТаблицаСвойств.Количество()); -КонецПроцедуры \ No newline at end of file +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьИзвестныеТипы() Экспорт + + ПолучитьОбъектДляПроверки("МойКлассныйТип"); + + Рефлектор = Новый Рефлектор; + + ИзвестныеТипы = Рефлектор.ИзвестныеТипы(); + + ПроверитьТипИзвестныхТипов(ИзвестныеТипы); + + Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл + ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип); + КонецЦикла; + + ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло); + юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений"); + юТест.ПроверитьИстину(ОписаниеТипаЧисло.Примитивный); + юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Пользовательский); + юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Коллекция); + + ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаМассив); + юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений"); + юТест.ПроверитьЛожь(ОписаниеТипаМассив.Примитивный); + юТест.ПроверитьЛожь(ОписаниеТипаМассив.Пользовательский); + юТест.ПроверитьИстину(ОписаниеТипаМассив.Коллекция); + + ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип); + юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений"); + юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Примитивный); + юТест.ПроверитьИстину(ОписаниеТипаМойКлассныйТип.Пользовательский); + юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Коллекция); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция() Экспорт + + ПолучитьОбъектДляПроверки("МойКлассныйТип"); + + Рефлектор = Новый Рефлектор; + + Отбор = Новый Структура("Коллекция", Истина); + + ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор); + + ПроверитьТипИзвестныхТипов(ИзвестныеТипы); + + Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл + ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип); + + юТест.ПроверитьИстину(ИзвестныйТип.Коллекция); + юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный); + юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский); + + КонецЦикла; + + ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаМассив); + юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный() Экспорт + + ПолучитьОбъектДляПроверки("МойКлассныйТип"); + + Рефлектор = Новый Рефлектор; + + Отбор = Новый Структура("Примитивный", Истина); + + ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор); + + ПроверитьТипИзвестныхТипов(ИзвестныеТипы); + + Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл + + ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип); + + юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция); + юТест.ПроверитьИстину(ИзвестныйТип.Примитивный); + юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский); + + КонецЦикла; + + ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло); + юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский() Экспорт + + ПолучитьОбъектДляПроверки("МойКлассныйТип"); + + Рефлектор = Новый Рефлектор; + + Отбор = Новый Структура("Пользовательский", Истина); + + ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор); + + ПроверитьТипИзвестныхТипов(ИзвестныеТипы); + + Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл + + ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип); + + юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция); + юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный); + юТест.ПроверитьИстину(ИзвестныйТип.Пользовательский); + + КонецЦикла; + + ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип")); + + юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип); + юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений"); + +КонецПроцедуры + +Процедура ПроверитьТипИзвестныхТипов(ИзвестныеТипы) + + юТест.ПроверитьТип(ИзвестныеТипы, "ТаблицаЗначений"); + юТест.ПроверитьНеРавенство(ИзвестныеТипы.Количество(), 0); + + юТест.ПроверитьРавенство(ИзвестныеТипы.Колонки.Количество(), 5); + юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Имя")); + юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Значение")); + юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Примитивный")); + юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Пользовательский")); + юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Коллекция")); + +КонецПроцедуры + +Процедура ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип) + + юТест.ПроверитьТип(ИзвестныйТип.Имя, "Строка"); + юТест.ПроверитьТип(ИзвестныйТип.Значение, "Тип"); + юТест.ПроверитьТип(ИзвестныйТип.Примитивный, "Булево"); + юТест.ПроверитьТип(ИзвестныйТип.Пользовательский, "Булево"); + юТест.ПроверитьТип(ИзвестныйТип.Коллекция, "Булево"); + + юТест.ПроверитьЗаполненность(ИзвестныйТип.Имя); + юТест.ПроверитьЗаполненность(ИзвестныйТип.Значение); + +КонецПроцедуры