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

Реализация пользовательских итераторов #1385

Merged
merged 6 commits into from
Jan 21, 2024

Conversation

EvilBeaver
Copy link
Owner

@EvilBeaver EvilBeaver commented Dec 27, 2023

@sfaqer приобщайся

Summary by CodeRabbit

  • New Features

    • Enhanced multilingual support with name existence checks for both Russian and English.
    • Improved script control flow by allowing conditional creation of user iterable contexts.
    • Added support for predefined directives and annotations in scripting engine.
  • Enhancements

    • Implemented a new iterable directive provider for script annotations.
    • Introduced enumerator wrapper to facilitate script interaction with user-defined contexts.
  • Bug Fixes

    • Resolved duplicate service registration issue for directive handlers.

Copy link

coderabbitai bot commented Dec 27, 2023

Walkthrough

Обновления включают улучшение поддержки многоязычности, уточнение обработки директив сценарного движка и расширение контекстов итерации. Был добавлен новый метод для проверки существования имени в двуязычных контекстах, дублирование регистрации службы и создание контекста итерации пользователя на основе атрибутов модуля. Кроме того, были внедрены предопределенные аннотации для сравнения имен без учета регистра и оболочка для сценарных перечислителей, что указывает на фокус на расширяемости и интернационализации в сценарном движке.

Changes

File Path Change Summary
src/OneScript.Language/Localization/BilingualString.cs Добавлен метод HasName для проверки существования двуязычного имени.
src/OneScript.Core/Commons/Utils.cs
src/OneScript.Core/Contexts/BslMethodInfo.cs
src/OneScript.Core/Contexts/BslScriptMethodInfo.cs
Добавлены новые импорты и изменения в классах и интерфейсах для поддержки многоязычности и расширения контекстов.
src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs
src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs
src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs
Внедрены новый интерфейс, класс и перечисление для проверки и регистрации предопределенных интерфейсов.
src/OneScript.Core/Exceptions/InterfaceCheckException.cs Добавлен новый класс для исключений связанных с проверкой интерфейсов.
src/OneScript.Core/Execution/IExecutableModule.cs
src/OneScript.Core/Sources/EmptyModule.cs
Внесены изменения в интерфейс и класс для поддержки словаря интерфейсов и их использования.
src/ScriptEngine/Compiler/CompilerFrontend.cs Прошел значительные изменения, включая добавление параметров в конструктор и обновления метода CompileInternal.
src/ScriptEngine/Hosting/EngineBuilderExtensions.cs Внесены изменения для включения новых пространств имен и вызова services.EnablePredefinedIterables().
src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs
src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs
Введены новые классы для обработки сценарных перечислителей и контекста итерации.
src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs
src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs
Добавлены новые классы для реализации контекста итерации и обработки двуязычных строк.
src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs
src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs
src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs
Введены новые классы и расширения для регистрации и доступа к интерфейсам в сценарном движке.
src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs
src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs
Добавлены новые классы для работы с итераторами в сценарном движке.
src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs Внедрен новый класс для проверки предопределенных интерфейсов, связанных с итераторами.
src/ScriptEngine/Machine/StackRuntimeModule.cs
src/OneScript.Native/Compiler/DynamicModule.cs
Внесены изменения в классы для поддержки словаря интерфейсов и их использования.
src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs Содержит тесты для функциональности, связанной с предопределенными интерфейсами в модуле OneScript.Core.
tests/iterators/annotated_iterator.os
tests/iterators/iterator.os
tests/iterators/test-iterators.os
Введены новые файлы и тестовые функции для проверки функциональности итераторов в сценарном движке.

🐇✨
В царстве единиц и нулей мы прыгаем и скакаем,
Через сценарии и коды, наши границы круты.
Новые изменения посеяны, урожай мы пожнем,
С каждой строкой кода наша логика ползет. 🌟🚀

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

Failed

  • 0.00% Coverage on New Code (is less than 80.00%)
  • 7.20% Duplicated Lines (%) on New Code (is greater than 3.00%)

Analysis Details

1 Issue

  • Bug0 Bugs
  • Vulnerability0 Vulnerabilities
  • Code Smell1 Code Smell

Coverage and Duplications

  • 0 percent coverage0.00% Coverage (0.00% Estimated after merge)
  • 10 percent duplication7.20% Duplicated Code (3.40% Estimated after merge)

View in SonarQube

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 3

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e05599b and 205123c.
Files selected for processing (8)
  • src/OneScript.Language/Localization/BilingualString.cs (2 hunks)
  • src/ScriptEngine/Hosting/EngineBuilderExtensions.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (2 hunks)
  • src/ScriptEngine/Machine/Contexts/BslPredefinedAnnotation.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/IterableDirectiveProvider.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/PredefinedDirectiveHandler.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs (1 hunks)
Additional comments: 13
src/ScriptEngine/Machine/Contexts/IterableDirectiveProvider.cs (1)
  • 12-20: The IterableDirectiveProvider class is well-defined and follows the convention of providing a bilingual name for the directive it represents. The GetNames method correctly returns the static Names field.
src/ScriptEngine/Machine/Contexts/BslPredefinedAnnotation.cs (1)
  • 14-19: The NameMatches method in BslPredefinedAnnotation correctly uses the HasName method from BilingualString to perform a case-insensitive comparison of annotation names. This is a good use of existing functionality to ensure consistent behavior across the application.
src/OneScript.Language/Localization/BilingualString.cs (1)
  • 59-62: The HasName method in BilingualString correctly checks for equality of the name in both Russian and English, using the provided StringComparison parameter. This allows for flexible comparison strategies and is a good addition for supporting bilingual functionality.
src/ScriptEngine/Machine/Contexts/PredefinedDirectiveHandler.cs (3)
  • 24-34: The constructor of PredefinedDirectiveHandler correctly initializes the _allLineContentLexer and _knownNames fields. The use of StringComparer.CurrentCultureIgnoreCase in the HashSet initialization ensures case-insensitive comparison, which is consistent with the rest of the application's localization approach.

  • 36-38: The DirectiveSupported method properly checks if a directive is known by using the _knownNames HashSet. This is an efficient way to check for the existence of an item in a collection.

  • 41-62: The ParseAnnotationInternal method correctly parses annotations and adds an error to the ErrorSink if there is unexpected content after the directive. This is a good practice for ensuring the correctness of the parsed directives.

src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs (2)
  • 34-53: The CheckModuleCompatibility method in UserIterableContextInstance correctly checks for the presence of the GetIterator method and throws a RuntimeException if it is not found or does not meet the expected criteria. This ensures that the module adheres to the required interface for iterables.

  • 85-99: The GetEnumerator method correctly creates a ScriptedEnumeratorWrapper if the script method call returns a UserScriptContextInstance. This is a good implementation of the IEnumerable interface, allowing for custom iteration logic in user scripts.

src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs (4)
  • 43-62: The CheckCompatibility method in ScriptedEnumeratorWrapper correctly checks for the presence and signatures of required methods. It throws a custom exception if the methods are missing or do not match the expected interface, which is crucial for the correct functioning of the enumerator.

  • 91-93: The Reset method throws NotSupportedException, which is standard practice for enumerators in .NET that do not support resetting. This is an appropriate implementation.

  • 96-102: The Current property getter correctly calls the script method and casts the result to BslValue. This ensures that the enumerator can provide the current item in the iteration.

  • 107-110: The Dispose method conditionally calls a script method if the _onDisposeMethod is found. This is a good practice for cleaning up resources in a managed way.

src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (1)
  • 216-225: The ScriptFactory method now conditionally creates a UserIterableContextInstance if the module has the appropriate attributes. This is a good implementation of the factory pattern, allowing for the creation of different types of script context instances based on module attributes.

Comment on lines 57 to 60
services.RegisterEnumerable<IExecutorProvider, StackMachineExecutor>();
services.RegisterEnumerable<IDirectiveHandler, ConditionalDirectiveHandler>();
services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();
services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();
Copy link

@coderabbitai coderabbitai bot Dec 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of a duplicate registration for IDirectiveHandler, RegionDirectiveHandler in the SetDefaultOptions method seems like an oversight. Duplicate registrations can lead to unexpected behavior and should be avoided unless intentionally designed for a specific purpose.

- services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
services.RegisterEnumerable<IExecutorProvider, StackMachineExecutor>();
services.RegisterEnumerable<IDirectiveHandler, ConditionalDirectiveHandler>();
services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();
services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();
services.RegisterEnumerable<IExecutorProvider, StackMachineExecutor>();
services.RegisterEnumerable<IDirectiveHandler, ConditionalDirectiveHandler>();
services.RegisterEnumerable<IDirectiveHandler, RegionDirectiveHandler>();

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-pastes are evil. Thanks, Rabbit

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EvilBeaver You're welcome! If there's anything else you need help with, feel free to ask. Happy coding! 🐇


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines 71 to 82
public int Count()
{
if (_getCountMethod == null)
throw new RuntimeException(
new BilingualString(
"Класс не поддерживает получение количества элементов, т.к. в нем отсутствует метод "+GetCountName.Russian+"()",
"Class doesn't support items counting, because method "+GetCountName.English+"() is not defined")
);

var ret = CallScriptMethod(_getCountMethod.DispatchId, Array.Empty<IValue>());

return (int)ret.AsNumber();
Copy link

@coderabbitai coderabbitai bot Dec 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Count method throws a RuntimeException if the _getCountMethod is not defined, which is appropriate for enforcing the contract of the ICollectionContext. However, the exception message should be consistent with the method being checked. The message references GetIteratorName instead of GetCountName.

- "Метод " + GetIteratorName.Russian + " должен быть функцией без параметров",
- "Method " + GetIteratorName.English + "() must be a function without parameters");
+ "Метод " + GetCountName.Russian + " должен быть функцией без параметров",
+ "Method " + GetCountName.English + "() must be a function without parameters");

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
public int Count()
{
if (_getCountMethod == null)
throw new RuntimeException(
new BilingualString(
"Класс не поддерживает получение количества элементов, т.к. в нем отсутствует метод "+GetCountName.Russian+"()",
"Class doesn't support items counting, because method "+GetCountName.English+"() is not defined")
);
var ret = CallScriptMethod(_getCountMethod.DispatchId, Array.Empty<IValue>());
return (int)ret.AsNumber();
public int Count()
{
if (_getCountMethod == null)
throw new RuntimeException(
new BilingualString(
"Метод " + GetCountName.Russian + " должен быть функцией без параметров",
"Method " + GetCountName.English + "() must be a function without parameters")
);
var ret = CallScriptMethod(_getCountMethod.DispatchId, Array.Empty<IValue>());
return (int)ret.AsNumber();

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fuckin smartass

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EvilBeaver, I understand that my previous comment may have come across as pedantic. My intention is to assist in maintaining clarity and consistency in the codebase. If you have any concerns or alternative suggestions, I'm here to help.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, go on. I'm just surprised how smart you are

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EvilBeaver, thank you for the encouragement! If you need further assistance or have more changes to review, feel free to let me know. I'm here to help!

(\__/) 
(•ㅅ•) 
/   づ

Comment on lines 122 to 128
public static RuntimeException MissingMethod(BilingualString methodName, Exception parent = null)
{
var error = new BilingualString(
"Обязательный метод "+methodName.Russian+"отсутствует, или не соответствует интерфейсу итератора",
"Required method "+methodName.English+" is missing or doesn't match iterator interface");

return new RuntimeException(error, parent);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MissingMethod method constructs an error message that seems to have a typo in the Russian version. There should be a space between the method name and "отсутствует".

- "Обязательный метод "+methodName.Russian+"отсутствует, или не соответствует интерфейсу итератора",
+ "Обязательный метод "+methodName.Russian+" отсутствует, или не соответствует интерфейсу итератора",

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
public static RuntimeException MissingMethod(BilingualString methodName, Exception parent = null)
{
var error = new BilingualString(
"Обязательный метод "+methodName.Russian+"отсутствует, или не соответствует интерфейсу итератора",
"Required method "+methodName.English+" is missing or doesn't match iterator interface");
return new RuntimeException(error, parent);
public static RuntimeException MissingMethod(BilingualString methodName, Exception parent = null)
{
var error = new BilingualString(
"Обязательный метод "+methodName.Russian+" отсутствует, или не соответствует интерфейсу итератора",
"Required method "+methodName.English+" is missing or doesn't match iterator interface");
return new RuntimeException(error, parent);

@sfaqer
Copy link
Contributor

sfaqer commented Dec 28, 2023

Какой кайф.) Постараюсь потестить эту ситуацию в ближайщие дни.)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 205123c and 5f19257.
Files selected for processing (6)
  • src/ScriptEngine/Hosting/EngineBuilderExtensions.cs (2 hunks)
  • src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (2 hunks)
  • src/ScriptEngine/Machine/Contexts/IterableDirectiveProvider.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/PredefinedAnnotationHandler.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs (1 hunks)
Additional comments: 2
src/ScriptEngine/Hosting/EngineBuilderExtensions.cs (1)
  • 58-66: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [18-66]

The registration of PredefinedAnnotationHandler and IterableAnnotationProvider in SetDefaultOptions is correct. Ensure that these registrations do not conflict with existing services and that all dependent components are aware of these new services.

src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (1)
  • 213-229: The conditional instantiation of UserIterableContextInstance in ScriptFactory is a significant change. Verify that the logic correctly identifies modules with iterable attributes and that this change does not affect other parts of the system that rely on UserScriptContextInstance.

Comment on lines 12 to 20
public class IterableAnnotationProvider : IPredefinedAnnotationProvider
{
public static readonly BilingualString Names = new BilingualString("Обходимое", "Iterable");

public BilingualString GetNames()
{
return Names;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation of IterableAnnotationProvider is correct and follows the expected pattern for an annotation provider. Consider adding XML documentation comments to the class and its members to explain their purpose and usage within the system.

Comment on lines 19 to 69
public class PredefinedAnnotationHandler : ModuleAnnotationDirectiveHandler
{
private readonly ILexer _allLineContentLexer;
private readonly HashSet<string> _knownNames;

public PredefinedAnnotationHandler(IEnumerable<IPredefinedAnnotationProvider> providers, IErrorSink errorSink) : base(errorSink)
{
var builder = new LexerBuilder();
builder.Detect((cs, i) => !char.IsWhiteSpace(cs))
.HandleWith(new WordLexerState());

_allLineContentLexer = builder.Build();

_knownNames = new HashSet<string>(providers.SelectMany(provider =>
new[] { provider.GetNames().Russian, provider.GetNames().English }), StringComparer.CurrentCultureIgnoreCase);
}

protected override bool DirectiveSupported(string directive)
{
return _knownNames.Contains(directive);
}

protected override void ParseAnnotationInternal(ref Lexem lastExtractedLexem, ILexer lexer, ParserContext parserContext)
{
var node = new AnnotationNode(NodeKind.Annotation, lastExtractedLexem);
_allLineContentLexer.Iterator = lexer.Iterator;

parserContext.AddChild(node);

// после ничего не должно находиться
var nextLexem = _allLineContentLexer.NextLexemOnSameLine();
lastExtractedLexem = lexer.NextLexem(); // сдвиг основного лексера
if (nextLexem.Type != LexemType.EndOfText)
{
var err = LocalizedErrors.ExpressionSyntax();
err.Position = new ErrorPositionInfo
{
LineNumber = node.Location.LineNumber,
ColumnNumber = node.Location.ColumnNumber,
Code = lexer.Iterator.GetCodeLine(node.Location.LineNumber),
ModuleName = lexer.Iterator.Source.Name
};
ErrorSink.AddError(err);
}
}
}

public interface IPredefinedAnnotationProvider
{
BilingualString GetNames();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation of PredefinedAnnotationHandler and IPredefinedAnnotationProvider is correct. It would be beneficial to add XML documentation comments to explain the responsibilities of the handler, the interface, and their methods.

Comment on lines 21 to 99
public class UserIterableContextInstance : UserScriptContextInstance, ICollectionContext<BslValue>
{
private static BilingualString GetIteratorName = new BilingualString("ПолучитьИтератор", "GetIterator");
private static BilingualString GetCountName = new BilingualString("Количество", "Count");

private BslScriptMethodInfo _getCountMethod;
private BslScriptMethodInfo _getIteratorMethod;

public UserIterableContextInstance(IExecutableModule module, TypeDescriptor asObjectOfType, IValue[] args = null) : base(module, asObjectOfType, args)
{
CheckModuleCompatibility(module);
}

private void CheckModuleCompatibility(IExecutableModule module)
{
var error = new BilingualString(
"Модуль объекта Обходимое должен содержать функцию " + GetIteratorName.Russian + "()",
"Module of Iterable must contain function " + GetIteratorName.English + "()");

try
{
_getIteratorMethod = (BslScriptMethodInfo)module.Methods.Single(method =>
GetIteratorName.HasName(method.Name, StringComparison.CurrentCultureIgnoreCase));
}
catch (InvalidOperationException e)
{
throw new RuntimeException(error, e);
}

if (!_getIteratorMethod.IsFunction() || _getIteratorMethod.GetBslParameters().Length != 0)
{
throw new RuntimeException(error);
}

_getCountMethod = (BslScriptMethodInfo)module.Methods.FirstOrDefault(method =>
GetCountName.HasName(method.Name, StringComparison.CurrentCultureIgnoreCase));

if (_getCountMethod != null)
{
var countError = new BilingualString(
"Метод " + GetCountName.Russian + " должен быть функцией без параметров",
"Method " + GetCountName.English + "() must be a function without parameters");

if (!_getCountMethod.IsFunction() || _getCountMethod.GetBslParameters().Length != 0)
{
throw new RuntimeException(countError);
}
}
}

public int Count()
{
if (_getCountMethod == null)
throw new RuntimeException(
new BilingualString(
"Класс не поддерживает получение количества элементов, т.к. в нем отсутствует метод "+GetCountName.Russian+"()",
"Class doesn't support items counting, because method "+GetCountName.English+"() is not defined")
);

var ret = CallScriptMethod(_getCountMethod.DispatchId, Array.Empty<IValue>());

return (int)ret.AsNumber();
}

public IEnumerator<BslValue> GetEnumerator()
{
var enumerator = CallScriptMethod(_getIteratorMethod.DispatchId, Array.Empty<IValue>());
if (!(enumerator is UserScriptContextInstance userObject))
{
throw ScriptedEnumeratorWrapper.IncompatibleInterfaceError();
}

return new ScriptedEnumeratorWrapper(userObject);
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation of UserIterableContextInstance is correct. It properly checks for the required methods and implements the ICollectionContext<BslValue> interface. Consider adding XML documentation comments to the class and its methods to explain their purpose and usage.

Comment on lines 19 to 129
DisposeMethodName = new BilingualString("ПриОсвобожденииОбъекта", "OnDispose");

private BslScriptMethodInfo _moveNextMethod;
private BslScriptMethodInfo _getCurrentMethod;
private BslScriptMethodInfo _onDisposeMethod;

public ScriptedEnumeratorWrapper(UserScriptContextInstance userObject)
{
_userObject = userObject;
CheckCompatibility();
}

private void CheckCompatibility()
{
_moveNextMethod = FindRequiredMethod(MoveNextMethodName);
_getCurrentMethod = FindRequiredMethod(GetCurrentMethodName);
_onDisposeMethod = FindOptionalMethod(DisposeMethodName);

if (!_moveNextMethod.IsFunction() || _moveNextMethod.GetBslParameters().Length != 0)
{
throw MissingMethod(MoveNextMethodName);
}

if (!_getCurrentMethod.IsFunction() || _getCurrentMethod.GetBslParameters().Length != 0)
{
throw MissingMethod(GetCurrentMethodName);
}

if (_onDisposeMethod != null && _onDisposeMethod.GetBslParameters().Length != 0)
{
throw MissingMethod(DisposeMethodName);
}
}

private BslScriptMethodInfo FindRequiredMethod(BilingualString names)
{
try
{
return (BslScriptMethodInfo)_userObject.Module.Methods.Single(m =>
names.HasName(m.Name, StringComparison.CurrentCultureIgnoreCase));
}
catch (InvalidOperationException e)
{
throw MissingMethod(names, e);
}
}

private BslScriptMethodInfo FindOptionalMethod(BilingualString names)
{
return (BslScriptMethodInfo)_userObject.Module.Methods.FirstOrDefault(m =>
names.HasName(m.Name, StringComparison.CurrentCultureIgnoreCase));

}

public bool MoveNext()
{
_userObject.CallAsFunction(_moveNextMethod.DispatchId, Array.Empty<IValue>(), out var result);
return result.AsBoolean();
}

public void Reset()
{
throw new System.NotSupportedException();
}

public BslValue Current
{
get
{
_userObject.CallAsFunction(_getCurrentMethod.DispatchId, Array.Empty<IValue>(), out var result);
return (BslValue)result;
}
}

object IEnumerator.Current => Current;

public void Dispose()
{
if (_onDisposeMethod != null)
_userObject.CallAsProcedure(_onDisposeMethod.DispatchId, Array.Empty<IValue>());
}

public static RuntimeException IncompatibleInterfaceError()
{
var error = new BilingualString(
"Итератор не соответствует интерфейсу итератора",
"Iterator doesn't match Iterator interface");

return new RuntimeException(error);
}

public static RuntimeException MissingMethod(BilingualString methodName, Exception parent = null)
{
var error = new BilingualString(
"Обязательный метод "+methodName.Russian+" отсутствует, или не соответствует интерфейсу итератора",
"Required method "+methodName.English+" is missing or doesn't match iterator interface");

return new RuntimeException(error, parent);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation of ScriptedEnumeratorWrapper is correct and adheres to the IEnumerator<BslValue> interface. Adding XML documentation comments would help clarify the purpose of each method and the class's role in the system.

Copy link

Failed

  • 0.00% Coverage on New Code (is less than 80.00%)
  • 7.16% Duplicated Lines (%) on New Code (is greater than 3.00%)

Analysis Details

0 Issues

  • Bug0 Bugs
  • Vulnerability0 Vulnerabilities
  • Code Smell0 Code Smells

Coverage and Duplications

  • 0 percent coverage0.00% Coverage (0.00% Estimated after merge)
  • 10 percent duplication7.16% Duplicated Code (3.40% Estimated after merge)

View in SonarQube

@EvilBeaver
Copy link
Owner Author

Какой кайф.) Постараюсь потестить эту ситуацию в ближайщие дни.)

@sfaqer это пока в ветке, с сайта не скачается, только если с билдсервера. Я скорее про решение вообще спрашивал - посмотри, как именно сделано

@nixel2007
Copy link
Collaborator

@EvilBeaver а тестов на бсл нет или я в глаза долблюсь?

@EvilBeaver
Copy link
Owner Author

@EvilBeaver а тестов на бсл нет или я в глаза долблюсь?

Будут. Пока нет

Comment on lines 23 to 27
private static readonly BilingualString
MoveNextMethodName = new BilingualString("ВыбратьСледующий", "MoveNext");

private static readonly BilingualString
GetCurrentMethodName = new BilingualString("ТекущийЭлемент", "CurrentItem");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я вот тут не очень понял, выбрать следующий должен установить курсор на следующий элемент и его вернуть? Или просто курсор передвинуть? А если следующего элемента не оказалось что делать? У нас же нет заградительного "ЕстьСледующий()", ну и если ВыбратьСледующий возвращает элемент, то зачем нужен текущий элемент?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут я так понимаю можно снять вопрос.
Если я правильно уловил логику то ВыбратьСледующий, проверяет есть ли следующий элемент и позиционирует курсор на следующий элемент, возвращая в качестве результат ответ на вопрос есть ли элемент. А ТекущийЭлемент возвращает то что указывает курсор.

Меня наверное нейминг немного смущает, из ВыбратьСледующий сложно сделать вывод что нужно булево вернуть, я в оригинальном ищью предлагал "ЕстьСледующий" и "Следующий", мне показалось оно так очевиднее, я не настаиваю, но чем не понравился нейминг из ишью?)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь интерфейс итератора C#, а не Явы. Мне он кажется в разы более удобным. Во-первых, мне не надо подстраиваться под него, имитируя апи явы снаружи, а во вторых, он и в целом адекватнее

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Имя Следующий вместо ВыбратьСледующий можно рассмотреть, да


public IEnumerator<BslValue> GetEnumerator()
{
var enumerator = CallScriptMethod(_getIteratorMethod.DispatchId, Array.Empty<IValue>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_getIteratorMethod.DispatchId

Тут лежит не индекс метода в методах модуля, по которому потом он ищется.

image

Короче вот на это примере у функции ПолучитьИтератор() DispatchId = 1, и получает итератор он из функции Количество, потому что за первым индексом именно она лежит, а если второго метода нет то оно падает =)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это может быть, с индексами там всратая магия, мог напутать, спасибо

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

Я немного не понял почему различаются указания на коллекцию и иттератор, типа коллекция выделяет как директива компиляции а иттератор как аннотация над конструктором

image

Это так задумано? Нет возможности сделать единообразно?)

@EvilBeaver
Copy link
Owner Author

Это так задумано? Нет возможности сделать единообразно?)

Возможность есть, но разве мой вариант не удобнее раз в пять? Есть синтаксис аннотаций на модуль, его призываю юзать. И реализация со стороны шарпа проще

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

Это так задумано? Нет возможности сделать единообразно?)

Возможность есть, но разве мой вариант не удобнее раз в пять? Есть синтаксис аннотаций на модуль, его призываю юзать. И реализация со стороны шарпа проще

Так а почему для итератора тогда другой?)

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

Это так задумано? Нет возможности сделать единообразно?)

Возможность есть, но разве мой вариант не удобнее раз в пять? Есть синтаксис аннотаций на модуль, его призываю юзать. И реализация со стороны шарпа проще

@nixel2007 fyi надо бы учесть что аннотации модуля могут быть произвольные в подсветке и прочем

@EvilBeaver
Copy link
Owner Author

Это так задумано? Нет возможности сделать единообразно?)

Возможность есть, но разве мой вариант не удобнее раз в пять? Есть синтаксис аннотаций на модуль, его призываю юзать. И реализация со стороны шарпа проще

Так а почему для итератора тогда другой?)

Как понять "другой"? Для итератора вообще ничего не нужно, он просто должен иметь условленные методы.

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

Это так задумано? Нет возможности сделать единообразно?)

Возможность есть, но разве мой вариант не удобнее раз в пять? Есть синтаксис аннотаций на модуль, его призываю юзать. И реализация со стороны шарпа проще

Так а почему для итератора тогда другой?)

Как понять "другой"? Для итератора вообще ничего не нужно, он просто должен иметь условленные методы.

А, я походу уже сам додумал xD
Я строго говоря с #Обходимое то только с отладчиком шаровым допер xD

@EvilBeaver
Copy link
Owner Author

@sfaqer да, я уже осознал, что надо сделать демонстрирующие тесты как можно быстрее

@EvilBeaver
Copy link
Owner Author

@sfaqer @nixel2007 а как вы смотрите вообще на отсутствие аннотации на модуле, а вместо этого такое:

  • Если в модуле есть функция без параметров, помеченная аннотацией "Итератор", то считать класс Обходимым. Такая функция может быть только одна

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

@sfaqer @nixel2007 а как вы смотрите вообще на отсутствие аннотации на модуле, а вместо этого такое:

  • Если в модуле есть функция без параметров, помеченная аннотацией "Итератор", то считать класс Обходимым. Такая функция может быть только одна

Утиная имплементация, если что-то похоже на коллекцию значит это коллекция xD

Мысль вообще интересная, только я пытаюсь понять не перебор ли это с магией, пока не могу понять.

@nixel2007
Copy link
Collaborator

@sfaqer @nixel2007 а как вы смотрите вообще на отсутствие аннотации на модуле, а вместо этого такое:

  • Если в модуле есть функция без параметров, помеченная аннотацией "Итератор", то считать класс Обходимым. Такая функция может быть только одна

Зачем её тогда помечать аннотацией? Пускай у неё будет магическое имя. Старый код не сломается, так как никто не будет старые классы пихать в длякаждого. А для нового класса проще.

@nixel2007
Copy link
Collaborator

P.S. Я пока не допираю, что вы имеете ввиду под "аннотациями на модуль". Такого концепта в языке не было раньше.

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

P.S. Я пока не допираю, что вы имеете ввиду под "аннотациями на модуль". Такого концепта в языке не было раньше.

#Использовать <- аннотация модуля

@nixel2007
Copy link
Collaborator

P.S. Я пока не допираю, что вы имеете ввиду под "аннотациями на модуль". Такого концепта в языке не было раньше.

#Использовать <- аннотация модуля

Но это же инструкция... препроцессору...

@sfaqer
Copy link
Contributor

sfaqer commented Dec 29, 2023

P.S. Я пока не допираю, что вы имеете ввиду под "аннотациями на модуль". Такого концепта в языке не было раньше.

#Использовать <- аннотация модуля

Но это же инструкция... препроцессору...

В шарповом коде это Module.Annotations так что нет xD

@EvilBeaver
Copy link
Owner Author

EvilBeaver commented Dec 29, 2023

Но это же инструкция... препроцессору...

Нет. Как и native это аннотация модуля. Но концепт существует только с 2.0, так что тут скорее моя вина, что я про это не кричал на каждом углу

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

@nixel2007 надо договориться о синтаксисе аннотаций модуля. Оставлять ли как сейчас через "решетку" в начале, или спилить это в пользу аннотации на конструкторе

Но если спилить в пользу аннотации на конструкторе, тогда для модулей который не классы фича будет недоступна?

@EvilBeaver
Copy link
Owner Author

@nixel2007 надо договориться о синтаксисе аннотаций модуля. Оставлять ли как сейчас через "решетку" в начале, или спилить это в пользу аннотации на конструкторе

Но если спилить в пользу аннотации на конструкторе, тогда для модулей который не классы фича будет недоступна?

А как ты себе представляешь "не-класс", который можно поместить в Для Каждого?

@nixel2007
Copy link
Collaborator

@nixel2007 надо договориться о синтаксисе аннотаций модуля. Оставлять ли как сейчас через "решетку" в начале, или спилить это в пользу аннотации на конструкторе

Я не против ни одного из вариантов. В случае аннотаций модуля скорее всего надо надо будет доработать bsl-parser, но это не проблема. Не хочу, чтобы это было единственной причиной использовать аннотации над конструктором, если концепция аннотаций модуля здесь (и в последствии) удобнее.

@EvilBeaver
Copy link
Owner Author

если концепция аннотаций модуля здесь (и в последствии) удобнее.

Я как раз и не уверен в том, что это удобнее. Попробовал набросать варианты и так и этак, не сказать, что аннотация в виде решетки однозначно и интуитивно понятна. В случае с нативом или с "версией языка" для условной "типизации" - понятно, а в случае с итераторами - нет.

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

@nixel2007 надо договориться о синтаксисе аннотаций модуля. Оставлять ли как сейчас через "решетку" в начале, или спилить это в пользу аннотации на конструкторе

Но если спилить в пользу аннотации на конструкторе, тогда для модулей который не классы фича будет недоступна?

А как ты себе представляешь "не-класс", который можно поместить в Для Каждого?

Я так понял мы в целом сейчас концепцию аннотаций модуля оскрипта обсуждаем, а не применительно к этой конкретной задачи, для текущей задачи разницы нет, да. А в целом при последующих добавлений аннотаций может вылезти

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jan 9, 2024

А если вот такой синтаксис аннотации модуля:
#[Обходимое]
чтобы впоследствии можно было писать
#[Обходимое, Сравнимое, ЕщеКакое]

@EvilBeaver
Copy link
Owner Author

Я так понял мы в целом сейчас концепцию аннотаций модуля оскрипта обсуждаем, а не применительно к этой конкретной задачи

@sfaqer как раз нет. Здесь хотелось бы обсудить именно подход к конкретно этой задаче. Что будет более удобно

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

Я так понял мы в целом сейчас концепцию аннотаций модуля оскрипта обсуждаем, а не применительно к этой конкретной задачи

@sfaqer как раз нет. Здесь хотелось бы обсудить именно подход к конкретно этой задаче. Что будет более удобно

Если мы ограничиваемся рамками юзер тайп коллешонс, то я думаю стандартные аннотации (через &) над конструкторами предпочтительнее как наиболее очевидная и понятная концепция

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

А если вот такой синтаксис аннотации модуля: #[Обходимое] чтобы впоследствии можно было писать #[Обходимое, Сравнимое, ЕщеКакое]

Кажется это уже какой-то
#Implements IEnumerate IComparable IComparer
=)

@EvilBeaver
Copy link
Owner Author

Сейчас еще вспомним про кастомные геттеры-сеттеры и кастомные индексаторы для доступа через []

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

и кастомные индексаторы для доступа через []

А вот кстати для коллекций было бы не плохо, если они объявлены как индексированные конечно

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

Потом ещё прикрутим переопределение мат операций (+ - / *) для классов и заживём

image

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jan 9, 2024

В общем, именно так. Как образец был #[derive(Debug,Clone)]
Я за то чтобы помещать аннотацию в начале модуля:

  • аннотация описывает свойство класса в целом
  • видна сразу при открытии исходного кода
  • ПриСозданииОбъекта() может отсутствовать по логике работы класса (это не совсем конструктор)

Также кажется необязательным отдельный класс для Итератора - функции Следующий()/ЕстьСледующий() могут содержаться в модуле класса Коллекциии и даже не быть экспортируемыми.

@EvilBeaver
Copy link
Owner Author

Также кажется необязательным отдельный класс для Итератора - функции Следующий()/ЕстьСледующий() могут содержаться в модуле класса Коллекциии и даже не быть экспортируемыми.

Он и в текущем PR необязательный. Можно ведь вернуть ЭтотОбъект из ПолучитьИтератор()

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

Также кажется необязательным отдельный класс для Итератора - функции Следующий()/ЕстьСледующий() могут содержаться в модуле класса Коллекциии и даже не быть экспортируемыми.

Оно как бы в первом приближении да, а во втором, когда у нас есть 10 тредов каждый из которых получает иттератор и ожидает что каждый из иттераторов обойдёт всю коллекцию, подобная реализация будет выглядеть дюже странно.
Так что как бы сделать и можно, но это крайне специфичная реализация крайне специфичной коллекции

@sfaqer
Copy link
Contributor

sfaqer commented Jan 9, 2024

  • ПриСозданииОбъекта() может отсутствовать по логике работы класса (это не совсем конструктор)

Но его же можно добавить, даже пустой, просто чтобы повесить аннотацию, в той же ОСени эксплуатируется повсеместно

@EvilBeaver EvilBeaver changed the title Первый подход к реализации итераторов Реализация пользовательских итераторов Jan 19, 2024
@EvilBeaver
Copy link
Owner Author

Парни, я адаптировал это в т.ч. под стиль ОСени, давайте согласуем имена волшебных методов и уже вольем

Copy link

Failed

  • 0.00% Coverage on New Code (is less than 80.00%)

Analysis Details

5 Issues

  • Bug0 Bugs
  • Vulnerability0 Vulnerabilities
  • Code Smell5 Code Smells

Coverage and Duplications

  • 0 percent coverage0.00% Coverage (0.00% Estimated after merge)
  • 3 percent duplication0.00% Duplicated Code (3.30% Estimated after merge)

View in SonarQube

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3fc1e75 and d0d2a3b.
Files selected for processing (30)
  • src/OneScript.Core/Commons/Utils.cs (1 hunks)
  • src/OneScript.Core/Contexts/BslMethodInfo.cs (2 hunks)
  • src/OneScript.Core/Contexts/BslScriptMethodInfo.cs (2 hunks)
  • src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs (1 hunks)
  • src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs (1 hunks)
  • src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs (1 hunks)
  • src/OneScript.Core/Exceptions/InterfaceCheckException.cs (1 hunks)
  • src/OneScript.Core/Execution/IExecutableModule.cs (2 hunks)
  • src/OneScript.Core/Sources/EmptyModule.cs (2 hunks)
  • src/OneScript.Language/Localization/BilingualString.cs (2 hunks)
  • src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs (1 hunks)
  • src/OneScript.Native/Compiler/DynamicModule.cs (2 hunks)
  • src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs (1 hunks)
  • src/ScriptEngine/Compiler/CompilerFrontend.cs (2 hunks)
  • src/ScriptEngine/Hosting/EngineBuilderExtensions.cs (2 hunks)
  • src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (3 hunks)
  • src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs (1 hunks)
  • src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs (6 hunks)
  • src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs (1 hunks)
  • src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs (1 hunks)
  • src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs (1 hunks)
  • src/ScriptEngine/Machine/Interfaces/IterablesModuleAnnotationsHandler.cs (1 hunks)
  • src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs (1 hunks)
  • src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs (1 hunks)
  • src/ScriptEngine/Machine/StackRuntimeModule.cs (1 hunks)
  • src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs (1 hunks)
  • tests/iterators/annotated_iterator.os (1 hunks)
  • tests/iterators/collection_method_style.os (1 hunks)
  • tests/iterators/test-iterators.os (1 hunks)
Files not reviewed due to errors (1)
  • src/OneScript.Sources/EmptyModule.cs (no review received)
Files skipped from review due to trivial changes (1)
  • src/OneScript.Core/Commons/Utils.cs
Additional comments: 39
tests/iterators/collection_method_style.os (1)
  • 2-20: Ключевое слово &Обходимое используется для аннотации класса как итерируемого. Это предполагает, что класс должен реализовать методы, необходимые для итерации, например, ПолучитьИтератор. В коде присутствует метод ПолучитьИтератор, который возвращает новый экземпляр ИтераторСАннотацией, что соответствует ожиданиям.
tests/iterators/annotated_iterator.os (1)
  • 2-24: Ключевое слово &Итератор используется для аннотации класса как итератора. Это предполагает, что класс должен реализовать методы, необходимые для итерации, такие как ВыбратьСледующий и ТекущийЭлемент. В коде присутствуют оба этих метода, и они реализованы в соответствии с ожидаемым поведением итератора.
src/OneScript.Core/Exceptions/InterfaceCheckException.cs (1)
  • 13-22: Класс InterfaceCheckException представляет собой исключение, которое может быть выброшено при проверке соответствия интерфейсу. Конструкторы класса принимают сообщение об ошибке и, опционально, внутреннее исключение. Это стандартная практика для исключений в .NET, и здесь нет никаких проблем.
src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs (1)
  • 12-22: Класс IterableBslInterface представляет интерфейс итерируемого объекта в BSL. Он содержит свойства для методов GetIteratorMethod и GetCountMethod, которые необходимы для реализации итерируемого объекта. Класс корректно определяет эти свойства как только для чтения, что является хорошей практикой для данных, которые не должны изменяться после инициализации.
src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs (1)
  • 13-22: Интерфейс IPredefinedInterfaceChecker определяет контракт для классов, которые будут проверять соответствие модулей предопределенным интерфейсам. Метод Validate предназначен для выполнения этой проверки. Всё выглядит корректно и соответствует назначению интерфейса.
src/OneScript.Core/Execution/IExecutableModule.cs (1)
  • 29-29: Добавление свойства Interfaces к интерфейсу IExecutableModule расширяет его функциональность, позволяя модулям иметь информацию о реализованных интерфейсах. Это изменение влияет на сигнатуру интерфейса и потенциально на логику и функциональность модулей, которые его реализуют. Необходимо убедиться, что все реализации интерфейса обновлены для поддержки этого нового свойства.
Verification successful

Добавление свойства Interfaces к интерфейсу IExecutableModule было успешно проверено. Все реализации интерфейса IExecutableModule в файлах EmptyModule.cs, DynamicModule.cs и StackRuntimeModule.cs были обновлены для поддержки этого нового свойства. Следовательно, комментарий к коду подтверждается текущим состоянием кодовой базы.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Проверка наличия свойства Interfaces во всех реализациях IExecutableModule
rg --type cs "class\s+\w+\s+:\s+IExecutableModule" --exec cat {} \; | rg "Interfaces"

Length of output: 497



Script:

#!/bin/bash
# Исправление скрипта для проверки наличия свойства Interfaces во всех реализациях IExecutableModule
# Используем `xargs` для выполнения команды `cat` на файлах, найденных с помощью `rg`
rg --type cs "class\s+\w+\s+:\s+IExecutableModule" -l | xargs rg "Interfaces"

Length of output: 528

src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs (1)
  • 12-24: Класс IteratorBslInterface корректно определяет интерфейс итератора в BSL, включая методы MoveNextMethod, GetCurrentMethod и OnDisposeMethod. Эти свойства соответствуют ожидаемым методам итератора и правильно определены как только для чтения.
src/ScriptEngine/Machine/Interfaces/IterablesModuleAnnotationsHandler.cs (1)
  • 15-26: Класс IterablesModuleAnnotationsHandler расширяет SingleWordModuleAnnotationHandler и предоставляет обработку аннотаций модуля, связанных с итерируемыми объектами. Использование HashSet для поддерживаемых имен аннотаций является эффективным способом обеспечения быстрого доступа к этим именам.
src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs (1)
  • 18-29: Класс NativeRuntimeAnnotationHandler был изменен для наследования от SingleWordModuleAnnotationHandler. Это изменение упрощает логику обработки аннотаций, удаляя необходимость в методе ParseAnnotationInternal. Теперь класс использует статический HashSet для определения поддерживаемых директив, что улучшает читаемость и поддержку кода.
src/OneScript.Native/Compiler/DynamicModule.cs (1)
  • 31-31: Добавление свойства Interfaces к классу DynamicModule позволяет хранить и извлекать интерфейсы, связанные с модулем. Это изменение вводит новую функциональность в класс, что может потребовать дополнительной проверки в контексте всего приложения.
Verification successful

Скрипт успешно нашел использование свойства Interfaces в различных частях кода. Основываясь на полученных результатах, можно сделать вывод, что свойство Interfaces используется не только в классе DynamicModule, но и в других местах, включая тесты и другие классы, связанные с интерфейсами и их регистрацией. Это указывает на то, что добавление свойства Interfaces в DynamicModule может влиять на эти части системы, и следует убедиться, что изменения совместимы с существующим использованием свойства.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Проверка использования свойства Interfaces в других частях кода
rg --type cs "Interfaces" --exec cat {} \; | rg -v "DynamicModule"

Length of output: 476



Script:

#!/bin/bash
# Исправление скрипта для поиска использования свойства Interfaces в других частях кода
rg --type cs "Interfaces" | grep -v "DynamicModule"

Length of output: 9025

src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs (1)
  • 17-37: Метод EnablePredefinedIterables добавляет поддержку предопределенных итерируемых интерфейсов в DI контейнер. Это расширение позволяет легко включать поддержку итерируемых объектов в приложение. Методы AddInterface и GetInterface предоставляют удобный API для работы с интерфейсами в модулях.
tests/iterators/test-iterators.os (1)
  • 3-57: Сценарий тестирования test-iterators.os включает в себя несколько тестовых процедур, которые проверяют различные аспекты работы итераторов. Код тестов выглядит корректным и соответствует стандартам написания тестов для итераторов.
src/OneScript.Core/Contexts/BslMethodInfo.cs (1)
  • 25-25: Изменение уровня доступа поля Annotations с private на protected позволяет наследникам класса BslMethodInfo получать доступ к аннотациям. Это изменение улучшает расширяемость и переиспользование кода.
src/ScriptEngine/Machine/StackRuntimeModule.cs (1)
  • 62-62: Добавление свойства Interfaces к классу StackRuntimeModule позволяет хранить и извлекать интерфейсы, связанные с модулем. Это изменение вводит новую функциональность в класс, что может потребовать дополнительной проверки в контексте всего приложения.
src/OneScript.Language/Localization/BilingualString.cs (1)
  • 59-62: Метод HasName в классе BilingualString предоставляет функциональность для проверки соответствия имени в обоих языках, что улучшает поддержку локализации. Опциональный параметр comparison позволяет настраивать тип сравнения, что делает метод гибким в использовании.
src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs (1)
  • 22-65: Класс UserIterableContextInstance реализует интерфейс ICollectionContext<BslValue> и предоставляет методы Count и GetEnumerator, необходимые для работы с итерируемыми объектами. Код соответствует ожидаемой логике итерируемых объектов и корректно обрабатывает возможные ошибки.
src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs (1)
  • 21-81: Класс ScriptedEnumeratorWrapper реализует интерфейс IEnumerator<BslValue> и оборачивает пользовательский скриптовый объект для использования в качестве итератора. Класс корректно реализует методы MoveNext, Reset, Current и Dispose, а также предоставляет статический метод для создания исключения несоответствия интерфейса. Всё выглядит корректно и соответствует ожиданиям.
src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs (1)
  • 19-71: Класс IterableBslInterfaceChecker реализует интерфейс IPredefinedInterfaceChecker и предоставляет логику для проверки соответствия модуля интерфейсу итерируемого объекта. Код корректно обрабатывает ошибки и добавляет интерфейс к модулю, если проверка проходит успешно.
src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs (1)
  • 16-80: Класс PredefinedInterfaceRegistration предоставляет механизм для регистрации предопределенных интерфейсов и аннотаций. Код корректно реализует методы сравнения и хэширования, что важно для использования в коллекциях.
src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs (1)
  • 18-82: Класс PredefinedInterfaceResolver используется для разрешения предопределенных интерфейсов в модулях. Код корректно обрабатывает регистрации интерфейсов и вызывает соответствующие проверки. Логика разрешения интерфейсов выглядит корректной и соответствует назначению класса.
src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs (1)
  • 19-77: Класс SingleWordModuleAnnotationHandler обрабатывает аннотации модуля, состоящие из одного слова. Код корректно обрабатывает директивы и добавляет ошибки в ErrorSink, если после директивы присутствует лишний текст. Это соответствует ожидаемому поведению обработчика аннотаций.
src/ScriptEngine/Compiler/CompilerFrontend.cs (1)
  • 5-43: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [27-79]

Изменения в классе CompilerFrontend включают добавление новых параметров в конструктор и использование PredefinedInterfaceResolver для разрешения интерфейсов перед возвратом модуля. Это улучшает процесс компиляции, позволяя проверять соответствие модулей предопределенным интерфейсам.

src/ScriptEngine/Hosting/EngineBuilderExtensions.cs (1)
  • 64-64: Вызов services.EnablePredefinedIterables() в методе SetDefaultOptions добавляет поддержку предопределенных итерируемых интерфейсов в DI контейнер. Это расширение позволяет легко включать поддержку итерируемых объектов в приложение.
src/OneScript.Core/Contexts/BslScriptMethodInfo.cs (1)
  • 122-127: Метод HasBslAnnotation в классе BslScriptMethodInfo предоставляет функциональность для проверки наличия аннотации BslAnnotationAttribute с использованием данного BilingualString. Это улучшение позволяет более гибко работать с аннотациями, учитывая поддержку локализации.
src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs (5)
  • 21-30: Константы IterableAnnotation, MoveNextMethodName, GetCurrentMethodName, и DisposeMethodName используют класс BilingualString для поддержки локализации. Это соответствует целям PR по улучшению локализации.
  • 32-39: Метод GetRegistrations возвращает регистрации интерфейсов, что соответствует ожидаемой функциональности для поддержки итераторов.
  • 41-44: Метод Validate вызывает CheckModule, что является стандартным подходом для проверки модуля на соответствие интерфейсу итератора.
  • 46-70: Метод CheckModule проверяет, что методы MoveNext, CurrentItem, и OnDispose соответствуют требованиям интерфейса итератора. Важно, чтобы методы не принимали параметров, что соответствует спецификации итераторов.
  • 73-99: Методы FindRequiredMethod и FindOptionalMethod используют класс BilingualString для поиска методов, что поддерживает локализацию. Исключение InterfaceCheckException использует BilingualString для сообщения об ошибке, что также соответствует целям PR.
src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs (4)
  • 21-49: Тест Test_CheckerReactsOnModuleAnnotations проверяет реакцию проверяющего на аннотации модуля, что соответствует ожидаемому поведению для новой функциональности итераторов.
  • 53-76: Тест Test_CheckerDoesNotReactsOnModuleAnnotations проверяет, что проверяющий не реагирует на отсутствие аннотаций, что также соответствует ожидаемому поведению.
  • 80-110: Тест Test_CheckerReactsOnlyOnceOnManyAnnotations убеждается, что проверяющий реагирует только один раз, даже если есть множество аннотаций, что предотвращает избыточную регистрацию.
  • 114-141: Тест Test_CheckerReactsOnlyOnMethodAnnotations проверяет, что проверяющий реагирует только на аннотации методов, что соответствует ожидаемому поведению для работы с итераторами.
src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs (1)
  • 217-227: Изменения в методе ScriptFactory включают условное создание экземпляра UserIterableContextInstance в зависимости от наличия интерфейса итератора, что соответствует описанию изменений в AI-generated summary.
src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs (5)
  • 26-35: Добавлены новые константы BilingualString для терминов, связанных с итераторами, и удалены соответствующие строковые константы. Это улучшает поддержку локализации и соответствует целям PR.
  • 67-68: В методе OnInstanceCreation используются новые константы BilingualString для вызова скриптового метода, что улучшает читаемость и поддержку локализации.
  • 99-100: В методе ActivateAsStringOverride также используются новые константы BilingualString, что соответствует изменениям в остальной части файла.
  • 161-161: Использование константы RaiseEventTerms в методе FindOwnMethod улучшает поддержку локализации и соответствует изменениям в остальной части файла.
  • 215-215: В методе GetOwnMethodsDefinition используется новая константа RaiseEventTerms для определения метода, что улучшает поддержку локализации и соответствует изменениям в остальной части файла.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d0d2a3b and 982cc38.
Files selected for processing (4)
  • src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs (1 hunks)
  • tests/iterators/annotated_iterator.os (1 hunks)
  • tests/iterators/iterator.os (1 hunks)
  • tests/iterators/test-iterators.os (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs
  • tests/iterators/annotated_iterator.os
  • tests/iterators/test-iterators.os
Additional comments: 1
tests/iterators/iterator.os (1)
  • 21-23: Функция ТекущийЭлемент возвращает текущий элемент коллекции. Нет замечаний к реализации этой функции.

Comment on lines +6 to +10
Процедура ПриСозданииОбъекта(пКоллекция)
Коллекция = пКоллекция;
Индекс = 0;
Размер = Коллекция.Количество();
КонецПроцедуры
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Процедура ПриСозданииОбъекта корректно инициализирует переменные Коллекция, Индекс и Размер. Однако отсутствует проверка на то, что передаваемый параметр пКоллекция действительно поддерживает метод Количество. Это может привести к ошибке времени выполнения, если пКоллекция не имеет такого метода.

Процедура ПриСозданииОбъекта(пКоллекция)
+    Если ТипЗнч(пКоллекция) <> Тип("Массив") Тогда
+        ВызватьИсключение "Переданный параметр не является коллекцией.";
+    КонецЕсли;
    Коллекция = пКоллекция;
    Индекс = 0;
    Размер = Коллекция.Количество();
КонецПроцедуры

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
Процедура ПриСозданииОбъекта(пКоллекция)
Коллекция = пКоллекция;
Индекс = 0;
Размер = Коллекция.Количество();
КонецПроцедуры
Процедура ПриСозданииОбъекта(пКоллекция)
Если ТипЗнч(пКоллекция) <> Тип("Массив") Тогда
ВызватьИсключение "Переданный параметр не является коллекцией.";
КонецЕсли;
Коллекция = пКоллекция;
Индекс = 0;
Размер = Коллекция.Количество();
КонецПроцедуры

Comment on lines +12 to +19
Функция Следующий()
Если Индекс < Размер-1 Тогда
Индекс = Индекс + 1;
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Copy link

@coderabbitai coderabbitai bot Jan 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Функция Следующий предназначена для перехода к следующему элементу итератора. Однако условие Индекс < Размер-1 неверно, так как оно не позволит получить доступ к последнему элементу коллекции. Индекс последнего элемента равен Размер - 1, и итератор должен иметь возможность вернуть и его.

Функция Следующий()
-    Если Индекс < Размер-1 Тогда
+    Если Индекс < Размер Тогда
        Индекс = Индекс + 1;
        Возврат Истина;
    Иначе
        Возврат Ложь;    
    КонецЕсли;
КонецФункции

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
Функция Следующий()
Если Индекс < Размер-1 Тогда
Индекс = Индекс + 1;
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Функция Следующий()
Если Индекс < Размер Тогда
Индекс = Индекс + 1;
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции

Copy link
Collaborator

@nixel2007 nixel2007 Jan 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Но ведь индексация ведётся от нуля

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nixel2007 Вы абсолютно правы, индексация начинается с нуля, и ваше замечание корректно. Условие Индекс < Размер-1 позволяет итератору корректно обработать все элементы коллекции, включая последний. Спасибо за уточнение.

Copy link

Passed

Analysis Details

4 Issues

  • Bug0 Bugs
  • Vulnerability0 Vulnerabilities
  • Code Smell4 Code Smells

Coverage and Duplications

  • No coverage informationNo coverage information (0.00% Estimated after merge)
  • 3 percent duplication0.00% Duplicated Code (3.30% Estimated after merge)

View in SonarQube

@EvilBeaver EvilBeaver merged commit ea6bf45 into develop Jan 21, 2024
4 checks passed
@EvilBeaver EvilBeaver deleted the feature/iterators-1269 branch January 21, 2024 09:49
@EvilBeaver EvilBeaver modified the milestone: v2.0-RC4 Jan 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants