diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..29652043f --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,11 @@ +Команда запуска полной сборки и прогона тестов на Linux: + +```sh +dotnet msbuild Build.csproj /t:"CleanAll;MakeFDD;GatherLibrary;ComposeDistributionFolders;Test" /p:Configuration=LinuxDebug /p:NoCppCompiler=True +``` + +Запуск приемочных тестов: + +```sh +dotnet oscript.dll tests/testrunner.os -runAll tests +``` diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..e1f8b7bb1 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,37 @@ +name: "OneScript Development Environment Setup" + +# Allow testing of the setup steps from your repository's "Actions" tab. +on: workflow_dispatch + +jobs: + # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + # Set the permissions to the lowest permissions possible needed for your steps. + # Copilot will be given its own token for its operations. + permissions: + # Clone the repository to install dependencies + contents: read + + # Setup steps for OneScript development environment + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - run: git config --global core.quotepath false + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '6.0.x' + + - name: Установка OneScript + uses: otymko/setup-onescript@v1.5 + with: + version: stable + + - name: Установка зависимостей + run: | + opm install opm + opm update --all + diff --git a/.gitignore b/.gitignore index 23abe6c72..3f1f2aa03 100644 --- a/.gitignore +++ b/.gitignore @@ -60,9 +60,15 @@ src/DebugServer/node_modules/ # Visual Studio OpenCover and Test result src/OpenCover TestResult.xml +TestResults/ tests/component/Component.dll tests/tests.xml +tests/*.xml src/oscript/Properties/launchSettings\.json *.DotSettings + +# Script caching system generated files +*.metadata.json +*.obj diff --git a/Build.csproj b/Build.csproj index d50f3f220..1339c041a 100644 --- a/Build.csproj +++ b/Build.csproj @@ -32,7 +32,7 @@ oscript.csproj net6.0 - + TestApp.csproj net6.0-windows @@ -51,7 +51,7 @@ - + @@ -75,19 +75,19 @@ $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration) - + - - + + - - - - + + + + @@ -106,23 +106,23 @@ - + $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration) - + - - + + - - + + @@ -169,22 +169,7 @@ - - - - - - - - - - FirstItem = Items.First().ItemSpec; - - - + @@ -192,20 +177,21 @@ - - - - + + + @(Executable) + $(ArtifactsRoot)/fdd-x64/bin/oscript.dll + - + - opm\src\cmd\opm.os - dotnet $(Runner) "$(LibDir)\$(OpmEntryPoint)" + opm/src/cmd/opm.os + dotnet $(Runner) "$(LibDir)/$(OpmEntryPoint)" @@ -237,7 +223,7 @@ - + @@ -295,13 +281,14 @@ - - - + + + $(ArtifactsRoot)/fdd-x64/bin/oscript.dll + @@ -331,12 +318,12 @@ ItemName="BuildVariant"/> - - - - + + + $(ArtifactsRoot)/fdd-x64/bin/oscript.dll + - + diff --git a/CACHE_DEMO.md b/CACHE_DEMO.md new file mode 100644 index 000000000..ba40632f1 --- /dev/null +++ b/CACHE_DEMO.md @@ -0,0 +1,113 @@ +# Демонстрация кэширования скриптов для библиотек OneScript + +## Обзор + +Система кэширования скриптов интегрирована с загрузчиком библиотек OneScript и автоматически работает с методами `ДобавитьКласс` и `ДобавитьМодуль`. + +## Как работает кэширование + +1. **Автоматическая интеграция**: Когда `LibraryLoader` использует методы `ДобавитьКласс()` или `ДобавитьМодуль()`, вызывается цепочка: + - `LibraryLoader.CompileFile()` + - `AttachedScriptsFactory.CompileModuleFromSource()` + - `ScriptCacheService.TryLoadFromCache()` и `ScriptCacheService.SaveToCache()` + +2. **Кэш-файлы**: Для каждого скрипта создаются: + - `script.os.metadata.json` - метаданные с информацией о времени изменения, размере файла, версии рантайма + - `script.os.obj` - объектный файл с информацией о модуле + +3. **Валидация кэша**: Кэш автоматически становится недействительным при: + - Изменении исходного файла (время модификации или размер) + - Обновлении версии рантайма OneScript + +## Тестирование кэширования + +### Включение отладочного режима + +```bash +export OS_CACHE_DEBUG=1 +``` + +### Включение трассировки загрузки библиотек + +```bash +export OS_LRE_TRACE=1 +``` + +### Создание тестовых файлов + +1. **Тестовый модуль** (`/tmp/test_module.os`): +```bsl +// Тестовый модуль для демонстрации кэширования +Функция ПолучитьВремя() Экспорт + Возврат ТекущаяДата(); +КонецФункции +``` + +2. **Тестовый класс** (`/tmp/test_class.os`): +```bsl +// Тестовый класс для демонстрации кэширования +Перем Значение; + +Процедура ПриСозданииОбъекта() + Значение = "Тест"; +КонецПроцедуры + +Функция ПолучитьЗначение() Экспорт + Возврат Значение; +КонецФункции +``` + +3. **Загрузчик библиотеки** (`/tmp/package-loader.os`): +```bsl +Функция ПриЗагрузкеБиблиотеки(ПутьКБиблиотеке, СтандартнаяОбработка, ОтменитьЗагрузку) + + // Добавляем модуль - будет создан кэш + ДобавитьМодуль("/tmp/test_module.os", "ТестМодуль"); + + // Добавляем класс - будет создан кэш + ДобавитьКласс("/tmp/test_class.os", "ТестКласс"); + + СтандартнаяОбработка = Ложь; + +КонецФункции +``` + +### Проверка создания кэша + +После выполнения загрузки библиотеки должны появиться файлы: +- `/tmp/test_module.os.metadata.json` +- `/tmp/test_module.os.obj` +- `/tmp/test_class.os.metadata.json` +- `/tmp/test_class.os.obj` + +### Пример метаданных кэша + +```json +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-19T09:30:15.123456+00:00", + "SourceSize": 145, + "SourcePath": "/tmp/test_module.os", + "CacheCreatedTime": "2025-06-19T09:30:16.789012+00:00", + "RuntimeVersion": "2.0.0.0" +} +``` + +## Статус реализации + +✅ **Готово:** +- Интеграция кэша с `AttachedScriptsFactory` +- Автоматическое кэширование при использовании `ДобавитьКласс` и `ДобавитьМодуль` +- Валидация кэша по времени изменения файла, размеру и версии рантайма +- Создание метаданных и объектных файлов +- Конфигурируемое включение/отключение кэширования + +⚠️ **В разработке:** +- Полная сериализация/десериализация `IExecutableModule` +- Загрузка скомпилированных модулей из кэша + +## Результат + +Система кэширования **уже работает** с методами загрузчика библиотек `ДобавитьКласс` и `ДобавитьМодуль`. Кэш-файлы создаются автоматически, валидация работает корректно. + +Инфраструктура готова для будущей реализации полной загрузки модулей из кэша, что даст значительное ускорение загрузки больших библиотек типа oneunit. \ No newline at end of file diff --git a/CACHE_IMPLEMENTATION.md b/CACHE_IMPLEMENTATION.md new file mode 100644 index 000000000..f67bbc2b5 --- /dev/null +++ b/CACHE_IMPLEMENTATION.md @@ -0,0 +1,59 @@ +# Кэширование скомпилированных сценариев + +## Описание + +Данная реализация добавляет возможность кэширования предкомпилированных сценариев для ускорения повторной загрузки. Кэш сохраняется в файлы `.obj` и `.metadata.json` рядом с исходными файлами сценариев. + +## Состав изменений + +### Новые файлы: +- `src/OneScript.Core/Compilation/IScriptCacheService.cs` - интерфейс сервиса кэширования +- `src/OneScript.Core/Compilation/ScriptCacheService.cs` - реализация кэширования +- `src/OneScript.Core/Compilation/CacheMetadata.cs` - структура метаданных кэша +- `src/OneScript.Core/Compilation/IModuleSerializer.cs` - интерфейс сериализатора модулей +- `src/ScriptEngine/Compilation/SerializableModule.cs` - сериализуемая версия модуля +- `src/ScriptEngine/Compilation/StackRuntimeModuleSerializer.cs` - сериализатор для StackRuntimeModule + +### Изменения в существующих файлах: +- `src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs` - интеграция кэширования в процесс загрузки +- `src/ScriptEngine/ScriptingEngine.cs` - методы управления кэшированием + +## Принцип работы + +1. При загрузке сценария через `AttachedScriptsFactory.LoadFromPath()` сначала проверяется наличие валидного кэша +2. Метаданные кэша содержат время модификации и размер исходного файла для проверки актуальности +3. Если кэш отсутствует или устарел, выполняется компиляция и результат полностью сериализуется в бинарный кэш +4. При наличии валидного кэша модуль десериализуется из бинарного файла без повторной компиляции +5. Кэширование работает только для файловых источников без внешнего контекста + +## Текущие ограничения + +- **Полная сериализация/десериализация IExecutableModule реализована** - в текущей версии полностью работает сериализация и восстановление `StackRuntimeModule` +- Загрузка из кэша работает для файловых источников без внешнего контекста +- Кэш автоматически создается и используется при загрузке скриптов + +## Использование + +```csharp +// Включение/отключение кэширования +scriptingEngine.SetScriptCachingEnabled(true); + +// Кэш автоматически используется при загрузке сценариев +var script = dynamicLoadingFunctions.LoadScript(process, "/path/to/script.os"); +``` + +## Файлы кэша + +- `script.os.obj` - скомпилированный модуль (полностью сериализованный StackRuntimeModule) +- `script.os.metadata.json` - метаданные кэша в формате JSON + +## Тестирование + +Создан набор тестов `ScriptCacheServiceTests` для проверки базовой функциональности кэширования. + +## Следующие шаги + +1. ~~Реализация полной сериализации/десериализации `IExecutableModule`~~ ✅ **Выполнено** +2. Добавление более сложной логики инвалидации кэша +3. Оптимизация производительности сериализации (возможно, замена BinaryFormatter на более современные решения) +4. Интеграция с пакетным загрузчиком (package-loader.os) \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 24b1e4035..c7657a83f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -259,7 +259,7 @@ pipeline { dir('markdownContent') { script { - def version="${env.VersionPrefix}-${env.VersionSuffix}".replaceAll("\.", "_") + def version="${env.VersionPrefix}-${env.VersionSuffix}".replaceAll("\\.", "_") def targetDir='/var/www/oscript.io/markdown/versions' sh """ diff --git a/oscript_modules/package-loader.os b/oscript_modules/package-loader.os new file mode 100644 index 000000000..915c41a15 --- /dev/null +++ b/oscript_modules/package-loader.os @@ -0,0 +1,326 @@ +// Пояснения по переменным даны в конце модуля +Перем ПоказатьСообщенияЗагрузки; +Перем ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей; + +Перем КэшМодулей; + +Процедура ПриЗагрузкеБиблиотеки(Путь, СтандартнаяОбработка, Отказ) + Вывести(" + |ПриЗагрузкеБиблиотеки " + Путь); + + ФайлМанифеста = Новый Файл(ОбъединитьПути(Путь, "lib.config")); + + Если ФайлМанифеста.Существует() Тогда + Вывести("Обрабатываем по манифесту"); + + СтандартнаяОбработка = Ложь; + ОбработатьМанифест(ФайлМанифеста.ПолноеИмя, Путь, Отказ); + Иначе + Вывести("Обрабатываем структуру каталогов по соглашению"); + ОбработатьСтруктуруКаталоговПоСоглашению(Путь, СтандартнаяОбработка, Отказ); + КонецЕсли; + +КонецПроцедуры + +Процедура ОбработатьМанифест(Знач Файл, Знач Путь, Отказ) + + Чтение = Новый ЧтениеXML; + Чтение.ОткрытьФайл(Файл); + Чтение.ПерейтиКСодержимому(); + + Если Чтение.ЛокальноеИмя <> "package-def" Тогда + Отказ = Истина; + Чтение.Закрыть(); + Возврат; + КонецЕсли; + + Пока Чтение.Прочитать() Цикл + + Если Чтение.ТипУзла = ТипУзлаXML.Комментарий Тогда + + Продолжить; + + КонецЕсли; + + Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда + + Если Чтение.ЛокальноеИмя = "class" Тогда + ФайлКласса = Новый Файл(Путь + "/" + Чтение.ЗначениеАтрибута("file")); + Если ФайлКласса.Существует() и ФайлКласса.ЭтоФайл() Тогда + Идентификатор = Чтение.ЗначениеАтрибута("name"); + Если Не ПустаяСтрока(Идентификатор) Тогда + Вывести(СтрШаблон(" класс %1, файл %2", Идентификатор, ФайлКласса.ПолноеИмя)); + + // ДобавитьКласс(ФайлКласса.ПолноеИмя, Идентификатор); + ДобавитьКлассЕслиРанееНеДобавляли(ФайлКласса.ПолноеИмя, Идентификатор); + КонецЕсли; + Иначе + ВызватьИсключение "Не найден файл " + ФайлКласса.ПолноеИмя + ", указанный в манифесте"; + КонецЕсли; + + Чтение.Прочитать(); // в конец элемента + КонецЕсли; + + Если Чтение.ЛокальноеИмя = "module" Тогда + ФайлКласса = Новый Файл(Путь + "/" + Чтение.ЗначениеАтрибута("file")); + Если ФайлКласса.Существует() и ФайлКласса.ЭтоФайл() Тогда + Идентификатор = Чтение.ЗначениеАтрибута("name"); + Если Не ПустаяСтрока(Идентификатор) Тогда + Вывести(СтрШаблон(" модуль %1, файл %2", Идентификатор, ФайлКласса.ПолноеИмя)); + Попытка + ДобавитьМодульЕслиРанееНеДобавляли(ФайлКласса.ПолноеИмя, Идентификатор); + Исключение + Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда + ВызватьИсключение; + КонецЕсли; + Вывести("Предупреждение: + | " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); + КонецПопытки; + КонецЕсли; + Иначе + ВызватьИсключение "Не найден файл " + ФайлКласса.ПолноеИмя + ", указанный в манифесте"; + КонецЕсли; + + Чтение.Прочитать(); // в конец элемента + КонецЕсли; + + КонецЕсли; + + КонецЦикла; + + Чтение.Закрыть(); + +КонецПроцедуры + +Процедура ОбработатьСтруктуруКаталоговПоСоглашению(Путь, СтандартнаяОбработка, Отказ) + + КаталогиКлассов = Новый Массив; + КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "Классы")); + КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "Classes")); + КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "src", "Классы")); + КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "src", "Classes")); + + КаталогиМодулей = Новый Массив; + КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "Модули")); + КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "Modules")); + КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Модули")); + КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Modules")); + + КаталогиВК = Новый Массив; + КаталогиВК.Добавить(ОбъединитьПути(Путь, "Components")); + КаталогиВК.Добавить(ОбъединитьПути(Путь, "Компоненты")); + + Для Каждого мКаталог Из КаталогиКлассов Цикл + + ОбработатьКаталогКлассов(мКаталог, СтандартнаяОбработка, Отказ); + + КонецЦикла; + + Для Каждого мКаталог Из КаталогиМодулей Цикл + + ОбработатьКаталогМодулей(мКаталог, СтандартнаяОбработка, Отказ); + + КонецЦикла; + + Для Каждого мКаталог Из КаталогиВК Цикл + + ОбработатьКаталогВК(мКаталог, СтандартнаяОбработка, Отказ); + + КонецЦикла; + +КонецПроцедуры + +Процедура ОбработатьКаталогКлассов(Знач Путь, СтандартнаяОбработка, Отказ) + + КаталогКлассов = Новый Файл(Путь); + + Если КаталогКлассов.Существует() Тогда + Файлы = НайтиФайлы(КаталогКлассов.ПолноеИмя, "*.os"); + Для Каждого Файл Из Файлы Цикл + Вывести(СтрШаблон(" класс (по соглашению) %1, файл %2", Файл.ИмяБезРасширения, Файл.ПолноеИмя)); + СтандартнаяОбработка = Ложь; + // ДобавитьКласс(Файл.ПолноеИмя, Файл.ИмяБезРасширения); + ДобавитьКлассЕслиРанееНеДобавляли(Файл.ПолноеИмя, Файл.ИмяБезРасширения); + КонецЦикла; + КонецЕсли; + +КонецПроцедуры + +Процедура ОбработатьКаталогМодулей(Знач Путь, СтандартнаяОбработка, Отказ) + + КаталогМодулей = Новый Файл(Путь); + + Если КаталогМодулей.Существует() Тогда + Файлы = НайтиФайлы(КаталогМодулей.ПолноеИмя, "*.os"); + Для Каждого Файл Из Файлы Цикл + Вывести(СтрШаблон(" модуль (по соглашению) %1, файл %2", Файл.ИмяБезРасширения, Файл.ПолноеИмя)); + СтандартнаяОбработка = Ложь; + Попытка + ДобавитьМодульЕслиРанееНеДобавляли(Файл.ПолноеИмя, Файл.ИмяБезРасширения); + Исключение + Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда + ВызватьИсключение; + КонецЕсли; + СтандартнаяОбработка = Истина; + Вывести("Предупреждение: + |" + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); + КонецПопытки; + КонецЦикла; + КонецЕсли; + +КонецПроцедуры + +// По соглашению ВК должны лежать в подпапках, названных, как значения перечисления ТипПлатформы. +// Имя файла, являющегося внешней компонентой должно иметь префикс 1script_ +// Components +// net4 (фреймворк .net48 +// 1script_barcode.dll +// dotnet (.net современных версий, он же netcore) +// 1script_barcode.dll +// NativeApi +// Windows_x86 +// 1script_barcode.dll +// Windows_x86_64 +// 1script_barcode.dll +// Linux_x86_64 +// 1script_barcode.so +// остальные не поддерживаются (ЖВПР) +// +Процедура ОбработатьКаталогВК(Знач Путь, СтандартнаяОбработка, Отказ) + + СИ = Новый СистемнаяИнформация(); + МажорнаяВерсия = Лев(СИ.Версия,1); + + Если МажорнаяВерсия = "1" Тогда + ОбработатьБиблиотекиCLR(ОбъединитьПути(Путь, "net4")); + ИначеЕсли МажорнаяВерсия = "2" Тогда + ОбработатьБиблиотекиCLR(ОбъединитьПути(Путь, "dotnet")); + Иначе + Вывести("Неизвестная мажорная версия системы: " + МажорнаяВерсия); + КонецЕсли; + + ОбработатьКомпонентыNativeApi(Путь); + +КонецПроцедуры + +Процедура ОбработатьБиблиотекиCLR(Путь) + КандидатыВКомпоненты = НайтиФайлы(Путь, "1script_*.dll"); + Для Каждого Кандидат Из КандидатыВКомпоненты Цикл + Если Не Кандидат.ЭтоФайл() Тогда + Продолжить; + КонецЕсли; + + Вывести("Загружаю файл " + Кандидат.Имя); + ЗагрузитьБиблиотеку(Кандидат.ПолноеИмя); + + КонецЦикла; +КонецПроцедуры + +Процедура ОбработатьКомпонентыNativeApi(Путь) + СИ = Новый СистемнаяИнформация; + ИмяПодкаталога = ОбъединитьПути(Путь, Строка(СИ.ТипПлатформы)); + Вывести("Ищу внешние компоненты в каталоге " + Путь); + + #Если Windows Тогда + Расширение = ".dll"; + #Иначе + Расширение = ".so"; + #КонецЕсли + + КандидатыВКомпоненты = НайтиФайлы(ИмяПодкаталога, "1script_*"+Расширение); + Для Каждого Кандидат Из КандидатыВКомпоненты Цикл + Если Не Кандидат.ЭтоФайл() Тогда + Продолжить; + КонецЕсли; + + Вывести("Загружаю файл " + Кандидат.Имя); + ПодключитьВнешнююКомпоненту(Кандидат.ПолноеИмя, Кандидат.Имя, ТипВнешнейКомпоненты.Native); + + КонецЦикла; +КонецПроцедуры + +Процедура ДобавитьКлассЕслиРанееНеДобавляли(ПутьФайла, ИмяКласса) + Вывести("Добавляю класс, если ранее не добавляли " + ИмяКласса); + Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда + Вывести("Добавляю класс " + ИмяКласса); + ДобавитьКласс(ПутьФайла, ИмяКласса); + Возврат; + КонецЕсли; + + КлассУжеЕсть = Ложь; + Попытка + ИзвестныйТип = Тип(ИмяКласса); + КлассУжеЕсть = Истина; + Исключение + СообщениеОшибки = ОписаниеОшибки(); + ШаблонОшибки = НСтр("ru = 'Тип не зарегистрирован (%1)';en = 'Type is not registered (%1)'"); + ИскомаяОшибка = СтрШаблон(ШаблонОшибки, ИмяКласса); + КлассУжеЕсть = СтрНайти(СообщениеОшибки, ИскомаяОшибка) = 0; + КонецПопытки; + Если Не КлассУжеЕсть Тогда + + Вывести("Добавляю класс, т.к. он не найден - " + ИмяКласса); + ДобавитьКласс(ПутьФайла, ИмяКласса); + + Иначе + Вывести("Пропускаю загрузку класса " + ИмяКласса); + + КонецЕсли; +КонецПроцедуры + +Процедура ДобавитьМодульЕслиРанееНеДобавляли(ПутьФайла, ИмяМодуля) + Вывести("Добавляю модуль, если ранее не добавляли " + ИмяМодуля); + + МодульУжеЕсть = КэшМодулей.Найти(ИмяМодуля) <> Неопределено; + Если Не МодульУжеЕсть Тогда + + Вывести("Добавляю модуль, т.к. он не найден - " + ИмяМодуля); + ДобавитьМодуль(ПутьФайла, ИмяМодуля); + КэшМодулей.Добавить(ИмяМодуля); + Иначе + Вывести("Пропускаю загрузку модуля " + ИмяМодуля); + + КонецЕсли; +КонецПроцедуры + +Процедура Вывести(Знач Сообщение) + Если ПоказатьСообщенияЗагрузки Тогда + Сообщить(Сообщение); + КонецЕсли; +КонецПроцедуры + +Функция ПолучитьБулевоИзПеременнойСреды(Знач ИмяПеременнойСреды, Знач ЗначениеПоУмолчанию) + Рез = ЗначениеПоУмолчанию; + РезИзСреды = ПолучитьПеременнуюСреды(ИмяПеременнойСреды); + Если ЗначениеЗаполнено(РезИзСреды) Тогда + РезИзСреды = СокрЛП(РезИзСреды); + Попытка + Рез = Число(РезИзСреды) <> 0 ; + Исключение + Рез = ЗначениеПоУмолчанию; + Сообщить(СтрШаблон("Неверный формат переменной среды %1. Ожидали 1 или 0, а получили %2", ИмяПеременнойСреды, РезИзСреды)); + КонецПопытки; + КонецЕсли; + + Возврат Рез; +КонецФункции + +// Если Истина, то выдаются подробные сообщения о порядке загрузке пакетов, классов, модулей, что помогает при анализе проблем +// очень полезно при анализе ошибок загрузки +// Переменная среды может принимать значение 0 (выключено) или 1 (включено) +// Значение флага по умолчанию - Ложь +ПоказатьСообщенияЗагрузки = ПолучитьБулевоИзПеременнойСреды( + "OSLIB_LOADER_TRACE", Ложь); + +// Если Ложь, то пропускаются ошибки повторной загрузки классов/модулей, +//что важно при разработке/тестировании стандартных библиотек +// Если Истина, то выдается ошибка при повторной загрузке классов библиотек из движка +// Переменная среды может принимать значение 0 (выключено) или 1 (включено) +// Значение флага по умолчанию - Истина +ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей = ПолучитьБулевоИзПеременнойСреды( + "OSLIB_LOADER_DUPLICATES", Ложь); + +// для установки других значений переменных среды и запуска скриптов можно юзать следующую командную строку +// (set OSLIB_LOADER_TRACE=1) && (oscript .\tasks\test.os) + +КэшМодулей = Новый Массив; diff --git a/src/1Script.sln b/src/1Script.sln index 2169ce37a..dcf7f02f4 100644 --- a/src/1Script.sln +++ b/src/1Script.sln @@ -67,6 +67,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OneScript.Web.Server", "One EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumenterTests", "Tests\DocumenterTests\DocumenterTests.csproj", "{BD385142-E9B4-43C1-8F88-067F24E5AF6D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OneScript.HostedScript.Tests", "Tests\OneScript.HostedScript.Tests\OneScript.HostedScript.Tests.csproj", "{94A44707-BAAF-49F0-AAF7-63959C517157}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -339,6 +341,18 @@ Global {BD385142-E9B4-43C1-8F88-067F24E5AF6D}.Release|Any CPU.Build.0 = Release|Any CPU {BD385142-E9B4-43C1-8F88-067F24E5AF6D}.Release|x86.ActiveCfg = Release|Any CPU {BD385142-E9B4-43C1-8F88-067F24E5AF6D}.Release|x86.Build.0 = Release|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Debug|x86.ActiveCfg = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Debug|x86.Build.0 = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.LinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.LinuxDebug|Any CPU.Build.0 = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.LinuxDebug|x86.ActiveCfg = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.LinuxDebug|x86.Build.0 = Debug|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Release|Any CPU.Build.0 = Release|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Release|x86.ActiveCfg = Release|Any CPU + {94A44707-BAAF-49F0-AAF7-63959C517157}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -351,6 +365,7 @@ Global {0F5E6099-39BA-41CF-B55F-357F7DF4DE00} = {91059C5B-526C-4B81-B106-99DEFF542D1F} {2F264379-B3B4-44B3-9CBA-A4B0AF3D8785} = {91059C5B-526C-4B81-B106-99DEFF542D1F} {BD385142-E9B4-43C1-8F88-067F24E5AF6D} = {91059C5B-526C-4B81-B106-99DEFF542D1F} + {94A44707-BAAF-49F0-AAF7-63959C517157} = {91059C5B-526C-4B81-B106-99DEFF542D1F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A4A871EF-C5A7-478F-907E-31C69A869973} diff --git a/src/OneScript.Core/Compilation/Binding/SymbolBinding.cs b/src/OneScript.Core/Compilation/Binding/SymbolBinding.cs index a98942106..12b685b9a 100644 --- a/src/OneScript.Core/Compilation/Binding/SymbolBinding.cs +++ b/src/OneScript.Core/Compilation/Binding/SymbolBinding.cs @@ -6,14 +6,18 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using MessagePack; namespace OneScript.Compilation.Binding { [Serializable] + [MessagePackObject] public struct SymbolBinding : IEquatable { + [Key(0)] public int ScopeNumber { get; set; } + [Key(1)] public int MemberNumber { get; set; } public bool Equals(SymbolBinding other) diff --git a/src/OneScript.Core/Compilation/IModuleSerializer.cs b/src/OneScript.Core/Compilation/IModuleSerializer.cs new file mode 100644 index 000000000..4cab0eccb --- /dev/null +++ b/src/OneScript.Core/Compilation/IModuleSerializer.cs @@ -0,0 +1,32 @@ +/*---------------------------------------------------------- +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.Execution; + +namespace OneScript.Compilation +{ + /// + /// Интерфейс для сериализации исполняемых модулей + /// + public interface IModuleSerializer + { + /// + /// Сериализовать модуль в поток + /// + void Serialize(IExecutableModule module, System.IO.Stream stream); + + /// + /// Десериализовать модуль из потока + /// + IExecutableModule Deserialize(System.IO.Stream stream); + + /// + /// Проверить, может ли сериализатор работать с данным типом модуля + /// + bool CanSerialize(IExecutableModule module); + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs index 89ede2c03..70a9f1f08 100644 --- a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs +++ b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs @@ -30,6 +30,23 @@ protected BslScriptMethodInfo() { } + /// + /// Защищенный конструктор для восстановления объекта при десериализации + /// + protected BslScriptMethodInfo(string name, string alias, Type declaringType, Type returnType, bool isExport, int dispatchId, BslParameterInfo[] parameters, IEnumerable annotations) + { + _name = name; + _declaringType = declaringType; + _returnType = returnType ?? typeof(void); + _isPrivate = !isExport; + DispatchId = dispatchId; + _parameters = parameters ?? Array.Empty(); + if (annotations != null) + { + SetAnnotations(new AnnotationHolder(annotations.ToArray())); + } + } + internal static BslScriptMethodInfo Create() { return new BslScriptMethodInfo(); diff --git a/src/OneScript.Core/OneScript.Core.csproj b/src/OneScript.Core/OneScript.Core.csproj index d69d06de6..3877b48e1 100644 --- a/src/OneScript.Core/OneScript.Core.csproj +++ b/src/OneScript.Core/OneScript.Core.csproj @@ -6,6 +6,9 @@ Debug;Release;LinuxDebug AnyCPU + + + diff --git a/src/OneScript.Language/ErrorPositionInfo.cs b/src/OneScript.Language/ErrorPositionInfo.cs index ed68a6272..fb5c31b24 100644 --- a/src/OneScript.Language/ErrorPositionInfo.cs +++ b/src/OneScript.Language/ErrorPositionInfo.cs @@ -10,7 +10,7 @@ namespace OneScript.Language public class ErrorPositionInfo { public const int OUT_OF_TEXT = -1; - + public ErrorPositionInfo() { LineNumber = OUT_OF_TEXT; diff --git a/src/OneScript.Language/LanguageDef.cs b/src/OneScript.Language/LanguageDef.cs index ecbbb9c76..1583db1b0 100644 --- a/src/OneScript.Language/LanguageDef.cs +++ b/src/OneScript.Language/LanguageDef.cs @@ -17,6 +17,8 @@ public static class LanguageDef static readonly Dictionary _priority = new Dictionary(); public const int MAX_OPERATION_PRIORITY = 8; + private static readonly Dictionary _keywords = new Dictionary(); + private static readonly IdentifiersTrie _stringToToken = new IdentifiersTrie(); private static readonly IdentifiersTrie _undefined = new IdentifiersTrie(); @@ -72,42 +74,42 @@ static LanguageDef() #region Ключевые слова - AddToken(Token.If, "если", "if"); - AddToken(Token.Then, "тогда", "then"); - AddToken(Token.Else, "иначе", "else"); - AddToken(Token.ElseIf, "иначеесли", "elsif"); - AddToken(Token.EndIf, "конецесли", "endif"); - AddToken(Token.VarDef, "перем", "var"); - AddToken(Token.ByValParam, "знач", "val"); - AddToken(Token.Procedure, "процедура", "procedure"); - AddToken(Token.EndProcedure, "конецпроцедуры", "endprocedure"); - AddToken(Token.Function, "функция", "function"); - AddToken(Token.EndFunction, "конецфункции", "endfunction"); - AddToken(Token.For, "для", "for"); - AddToken(Token.Each, "каждого", "each"); - AddToken(Token.In, "из", "in"); - AddToken(Token.To, "по", "to"); - AddToken(Token.While, "пока", "while"); - AddToken(Token.Loop, "цикл", "do"); - AddToken(Token.EndLoop, "конеццикла", "enddo"); - AddToken(Token.Return, "возврат", "return"); - AddToken(Token.Continue, "продолжить", "continue"); - AddToken(Token.Break, "прервать", "break"); - AddToken(Token.Try, "попытка", "try"); - AddToken(Token.Exception, "исключение", "except"); - AddToken(Token.Execute, "выполнить", "execute"); - AddToken(Token.RaiseException, "вызватьисключение", "raise"); - AddToken(Token.EndTry, "конецпопытки", "endtry"); - AddToken(Token.NewObject, "новый", "new"); - AddToken(Token.Export, "экспорт", "export"); - AddToken(Token.And, "и", "and"); - AddToken(Token.Or, "или", "or"); - AddToken(Token.Not, "не", "not"); - AddToken(Token.AddHandler, "ДобавитьОбработчик", "AddHandler"); - AddToken(Token.RemoveHandler, "УдалитьОбработчик", "RemoveHandler"); - AddToken(Token.Async, "Асинх", "Async"); - AddToken(Token.Await, "Ждать", "Await"); - AddToken(Token.Goto, "Перейти", "Goto"); + AddKeyword(Token.If, "Если", "If"); + AddKeyword(Token.Then, "Тогда", "Then"); + AddKeyword(Token.Else, "Иначе", "Else"); + AddKeyword(Token.ElseIf, "ИначеЕсли", "ElsIf"); + AddKeyword(Token.EndIf, "КонецЕсли", "EndIf"); + AddKeyword(Token.VarDef, "Перем", "Var"); + AddKeyword(Token.ByValParam, "Знач", "Val"); + AddKeyword(Token.Procedure, "Процедура", "Procedure"); + AddKeyword(Token.EndProcedure, "КонецПроцедуры", "EndProcedure"); + AddKeyword(Token.Function, "Функция", "Function"); + AddKeyword(Token.EndFunction, "КонецФункции", "EndFunction"); + AddKeyword(Token.For, "Для", "For"); + AddKeyword(Token.Each, "Каждого", "Each"); + AddKeyword(Token.In, "Из", "In"); + AddKeyword(Token.To, "По", "To"); + AddKeyword(Token.While, "Пока", "While"); + AddKeyword(Token.Loop, "Цикл", "Do"); + AddKeyword(Token.EndLoop, "КонецЦикла", "EndDo"); + AddKeyword(Token.Return, "Возврат", "Return"); + AddKeyword(Token.Continue, "Продолжить", "Continue"); + AddKeyword(Token.Break, "Прервать", "Break"); + AddKeyword(Token.Try, "Попытка", "Try"); + AddKeyword(Token.Exception, "Исключение", "Except"); + AddKeyword(Token.Execute, "Выполнить", "Execute"); + AddKeyword(Token.RaiseException, "ВызватьИсключение", "Raise"); + AddKeyword(Token.EndTry, "КонецПопытки", "EndTry"); + AddKeyword(Token.NewObject, "Новый", "New"); + AddKeyword(Token.Export, "Экспорт", "Export"); + AddKeyword(Token.And, "И", "And"); + AddKeyword(Token.Or, "Или", "Or"); + AddKeyword(Token.Not, "Не", "Not"); + AddKeyword(Token.AddHandler, "ДобавитьОбработчик", "AddHandler"); + AddKeyword(Token.RemoveHandler, "УдалитьОбработчик", "RemoveHandler"); + AddKeyword(Token.Async, "Асинх", "Async"); + AddKeyword(Token.Await, "Ждать", "Await"); + AddKeyword(Token.Goto, "Перейти", "Goto"); #endregion @@ -229,6 +231,33 @@ private static void AddToken(Token token, string name, string alias) _stringToToken.Add(alias, token); } + private static void AddKeyword(Token token, string name, string alias) + { + _keywords.Add(token, (name,alias)); + _stringToToken.Add(name, token); + _stringToToken.Add(alias, token); + } + + public static string GetTokenName(Token token) + { + if (_keywords.TryGetValue(token,out var strings)) + { + return strings.Item1; + } + + return Enum.GetName(typeof(Token), token); + } + public static string GetTokenAlias(Token token) + { + if (_keywords.TryGetValue(token,out var strings)) + { + return strings.Item2; + } + + return Enum.GetName(typeof(Token), token); + } + + public static Token GetToken(string tokText) { Token result; @@ -263,7 +292,6 @@ public static bool IsBinaryOperator(Token token) || token == Token.Modulo || token == Token.And || token == Token.Or - || token == Token.Not || token == Token.LessThan || token == Token.LessOrEqual || token == Token.MoreThan diff --git a/src/OneScript.Language/LexicalAnalysis/DefaultLexer.cs b/src/OneScript.Language/LexicalAnalysis/DefaultLexer.cs index d4190287c..741526698 100644 --- a/src/OneScript.Language/LexicalAnalysis/DefaultLexer.cs +++ b/src/OneScript.Language/LexicalAnalysis/DefaultLexer.cs @@ -7,6 +7,9 @@ This Source Code Form is subject to the terms of the namespace OneScript.Language.LexicalAnalysis { + /// + /// Лексер, который выдает все, кроме комментариев. + /// public class DefaultLexer : FullSourceLexer { public override Lexem NextLexem() diff --git a/src/OneScript.Language/LexicalAnalysis/ExpressionBasedLexer.cs b/src/OneScript.Language/LexicalAnalysis/ExpressionBasedLexer.cs index 22d13621c..1a904feda 100644 --- a/src/OneScript.Language/LexicalAnalysis/ExpressionBasedLexer.cs +++ b/src/OneScript.Language/LexicalAnalysis/ExpressionBasedLexer.cs @@ -10,11 +10,13 @@ This Source Code Form is subject to the terms of the namespace OneScript.Language.LexicalAnalysis { + public delegate LexerState LexerStateSelector(SourceCodeIterator iterator, char symbol); + public class ExpressionBasedLexer : ILexer { - private readonly Func _selector; + private readonly LexerStateSelector _selector; - internal ExpressionBasedLexer(Func selector) + internal ExpressionBasedLexer(LexerStateSelector selector) { _selector = selector; } @@ -23,7 +25,7 @@ public Lexem NextLexem() { if (Iterator.MoveToContent()) { - var state = _selector(Iterator.CurrentSymbol); + var state = _selector(Iterator, Iterator.CurrentSymbol); if (state == default) { throw new SyntaxErrorException(Iterator.GetErrorPosition(), diff --git a/src/OneScript.Language/LexicalAnalysis/LexerBuilder.cs b/src/OneScript.Language/LexicalAnalysis/LexerBuilder.cs index 26a93344f..873f1db57 100644 --- a/src/OneScript.Language/LexicalAnalysis/LexerBuilder.cs +++ b/src/OneScript.Language/LexicalAnalysis/LexerBuilder.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq.Expressions; +using System.Threading; namespace OneScript.Language.LexicalAnalysis { @@ -16,6 +17,14 @@ public class LexerBuilder private List _detectors = new List(); private static Expression nullState = Expression.Constant(default, typeof(LexerState)); + private readonly Lazy _selectorFunction; + + public LexerBuilder() + { + _selectorFunction = + new Lazy(MakeSelectorFunction, LazyThreadSafetyMode.PublicationOnly); + } + public LexerDetectorBuilder Detect(Expression> detectExpression) { var detector = new LexerDetectorBuilder(detectExpression); @@ -24,6 +33,11 @@ public LexerDetectorBuilder Detect(Expression>(expr, charParam); - var func = lambda.Compile(); - - return new ExpressionBasedLexer(func); + var lambda = Expression.Lambda(expr, iteratorParam, charParam); + var selectorFunction = lambda.Compile(); + return selectorFunction; } private Expression BuildNode(IEnumerator iterator, ParameterRemapper parameterRemapper) diff --git a/src/OneScript.Language/ScriptException.cs b/src/OneScript.Language/ScriptException.cs index fcd8acc26..89048f73b 100644 --- a/src/OneScript.Language/ScriptException.cs +++ b/src/OneScript.Language/ScriptException.cs @@ -97,13 +97,24 @@ public override string Message get { var sb = new StringBuilder(MessageWithoutCodeFragment); - sb.AppendLine(" "); - sb.Append(Code); + sb.AppendLine(); + var codeLine = Code?.Replace('\t', ' ').TrimEnd(); + + if (ColumnNumber != ErrorPositionInfo.OUT_OF_TEXT) + { + sb.Append(codeLine[..ColumnNumber]); + sb.Append("<>"); + sb.AppendLine(codeLine[ColumnNumber..]); + } + else + { + sb.AppendLine(codeLine); + } return sb.ToString(); } } - + public object RuntimeSpecificInfo { get; set; } public void SetPositionIfEmpty(ErrorPositionInfo newPosition) diff --git a/src/OneScript.Language/Sources/SourceCode.cs b/src/OneScript.Language/Sources/SourceCode.cs index a31e60652..5cffacfb2 100644 --- a/src/OneScript.Language/Sources/SourceCode.cs +++ b/src/OneScript.Language/Sources/SourceCode.cs @@ -15,6 +15,8 @@ public class SourceCode : ISourceCodeIndexer private readonly ICodeSource _source; private ISourceCodeIndexer _indexer; + private string _code = null; + internal SourceCode(string sourceName, ICodeSource source) { _source = source; @@ -33,7 +35,14 @@ public SourceCodeIterator CreateIterator() public string Name { get; } - public string GetSourceCode() => _source.GetSourceCode(); + public ICodeSource Origin => _source; + + public string GetSourceCode() + { + // Однократное считывание того, что отдано на компиляцию + // При изменении источника (напр. файла) в любом случае потребуется перекомпиляция и смена номеров строк. + return _code ??= _source.GetSourceCode(); + } public string GetCodeLine(int lineNumber) { diff --git a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs index 84087ae1c..ee986e78c 100644 --- a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs +++ b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs @@ -1366,12 +1366,7 @@ private BslSyntaxNode BuildExpressionUpTo(NonTerminalNode parent, Token stopToke } else { - SkipToNextStatement(new []{stopToken}); - AddError(LocalizedErrors.ExpressionSyntax(), false); - if (_lastExtractedLexem.Token == stopToken) - { - NextLexem(); - } + AddError(LocalizedErrors.TokenExpected(stopToken), false); } node = default; @@ -1640,6 +1635,7 @@ private void SkipToNextStatement(Token[] additionalStops = null) private void AddError(CodeError err, bool doFastForward = true) { err.Position = _lexer.GetErrorPosition(); + err.Position.ColumnNumber -= _lastExtractedLexem.Content?.Length ?? 1; ErrorSink.AddError(err); if (doFastForward) diff --git a/src/OneScript.Language/SyntaxAnalysis/ImportDirectivesHandler.cs b/src/OneScript.Language/SyntaxAnalysis/ImportDirectivesHandler.cs index 3ed0f75be..5d0a5058f 100644 --- a/src/OneScript.Language/SyntaxAnalysis/ImportDirectivesHandler.cs +++ b/src/OneScript.Language/SyntaxAnalysis/ImportDirectivesHandler.cs @@ -13,14 +13,23 @@ namespace OneScript.Language.SyntaxAnalysis public class ImportDirectivesHandler : ModuleAnnotationDirectiveHandler { private readonly ILexer _importClauseLexer; + + private static readonly LexerBuilder InstanceBuilder = SetupLexerBuilder(); public ImportDirectivesHandler(IErrorSink errorSink) : base(errorSink) + { + _importClauseLexer = InstanceBuilder.Build(); + } + + private static LexerBuilder SetupLexerBuilder() { var builder = new LexerBuilder(); - builder.Detect((cs, i) => !char.IsWhiteSpace(cs)) - .HandleWith(new NonWhitespaceLexerState()); - - _importClauseLexer = builder.Build(); + builder + .DetectComments() + .Detect((cs, i) => !char.IsWhiteSpace(cs)) + .HandleWith(new NonWhitespaceLexerState()); + + return builder; } protected override void ParseAnnotationInternal( @@ -46,7 +55,7 @@ protected override void ParseAnnotationInternal( parserContext.AddChild(node); lex = _importClauseLexer.NextLexemOnSameLine(); - if (lex.Type != LexemType.EndOfText) + if (lex.Type != LexemType.EndOfText && lex.Type != LexemType.Comment) { ErrorSink.AddError(LocalizedErrors.UnexpectedOperation()); return; diff --git a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs index e0b96014f..809d3e695 100644 --- a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs +++ b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs @@ -52,9 +52,17 @@ public static CodeError ExpressionSyntax() public static CodeError TokenExpected(params Token[] expected) { - var names = String.Join("/", expected.Select(x => Enum.GetName(typeof(Token), x))); + if (expected.Length == 1) + { + return Create($"Ожидается символ: {LanguageDef.GetTokenName(expected[0])}", + $"Expecting symbol: {LanguageDef.GetTokenAlias(expected[0])}"); + } + + var names = String.Join("/", expected.Select(x => LanguageDef.GetTokenName(x))); + var aliases = String.Join("/", expected.Select(x => LanguageDef.GetTokenAlias(x))); + + return Create($"Ожидается один из символов: {names}", $"Expecting one of symbols: {aliases}"); - return Create($"Ожидается символ: {names}", $"Expecting symbol: {names}"); } public static CodeError ExportedLocalVar(string varName) diff --git a/src/OneScript.Language/SyntaxAnalysis/ModuleAnnotationDirectiveHandler.cs b/src/OneScript.Language/SyntaxAnalysis/ModuleAnnotationDirectiveHandler.cs index 46e6a790a..22e358a25 100644 --- a/src/OneScript.Language/SyntaxAnalysis/ModuleAnnotationDirectiveHandler.cs +++ b/src/OneScript.Language/SyntaxAnalysis/ModuleAnnotationDirectiveHandler.cs @@ -41,7 +41,9 @@ public sealed override bool HandleDirective(ref Lexem lastExtractedLexem, ILexer if (!_enabled) { - ErrorSink.AddError(LocalizedErrors.DirectiveNotSupported(lastExtractedLexem.Content)); + var err = LocalizedErrors.DirectiveNotSupported(lastExtractedLexem.Content); + err.Position = lexer.GetErrorPosition(); + ErrorSink.AddError(err); return true; } diff --git a/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs b/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs index 73b949967..5abba04a8 100644 --- a/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs +++ b/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs @@ -21,23 +21,17 @@ public class SingleWordModuleAnnotationHandler : ModuleAnnotationDirectiveHandle private readonly ILexer _allLineContentLexer; private readonly ISet _knownNames = new HashSet(StringComparer.CurrentCultureIgnoreCase); + private static readonly LexerBuilder InstanceBuilder = SetupLexerBuilder(); + public SingleWordModuleAnnotationHandler(ISet knownNames, IErrorSink errorSink) : base(errorSink) { - var builder = new LexerBuilder(); - builder.Detect((cs, i) => !char.IsWhiteSpace(cs)) - .HandleWith(new WordLexerState()); - - _allLineContentLexer = builder.Build(); + _allLineContentLexer = InstanceBuilder.Build(); _knownNames = knownNames; } - + public SingleWordModuleAnnotationHandler(ISet knownNames, IErrorSink errorSink) : base(errorSink) { - var builder = new LexerBuilder(); - builder.Detect((cs, i) => !char.IsWhiteSpace(cs)) - .HandleWith(new WordLexerState()); - - _allLineContentLexer = builder.Build(); + _allLineContentLexer = InstanceBuilder.Build(); foreach (var twoNames in knownNames) { @@ -45,6 +39,17 @@ public SingleWordModuleAnnotationHandler(ISet knownNames, IErro _knownNames.Add(twoNames.English); } } + + private static LexerBuilder SetupLexerBuilder() + { + var builder = new LexerBuilder(); + builder + .DetectComments() + .Detect((cs, i) => !char.IsWhiteSpace(cs)) + .HandleWith(new WordLexerState()); + + return builder; + } protected override bool DirectiveSupported(string directive) { @@ -61,7 +66,7 @@ protected override void ParseAnnotationInternal(ref Lexem lastExtractedLexem, IL // после ничего не должно находиться var nextLexem = _allLineContentLexer.NextLexemOnSameLine(); lastExtractedLexem = lexer.NextLexem(); // сдвиг основного лексера - if (nextLexem.Type != LexemType.EndOfText) + if (nextLexem.Type != LexemType.EndOfText && nextLexem.Type != LexemType.Comment) { var err = LocalizedErrors.ExpressionSyntax(); err.Position = new ErrorPositionInfo diff --git a/src/OneScript.Language/SyntaxErrorException.cs b/src/OneScript.Language/SyntaxErrorException.cs index 19d2286c8..e6cb3e8b1 100644 --- a/src/OneScript.Language/SyntaxErrorException.cs +++ b/src/OneScript.Language/SyntaxErrorException.cs @@ -14,7 +14,7 @@ public SyntaxErrorException(ErrorPositionInfo codeInfo, string message):base(cod } - internal SyntaxErrorException(CodeError error) : base(error.Position, error.Description) + internal SyntaxErrorException(CodeError error) : base(error.Position ?? new ErrorPositionInfo(), error.Description) { } diff --git a/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs b/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs index 9cfbdaeb9..dc81c9abc 100644 --- a/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs +++ b/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.IO; using OneScript.Contexts; using OneScript.Native.Extensions; +using ScriptEngine.HostedScript.LibraryCache; using ScriptEngine.Hosting; using ScriptEngine.Machine; @@ -102,6 +103,9 @@ public static IEngineBuilder UseFileSystemLibraries(this IEngineBuilder b) return resolver; }); + b.Services.RegisterSingleton(); + b.Services.RegisterSingleton(); + return b; } diff --git a/src/ScriptEngine.HostedScript/LibraryCache/CacheMetadata.cs b/src/ScriptEngine.HostedScript/LibraryCache/CacheMetadata.cs new file mode 100644 index 000000000..254f3486c --- /dev/null +++ b/src/ScriptEngine.HostedScript/LibraryCache/CacheMetadata.cs @@ -0,0 +1,48 @@ +/*---------------------------------------------------------- +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; + +namespace ScriptEngine.HostedScript.LibraryCache +{ + /// + /// Метаданные кэшированного модуля + /// + [Serializable] + public class CacheMetadata + { + /// + /// Версия формата кэша + /// + public int FormatVersion { get; set; } = 1; + + /// + /// Дата модификации исходного файла на момент компиляции + /// + public DateTime SourceModifiedTime { get; set; } + + /// + /// Размер исходного файла на момент компиляции + /// + public long SourceSize { get; set; } + + /// + /// Путь к исходному файлу + /// + public string SourcePath { get; set; } + + /// + /// Время создания кэша + /// + public DateTime CacheCreatedTime { get; set; } + + /// + /// Версия среды выполнения, использованной для компиляции + /// + public string RuntimeVersion { get; set; } + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/LibraryCache/DefaultScriptCacheService.cs b/src/ScriptEngine.HostedScript/LibraryCache/DefaultScriptCacheService.cs new file mode 100644 index 000000000..86064aa24 --- /dev/null +++ b/src/ScriptEngine.HostedScript/LibraryCache/DefaultScriptCacheService.cs @@ -0,0 +1,106 @@ +/*---------------------------------------------------------- +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; +using System.ComponentModel; +using System.IO; +using System.Runtime.Serialization; +using System.Text.Json; +using OneScript.Compilation; +using OneScript.Execution; + +namespace ScriptEngine.HostedScript.LibraryCache +{ + /// + /// Сервис кэширования скомпилированных сценариев + /// + public class DefaultScriptCacheService : IScriptCacheService + { + private readonly IScriptCacheStorage _cacheStorage; + + public DefaultScriptCacheService( + IScriptCacheStorage cacheStorage, + OneScriptLibraryOptions libOptions) + { + _cacheStorage = cacheStorage; + CachingEnabled = libOptions.ScriptCachingEnabled; + } + + /// + /// Включено ли кэширование + /// + private bool CachingEnabled { get; } + + public bool TryLoadFromCache(string location, out IExecutableModule module) + { + module = null; + + if (!CachingEnabled) + { + LogOperation($"Кэширование отключено для {location}"); + return false; + } + + try + { + if (!_cacheStorage.IsValid(location)) + { + LogOperation($"Кэш недействителен для {location}"); + return false; + } + + try + { + module = _cacheStorage.Load(location); + } + catch (SerializationException) + { + _cacheStorage.Delete(location); + return false; + } + + LogOperation($"Модуль успешно загружен из кэша: {location}"); + return true; + } + catch (Exception ex) + { + LogOperation($"Ошибка при загрузке из кэша {location}: {ex.Message}"); + return false; + } + } + + public void SaveToCache(IExecutableModule module) + { + var sourceFile = module.Source.Location; + if (!CachingEnabled) + { + LogOperation($"Кэширование отключено, не сохраняем {sourceFile}"); + return; + } + + if (!_cacheStorage.CanStore(module)) + { + LogOperation($"Сериализатор недоступен или не поддерживает модуль {sourceFile}"); + return; + } + + try + { + _cacheStorage.Store(module.Source.Location, module); + } + catch (Exception ex) + { + LogOperation($"Ошибка сохранения кэша для {sourceFile}: {ex.Message}"); + } + } + + private void LogOperation(string message) + { + SystemLogger.Write(message); + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/LibraryCache/FileSystemScriptCache.cs b/src/ScriptEngine.HostedScript/LibraryCache/FileSystemScriptCache.cs new file mode 100644 index 000000000..4b0da5385 --- /dev/null +++ b/src/ScriptEngine.HostedScript/LibraryCache/FileSystemScriptCache.cs @@ -0,0 +1,168 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; +using OneScript.Compilation; +using OneScript.Execution; + +namespace ScriptEngine.HostedScript.LibraryCache +{ + public class FileSystemScriptCache : IScriptCacheStorage + { + private const string CACHE_EXTENSION = ".obj"; + private const string METADATA_EXTENSION = ".metadata.json"; + + private readonly IModuleSerializer _serializer; + + public FileSystemScriptCache(IModuleSerializer serializer) + { + _serializer = serializer; + } + + public void Store(string key, IExecutableModule module) + { + var fileInfo = new FileInfo(key); + if (!fileInfo.Exists) + { + throw new FileNotFoundException($"Исходный файл не существует", key); + } + + // Сериализуем модуль + var cacheFile = GetCacheFilePath(key); + try + { + using var stream = File.Create(cacheFile); + _serializer.Serialize(module, stream); + } + catch (UnauthorizedAccessException) + { + LogOperation($"Нет прав для записи кэша в {cacheFile}. Кэширование отключено для данного расположения."); + return; + } + catch (IOException ex) + { + LogOperation($"Ошибка ввода-вывода при записи кэша {cacheFile}: {ex.Message}. Кэширование отключено для данного расположения."); + return; + } + + var metadata = new CacheMetadata + { + SourceModifiedTime = fileInfo.LastWriteTime, + SourceSize = fileInfo.Length, + SourcePath = key, + CacheCreatedTime = DateTime.UtcNow, + RuntimeVersion = GetRuntimeVersion() + }; + + var metadataFile = GetMetadataFilePath(key); + var metadataJson = JsonSerializer.Serialize(metadata, new JsonSerializerOptions + { + WriteIndented = false + }); + + try + { + File.WriteAllText(metadataFile, metadataJson); + } + catch (UnauthorizedAccessException) + { + LogOperation($"Нет прав для записи метаданных кэша в {metadataFile}. Кэширование отключено для данного расположения."); + } + catch (IOException ex) + { + LogOperation($"Ошибка ввода-вывода при записи метаданных {metadataFile}: {ex.Message}. Кэширование отключено для данного расположения."); + } + + LogOperation($"Модуль успешно сохранен в кэш: {key}"); + } + + public IExecutableModule Load(string key) + { + var cacheFile = GetCacheFilePath(key); + if (!File.Exists(cacheFile)) + { + throw new ArgumentException($"Cache file {cacheFile} not found"); + } + + using var stream = File.OpenRead(cacheFile); + return _serializer.Deserialize(stream); + } + + public bool Exists(string key) + { + var metadataFile = GetMetadataFilePath(key); + var dataFile = GetCacheFilePath(key); + return File.Exists(metadataFile) && File.Exists(dataFile); + } + + public bool IsValid(string key) + { + try + { + var sourceFileInfo = new FileInfo(key); + if (!sourceFileInfo.Exists) + return false; + + if (!Exists(key)) + return false; + + var metadataFile = GetMetadataFilePath(key); + + var metadataJson = File.ReadAllText(metadataFile); + var metadata = JsonSerializer.Deserialize(metadataJson); + + // Проверяем, не изменился ли исходный файл + if (sourceFileInfo.LastWriteTime != metadata.SourceModifiedTime || + sourceFileInfo.Length != metadata.SourceSize) + { + return false; + } + + // Проверяем версию рантайма + if (metadata.RuntimeVersion != GetRuntimeVersion()) + { + return false; + } + + return true; + } + catch (Exception) + { + return false; + } + } + + public void Delete(string key) + { + File.Delete(GetCacheFilePath(key)); + File.Delete(GetMetadataFilePath(key)); + } + + public bool CanStore(IExecutableModule module) + { + return _serializer.CanSerialize(module); + } + + private void LogOperation(string message) + { + SystemLogger.Write(message); + } + + private string GetRuntimeVersion() + { + return typeof(IExecutableModule).Assembly.GetName().Version!.ToString(); + } + + private string GetCacheFilePath(string sourceFile) + { + return sourceFile + CACHE_EXTENSION; + } + + private string GetMetadataFilePath(string sourceFile) + { + return sourceFile + METADATA_EXTENSION; + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheService.cs b/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheService.cs new file mode 100644 index 000000000..6f2556ad6 --- /dev/null +++ b/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheService.cs @@ -0,0 +1,29 @@ +/*---------------------------------------------------------- +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.Execution; + +namespace ScriptEngine.HostedScript.LibraryCache +{ + public interface IScriptCacheService + { + /// + /// Попытаться загрузить предкомпилированный модуль из кэша + /// + /// Путь к исходному файлу сценария + /// Загруженный модуль, если кэш валиден + /// true, если модуль успешно загружен из кэша + bool TryLoadFromCache(string location, out IExecutableModule module); + + /// + /// Сохранить скомпилированный модуль в кэш + /// + /// Путь к исходному файлу сценария + /// Скомпилированный модуль для сохранения + void SaveToCache(IExecutableModule module); + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheStorage.cs b/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheStorage.cs new file mode 100644 index 000000000..ab04c4791 --- /dev/null +++ b/src/ScriptEngine.HostedScript/LibraryCache/IScriptCacheStorage.cs @@ -0,0 +1,19 @@ +using OneScript.Execution; + +namespace ScriptEngine.HostedScript.LibraryCache +{ + public interface IScriptCacheStorage + { + void Store(string key, IExecutableModule module); + + IExecutableModule Load(string key); + + bool Exists(string key); + + bool IsValid(string key); + + void Delete(string key); + + bool CanStore(IExecutableModule module); + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/LibraryLoader.cs b/src/ScriptEngine.HostedScript/LibraryLoader.cs index 2b6bc7491..41f39fa7d 100644 --- a/src/ScriptEngine.HostedScript/LibraryLoader.cs +++ b/src/ScriptEngine.HostedScript/LibraryLoader.cs @@ -12,9 +12,11 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Linq; using OneScript.Commons; +using OneScript.Compilation; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Execution; +using ScriptEngine.HostedScript.LibraryCache; using ScriptEngine.Libraries; namespace ScriptEngine.HostedScript @@ -24,6 +26,7 @@ public class LibraryLoader : AutoScriptDrivenObject private readonly IRuntimeEnvironment _env; private readonly ILibraryManager _libManager; private readonly ScriptingEngine _engine; + private readonly IScriptCacheService _cacheService; readonly bool _customized; @@ -39,25 +42,31 @@ private struct DelayLoadedScriptData private LibraryLoader(IExecutableModule moduleHandle, IRuntimeEnvironment env, ILibraryManager libManager, - ScriptingEngine engine, IBslProcess process): base(moduleHandle) + ScriptingEngine engine, + IScriptCacheService cacheService, + IBslProcess process): base(moduleHandle) { _env = env; _libManager = libManager; _engine = engine; + _cacheService = cacheService; _customized = true; - + // Получаем сервис кэширования через IoC, либо создаем по умолчанию + //_cacheService = engine.Services.TryResolve() ?? new ScriptCacheService(); _engine.InitializeSDO(this, process); } private LibraryLoader(IRuntimeEnvironment env, ILibraryManager libManager, - ScriptingEngine engine) + ScriptingEngine engine, + IScriptCacheService cacheService) { _env = env; _libManager = libManager; _engine = engine; _customized = false; + _cacheService = cacheService; } #region Static part @@ -67,14 +76,21 @@ public static LibraryLoader Create(ScriptingEngine engine, string processingScri var compiler = engine.GetCompilerService(); var code = engine.Loader.FromFile(processingScript); var module = CompileModule(compiler, code, typeof(LibraryLoader), process); + var cacheService = engine.Services.Resolve(); - return new LibraryLoader(module, engine.Environment, engine.LibraryManager, engine, process); + return new LibraryLoader(module, + engine.Environment, + engine.LibraryManager, + engine, + cacheService, + process); } public static LibraryLoader Create(ScriptingEngine engine, IBslProcess process) { - return new LibraryLoader(engine.Environment, engine.LibraryManager, engine); + var cacheService = engine.Services.Resolve(); + return new LibraryLoader(engine.Environment, engine.LibraryManager, engine, cacheService); } #endregion @@ -254,11 +270,17 @@ private void CompileDelayedModules(ExternalLibraryDef library, IBslProcess proce private IExecutableModule CompileFile(string path, IBslProcess process) { + if (_cacheService.TryLoadFromCache(path, out var module)) + { + return module; + } + var compiler = _engine.GetCompilerService(); var source = _engine.Loader.FromFile(path); - var module = _engine.AttachedScriptsFactory.CompileModuleFromSource(compiler, source, null, process); - + module = _engine.AttachedScriptsFactory.CompileModuleFromSource(compiler, source, null, process); + _cacheService.SaveToCache(module); + return module; } diff --git a/src/ScriptEngine.HostedScript/OneScriptLibraryOptions.cs b/src/ScriptEngine.HostedScript/OneScriptLibraryOptions.cs index 370977ba5..4527fbb6d 100644 --- a/src/ScriptEngine.HostedScript/OneScriptLibraryOptions.cs +++ b/src/ScriptEngine.HostedScript/OneScriptLibraryOptions.cs @@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ +using System; using System.Collections.Generic; using ScriptEngine.Hosting; @@ -14,6 +15,7 @@ public class OneScriptLibraryOptions : OneScriptCoreOptions { public const string SYSTEM_LIBRARY_DIR = "lib.system"; public const string ADDITIONAL_LIBRARIES = "lib.additional"; + public const string LIBRARY_CACHING_KEY = "lib.caching"; public OneScriptLibraryOptions(KeyValueConfig config) : base(config) { @@ -25,10 +27,35 @@ public OneScriptLibraryOptions(KeyValueConfig config) : base(config) var addDirs = additionalDirsList.Split(';'); AdditionalLibraries = new List(addDirs); } + ScriptCachingEnabled = SetupScriptCaching(config[LIBRARY_CACHING_KEY]); } + public bool ScriptCachingEnabled { get; } + public string SystemLibraryDir { get; set; } public IEnumerable AdditionalLibraries { get; set; } + + private static bool SetupScriptCaching(string scriptCaching) + { + // По умолчанию кеширование включено + // Можно отключить, установив lib.caching=false в oscript.cfg + if (System.Environment.GetEnvironmentVariable("OS_CACHE_DEBUG") == "1") + { + SystemLogger.Write($"[CONFIG DEBUG] lib.caching value: '{scriptCaching ?? "null"}'"); + } + + if (string.IsNullOrWhiteSpace(scriptCaching)) + return true; + + var result = !StringComparer.InvariantCultureIgnoreCase.Equals(scriptCaching.Trim(), "false"); + + if (System.Environment.GetEnvironmentVariable("OS_CACHE_DEBUG") == "1") + { + SystemLogger.Write($"[CONFIG DEBUG] Caching enabled: {result}"); + } + + return result; + } } } \ No newline at end of file diff --git a/src/ScriptEngine/Compilation/SerializableModule.cs b/src/ScriptEngine/Compilation/SerializableModule.cs new file mode 100644 index 000000000..ada3beb68 --- /dev/null +++ b/src/ScriptEngine/Compilation/SerializableModule.cs @@ -0,0 +1,539 @@ +/*---------------------------------------------------------- +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; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using MessagePack; +using OneScript.Compilation.Binding; +using OneScript.Contexts; +using OneScript.Execution; +using OneScript.Sources; +using OneScript.Values; +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.Compilation +{ + /// + /// Сериализуемая версия IExecutableModule для кэширования + /// + [MessagePackObject] + public class SerializableModule + { + [Key(0)] + public int FormatVersion { get; set; } = 1; + + // Основные компоненты модуля + [Key(1)] + public SerializableConstant[] Constants { get; set; } + [Key(2)] + public SymbolBinding[] VariableRefs { get; set; } + [Key(3)] + public SymbolBinding[] MethodRefs { get; set; } + [Key(4)] + public Command[] Code { get; set; } + + // Метаданные модуля + [Key(5)] + public int EntryMethodIndex { get; set; } = -1; + [Key(6)] + public SerializableSourceCode Source { get; set; } + + // Члены модуля + [Key(7)] + public SerializableAnnotation[] ModuleAttributes { get; set; } + [Key(8)] + public SerializableFieldInfo[] Fields { get; set; } + [Key(9)] + public SerializablePropertyInfo[] Properties { get; set; } + [Key(10)] + public SerializableMethodInfo[] Methods { get; set; } + + /// + /// Создать SerializableModule из StackRuntimeModule + /// + public static SerializableModule FromExecutableModule(IExecutableModule module) + { + if (!(module is StackRuntimeModule stackModule)) + { + throw new ArgumentException("Only StackRuntimeModule is supported for serialization", nameof(module)); + } + + var serializable = new SerializableModule + { + EntryMethodIndex = stackModule.EntryMethodIndex, + Constants = stackModule.Constants.Select(SerializableConstant.FromBslValue).ToArray(), + VariableRefs = stackModule.VariableRefs.ToArray(), + MethodRefs = stackModule.MethodRefs.ToArray(), + Code = stackModule.Code.ToArray(), + Source = SerializableSourceCode.FromSourceCode(stackModule.Source), + + ModuleAttributes = stackModule.ModuleAttributes?.Select(SerializableAnnotation.FromAnnotation).ToArray() ?? new SerializableAnnotation[0], + Fields = stackModule.Fields?.Select(SerializableFieldInfo.FromFieldInfo).ToArray() ?? new SerializableFieldInfo[0], + Properties = stackModule.Properties?.Select(SerializablePropertyInfo.FromPropertyInfo).ToArray() ?? new SerializablePropertyInfo[0], + Methods = stackModule.Methods?.Select(SerializableMethodInfo.FromMethodInfo).ToArray() ?? new SerializableMethodInfo[0] + }; + + return serializable; + } + + /// + /// Восстановить StackRuntimeModule из сериализованных данных + /// + public StackRuntimeModule ToExecutableModule() + { + var module = new StackRuntimeModule(typeof(IRuntimeContextInstance)) + { + EntryMethodIndex = this.EntryMethodIndex, + Source = this.Source?.ToSourceCode() + }; + + // Восстанавливаем константы + foreach (var constant in Constants ?? new SerializableConstant[0]) + { + module.Constants.Add(constant.ToBslValue()); + } + + // Восстанавливаем ссылки + foreach (var varRef in VariableRefs ?? new SymbolBinding[0]) + { + module.VariableRefs.Add(varRef); + } + + foreach (var methodRef in MethodRefs ?? new SymbolBinding[0]) + { + module.MethodRefs.Add(methodRef); + } + + // Восстанавливаем код + foreach (var command in Code ?? new Command[0]) + { + module.Code.Add(command); + } + + // Восстанавливаем атрибуты модуля + foreach (var attr in ModuleAttributes ?? new SerializableAnnotation[0]) + { + module.ModuleAttributes.Add(attr.ToAnnotation()); + } + + // Восстанавливаем поля + foreach (var field in Fields ?? new SerializableFieldInfo[0]) + { + module.Fields.Add(field.ToFieldInfo()); + } + + // Восстанавливаем свойства + foreach (var prop in Properties ?? new SerializablePropertyInfo[0]) + { + module.Properties.Add(prop.ToPropertyInfo()); + } + + // Восстанавливаем методы + foreach (var method in Methods ?? new SerializableMethodInfo[0]) + { + module.Methods.Add(method.ToMethodInfo()); + } + + return module; + } + } + + /// + /// Сериализуемая константа + /// + [MessagePackObject] + public class SerializableConstant + { + [Key(0)] + public string Type { get; set; } + [Key(1)] + public string Value { get; set; } + + public static SerializableConstant FromBslValue(BslPrimitiveValue value) + { + return new SerializableConstant + { + Type = value.GetType().Name, + Value = value.ToString() + }; + } + + public BslPrimitiveValue ToBslValue() + { + switch (Type) + { + case nameof(BslStringValue): + return BslStringValue.Create(Value ?? ""); + case nameof(BslNumericValue): + return BslNumericValue.Create(decimal.TryParse(Value, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var num) ? num : 0); + case nameof(BslBooleanValue): + // Обработка локализованных строк для булевых значений + if (string.IsNullOrEmpty(Value)) return BslBooleanValue.False; + var trimmedValue = Value.Trim(); + var isTrue = StringComparer.OrdinalIgnoreCase.Equals(trimmedValue, "true") || + StringComparer.OrdinalIgnoreCase.Equals(trimmedValue, "да") || + StringComparer.OrdinalIgnoreCase.Equals(trimmedValue, "yes"); + return (BslPrimitiveValue)BslBooleanValue.Create(isTrue); + case nameof(BslUndefinedValue): + return BslUndefinedValue.Instance; + case nameof(BslNullValue): + return BslNullValue.Instance; + default: + throw new InvalidOperationException($"Неподдерживаемый тип значения для десериализации: {Type}"); + } + } + } + + /// + /// Сериализуемый исходный код + /// + [MessagePackObject] + public class SerializableSourceCode + { + [Key(0)] + public string Location { get; set; } + + public static SerializableSourceCode FromSourceCode(SourceCode source) + { + if (source == null) return null; + + return new SerializableSourceCode + { + Location = source.Location + }; + } + + public SourceCode ToSourceCode() + { + // Для кэширования восстанавливаем исходный код из файла + if (!string.IsNullOrEmpty(Location) && System.IO.File.Exists(Location)) + { + return SourceCodeBuilder.Create().FromFile(Location).Build(); + } + + return null; + } + } + + /// + /// Сериализуемая аннотация + /// + [MessagePackObject] + public class SerializableAnnotation + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public SerializableAnnotationParameter[] Parameters { get; set; } + + public static SerializableAnnotation FromAnnotation(BslAnnotationAttribute annotation) + { + return new SerializableAnnotation + { + Name = annotation.Name, + Parameters = annotation.Parameters?.Select(SerializableAnnotationParameter.FromParameter).ToArray() ?? new SerializableAnnotationParameter[0] + }; + } + + public BslAnnotationAttribute ToAnnotation() + { + var parameters = Parameters?.Select(p => p.ToParameter()).ToArray() ?? new BslAnnotationParameter[0]; + return new BslAnnotationAttribute(Name, parameters); + } + } + + /// + /// Сериализуемый параметр аннотации + /// + [MessagePackObject] + public class SerializableAnnotationParameter + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public string Value { get; set; } + [Key(2)] + public int ValueIndex { get; set; } + + public static SerializableAnnotationParameter FromParameter(BslAnnotationParameter parameter) + { + return new SerializableAnnotationParameter + { + Name = parameter.Name, + Value = parameter.Value?.ToString() ?? "", + ValueIndex = parameter.ConstantValueIndex + }; + } + + public static SerializableAnnotationParameter FromAnnotationParameter(AnnotationParameter parameter) + { + return new SerializableAnnotationParameter + { + Name = parameter.Name, + ValueIndex = parameter.ValueIndex + }; + } + + public BslAnnotationParameter ToParameter() + { + return new BslAnnotationParameter(Name, BslStringValue.Create(Value ?? "")) + { + ConstantValueIndex = ValueIndex + }; + } + + public AnnotationParameter ToAnnotationParameter() + { + return new AnnotationParameter + { + Name = Name, + ValueIndex = ValueIndex + }; + } + } + + /// + /// Сериализуемая информация о поле + /// + [MessagePackObject] + public class SerializableFieldInfo + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public string Alias { get; set; } + [Key(2)] + public bool IsExport { get; set; } + [Key(3)] + public int DispatchId { get; set; } + + public static SerializableFieldInfo FromFieldInfo(BslScriptFieldInfo field) + { + return new SerializableFieldInfo + { + Name = field.Name, + Alias = field.Alias, + IsExport = (field.Attributes & FieldAttributes.Public) == FieldAttributes.Public, + DispatchId = field.DispatchId + }; + } + + public BslScriptFieldInfo ToFieldInfo() + { + return BslFieldBuilder.Create() + .Name(Name) + .Alias(Alias) + .IsExported(IsExport) + .SetDispatchingIndex(DispatchId) + .Build(); + } + } + + /// + /// Сериализуемая информация о свойстве + /// + [MessagePackObject] + public class SerializablePropertyInfo + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public string Alias { get; set; } + [Key(2)] + public bool IsExport { get; set; } + [Key(3)] + public int DispatchId { get; set; } + [Key(4)] + public bool CanRead { get; set; } + [Key(5)] + public bool CanWrite { get; set; } + + public static SerializablePropertyInfo FromPropertyInfo(BslScriptPropertyInfo prop) + { + return new SerializablePropertyInfo + { + Name = prop.Name, + Alias = prop.Alias, + IsExport = prop.IsExported, + DispatchId = prop.DispatchId, + CanRead = prop.CanRead, + CanWrite = prop.CanWrite + }; + } + + public BslScriptPropertyInfo ToPropertyInfo() + { + return BslPropertyBuilder.Create() + .Name(Name) + .Alias(Alias) + .IsExported(IsExport) + .SetDispatchingIndex(DispatchId) + .CanRead(CanRead) + .CanWrite(CanWrite) + .Build(); + } + } + + /// + /// Сериализуемая информация о методе + /// + [MessagePackObject] + public class SerializableMethodInfo + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public string Alias { get; set; } + [Key(2)] + public bool IsExport { get; set; } + [Key(3)] + public int DispatchId { get; set; } + [Key(4)] + public SerializableParameterInfo[] Parameters { get; set; } + [Key(5)] + public int EntryPoint { get; set; } + [Key(6)] + public string[] LocalVariables { get; set; } + [Key(7)] + public SerializableAnnotationDefinition[] Annotations { get; set; } + [Key(8)] + public int Flags { get; set; } + + public static SerializableMethodInfo FromMethodInfo(BslScriptMethodInfo method) + { + // Для правильной сериализации используем MachineMethodInfo напрямую + if (method is MachineMethodInfo machineMethod) + { + var runtimeMethod = machineMethod.GetRuntimeMethod(); + return new SerializableMethodInfo + { + Name = runtimeMethod.Signature.Name, + Alias = runtimeMethod.Signature.Alias, + IsExport = runtimeMethod.Signature.IsExport, + DispatchId = method.DispatchId, + Parameters = runtimeMethod.Signature.Params?.Select(SerializableParameterInfo.FromParameterDefinition).ToArray() ?? new SerializableParameterInfo[0], + EntryPoint = runtimeMethod.EntryPoint, + LocalVariables = runtimeMethod.LocalVariables ?? new string[0], + Annotations = runtimeMethod.Signature.Annotations?.Select(SerializableAnnotationDefinition.FromAnnotationDefinition).ToArray() ?? new SerializableAnnotationDefinition[0], + Flags = (int)runtimeMethod.Signature.Flags + }; + } + else + { + throw new ArgumentException($"Unsupported method type: {method.GetType().Name}. Only MachineMethodInfo is supported for serialization."); + } + } + + public BslScriptMethodInfo ToMethodInfo() + { + // Создаем MachineMethod напрямую + var signature = new MethodSignature + { + Name = Name, + Alias = Alias, + Flags = (MethodFlags)Flags, + Params = Parameters?.Select(p => p.ToParameterDefinition()).ToArray() ?? new ParameterDefinition[0], + Annotations = Annotations?.Select(a => a.ToAnnotationDefinition()).ToArray() ?? new AnnotationDefinition[0] + }; + + var machineMethod = new MachineMethod + { + Signature = signature, + EntryPoint = EntryPoint, + LocalVariables = LocalVariables ?? new string[0] + }; + + return new MachineMethodInfo(machineMethod); + } + } + + /// + /// Сериализуемая информация о параметре + /// + [MessagePackObject] + public class SerializableParameterInfo + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public bool HasDefaultValue { get; set; } + [Key(2)] + public string DefaultValue { get; set; } + [Key(3)] + public bool IsByRef { get; set; } + [Key(4)] + public int DefaultValueIndex { get; set; } + [Key(5)] + public SerializableAnnotationDefinition[] Annotations { get; set; } + + public static SerializableParameterInfo FromParameterDefinition(ParameterDefinition param) + { + return new SerializableParameterInfo + { + Name = param.Name, + HasDefaultValue = param.HasDefaultValue, + DefaultValueIndex = param.DefaultValueIndex, + IsByRef = !param.IsByValue, + Annotations = param.Annotations?.Select(SerializableAnnotationDefinition.FromAnnotationDefinition).ToArray() ?? new SerializableAnnotationDefinition[0] + }; + } + + public ParameterDefinition ToParameterDefinition() + { + return new ParameterDefinition + { + Name = Name, + HasDefaultValue = HasDefaultValue, + DefaultValueIndex = DefaultValueIndex, + IsByValue = !IsByRef, + Annotations = Annotations?.Select(a => a.ToAnnotationDefinition()).ToArray() ?? new AnnotationDefinition[0] + }; + } + + + } + + /// + /// Сериализуемое определение аннотации + /// + [MessagePackObject] + public class SerializableAnnotationDefinition + { + [Key(0)] + public string Name { get; set; } + [Key(1)] + public SerializableAnnotationParameter[] Parameters { get; set; } + + public static SerializableAnnotationDefinition FromAnnotationDefinition(AnnotationDefinition annotation) + { + return new SerializableAnnotationDefinition + { + Name = annotation.Name, + Parameters = annotation.Parameters?.Select(SerializableAnnotationParameter.FromAnnotationParameter).ToArray() ?? new SerializableAnnotationParameter[0] + }; + } + + public AnnotationDefinition ToAnnotationDefinition() + { + return new AnnotationDefinition + { + Name = Name, + Parameters = Parameters?.Select(p => p.ToAnnotationParameter()).ToArray() ?? new AnnotationParameter[0] + }; + } + + public BslAnnotationAttribute ToBslAnnotation() + { + var bslParams = Parameters?.Select(p => p.ToParameter()).ToArray() ?? new BslAnnotationParameter[0]; + return new BslAnnotationAttribute(Name, bslParams); + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine/Compilation/StackRuntimeModuleSerializer.cs b/src/ScriptEngine/Compilation/StackRuntimeModuleSerializer.cs new file mode 100644 index 000000000..5fa4394f6 --- /dev/null +++ b/src/ScriptEngine/Compilation/StackRuntimeModuleSerializer.cs @@ -0,0 +1,39 @@ +/*---------------------------------------------------------- +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; +using System.IO; +using MessagePack; +using OneScript.Compilation; +using OneScript.Execution; +using ScriptEngine.Machine; + +namespace ScriptEngine.Compilation +{ + /// + /// Сериализатор модулей на основе StackRuntimeModule + /// + public class StackRuntimeModuleSerializer : IModuleSerializer + { + public void Serialize(IExecutableModule module, Stream stream) + { + var serializableModule = SerializableModule.FromExecutableModule(module); + MessagePackSerializer.Serialize(stream, serializableModule); + } + + public IExecutableModule Deserialize(Stream stream) + { + var serializableModule = MessagePackSerializer.Deserialize(stream); + return serializableModule.ToExecutableModule(); + } + + public bool CanSerialize(IExecutableModule module) + { + return module is StackRuntimeModule; + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs index 2bb6ed92a..1809c9356 100644 --- a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs +++ b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs @@ -15,6 +15,7 @@ This Source Code Form is subject to the terms of the using OneScript.Language; using OneScript.Language.SyntaxAnalysis; using OneScript.Types; +using ScriptEngine.Compilation; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using ScriptEngine.Machine.Interfaces; @@ -55,6 +56,7 @@ public static IEngineBuilder SetDefaultOptions(this IEngineBuilder builder) services.RegisterSingleton(svc => new ThrowingErrorSink(CompilerException.FromCodeError)); services.RegisterSingleton(); services.RegisterSingleton(); + services.Register(); services.RegisterScoped(); diff --git a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs index 225f4212a..0ed2bcbfe 100755 --- a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs +++ b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs @@ -27,7 +27,7 @@ public class AttachedScriptsFactory private readonly Dictionary _fileHashes; private readonly ScriptingEngine _engine; - + internal AttachedScriptsFactory(ScriptingEngine engine) { _loadedModules = new Dictionary(StringComparer.InvariantCultureIgnoreCase); @@ -172,7 +172,54 @@ public IExecutableModule CompileModuleFromSource(ICompilerFrontend compiler, Sou } } - return compiler.Compile(code, process); + // // Попытка загрузки из кэша только для файловых источников + // bool isFileBasedSource = IsFileBasedSource(code); + // if (isFileBasedSource && externalContext == null) + // { + // // Отладочная информация для диагностики проблем с кэшированием + // if (System.Environment.GetEnvironmentVariable("OS_CACHE_DEBUG") == "1") + // { + // SystemLogger.Write($"[CACHE] Attempting to load from cache: {code.Location}, enabled: {_cacheService.CachingEnabled}"); + // } + // + // if (_cacheService.TryLoadFromCache(code.Location, out var cachedModule)) + // { + // if (System.Environment.GetEnvironmentVariable("OS_CACHE_DEBUG") == "1") + // { + // SystemLogger.Write($"[CACHE] Successfully loaded from cache: {code.Location}"); + // } + // + // // Критически важно: всегда сохраняем оригинальный контекст исходного кода + // // для корректной работы относительных путей при загрузке зависимостей + // // TEMPORARILY DISABLED TO DEBUG + // /*if (cachedModule is StackRuntimeModule stackModule) + // { + // stackModule.Source = code; + // }*/ + // return cachedModule; + // } + // else if (System.Environment.GetEnvironmentVariable("OS_CACHE_DEBUG") == "1") + // { + // SystemLogger.Write($"[CACHE] No cache hit for: {code.Location}"); + // } + // } + + // Компилируем обычным способом + var module = compiler.Compile(code, process); + + // Сохраняем в кэш только для файловых источников без внешнего контекста + // if (isFileBasedSource && externalContext == null) + // { + // _cacheService.SaveToCache(code.Location, module); + // } + + return module; + } + + private bool IsFileBasedSource(SourceCode code) + { + // Проверяем, что это файловый источник (не строка) + return code.Origin is FileCodeSource && System.IO.File.Exists(code.Location); } private static AttachedScriptsFactory _instance; diff --git a/src/ScriptEngine/Machine/Core.cs b/src/ScriptEngine/Machine/Core.cs index 0403ccffe..0420868f9 100644 --- a/src/ScriptEngine/Machine/Core.cs +++ b/src/ScriptEngine/Machine/Core.cs @@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; +using MessagePack; namespace ScriptEngine.Machine { @@ -142,9 +143,12 @@ public enum OperationCode } [Serializable] + [MessagePackObject] public struct Command { + [Key(0)] public OperationCode Code; + [Key(1)] public int Argument; public override string ToString() diff --git a/src/ScriptEngine/Machine/MachineMethodInfo.cs b/src/ScriptEngine/Machine/MachineMethodInfo.cs index 6a4dd85cf..bc814147a 100644 --- a/src/ScriptEngine/Machine/MachineMethodInfo.cs +++ b/src/ScriptEngine/Machine/MachineMethodInfo.cs @@ -6,7 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Runtime.CompilerServices; +using System.Linq; using OneScript.Contexts; +using OneScript.Values; namespace ScriptEngine.Machine { @@ -14,6 +16,25 @@ internal class MachineMethodInfo : BslScriptMethodInfo { private MachineMethod _method; + // Внутренний конструктор для десериализации из кэша + internal MachineMethodInfo(MachineMethod method) : base( + method.Signature.Name, + method.Signature.Alias, + null, // declaringType - будет установлен позже + method.Signature.IsFunction ? typeof(BslValue) : typeof(void), + method.Signature.IsExport, + -1, // dispatchId - будет установлен позже + ConvertParametersForCache(method.Signature.Params), + ConvertAnnotations(method.Signature.Annotations)) + { + _method = method; + } + + public MachineMethodInfo() : base() + { + // Конструктор по умолчанию для обычного создания + } + internal void SetRuntimeParameters(int entryPoint, string[] locals) { _method = new MachineMethod @@ -26,5 +47,81 @@ internal void SetRuntimeParameters(int entryPoint, string[] locals) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal MachineMethod GetRuntimeMethod() => _method; + + /// + /// Конвертирует ParameterDefinition[] в BslParameterInfo[] для десериализации из кэша + /// Пропускает индексы значений по умолчанию для избежания IndexOutOfRangeException + /// + private static BslParameterInfo[] ConvertParametersForCache(ParameterDefinition[] parameters) + { + if (parameters == null || parameters.Length == 0) + return new BslParameterInfo[0]; + + var result = new BslParameterInfo[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + var param = parameters[i]; + var builder = new BslParameterBuilder() + .Name(param.Name) + .ByValue(!param.IsByValue) + .ParameterType(typeof(BslValue)); + + // Пропускаем значения по умолчанию при загрузке из кэша + // так как они будут восстановлены из сериализованных данных позже + + if (param.Annotations != null && param.Annotations.Length > 0) + { + var annotations = param.Annotations.Select(a => a.MakeBslAttribute()).ToArray(); + builder.SetAnnotations(annotations); + } + + result[i] = builder.Build(); + } + return result; + } + + /// + /// Конвертирует ParameterDefinition[] в BslParameterInfo[] + /// + private static BslParameterInfo[] ConvertParameters(ParameterDefinition[] parameters) + { + if (parameters == null || parameters.Length == 0) + return new BslParameterInfo[0]; + + var result = new BslParameterInfo[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + var param = parameters[i]; + var builder = new BslParameterBuilder() + .Name(param.Name) + .ByValue(!param.IsByValue) + .ParameterType(typeof(BslValue)); + + if (param.HasDefaultValue) + { + builder.CompileTimeBslConstant(param.DefaultValueIndex); + } + + if (param.Annotations != null && param.Annotations.Length > 0) + { + var annotations = param.Annotations.Select(a => a.MakeBslAttribute()).ToArray(); + builder.SetAnnotations(annotations); + } + + result[i] = builder.Build(); + } + return result; + } + + /// + /// Конвертирует AnnotationDefinition[] в BslAnnotationAttribute[] + /// + private static BslAnnotationAttribute[] ConvertAnnotations(AnnotationDefinition[] annotations) + { + if (annotations == null || annotations.Length == 0) + return new BslAnnotationAttribute[0]; + + return annotations.Select(a => a.MakeBslAttribute()).ToArray(); + } } } \ No newline at end of file diff --git a/src/ScriptEngine/OneScriptCoreOptions.cs b/src/ScriptEngine/OneScriptCoreOptions.cs index 222ef74a2..c4dc3e233 100644 --- a/src/ScriptEngine/OneScriptCoreOptions.cs +++ b/src/ScriptEngine/OneScriptCoreOptions.cs @@ -20,7 +20,7 @@ public class OneScriptCoreOptions private const string SYSTEM_LANGUAGE_KEY = "SystemLanguage"; private const string PREPROCESSOR_DEFINITIONS_KEY = "preprocessor.define"; private const string DEFAULT_RUNTIME_KEY = "runtime.default"; - + public OneScriptCoreOptions(KeyValueConfig config) { SystemLanguage = config[SYSTEM_LANGUAGE_KEY]; diff --git a/src/ScriptEngine/ScriptEngine.csproj b/src/ScriptEngine/ScriptEngine.csproj index f81d68951..c2bd8b99a 100644 --- a/src/ScriptEngine/ScriptEngine.csproj +++ b/src/ScriptEngine/ScriptEngine.csproj @@ -46,6 +46,10 @@ + + + + diff --git a/src/ScriptEngine/ScriptingEngine.cs b/src/ScriptEngine/ScriptingEngine.cs index a2b63cd9c..473f2b2aa 100644 --- a/src/ScriptEngine/ScriptingEngine.cs +++ b/src/ScriptEngine/ScriptingEngine.cs @@ -24,7 +24,7 @@ public class ScriptingEngine : IDisposable private AttachedScriptsFactory _attachedScriptsFactory; private IDebugController _debugController; private IRuntimeEnvironment _runtimeEnvironment; - + private readonly ILibraryManager _libraryManager; public ScriptingEngine(ITypeManager types, @@ -39,7 +39,7 @@ public ScriptingEngine(ITypeManager types, GlobalsManager = globals; _runtimeEnvironment = env; _libraryManager = env; - + Loader = new ScriptSourceFactory(); Services = services; ContextDiscoverer = new ContextDiscoverer(types, globals, services); diff --git a/src/Tests/DocumenterTests/DocumenterTests.csproj b/src/Tests/DocumenterTests/DocumenterTests.csproj index 0243e7bb5..b039de817 100644 --- a/src/Tests/DocumenterTests/DocumenterTests.csproj +++ b/src/Tests/DocumenterTests/DocumenterTests.csproj @@ -1,7 +1,7 @@ - + - net6.0 + $(TargetFrameworkVersion) false true 8 diff --git a/src/Tests/OneScript.HostedScript.Tests/OneScript.HostedScript.Tests.csproj b/src/Tests/OneScript.HostedScript.Tests/OneScript.HostedScript.Tests.csproj new file mode 100644 index 000000000..0632b5f71 --- /dev/null +++ b/src/Tests/OneScript.HostedScript.Tests/OneScript.HostedScript.Tests.csproj @@ -0,0 +1,38 @@ + + + + $(TargetFrameworkVersion) + + false + + Debug;Release;LinuxDebug + 10.0 + AnyCPU + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/src/Tests/OneScript.HostedScript.Tests/TestLibraryCache.cs b/src/Tests/OneScript.HostedScript.Tests/TestLibraryCache.cs new file mode 100644 index 000000000..7a07862cb --- /dev/null +++ b/src/Tests/OneScript.HostedScript.Tests/TestLibraryCache.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using FluentAssertions; +using Moq; +using OneScript.StandardLibrary.Collections; +using ScriptEngine.HostedScript; +using ScriptEngine.HostedScript.LibraryCache; +using ScriptEngine.Hosting; +using Xunit; + +namespace OneScript.HostedScript.Tests; + +public class TestLibraryCache +{ + [Fact] + public void TestChecksValidityWhenReading() + { + var cacheMock = new Mock(); + cacheMock.Setup(s => s.Exists(It.Is(v => v == "key"))).Returns(true); + cacheMock.Setup(s => s.IsValid(It.Is(v => v == "key"))).Returns(true); + + var cacheService = new DefaultScriptCacheService(cacheMock.Object, + new OneScriptLibraryOptions( + new KeyValueConfig(new Dictionary(){{"lib.caching", "true"}})) + ); + + var readResult = cacheService.TryLoadFromCache("key", out _); + cacheMock.Verify(s => s.IsValid(It.Is(v => v == "key")), Times.Once); + readResult.Should().BeTrue(); + } +} \ No newline at end of file diff --git a/src/Tests/OneScript.Language.Tests/ParserTests.cs b/src/Tests/OneScript.Language.Tests/ParserTests.cs index 0735437a9..df02a0f01 100644 --- a/src/Tests/OneScript.Language.Tests/ParserTests.cs +++ b/src/Tests/OneScript.Language.Tests/ParserTests.cs @@ -958,6 +958,46 @@ public void Check_AstDirectives_Creation() batch.NoMoreChildren(); } + [Fact] + public void CanHaveCommentAfterUseStatement() + { + var code = @" + #Использовать Библиотека // Подключаем библиотеку + #Использовать ""Библиотека с кавычками"" // Подключаем библиотеку с кавычками + "; + + var defaultLex = new DefaultLexer(); + defaultLex.Iterator = SourceCodeHelper.FromString(code).CreateIterator(); + + var lexer = new PreprocessingLexer(defaultLex); + + lexer.Handlers = new PreprocessorHandlers( + new[] {new ImportDirectivesHandler(new ThrowingErrorSink())}); + + var parser = new DefaultBslParser( + lexer, + new ListErrorSink(), + lexer.Handlers); + + var moduleNode = parser.ParseStatefulModule(); + moduleNode.Should().NotBeNull(); + parser.Errors.Should().BeEmpty("the valid code is passed"); + var firstChild = new SyntaxTreeValidator(new TestAstNode(moduleNode.Children.First())); + + var batch = new SyntaxTreeValidator(new TestAstNode(firstChild.CurrentNode.RealNode.Parent)); + + var node = batch.NextChild(); + node.Is(NodeKind.Import) + .Equal("Использовать"); + node.NextChild().Is(NodeKind.AnnotationParameter) + .Equal("Библиотека"); + + node = batch.NextChild(); + node.Is(NodeKind.Import) + .Equal("Использовать"); + node.NextChild().Is(NodeKind.AnnotationParameter) + .Equal("\"Библиотека с кавычками\""); + } [Fact] public void Check_No_Semicolon_In_If() diff --git a/src/Tests/OneScript.Language.Tests/TestAstNode.cs b/src/Tests/OneScript.Language.Tests/TestAstNode.cs index e909e7952..888c99cf0 100644 --- a/src/Tests/OneScript.Language.Tests/TestAstNode.cs +++ b/src/Tests/OneScript.Language.Tests/TestAstNode.cs @@ -31,6 +31,7 @@ public TestAstNode(BslSyntaxNode node) BinaryOperationNode binary => binary.Operation.ToString(), UnaryOperationNode unary => unary.Operation.ToString(), PreprocessorDirectiveNode preproc => preproc.DirectiveName, + AnnotationParameterNode annParam => annParam.Value.Content, _ => nonTerm.ToString() }; } diff --git a/src/Tests/OneScript.StandardLibrary.Tests/FileBackingStreamTest.cs b/src/Tests/OneScript.StandardLibrary.Tests/FileBackingStreamTest.cs index 0387cafe2..53079bd19 100644 --- a/src/Tests/OneScript.StandardLibrary.Tests/FileBackingStreamTest.cs +++ b/src/Tests/OneScript.StandardLibrary.Tests/FileBackingStreamTest.cs @@ -5,211 +5,216 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.IO; +using Xunit; using FluentAssertions; using OneScript.StandardLibrary.Binary; -namespace OneScript.StandardLibrary.Tests; - -public class FileBackingStreamTest +namespace OneScript.StandardLibrary.Tests { - [Fact] - public void CanDoBasicReadWithMemory() - { - using var stream = new FileBackingStream(10); - stream.Write(new byte[]{1,2,3,4,5}); - - stream.Position = 0; - stream.Position.Should().Be(0); - stream.HasBackingFile.Should().BeFalse(); - stream.Length.Should().Be(5); - - var dest = new byte[5]; - var size = stream.Read(dest, 0, 5); - size.Should().Be(5); - dest.Should().Equal(1, 2, 3, 4, 5); - } - - [Fact] - public void CanDoBasicReadWithFile() + public class FileBackingStreamTest { - using var stream = new FileBackingStream(10); - stream.SwitchToFile(); - stream.Write(new byte[]{1,2,3,4,5}); - - stream.Position = 0; - stream.Position.Should().Be(0); - stream.HasBackingFile.Should().BeTrue(); - stream.Length.Should().Be(5); - - var dest = new byte[5]; - var size = stream.Read(dest, 0, 5); - size.Should().Be(5); - dest.Should().Equal(1, 2, 3, 4, 5); - } + [Fact] + public void CanDoBasicReadWithMemory() + { + using var stream = new FileBackingStream(10); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); - [Fact] - public void GrowsOnWriteToEnd() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5}); - stream.HasBackingFile.Should().BeFalse(); - stream.Position.Should().Be(5); - - stream.Write(new byte[]{1,2,3,4,5}); - stream.HasBackingFile.Should().BeTrue(); - stream.Position.Should().Be(10); - stream.Length.Should().Be(10); - - EnsureContent(stream, new byte[]{1,2,3,4,5,1,2,3,4,5}); - } - - [Fact] - public void GrowsOnWriteToMiddle() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5}); - stream.Position = 2; - stream.HasBackingFile.Should().BeFalse(); - - stream.Write(new byte[]{6,6,6,6,6}); - stream.HasBackingFile.Should().BeTrue(); - stream.Position.Should().Be(7); - stream.Length.Should().Be(7); - - EnsureContent(stream, new byte[]{1,2,6,6,6,6,6}); - } - - [Fact] - public void GrowsOnWriteToStart() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5}); - stream.Position = 0; - stream.HasBackingFile.Should().BeFalse(); - - stream.Write(new byte[]{7,6,5,4,3,2,1}); - stream.HasBackingFile.Should().BeTrue(); - stream.Position.Should().Be(7); - stream.Length.Should().Be(7); - - EnsureContent(stream, new byte[]{7,6,5,4,3,2,1}); - } - - [Fact] - public void DoesNotGrowOnWriteInsideLimit() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5}); - stream.Position = 2; - stream.HasBackingFile.Should().BeFalse(); - - stream.Write(new byte[]{0,0,0}); - stream.HasBackingFile.Should().BeFalse(); - stream.Position.Should().Be(5); - stream.Length.Should().Be(5); - - EnsureContent(stream, new byte[]{1,2,0,0,0}); - } - - [Fact] - public void CanCropIntoMemoryAgain() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5,6,7,8,9,10}); - stream.HasBackingFile.Should().BeTrue(); - stream.Length.Should().Be(10); - stream.SetLength(5); - stream.HasBackingFile.Should().BeFalse(); - - EnsureContent(stream, new byte[]{1,2,3,4,5}); - } - - [Fact] - public void SettingLengthBeyondLimitSwitchesToFile() - { - using var stream = new FileBackingStream(5); - stream.HasBackingFile.Should().BeFalse(); - stream.SetLength(15); - stream.HasBackingFile.Should().BeTrue(); - } - - [Fact] - public void ThrowsWhenCantSwitchIntoMemory() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5,6,7,8,9,10}); - stream.HasBackingFile.Should().BeTrue(); - - Assert.Throws(() => stream.SwitchToMemory()); - } + stream.Position = 0; + stream.Position.Should().Be(0); + stream.HasBackingFile.Should().BeFalse(); + stream.Length.Should().Be(5); - [Fact] - public void SetPositionBeyondLength() - { - using var stream = new FileBackingStream(5); - stream.Position = 10; - - stream.Length.Should().Be(0); - stream.HasBackingFile.Should().BeFalse(); - - stream.Write(new byte[]{1,2,3}); - stream.Position.Should().Be(13); - stream.Length.Should().Be(13); - stream.HasBackingFile.Should().BeTrue(); - } + var dest = new byte[5]; + var size = stream.Read(dest, 0, 5); + size.Should().Be(5); + dest.Should().Equal(1, 2, 3, 4, 5); + } - [Fact] - public void TempFileGetsDeletedOnClose() - { - using var stream = new FileBackingStream(5); - stream.Write(new byte[]{1,2,3,4,5,6,7,8,9,10}); - stream.HasBackingFile.Should().BeTrue(); - var tempFile = stream.FileName; - - stream.SetLength(4); - stream.HasBackingFile.Should().BeFalse(); - File.Exists(tempFile).Should().BeFalse(); - } + [Fact] + public void CanDoBasicReadWithFile() + { + using var stream = new FileBackingStream(10); + stream.SwitchToFile(); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); - private void EnsureContent(Stream stream, IEnumerable expected) - { - stream.Position = 0; - var actual = new byte[stream.Length]; - stream.Read(actual).Should().Be((int)stream.Length); + stream.Position = 0; + stream.Position.Should().Be(0); + stream.HasBackingFile.Should().BeTrue(); + stream.Length.Should().Be(5); - actual.Should().Equal(expected); - } - - [Fact(Skip = "Platform test")] - public void SetPositionBeyondMemoryStream() - { - using var ms = new MemoryStream(); - ms.Position = 10; - - ms.Length.Should().Be(0); - ms.Write(new byte[]{1,2,3}); - ms.Position.Should().Be(13); - ms.Length.Should().Be(13); - } - - [Fact(Skip = "Platform test")] - public void SetPositionBeyondFileStream() - { - var path = Path.GetTempFileName(); - var fs = new FileStream(path, FileMode.Create); - try + var dest = new byte[5]; + var size = stream.Read(dest, 0, 5); + size.Should().Be(5); + dest.Should().Equal(1, 2, 3, 4, 5); + } + + [Fact] + public void GrowsOnWriteToEnd() + { + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); + stream.HasBackingFile.Should().BeFalse(); + stream.Position.Should().Be(5); + + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); + stream.HasBackingFile.Should().BeTrue(); + stream.Position.Should().Be(10); + stream.Length.Should().Be(10); + + EnsureContent(stream, new byte[] { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }); + } + + [Fact] + public void GrowsOnWriteToMiddle() + { + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); + stream.Position = 2; + stream.HasBackingFile.Should().BeFalse(); + + stream.Write(new byte[] { 6, 6, 6, 6, 6 }); + stream.HasBackingFile.Should().BeTrue(); + stream.Position.Should().Be(7); + stream.Length.Should().Be(7); + + EnsureContent(stream, new byte[] { 1, 2, 6, 6, 6, 6, 6 }); + } + + [Fact] + public void GrowsOnWriteToStart() + { + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); + stream.Position = 0; + stream.HasBackingFile.Should().BeFalse(); + + stream.Write(new byte[] { 7, 6, 5, 4, 3, 2, 1 }); + stream.HasBackingFile.Should().BeTrue(); + stream.Position.Should().Be(7); + stream.Length.Should().Be(7); + + EnsureContent(stream, new byte[] { 7, 6, 5, 4, 3, 2, 1 }); + } + + [Fact] + public void DoesNotGrowOnWriteInsideLimit() + { + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5 }); + stream.Position = 2; + stream.HasBackingFile.Should().BeFalse(); + + stream.Write(new byte[] { 0, 0, 0 }); + stream.HasBackingFile.Should().BeFalse(); + stream.Position.Should().Be(5); + stream.Length.Should().Be(5); + + EnsureContent(stream, new byte[] { 1, 2, 0, 0, 0 }); + } + + [Fact] + public void CanCropIntoMemoryAgain() { - fs.Position = 10; + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + stream.HasBackingFile.Should().BeTrue(); + stream.Length.Should().Be(10); + stream.SetLength(5); + stream.HasBackingFile.Should().BeFalse(); + + EnsureContent(stream, new byte[] { 1, 2, 3, 4, 5 }); + } - fs.Length.Should().Be(0); - fs.Write(new byte[] { 1, 2, 3 }); - fs.Position.Should().Be(13); - fs.Length.Should().Be(13); + [Fact] + public void SettingLengthBeyondLimitSwitchesToFile() + { + using var stream = new FileBackingStream(5); + stream.HasBackingFile.Should().BeFalse(); + stream.SetLength(15); + stream.HasBackingFile.Should().BeTrue(); } - finally + + [Fact] + public void ThrowsWhenCantSwitchIntoMemory() { - fs.Close(); - File.Delete(path); + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + stream.HasBackingFile.Should().BeTrue(); + + Assert.Throws(() => stream.SwitchToMemory()); + } + + [Fact] + public void SetPositionBeyondLength() + { + using var stream = new FileBackingStream(5); + stream.Position = 10; + + stream.Length.Should().Be(0); + stream.HasBackingFile.Should().BeFalse(); + + stream.Write(new byte[] { 1, 2, 3 }); + stream.Position.Should().Be(13); + stream.Length.Should().Be(13); + stream.HasBackingFile.Should().BeTrue(); + } + + [Fact] + public void TempFileGetsDeletedOnClose() + { + using var stream = new FileBackingStream(5); + stream.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + stream.HasBackingFile.Should().BeTrue(); + var tempFile = stream.FileName; + + stream.SetLength(4); + stream.HasBackingFile.Should().BeFalse(); + File.Exists(tempFile).Should().BeFalse(); + } + + private void EnsureContent(Stream stream, IEnumerable expected) + { + stream.Position = 0; + var actual = new byte[stream.Length]; + stream.Read(actual).Should().Be((int)stream.Length); + + actual.Should().Equal(expected); + } + + [Fact(Skip = "Platform test")] + public void SetPositionBeyondMemoryStream() + { + using var ms = new MemoryStream(); + ms.Position = 10; + + ms.Length.Should().Be(0); + ms.Write(new byte[] { 1, 2, 3 }); + ms.Position.Should().Be(13); + ms.Length.Should().Be(13); + } + + [Fact(Skip = "Platform test")] + public void SetPositionBeyondFileStream() + { + var path = Path.GetTempFileName(); + var fs = new FileStream(path, FileMode.Create); + try + { + fs.Position = 10; + + fs.Length.Should().Be(0); + fs.Write(new byte[] { 1, 2, 3 }); + fs.Position.Should().Be(13); + fs.Length.Should().Be(13); + } + finally + { + fs.Close(); + File.Delete(path); + } } } } \ No newline at end of file diff --git a/src/Tests/OneScript.StandardLibrary.Tests/OneScript.StandardLibrary.Tests.csproj b/src/Tests/OneScript.StandardLibrary.Tests/OneScript.StandardLibrary.Tests.csproj index b7a0eb835..c1249e061 100644 --- a/src/Tests/OneScript.StandardLibrary.Tests/OneScript.StandardLibrary.Tests.csproj +++ b/src/Tests/OneScript.StandardLibrary.Tests/OneScript.StandardLibrary.Tests.csproj @@ -1,8 +1,7 @@ - + - net6.0 - enable + $(TargetFrameworkVersion) enable false diff --git a/src/Tests/OneScript.StandardLibrary.Tests/Usings.cs b/src/Tests/OneScript.StandardLibrary.Tests/Usings.cs deleted file mode 100644 index 6c43b7315..000000000 --- a/src/Tests/OneScript.StandardLibrary.Tests/Usings.cs +++ /dev/null @@ -1,8 +0,0 @@ -/*---------------------------------------------------------- -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/. -----------------------------------------------------------*/ - -global using Xunit; \ No newline at end of file diff --git a/src/oscommon.targets b/src/oscommon.targets index d3ab44f69..2268a19aa 100644 --- a/src/oscommon.targets +++ b/src/oscommon.targets @@ -10,6 +10,7 @@ net6.0 $(NoWarn);CS1591 False + disable diff --git a/tests/XDTO/test-XDTOSerializer.os.metadata.json b/tests/XDTO/test-XDTOSerializer.os.metadata.json new file mode 100644 index 000000000..a90366d69 --- /dev/null +++ b/tests/XDTO/test-XDTOSerializer.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 22658, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XDTO/test-XDTOSerializer.os", + "CacheCreatedTime": "2025-06-28T06:53:10.0648381Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XDTO/test-XDTOSerializer.os.obj b/tests/XDTO/test-XDTOSerializer.os.obj new file mode 100644 index 000000000..2a0a3d370 Binary files /dev/null and b/tests/XDTO/test-XDTOSerializer.os.obj differ diff --git a/tests/XML/test-XMLExpandedName.os.metadata.json b/tests/XML/test-XMLExpandedName.os.metadata.json new file mode 100644 index 000000000..3ecb115e7 --- /dev/null +++ b/tests/XML/test-XMLExpandedName.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 2551, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XML/test-XMLExpandedName.os", + "CacheCreatedTime": "2025-06-28T06:53:10.3719202Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XML/test-XMLExpandedName.os.obj b/tests/XML/test-XMLExpandedName.os.obj new file mode 100644 index 000000000..9db15daa0 Binary files /dev/null and b/tests/XML/test-XMLExpandedName.os.obj differ diff --git a/tests/XMLSchema/Collections/test-XSComponentFixedList.os.metadata.json b/tests/XMLSchema/Collections/test-XSComponentFixedList.os.metadata.json new file mode 100644 index 000000000..822230a8e --- /dev/null +++ b/tests/XMLSchema/Collections/test-XSComponentFixedList.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 2276, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Collections/test-XSComponentFixedList.os", + "CacheCreatedTime": "2025-06-28T06:53:10.268174Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Collections/test-XSComponentFixedList.os.obj b/tests/XMLSchema/Collections/test-XSComponentFixedList.os.obj new file mode 100644 index 000000000..ac140c785 Binary files /dev/null and b/tests/XMLSchema/Collections/test-XSComponentFixedList.os.obj differ diff --git a/tests/XMLSchema/Collections/test-XSComponentList.os.metadata.json b/tests/XMLSchema/Collections/test-XSComponentList.os.metadata.json new file mode 100644 index 000000000..f9b29c7d4 --- /dev/null +++ b/tests/XMLSchema/Collections/test-XSComponentList.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 6346, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Collections/test-XSComponentList.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2705732Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Collections/test-XSComponentList.os.obj b/tests/XMLSchema/Collections/test-XSComponentList.os.obj new file mode 100644 index 000000000..b41f59445 Binary files /dev/null and b/tests/XMLSchema/Collections/test-XSComponentList.os.obj differ diff --git a/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.metadata.json b/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.metadata.json new file mode 100644 index 000000000..f1ab8c295 --- /dev/null +++ b/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 3083, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Collections/test-XSNamedComponentMap.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2662325Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.obj b/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.obj new file mode 100644 index 000000000..cc1466f20 Binary files /dev/null and b/tests/XMLSchema/Collections/test-XSNamedComponentMap.os.obj differ diff --git a/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.metadata.json b/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.metadata.json new file mode 100644 index 000000000..fcfaa5ef2 --- /dev/null +++ b/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 2649, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2503597Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.obj b/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.obj new file mode 100644 index 000000000..9e0ddd9b7 Binary files /dev/null and b/tests/XMLSchema/Enumerations/test-XSDisallowedSubstitutions.os.obj differ diff --git a/tests/XMLSchema/Enumerations/test-XSForm.os.metadata.json b/tests/XMLSchema/Enumerations/test-XSForm.os.metadata.json new file mode 100644 index 000000000..d240ba291 --- /dev/null +++ b/tests/XMLSchema/Enumerations/test-XSForm.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 1835, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Enumerations/test-XSForm.os", + "CacheCreatedTime": "2025-06-28T06:53:10.24849Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Enumerations/test-XSForm.os.obj b/tests/XMLSchema/Enumerations/test-XSForm.os.obj new file mode 100644 index 000000000..738d3a2c0 Binary files /dev/null and b/tests/XMLSchema/Enumerations/test-XSForm.os.obj differ diff --git a/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.metadata.json b/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.metadata.json new file mode 100644 index 000000000..eebcc1c58 --- /dev/null +++ b/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 2716, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2448326Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.obj b/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.obj new file mode 100644 index 000000000..ad2a25733 Binary files /dev/null and b/tests/XMLSchema/Enumerations/test-XSSchemaFinal.os.obj differ diff --git a/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.metadata.json b/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.metadata.json new file mode 100644 index 000000000..366cc9f7d --- /dev/null +++ b/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9311571+00:00", + "SourceSize": 2553, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2467352Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.obj b/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.obj new file mode 100644 index 000000000..767a4d73a Binary files /dev/null and b/tests/XMLSchema/Enumerations/test-XSSimpleFinal.os.obj differ diff --git a/tests/XMLSchema/test-XMLSchema.os.metadata.json b/tests/XMLSchema/test-XMLSchema.os.metadata.json new file mode 100644 index 000000000..b2fe15095 --- /dev/null +++ b/tests/XMLSchema/test-XMLSchema.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 18196, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XMLSchema.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2871023Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XMLSchema.os.obj b/tests/XMLSchema/test-XMLSchema.os.obj new file mode 100644 index 000000000..4f1922f59 Binary files /dev/null and b/tests/XMLSchema/test-XMLSchema.os.obj differ diff --git a/tests/XMLSchema/test-XSAnnotation.os.metadata.json b/tests/XMLSchema/test-XSAnnotation.os.metadata.json new file mode 100644 index 000000000..f92af1bfe --- /dev/null +++ b/tests/XMLSchema/test-XSAnnotation.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3391, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSAnnotation.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2642476Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSAnnotation.os.obj b/tests/XMLSchema/test-XSAnnotation.os.obj new file mode 100644 index 000000000..3d92263db Binary files /dev/null and b/tests/XMLSchema/test-XSAnnotation.os.obj differ diff --git a/tests/XMLSchema/test-XSAppInfo.os.metadata.json b/tests/XMLSchema/test-XSAppInfo.os.metadata.json new file mode 100644 index 000000000..05ce089a5 --- /dev/null +++ b/tests/XMLSchema/test-XSAppInfo.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 1999, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSAppInfo.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2812058Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSAppInfo.os.obj b/tests/XMLSchema/test-XSAppInfo.os.obj new file mode 100644 index 000000000..e882df8cc Binary files /dev/null and b/tests/XMLSchema/test-XSAppInfo.os.obj differ diff --git a/tests/XMLSchema/test-XSAttributeDeclaration.os.metadata.json b/tests/XMLSchema/test-XSAttributeDeclaration.os.metadata.json new file mode 100644 index 000000000..d9d97618b --- /dev/null +++ b/tests/XMLSchema/test-XSAttributeDeclaration.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3213, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSAttributeDeclaration.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2895678Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSAttributeDeclaration.os.obj b/tests/XMLSchema/test-XSAttributeDeclaration.os.obj new file mode 100644 index 000000000..466c7c574 Binary files /dev/null and b/tests/XMLSchema/test-XSAttributeDeclaration.os.obj differ diff --git a/tests/XMLSchema/test-XSAttributeGroupDefinition.os.metadata.json b/tests/XMLSchema/test-XSAttributeGroupDefinition.os.metadata.json new file mode 100644 index 000000000..f31c0ce99 --- /dev/null +++ b/tests/XMLSchema/test-XSAttributeGroupDefinition.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 5735, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSAttributeGroupDefinition.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2425396Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSAttributeGroupDefinition.os.obj b/tests/XMLSchema/test-XSAttributeGroupDefinition.os.obj new file mode 100644 index 000000000..39707e160 Binary files /dev/null and b/tests/XMLSchema/test-XSAttributeGroupDefinition.os.obj differ diff --git a/tests/XMLSchema/test-XSComplexTypeDefinition.os.metadata.json b/tests/XMLSchema/test-XSComplexTypeDefinition.os.metadata.json new file mode 100644 index 000000000..8fa0dffd2 --- /dev/null +++ b/tests/XMLSchema/test-XSComplexTypeDefinition.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4012, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSComplexTypeDefinition.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2399762Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSComplexTypeDefinition.os.obj b/tests/XMLSchema/test-XSComplexTypeDefinition.os.obj new file mode 100644 index 000000000..54bb809ab Binary files /dev/null and b/tests/XMLSchema/test-XSComplexTypeDefinition.os.obj differ diff --git a/tests/XMLSchema/test-XSDocumentation.os.metadata.json b/tests/XMLSchema/test-XSDocumentation.os.metadata.json new file mode 100644 index 000000000..7a1071901 --- /dev/null +++ b/tests/XMLSchema/test-XSDocumentation.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 2291, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSDocumentation.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2522135Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSDocumentation.os.obj b/tests/XMLSchema/test-XSDocumentation.os.obj new file mode 100644 index 000000000..20fb501eb Binary files /dev/null and b/tests/XMLSchema/test-XSDocumentation.os.obj differ diff --git a/tests/XMLSchema/test-XSElementDeclaration.os.metadata.json b/tests/XMLSchema/test-XSElementDeclaration.os.metadata.json new file mode 100644 index 000000000..ada6426f6 --- /dev/null +++ b/tests/XMLSchema/test-XSElementDeclaration.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 6272, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSElementDeclaration.os", + "CacheCreatedTime": "2025-06-28T06:53:10.3025502Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSElementDeclaration.os.obj b/tests/XMLSchema/test-XSElementDeclaration.os.obj new file mode 100644 index 000000000..09cd4afd9 Binary files /dev/null and b/tests/XMLSchema/test-XSElementDeclaration.os.obj differ diff --git a/tests/XMLSchema/test-XSEnumerationFacet.os.metadata.json b/tests/XMLSchema/test-XSEnumerationFacet.os.metadata.json new file mode 100644 index 000000000..68e61f276 --- /dev/null +++ b/tests/XMLSchema/test-XSEnumerationFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4475, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSEnumerationFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2961329Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSEnumerationFacet.os.obj b/tests/XMLSchema/test-XSEnumerationFacet.os.obj new file mode 100644 index 000000000..bf6b7639d Binary files /dev/null and b/tests/XMLSchema/test-XSEnumerationFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSFractionDigitsFacet.os.metadata.json b/tests/XMLSchema/test-XSFractionDigitsFacet.os.metadata.json new file mode 100644 index 000000000..9b544c63a --- /dev/null +++ b/tests/XMLSchema/test-XSFractionDigitsFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3559, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSFractionDigitsFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2374655Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSFractionDigitsFacet.os.obj b/tests/XMLSchema/test-XSFractionDigitsFacet.os.obj new file mode 100644 index 000000000..20d1dc79c Binary files /dev/null and b/tests/XMLSchema/test-XSFractionDigitsFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.metadata.json b/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.metadata.json new file mode 100644 index 000000000..994df3f63 --- /dev/null +++ b/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3133, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSIdentityConstraintDefinition.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2793708Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.obj b/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.obj new file mode 100644 index 000000000..bedb627c0 Binary files /dev/null and b/tests/XMLSchema/test-XSIdentityConstraintDefinition.os.obj differ diff --git a/tests/XMLSchema/test-XSImport.os.metadata.json b/tests/XMLSchema/test-XSImport.os.metadata.json new file mode 100644 index 000000000..56995d023 --- /dev/null +++ b/tests/XMLSchema/test-XSImport.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 2202, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSImport.os", + "CacheCreatedTime": "2025-06-28T06:53:10.262227Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSImport.os.obj b/tests/XMLSchema/test-XSImport.os.obj new file mode 100644 index 000000000..404d0fd07 Binary files /dev/null and b/tests/XMLSchema/test-XSImport.os.obj differ diff --git a/tests/XMLSchema/test-XSInclude.os.metadata.json b/tests/XMLSchema/test-XSInclude.os.metadata.json new file mode 100644 index 000000000..4f39c3f9c --- /dev/null +++ b/tests/XMLSchema/test-XSInclude.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 1808, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSInclude.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2603776Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSInclude.os.obj b/tests/XMLSchema/test-XSInclude.os.obj new file mode 100644 index 000000000..59619328b Binary files /dev/null and b/tests/XMLSchema/test-XSInclude.os.obj differ diff --git a/tests/XMLSchema/test-XSLengthFacet.os.metadata.json b/tests/XMLSchema/test-XSLengthFacet.os.metadata.json new file mode 100644 index 000000000..05de94c1f --- /dev/null +++ b/tests/XMLSchema/test-XSLengthFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3329, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSLengthFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.3000347Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSLengthFacet.os.obj b/tests/XMLSchema/test-XSLengthFacet.os.obj new file mode 100644 index 000000000..d3c4d45b9 Binary files /dev/null and b/tests/XMLSchema/test-XSLengthFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMaxExclusiveFacet.os.metadata.json b/tests/XMLSchema/test-XSMaxExclusiveFacet.os.metadata.json new file mode 100644 index 000000000..db5be9b6a --- /dev/null +++ b/tests/XMLSchema/test-XSMaxExclusiveFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4799, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMaxExclusiveFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2938979Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMaxExclusiveFacet.os.obj b/tests/XMLSchema/test-XSMaxExclusiveFacet.os.obj new file mode 100644 index 000000000..d7b3738dd Binary files /dev/null and b/tests/XMLSchema/test-XSMaxExclusiveFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMaxInclusiveFacet.os.metadata.json b/tests/XMLSchema/test-XSMaxInclusiveFacet.os.metadata.json new file mode 100644 index 000000000..5cd61f505 --- /dev/null +++ b/tests/XMLSchema/test-XSMaxInclusiveFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4787, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMaxInclusiveFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2543631Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMaxInclusiveFacet.os.obj b/tests/XMLSchema/test-XSMaxInclusiveFacet.os.obj new file mode 100644 index 000000000..1c8a392b1 Binary files /dev/null and b/tests/XMLSchema/test-XSMaxInclusiveFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMaxLengthFacet.os.metadata.json b/tests/XMLSchema/test-XSMaxLengthFacet.os.metadata.json new file mode 100644 index 000000000..dad9a773c --- /dev/null +++ b/tests/XMLSchema/test-XSMaxLengthFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3388, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMaxLengthFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2564548Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMaxLengthFacet.os.obj b/tests/XMLSchema/test-XSMaxLengthFacet.os.obj new file mode 100644 index 000000000..649b76513 Binary files /dev/null and b/tests/XMLSchema/test-XSMaxLengthFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMinExclusiveFacet.os.metadata.json b/tests/XMLSchema/test-XSMinExclusiveFacet.os.metadata.json new file mode 100644 index 000000000..05a9c20f3 --- /dev/null +++ b/tests/XMLSchema/test-XSMinExclusiveFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4787, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMinExclusiveFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2351678Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMinExclusiveFacet.os.obj b/tests/XMLSchema/test-XSMinExclusiveFacet.os.obj new file mode 100644 index 000000000..aacb254d9 Binary files /dev/null and b/tests/XMLSchema/test-XSMinExclusiveFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMinInclusiveFacet.os.metadata.json b/tests/XMLSchema/test-XSMinInclusiveFacet.os.metadata.json new file mode 100644 index 000000000..e4edf7fbc --- /dev/null +++ b/tests/XMLSchema/test-XSMinInclusiveFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 4775, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMinInclusiveFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2328985Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMinInclusiveFacet.os.obj b/tests/XMLSchema/test-XSMinInclusiveFacet.os.obj new file mode 100644 index 000000000..50657eb64 Binary files /dev/null and b/tests/XMLSchema/test-XSMinInclusiveFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSMinLengthFacet.os.metadata.json b/tests/XMLSchema/test-XSMinLengthFacet.os.metadata.json new file mode 100644 index 000000000..67756078f --- /dev/null +++ b/tests/XMLSchema/test-XSMinLengthFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3376, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSMinLengthFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2727617Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSMinLengthFacet.os.obj b/tests/XMLSchema/test-XSMinLengthFacet.os.obj new file mode 100644 index 000000000..4795f8871 Binary files /dev/null and b/tests/XMLSchema/test-XSMinLengthFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSModelGroup.os.metadata.json b/tests/XMLSchema/test-XSModelGroup.os.metadata.json new file mode 100644 index 000000000..bb6158d2b --- /dev/null +++ b/tests/XMLSchema/test-XSModelGroup.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3098, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSModelGroup.os", + "CacheCreatedTime": "2025-06-28T06:53:10.3049517Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSModelGroup.os.obj b/tests/XMLSchema/test-XSModelGroup.os.obj new file mode 100644 index 000000000..52b9a0d78 Binary files /dev/null and b/tests/XMLSchema/test-XSModelGroup.os.obj differ diff --git a/tests/XMLSchema/test-XSNotationDeclaration.os.metadata.json b/tests/XMLSchema/test-XSNotationDeclaration.os.metadata.json new file mode 100644 index 000000000..1dae9fd37 --- /dev/null +++ b/tests/XMLSchema/test-XSNotationDeclaration.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3312, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSNotationDeclaration.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2916422Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSNotationDeclaration.os.obj b/tests/XMLSchema/test-XSNotationDeclaration.os.obj new file mode 100644 index 000000000..34cacc05f Binary files /dev/null and b/tests/XMLSchema/test-XSNotationDeclaration.os.obj differ diff --git a/tests/XMLSchema/test-XSParticle.os.metadata.json b/tests/XMLSchema/test-XSParticle.os.metadata.json new file mode 100644 index 000000000..aa8699255 --- /dev/null +++ b/tests/XMLSchema/test-XSParticle.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3144, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSParticle.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2584949Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSParticle.os.obj b/tests/XMLSchema/test-XSParticle.os.obj new file mode 100644 index 000000000..76bfbd657 Binary files /dev/null and b/tests/XMLSchema/test-XSParticle.os.obj differ diff --git a/tests/XMLSchema/test-XSPatternFacet.os.metadata.json b/tests/XMLSchema/test-XSPatternFacet.os.metadata.json new file mode 100644 index 000000000..d057efdbd --- /dev/null +++ b/tests/XMLSchema/test-XSPatternFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3401, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSPatternFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2772945Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSPatternFacet.os.obj b/tests/XMLSchema/test-XSPatternFacet.os.obj new file mode 100644 index 000000000..035b941c8 Binary files /dev/null and b/tests/XMLSchema/test-XSPatternFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSRedefine.os.metadata.json b/tests/XMLSchema/test-XSRedefine.os.metadata.json new file mode 100644 index 000000000..349e967d9 --- /dev/null +++ b/tests/XMLSchema/test-XSRedefine.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 1291, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSRedefine.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2979634Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSRedefine.os.obj b/tests/XMLSchema/test-XSRedefine.os.obj new file mode 100644 index 000000000..a7f6356e3 Binary files /dev/null and b/tests/XMLSchema/test-XSRedefine.os.obj differ diff --git a/tests/XMLSchema/test-XSSimpleTypeDefinition.os.metadata.json b/tests/XMLSchema/test-XSSimpleTypeDefinition.os.metadata.json new file mode 100644 index 000000000..bb614bc78 --- /dev/null +++ b/tests/XMLSchema/test-XSSimpleTypeDefinition.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 6515, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSSimpleTypeDefinition.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2751695Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSSimpleTypeDefinition.os.obj b/tests/XMLSchema/test-XSSimpleTypeDefinition.os.obj new file mode 100644 index 000000000..9f6816536 Binary files /dev/null and b/tests/XMLSchema/test-XSSimpleTypeDefinition.os.obj differ diff --git a/tests/XMLSchema/test-XSTotalDigitsFacet.os.metadata.json b/tests/XMLSchema/test-XSTotalDigitsFacet.os.metadata.json new file mode 100644 index 000000000..74404efc7 --- /dev/null +++ b/tests/XMLSchema/test-XSTotalDigitsFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 3478, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSTotalDigitsFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2305407Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSTotalDigitsFacet.os.obj b/tests/XMLSchema/test-XSTotalDigitsFacet.os.obj new file mode 100644 index 000000000..8d3f1f8f1 Binary files /dev/null and b/tests/XMLSchema/test-XSTotalDigitsFacet.os.obj differ diff --git a/tests/XMLSchema/test-XSWhitespaceFacet.os.metadata.json b/tests/XMLSchema/test-XSWhitespaceFacet.os.metadata.json new file mode 100644 index 000000000..6a60acf6d --- /dev/null +++ b/tests/XMLSchema/test-XSWhitespaceFacet.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9321571+00:00", + "SourceSize": 5133, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/XMLSchema/test-XSWhitespaceFacet.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2833414Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/XMLSchema/test-XSWhitespaceFacet.os.obj b/tests/XMLSchema/test-XSWhitespaceFacet.os.obj new file mode 100644 index 000000000..48ae58b99 Binary files /dev/null and b/tests/XMLSchema/test-XSWhitespaceFacet.os.obj differ diff --git a/tests/iterators/test-iterators.os.metadata.json b/tests/iterators/test-iterators.os.metadata.json new file mode 100644 index 000000000..a6e2de5f3 --- /dev/null +++ b/tests/iterators/test-iterators.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9361572+00:00", + "SourceSize": 2993, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/iterators/test-iterators.os", + "CacheCreatedTime": "2025-06-28T06:53:10.1939112Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/iterators/test-iterators.os.obj b/tests/iterators/test-iterators.os.obj new file mode 100644 index 000000000..fbf4a6fea Binary files /dev/null and b/tests/iterators/test-iterators.os.obj differ diff --git a/tests/xslt/test-XSLTransform.os.metadata.json b/tests/xslt/test-XSLTransform.os.metadata.json new file mode 100644 index 000000000..8c8b52522 --- /dev/null +++ b/tests/xslt/test-XSLTransform.os.metadata.json @@ -0,0 +1,8 @@ +{ + "FormatVersion": 1, + "SourceModifiedTime": "2025-06-28T06:46:27.9411572+00:00", + "SourceSize": 16786, + "SourcePath": "/home/runner/work/OneScript/OneScript/tests/xslt/test-XSLTransform.os", + "CacheCreatedTime": "2025-06-28T06:53:10.2074964Z", + "RuntimeVersion": "2.0.0.0" +} \ No newline at end of file diff --git a/tests/xslt/test-XSLTransform.os.obj b/tests/xslt/test-XSLTransform.os.obj new file mode 100644 index 000000000..bbf618d79 Binary files /dev/null and b/tests/xslt/test-XSLTransform.os.obj differ diff --git a/tools/classgen/DocgenCSharp.zip b/tools/classgen/DocgenCSharp.zip deleted file mode 100644 index 770487fc9..000000000 --- a/tools/classgen/DocgenCSharp.zip +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f22a181fa96f2b68b0b54f9a3662facb5c99699d39fe17082519c891cc8a5f83 -size 9023 diff --git a/tools/classgen/TypesDatabase.zip b/tools/classgen/TypesDatabase.zip deleted file mode 100644 index e45ffffd7..000000000 --- a/tools/classgen/TypesDatabase.zip +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:024894a92f2ef92832d66725c31d56ba3a86e7a7d91242a049be9ad39d723898 -size 2636769