Skip to content

Commit

Permalink
Merge pull request #1371 from Mr-Rm/v2/fix-reflector
Browse files Browse the repository at this point in the history
v2 Рефлектор: fix#1364, вызов COM, мелкие правки
  • Loading branch information
EvilBeaver authored Oct 23, 2023
2 parents 70474cc + f7ce1bb commit a87287b
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 32 deletions.
7 changes: 7 additions & 0 deletions src/OneScript.Language/LexicalAnalysis/LabelLexerState.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/

using System.Diagnostics;
using OneScript.Localization;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/

using OneScript.Language.LexicalAnalysis;

namespace OneScript.Language.SyntaxAnalysis.AstNodes
Expand Down
7 changes: 7 additions & 0 deletions src/OneScript.Language/SyntaxAnalysis/AstNodes/LabelNode.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/

using OneScript.Language.LexicalAnalysis;

namespace OneScript.Language.SyntaxAnalysis.AstNodes
Expand Down
53 changes: 31 additions & 22 deletions src/OneScript.StandardLibrary/Reflector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ public IValue CallMethod(IRuntimeContextInstance target, string methodName, Arra
var methodIdx = target.GetMethodNumber(methodName);
var methInfo = target.GetMethodInfo(methodIdx);

var argsToPass = GetArgsToPass(arguments, methInfo.GetParameters());

IValue[] argsToPass;
if (target.DynamicMethodSignatures)
argsToPass = arguments?.ToArray() ?? Array.Empty<IValue>();
else
argsToPass = GetArgsToPass(arguments, methInfo.GetParameters());

IValue retValue = ValueFactory.Create();
if (methInfo.IsFunction())
{
Expand All @@ -79,34 +83,39 @@ public IValue CallMethod(IRuntimeContextInstance target, string methodName, Arra

private static IValue[] GetArgsToPass(ArrayImpl arguments, ParameterInfo[] parameters)
{
var argsToPass = new List<IValue>();
if (arguments != null)
{
argsToPass.AddRange(arguments);
}

if (parameters.Length < argsToPass.Count)
var argValues = arguments?.ToArray() ?? Array.Empty<IValue>();
// ArrayImpl не может (не должен!) содержать null или NotAValidValue

if (argValues.Length > parameters.Length)
throw RuntimeException.TooManyArgumentsPassed();

for (int i = 0; i < argsToPass.Count; i++)
var argsToPass = new IValue[parameters.Length];

int i = 0;
for (; i < argValues.Length; i++)
{
if (parameters[i].IsByRef())
argsToPass[i] = Variable.Create(argsToPass[i], $"reflectorArg{i}");
argsToPass[i] = Variable.Create(argValues[i], "");
else
argsToPass[i] = argValues[i];
}
while (argsToPass.Count < parameters.Length)
for (; i < parameters.Length; i++)
{
argsToPass.Add(null);
if (!parameters[i].HasDefaultValue)
throw RuntimeException.TooFewArgumentsPassed();

// else keep null as a default value
}

return argsToPass.ToArray();
return argsToPass;
}

/// <summary>
/// Проверяет существование указанного метода у переданного объекта..
/// Проверяет существование указанного метода у переданного объекта.
/// </summary>
/// <param name="target">Объект, из которого получаем таблицу методов.</param>
/// <param name="methodName">Имя метода для вызова</param>
/// <returns>Истину, если метод существует, и Ложь в обратном случае. </returns>
/// <returns>Истина, если метод существует, и Ложь в обратном случае. </returns>
[ContextMethod("МетодСуществует", "MethodExists")]
public bool MethodExists(IValue target, string methodName)
{
Expand Down Expand Up @@ -206,10 +215,10 @@ private static RuntimeException NonReflectableType()
}

/// <summary>
/// Получает таблицу методов для переданного объекта..
/// Получает таблицу методов для переданного объекта.
/// </summary>
/// <param name="target">Объект, из которого получаем таблицу методов.</param>
/// <returns>Таблица значений колонками: Имя, Количество, ЭтоФункция, Аннотации</returns>
/// <returns>Таблица значений с колонками: Имя, Количество, ЭтоФункция, Аннотации, Параметры, Экспорт</returns>
[ContextMethod("ПолучитьТаблицуМетодов", "GetMethodsTable")]
public ValueTable GetMethodsTable(IValue target)
{
Expand Down Expand Up @@ -320,7 +329,7 @@ private static void FillMethodsTable(ValueTable result, IEnumerable<BslMethodInf
var isFunctionColumn = result.Columns.Add("ЭтоФункция", TypeDescription.BooleanType(), "Это функция");
var annotationsColumn = result.Columns.Add("Аннотации", new TypeDescription(), "Аннотации");
var paramsColumn = result.Columns.Add("Параметры", new TypeDescription(), "Параметры");
var isExportlColumn = result.Columns.Add("Экспорт", new TypeDescription(), "Экспорт");
var isExportlColumn = result.Columns.Add("Экспорт", TypeDescription.BooleanType(), "Экспорт");

foreach (var methInfo in methods)
{
Expand All @@ -339,7 +348,7 @@ private static void FillMethodsTable(ValueTable result, IEnumerable<BslMethodInf
var paramNameColumn = paramTable.Columns.Add("Имя", TypeDescription.StringType(), "Имя");
var paramByValue = paramTable.Columns.Add("ПоЗначению", TypeDescription.BooleanType(), "По значению");
var paramHasDefaultValue = paramTable.Columns.Add("ЕстьЗначениеПоУмолчанию", TypeDescription.BooleanType(), "Есть значение по-умолчанию");
var paramDefaultValue = paramTable.Columns.Add("ЗначениеПоУмолчанию", null, "Значение по умолчанию");
var paramDefaultValue = paramTable.Columns.Add("ЗначениеПоУмолчанию", new TypeDescription(), "Значение по умолчанию");
var paramAnnotationsColumn = paramTable.Columns.Add("Аннотации", new TypeDescription(), "Аннотации");

new_row.Set(paramsColumn, paramTable);
Expand All @@ -362,11 +371,11 @@ private static void FillMethodsTable(ValueTable result, IEnumerable<BslMethodInf
}

/// <summary>
/// Получает таблицу свойств для переданного объекта..
/// Получает таблицу свойств для переданного объекта.
/// </summary>
/// <param name="target">Объект, из которого получаем таблицу свойств.</param>
/// <param name="withPrivate">Включить в результат приватные поля</param>
/// <returns>Таблица значений с колонками - Имя, Аннотации</returns>
/// <returns>Таблица значений с колонками - Имя, Аннотации, Экспорт</returns>
[ContextMethod("ПолучитьТаблицуСвойств", "GetPropertiesTable")]
public ValueTable GetPropertiesTable(IValue target, bool withPrivate = false)
{
Expand Down
10 changes: 2 additions & 8 deletions src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,8 @@ public void Dispose()

#endregion

public override bool DynamicMethodSignatures
{
get
{
return true;
}
}

public override bool DynamicMethodSignatures => true;

[ScriptConstructor]
public static COMWrapperContext Constructor(IValue[] args)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,11 @@ public override int GetMethodNumber(string name)

public override BslMethodInfo GetMethodInfo(int methodNumber)
{
//TODO: Доработать RcwMethodMetadata
return BslMethodBuilder.Create().Build();
var md = _methods[methodNumber];
return BslMethodBuilder.Create()
.Name(md.Name)
.ReturnType(md.IsFunction ?? true ? typeof(IValue) : typeof(void))
.Build();
}

private MethodSignature GetMethodDescription(int methodNumber)
Expand Down
56 changes: 56 additions & 0 deletions tests/reflector.os
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьМетод_ПолучитьТаблицуСвойств");

ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаСПараметрамиПоУмолчанию");
ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаБезПараметровПоУмолчанию");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПараметровПоУмолчанию");

ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодСуществуетДляТипа");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПолучитьТаблицуМетодовДляТипа");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПолучитьТаблицуСвойствДляСистемногоТипа");
Expand All @@ -47,6 +50,10 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный");
ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский");

#Если Windows Тогда
ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаComОбъекта");
#КонецЕсли

Возврат ВсеТесты;
КонецФункции

Expand Down Expand Up @@ -420,6 +427,47 @@

КонецФункции

Процедура ТестДолжен_ПроверитьВызовМетодаБезПараметровПоУмолчанию() Экспорт
Рефлектор = Новый Рефлектор;

Массив = Новый Массив(1);
Арг = Новый Массив;
Арг.Добавить(0);

Ошибка = Ложь;
Попытка
Рефлектор.ВызватьМетод(Массив, "Установить", Арг);
Ч = Массив[0];
Ошибка = Истина;
Исключение
Сообщение = ОписаниеОшибки();
Если СтрНайти(Сообщение,"NullReferenceException") <> 0 Тогда
Ошибка = Истина;
КонецЕсли;
КонецПопытки;

Если Ошибка Тогда
юТест.ТестПровален("Вызов рефлектора с недостаточным количеством параметров без умолчания");
КонецЕсли;

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

Процедура ТестПередачиПараметровПоУмолчанию(Пар1, Пар2="п2") Экспорт
юТест.ПроверитьРавенство(Пар1, "п1", "Тест передачи параметров: параметр 1");
юТест.ПроверитьРавенство(Пар2, "п2", "Тест передачи параметров: параметр 2");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьПередачуПараметровПоУмолчанию() Экспорт
Рефлектор = Новый Рефлектор;

Массив = Новый Массив(1);
Арг = Новый Массив;
Арг.Добавить("п1");
Рефлектор.ВызватьМетод(ЭтотОбъект, "ТестПередачиПараметровПоУмолчанию", Арг);

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


Процедура ТестДолжен_ПроверитьМетодСуществуетДляТипа() Экспорт

Рефлектор = Новый Рефлектор;
Expand Down Expand Up @@ -826,3 +874,11 @@
юТест.ПроверитьЗаполненность(ИзвестныйТип.Значение);

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

#Если Windows Тогда
Процедура ТестДолжен_ПроверитьВызовМетодаComОбъекта() Экспорт
FSO = ПолучитьCOMОбъект("", "Scripting.FileSystemObject");
Рез = FSO.DriveExists("C");
юТест.ПроверитьТип(Рез, "Булево");
КонецПроцедуры
#КонецЕсли

0 comments on commit a87287b

Please sign in to comment.