Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

В рефлектор добавлен метод ИзвестныеТипы() #1368

Merged
merged 4 commits into from
Oct 19, 2023
Merged
4 changes: 4 additions & 0 deletions src/OneScript.Core/Types/ITypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the
----------------------------------------------------------*/

using System;
using System.Collections.Generic;

namespace OneScript.Types
{
Expand All @@ -25,5 +26,8 @@ public interface ITypeManager

bool IsKnownType(Type type);
bool IsKnownType(string typeName);

IReadOnlyList<TypeDescriptor> RegisteredTypes();

}
}
56 changes: 54 additions & 2 deletions src/OneScript.StandardLibrary/Reflector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +31,13 @@ namespace OneScript.StandardLibrary
[ContextClass("Рефлектор","Reflector")]
public class ReflectorContext : AutoContext<ReflectorContext>
{
private readonly ITypeManager _typeManager;

private ReflectorContext(ITypeManager typeManager)
{
_typeManager = typeManager;
}

/// <summary>
/// Вызывает метод по его имени.
/// </summary>
Expand Down Expand Up @@ -478,10 +486,54 @@ public static Type ReflectContext(Type clrType)
.Build();
}

/// <summary>
/// Возвращает все известные типы
/// </summary>
/// <param name="filter">Структура - Условия поиска. Ключ - имя колонки, значение - искомое значение </param>
/// <returns>
/// ТаблицаЗначений:
/// * Имя - Строка - Имя типа
/// * Значение - Тип - Тип
/// * Примитивный - Булево - Это примитивный тип
/// * Пользовательский - Булево - Это пользовательский типа
/// * Коллекция - Булево - Это коллекция
/// </returns>
[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<BslTypeValue>() { 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);
}
}
}
5 changes: 5 additions & 0 deletions src/ScriptEngine/Machine/DefaultTypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public bool IsKnownType(string typeName)
return _knownTypes.Any(x => x.Name.ToUpperInvariant() == nameToUpper);
}

public IReadOnlyList<TypeDescriptor> RegisteredTypes()
{
return _knownTypes;
sfaqer marked this conversation as resolved.
Show resolved Hide resolved
}

public Type NewInstanceHandler
{
get
Expand Down
162 changes: 160 additions & 2 deletions tests/reflector.os
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьРефлексиюДля_ЭтотОбъект");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПустыеАннотации");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПриватныеПоля");

ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы");
ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция");
ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный");
ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский");

Возврат ВсеТесты;
КонецФункции
Expand Down Expand Up @@ -215,7 +220,7 @@
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Пример);

юТест.ПроверитьРавенство(Строка(ТипЗнч(ТаблицаМетодов)), "ТаблицаЗначений", "ТаблицаМетодов");
юТест.ПроверитьРавенство(6, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()");
юТест.ПроверитьРавенство(7, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()");

Метод0 = ТаблицаМетодов.Найти("ВызватьМетод", "Имя");
юТест.ПроверитьНеРавенство(Неопределено, Метод0, "Метод0");
Expand Down Expand Up @@ -667,4 +672,157 @@
юТест.ПроверитьНеравенство(0, ТаблицаМетодов.Количество());
юТест.ПроверитьНеравенство(0, ТаблицаСвойств.Количество());

КонецПроцедуры
КонецПроцедуры

Процедура ТестДолжен_ПроверитьИзвестныеТипы() Экспорт

ПолучитьОбъектДляПроверки("МойКлассныйТип");

Рефлектор = Новый Рефлектор;

ИзвестныеТипы = Рефлектор.ИзвестныеТипы();

ПроверитьТипИзвестныхТипов(ИзвестныеТипы);

Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);
КонецЦикла;

ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число"));

юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло);
юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений");
юТест.ПроверитьИстину(ОписаниеТипаЧисло.Примитивный);
юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Пользовательский);
юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Коллекция);

ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив"));

юТест.ПроверитьЗаполненность(ОписаниеТипаМассив);
юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений");
юТест.ПроверитьЛожь(ОписаниеТипаМассив.Примитивный);
юТест.ПроверитьЛожь(ОписаниеТипаМассив.Пользовательский);
юТест.ПроверитьИстину(ОписаниеТипаМассив.Коллекция);

ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип"));

юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип);
юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений");
юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Примитивный);
юТест.ПроверитьИстину(ОписаниеТипаМойКлассныйТип.Пользовательский);
юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Коллекция);

КонецПроцедуры

Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция() Экспорт

ПолучитьОбъектДляПроверки("МойКлассныйТип");

Рефлектор = Новый Рефлектор;

Отбор = Новый Структура("Коллекция", Истина);

ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);

ПроверитьТипИзвестныхТипов(ИзвестныеТипы);

Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);

юТест.ПроверитьИстину(ИзвестныйТип.Коллекция);
юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный);
юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский);

КонецЦикла;

ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив"));

юТест.ПроверитьЗаполненность(ОписаниеТипаМассив);
юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений");

КонецПроцедуры

Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный() Экспорт

ПолучитьОбъектДляПроверки("МойКлассныйТип");

Рефлектор = Новый Рефлектор;

Отбор = Новый Структура("Примитивный", Истина);

ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);

ПроверитьТипИзвестныхТипов(ИзвестныеТипы);

Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл

ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);

юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция);
юТест.ПроверитьИстину(ИзвестныйТип.Примитивный);
юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский);

КонецЦикла;

ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число"));

юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло);
юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений");

КонецПроцедуры

Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский() Экспорт

ПолучитьОбъектДляПроверки("МойКлассныйТип");

Рефлектор = Новый Рефлектор;

Отбор = Новый Структура("Пользовательский", Истина);

ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);

ПроверитьТипИзвестныхТипов(ИзвестныеТипы);

Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл

ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);

юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция);
юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный);
юТест.ПроверитьИстину(ИзвестныйТип.Пользовательский);

КонецЦикла;

ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип"));

юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип);
юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений");

КонецПроцедуры

Процедура ПроверитьТипИзвестныхТипов(ИзвестныеТипы)

юТест.ПроверитьТип(ИзвестныеТипы, "ТаблицаЗначений");
юТест.ПроверитьНеРавенство(ИзвестныеТипы.Количество(), 0);

юТест.ПроверитьРавенство(ИзвестныеТипы.Колонки.Количество(), 5);
юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Имя"));
юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Значение"));
юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Примитивный"));
юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Пользовательский"));
юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Коллекция"));

КонецПроцедуры

Процедура ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип)

юТест.ПроверитьТип(ИзвестныйТип.Имя, "Строка");
юТест.ПроверитьТип(ИзвестныйТип.Значение, "Тип");
юТест.ПроверитьТип(ИзвестныйТип.Примитивный, "Булево");
юТест.ПроверитьТип(ИзвестныйТип.Пользовательский, "Булево");
юТест.ПроверитьТип(ИзвестныйТип.Коллекция, "Булево");

юТест.ПроверитьЗаполненность(ИзвестныйТип.Имя);
юТест.ПроверитьЗаполненность(ИзвестныйТип.Значение);

КонецПроцедуры