diff --git a/.gitattributes b/.gitattributes index 065265706..bad6b35de 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,4 @@ -*.sh text eol=lf \ No newline at end of file +*.sh text eol=lf + +install/opm text eol=lf +install/oscript text eol=lf diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index b9644c37b..9808531a8 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,20 +4,6 @@ about: Предложить идею для проекта --- - - # Описание задачи **Опишите вашу Цель, которую вы сможете достичь с помощью новой функциональности** diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..8331a54b4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml new file mode 100644 index 000000000..c06a1bcdf --- /dev/null +++ b/.github/workflows/rebase.yml @@ -0,0 +1,19 @@ +name: Automatic Rebase +on: + issue_comment: + types: [created] +jobs: + rebase: + name: Rebase + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') + runs-on: ubuntu-latest + steps: + - name: Checkout the latest code + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 # otherwise, you will fail to push refs to dest repo + - name: Automatic Rebase + uses: cirrus-actions/rebase@1.8 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml new file mode 100644 index 000000000..ea0b66d77 --- /dev/null +++ b/.github/workflows/sonar.yml @@ -0,0 +1,69 @@ +name: QA + +on: + push: + pull_request: + +jobs: + sonar: + name: SonarQube + runs-on: windows-latest + if: (github.repository == 'EvilBeaver/OneScript' ) && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name) + steps: + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: temurin + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Cache SonarQube packages + uses: actions/cache@v3 + with: + path: ~\sonar\cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache SonarQube scanner + id: cache-sonar-scanner + uses: actions/cache@v3 + with: + path: .\.sonar\scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + - name: Install SonarQube scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + shell: powershell + run: | + New-Item -Path .\.sonar\scanner -ItemType Directory + dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner + - name: Install coverage tool + shell: powershell + run: | + dotnet tool install --global dotnet-coverage + - name: Compute branch name + uses: nelonoel/branch-name@v1.0.1 + - name: Prepare analysis (branch) + if: github.event_name == 'push' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + shell: powershell + run: | + .\.sonar\scanner\dotnet-sonarscanner begin /k:"OneScript" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.branch.name=${{ env.BRANCH_NAME }} /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonar.openbsl.ru" + - name: Prepare analysis (pull-request) + if: github.event_name == 'pull_request' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + shell: powershell + run: | + .\.sonar\scanner\dotnet-sonarscanner begin /k:"OneScript" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.pullrequest.key=${{ github.event.pull_request.number }} /d:sonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} /d:sonar.pullrequest.base=${{ github.event.pull_request.base.ref }} /d:sonar.scm.revision=${{ github.event.pull_request.head.sha }} /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonar.openbsl.ru" + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + shell: powershell + run: | + dotnet publish src/oscript/oscript.csproj + dotnet-coverage collect "dotnet msbuild Build_Core.csproj -t:UnitTests" -f xml -o "coverage.xml" + .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/Build_Core.csproj b/Build_Core.csproj index 104c1f0ce..94e4a1c82 100644 --- a/Build_Core.csproj +++ b/Build_Core.csproj @@ -8,7 +8,6 @@ $(BUILD_NUMBER) 0 - $(MSBuildProjectDirectory)/built $(MSBuildProjectDirectory)/built $(ArtifactsRoot)/lib $(ArtifactsRoot)\vscode\ @@ -70,7 +69,7 @@ ItemName="BuildVariant"/> - + $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration) @@ -84,6 +83,16 @@ + + + + + + + + + + @@ -96,9 +105,9 @@ - + - + $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration) @@ -110,6 +119,15 @@ + + + + + + + + + @@ -163,11 +181,10 @@ - - + + - @@ -187,7 +204,8 @@ + Condition="'$(SkipLibraryDownload)' == ''" + UseUtf8Encoding="Always"/> @@ -239,6 +257,7 @@ WorkingDirectory="$(TestsRoot)/%(TestAssemblies.Identity)" Command="dotnet test --logger:"junit;LogFilePath=$(MSBuildProjectDirectory)/tests/%(TestAssemblies.Identity).xml"" IgnoreExitCode="true" + UseUtf8Encoding="Always" /> @@ -255,7 +274,14 @@ - + + + @@ -284,7 +310,7 @@ - + @@ -323,7 +349,7 @@ + Command="dotnet nuget push %(NugetAbleProject.Identity).$(ReleaseNumber).nupkg -k $(NugetToken) -s https://api.nuget.org/v3/index.json" UseUtf8Encoding="Always"/> diff --git a/Jenkinsfile b/Jenkinsfile index 7f667e038..4213103b5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,29 +5,29 @@ pipeline { environment { VersionPrefix = '2.0.0' - VersionSuffix = 'rc2' + VersionSuffix = 'rc3' outputEnc = '65001' } stages { + stage('Prepare Linux Environment') { + agent{ label 'master'} + steps{ + dir('install'){ + sh 'chmod +x make-dockers.sh && ./make-dockers.sh' + } + withCredentials([usernamePassword(credentialsId: 'docker-hub', passwordVariable: 'dockerpassword', usernameVariable: 'dockeruser')]) { + sh """ + docker login -p $dockerpassword -u $dockeruser + docker push oscript/onescript-builder:deb + docker push oscript/onescript-builder:rpm + docker push oscript/onescript-builder:gcc + """.stripIndent() + } + } + } stage('Build'){ parallel { - stage('Prepare Linux Environment') { - agent{ label 'master'} - steps{ - dir('install'){ - sh 'chmod +x make-dockers.sh && ./make-dockers.sh' - } - withCredentials([usernamePassword(credentialsId: 'docker-hub', passwordVariable: 'dockerpassword', usernameVariable: 'dockeruser')]) { - sh """ - docker login -p $dockerpassword -u $dockeruser - docker push oscript/onescript-builder:deb - docker push oscript/onescript-builder:rpm - """.stripIndent() - } - } - } - stage('Windows Build') { agent { label 'windows' } @@ -64,6 +64,32 @@ pipeline { } } } + + stage('Linux Build') { + agent { + docker { + image 'oscript/onescript-builder:gcc' + label 'linux' + } + } + + steps { + sh 'mkdir -p built/tmp/na-proxy && mkdir -p built/tmp/na-tests' + dir('src/ScriptEngine.NativeApi') { + sh './build.sh' + sh 'cp *.so ../../built/tmp/na-proxy' + } + dir('tests/native-api') { + sh './build.sh' + sh 'cp *.so ../../built/tmp/na-tests' + } + dir('output') { + sh 'cp -Rv ../built/tmp/* .' + } + stash includes: 'output/na-proxy/*.so', name: 'nativeApiSo' + stash includes: 'output/na-tests/*.so', name: 'nativeApiTestsSo' + } + } } } stage('VSCode debugger Build') { @@ -125,6 +151,11 @@ pipeline { } unstash 'buildResults' + unstash 'nativeApiSo' + unstash 'nativeApiTestsSo' + + sh 'cp output/na-proxy/*.so ./built/linux-x64/bin/' + sh 'mkdir -p tests/native-api/build64 && cp output/na-tests/*.so ./tests/native-api/build64/' sh '''\ if [ ! -d lintests ]; then @@ -154,6 +185,10 @@ pipeline { } unstash 'buildResults' + unstash 'nativeApiSo' + + bat 'xcopy output\\na-proxy\\*64.so built\\linux-64\\bin\\' + script { if (env.BRANCH_NAME == "preview") { @@ -197,7 +232,7 @@ pipeline { } } - stage ('Publishing preview') { + stage ('Publishing preview') { when { anyOf { branch 'release/preview'; } diff --git a/README.md b/README.md index c9efffdaf..7737b5d62 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,11 @@ OneScript позволяет создавать и выполнять текст - выполнить команду `mono ovm.exe install stable` - выполнить команду `mono ovm.exe use stable` - перезапустить терминал + +Донастройка Self-Contained варианта поставки (не требующего инсталляции dotnet) + +``` +chmod +x ./oscript +xattr -d com.apple.quarantine *.dylib oscript +codesign -s - ./oscript +``` diff --git a/install/builders/deb/oscript b/install/builders/deb/oscript index 65af38659..3644f82d4 100755 --- a/install/builders/deb/oscript +++ b/install/builders/deb/oscript @@ -1,3 +1,3 @@ #!/bin/sh -mono /usr/share/oscript/bin/oscript.exe "$@" +dotnet /usr/share/oscript/bin/oscript.dll "$@" diff --git a/install/builders/deb/oscript-cgi b/install/builders/deb/oscript-cgi index f62a3fe07..caca00423 100755 --- a/install/builders/deb/oscript-cgi +++ b/install/builders/deb/oscript-cgi @@ -4,5 +4,5 @@ if [ -z "$SCRIPT_FILENAME" ]; then export SCRIPT_FILENAME=$1 fi -mono /usr/share/oscript/bin/oscript.exe -cgi "$@" +oscript -cgi "$@" diff --git a/install/builders/deb/oscript-opm b/install/builders/deb/oscript-opm index f847629a6..1c357d9c4 100755 --- a/install/builders/deb/oscript-opm +++ b/install/builders/deb/oscript-opm @@ -1,4 +1,4 @@ #!/bin/sh OSPATH=/usr/share/oscript -mono $OSPATH/bin/oscript.exe $OSPATH/lib/opm/src/cmd/opm.os "$@" +oscript $OSPATH/lib/opm/src/cmd/opm.os "$@" diff --git a/install/builders/msi/README.md b/install/builders/msi/README.md deleted file mode 100644 index 394545228..000000000 --- a/install/builders/msi/README.md +++ /dev/null @@ -1 +0,0 @@ -# WiX wili be here \ No newline at end of file diff --git a/install/builders/nativeapi/Dockerfile b/install/builders/nativeapi/Dockerfile index e65d29dde..c3df70df9 100644 --- a/install/builders/nativeapi/Dockerfile +++ b/install/builders/nativeapi/Dockerfile @@ -2,21 +2,4 @@ FROM ubuntu:18.04 RUN apt-get update -qq \ && dpkg --add-architecture i386 \ - && apt-get install -y -qq build-essential cmake uuid-dev libc6-dev gcc-multilib g++-multilib - -WORKDIR /src/proxy -COPY /src/ScriptEngine.NativeApi /src/proxy -RUN chmod +x build.sh && ./build.sh - -WORKDIR /src/tests -COPY /tests/native-api /src/tests -RUN chmod +x build.sh && ./build.sh - -RUN cd / \ - && mkdir built \ - && mkdir built/tmp \ - && mkdir built/tmp/bin \ - && mkdir built/tmp/tests \ - && cp /src/proxy/*.so built/tmp/bin \ - && cp /src/tests/*.so built/tmp/tests \ - && chmod -x built/tmp/bin/*.so \ No newline at end of file + && apt-get install -y -qq build-essential cmake uuid-dev libc6-dev gcc-multilib g++-multilib \ No newline at end of file diff --git a/install/builders/rpm/oscript b/install/builders/rpm/oscript index 65af38659..3644f82d4 100644 --- a/install/builders/rpm/oscript +++ b/install/builders/rpm/oscript @@ -1,3 +1,3 @@ #!/bin/sh -mono /usr/share/oscript/bin/oscript.exe "$@" +dotnet /usr/share/oscript/bin/oscript.dll "$@" diff --git a/install/builders/rpm/oscript-opm b/install/builders/rpm/oscript-opm index f847629a6..1c357d9c4 100644 --- a/install/builders/rpm/oscript-opm +++ b/install/builders/rpm/oscript-opm @@ -1,4 +1,4 @@ #!/bin/sh OSPATH=/usr/share/oscript -mono $OSPATH/bin/oscript.exe $OSPATH/lib/opm/src/cmd/opm.os "$@" +oscript $OSPATH/lib/opm/src/cmd/opm.os "$@" diff --git a/install/opm b/install/opm new file mode 100644 index 000000000..e6e62bc7b --- /dev/null +++ b/install/opm @@ -0,0 +1,8 @@ +#!/bin/bash + +THISDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +LIB="$THISDIR/../lib" +OPM=$LIB/opm/src/cmd/opm.os + +oscript $OPM "$@" diff --git a/install/opm.bat b/install/opm.bat index 3fd12a362..1105eba2c 100644 --- a/install/opm.bat +++ b/install/opm.bat @@ -5,4 +5,4 @@ setlocal set lib="%~dp0..\lib" set opm=%lib%\opm\src\cmd\opm.os -oscript.exe %opm% %* +oscript %opm% %* diff --git a/install/opm.ospx b/install/opm.ospx index 36365671f..661b6ff2b 100644 Binary files a/install/opm.ospx and b/install/opm.ospx differ diff --git a/install/oscript b/install/oscript new file mode 100644 index 000000000..d2cbc30be --- /dev/null +++ b/install/oscript @@ -0,0 +1,5 @@ +#!/bin/bash + +THISDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +dotnet "$THISDIR/oscript.dll" "$@" diff --git a/install/oscript.bat b/install/oscript.bat new file mode 100644 index 000000000..abb4ca583 --- /dev/null +++ b/install/oscript.bat @@ -0,0 +1,3 @@ +@echo off + +dotnet %~dp0oscript.dll %* diff --git a/src/1Script.sln b/src/1Script.sln index fc18d92e7..9da3cfeaf 100644 --- a/src/1Script.sln +++ b/src/1Script.sln @@ -20,6 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\Build.csproj = ..\Build.csproj oscommon.targets = oscommon.targets ..\Build_Core.csproj = ..\Build_Core.csproj + ..\Jenkinsfile = ..\Jenkinsfile EndProjectSection EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Installer", "Installer\Installer.wixproj", "{BBE794A6-B159-422F-B655-B7F03F25F223}" diff --git a/src/OneScript.Core/Commons/IndexedNameValueCollection.cs b/src/OneScript.Core/Commons/IndexedNameValueCollection.cs index 059764382..94e2631ff 100644 --- a/src/OneScript.Core/Commons/IndexedNameValueCollection.cs +++ b/src/OneScript.Core/Commons/IndexedNameValueCollection.cs @@ -58,7 +58,7 @@ public T this[string name] public void AddName(int index, string name) { if (index < 0 || index >= _values.Count) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(index)); _nameIndex[name] = index; } diff --git a/src/OneScript.Core/Compilation/Binding/AliasedVariableSymbol.cs b/src/OneScript.Core/Compilation/Binding/AliasedVariableSymbol.cs new file mode 100644 index 000000000..bca92f5e2 --- /dev/null +++ b/src/OneScript.Core/Compilation/Binding/AliasedVariableSymbol.cs @@ -0,0 +1,34 @@ +/*---------------------------------------------------------- +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 OneScript.Values; + +namespace OneScript.Compilation.Binding +{ + public class AliasedVariableSymbol : IVariableSymbol + { + public AliasedVariableSymbol(string name, string alias, Type type) + { + Name = name; + Alias = alias; + Type = type; + } + + public AliasedVariableSymbol(string name, string alias) + { + Name = name; + Alias = alias; + Type = typeof(BslValue); + } + + public string Name { get; } + + public string Alias { get; } + + public Type Type { get; } + } +} diff --git a/src/OneScript.Core/Compilation/Binding/SymbolTable.cs b/src/OneScript.Core/Compilation/Binding/SymbolTable.cs index 10e1ac2ad..7c5ae829c 100644 --- a/src/OneScript.Core/Compilation/Binding/SymbolTable.cs +++ b/src/OneScript.Core/Compilation/Binding/SymbolTable.cs @@ -7,7 +7,6 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using OneScript.Contexts; -using OneScript.Values; namespace OneScript.Compilation.Binding { @@ -65,7 +64,7 @@ public bool FindVariable(string name, out SymbolBinding binding) return false; } - public bool FindMethod(string name, out SymbolBinding binding) + public bool TryFindMethodBinding(string name, out SymbolBinding binding) { for (int i = _bindings.Count - 1; i >= 0; i--) { @@ -86,6 +85,18 @@ public bool FindMethod(string name, out SymbolBinding binding) return false; } + public bool TryFindMethod(string name, out IMethodSymbol method) + { + if (TryFindMethodBinding(name, out var binding)) + { + method = GetMethod(binding); + return true; + } + + method = default; + return false; + } + public SymbolBinding DefineMethod(IMethodSymbol symbol) { var index = _bindings[ScopeCount - 1].scope.DefineMethod(symbol); diff --git a/src/OneScript.Core/Compilation/ICompileTimeDependencyResolver.cs b/src/OneScript.Core/Compilation/ICompileTimeDependencyResolver.cs new file mode 100644 index 000000000..0fc5b30e3 --- /dev/null +++ b/src/OneScript.Core/Compilation/ICompileTimeDependencyResolver.cs @@ -0,0 +1,16 @@ +/*---------------------------------------------------------- +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.Sources; + +namespace OneScript.Compilation +{ + public interface ICompileTimeDependencyResolver + { + void Resolve(SourceCode module, string libraryName); + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Compilation/ICompilerBackend.cs b/src/OneScript.Core/Compilation/ICompilerBackend.cs index 2904c8317..158210d98 100644 --- a/src/OneScript.Core/Compilation/ICompilerBackend.cs +++ b/src/OneScript.Core/Compilation/ICompilerBackend.cs @@ -10,7 +10,6 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation.Binding; using OneScript.Execution; using OneScript.Language.SyntaxAnalysis.AstNodes; -using OneScript.Sources; namespace OneScript.Compilation { diff --git a/src/OneScript.Core/Contexts/BslMethodBuilder.cs b/src/OneScript.Core/Contexts/BslMethodBuilder.cs index 018c35f9e..818be5b59 100644 --- a/src/OneScript.Core/Contexts/BslMethodBuilder.cs +++ b/src/OneScript.Core/Contexts/BslMethodBuilder.cs @@ -76,7 +76,7 @@ public BslMethodBuilder IsExported(bool exportFlag) return this; } - public BslMethodBuilder SetAnnotations(IEnumerable annotations) + public BslMethodBuilder SetAnnotations(IEnumerable annotations) { _member.SetAnnotations(annotations); return this; diff --git a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs index 7dacf42d5..0dd00e1e4 100644 --- a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs +++ b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs @@ -23,7 +23,7 @@ public class BslScriptMethodInfo : BslMethodInfo, IBuildableMethod private Type _returnType = typeof(void); private string _name; private bool _isPrivate = true; - private BslParameterInfo[] _parameters = Array.Empty(); + protected BslParameterInfo[] _parameters = Array.Empty(); protected BslScriptMethodInfo() { diff --git a/src/OneScript.Core/Commons/BslCoreException.cs b/src/OneScript.Core/Exceptions/BslCoreException.cs similarity index 85% rename from src/OneScript.Core/Commons/BslCoreException.cs rename to src/OneScript.Core/Exceptions/BslCoreException.cs index 40e63ec95..5de478ca8 100644 --- a/src/OneScript.Core/Commons/BslCoreException.cs +++ b/src/OneScript.Core/Exceptions/BslCoreException.cs @@ -6,11 +6,12 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using OneScript.Language; using OneScript.Localization; -namespace OneScript.Commons +namespace OneScript.Exceptions { - public class BslCoreException : ApplicationException + public class BslCoreException : ScriptException { public BslCoreException(BilingualString message) : base(message.ToString()) { diff --git a/src/OneScript.Core/Commons/BslExceptions.cs b/src/OneScript.Core/Exceptions/BslExceptions.cs similarity index 98% rename from src/OneScript.Core/Commons/BslExceptions.cs rename to src/OneScript.Core/Exceptions/BslExceptions.cs index 55242a7ba..1bccf03a7 100644 --- a/src/OneScript.Core/Commons/BslExceptions.cs +++ b/src/OneScript.Core/Exceptions/BslExceptions.cs @@ -8,7 +8,7 @@ This Source Code Form is subject to the terms of the using OneScript.Localization; using OneScript.Values; -namespace OneScript.Commons +namespace OneScript.Exceptions { public static class BslExceptions { diff --git a/src/OneScript.Core/Exceptions/DependencyResolveException.cs b/src/OneScript.Core/Exceptions/DependencyResolveException.cs new file mode 100644 index 000000000..8d101f87d --- /dev/null +++ b/src/OneScript.Core/Exceptions/DependencyResolveException.cs @@ -0,0 +1,18 @@ +/*---------------------------------------------------------- +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.Localization; + +namespace OneScript.Exceptions +{ + public class DependencyResolveException : RuntimeException + { + public DependencyResolveException(BilingualString message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs b/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs new file mode 100644 index 000000000..c623b4c0a --- /dev/null +++ b/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs @@ -0,0 +1,25 @@ +/*---------------------------------------------------------- +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 OneScript.Contexts; +using OneScript.Values; + +namespace OneScript.Exceptions +{ + /// + /// Фабрика объекта ИнформацияОбОшибке по исключению. + /// + public interface IExceptionInfoFactory + { + BslObjectValue GetExceptionInfo(Exception exception); + + string GetExceptionDescription(IRuntimeContextInstance exceptionInfo); + + Exception Raise(object raiseValue); + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Commons/PropertyAccessException.cs b/src/OneScript.Core/Exceptions/PropertyAccessException.cs similarity index 98% rename from src/OneScript.Core/Commons/PropertyAccessException.cs rename to src/OneScript.Core/Exceptions/PropertyAccessException.cs index 42010b1dd..8cf87fc25 100644 --- a/src/OneScript.Core/Commons/PropertyAccessException.cs +++ b/src/OneScript.Core/Exceptions/PropertyAccessException.cs @@ -8,7 +8,7 @@ This Source Code Form is subject to the terms of the using System; using OneScript.Localization; -namespace OneScript.Commons +namespace OneScript.Exceptions { public class PropertyAccessException : RuntimeException { diff --git a/src/OneScript.Core/Commons/RuntimeException.cs b/src/OneScript.Core/Exceptions/RuntimeException.cs similarity index 99% rename from src/OneScript.Core/Commons/RuntimeException.cs rename to src/OneScript.Core/Exceptions/RuntimeException.cs index e14fdfeb4..b751762b4 100644 --- a/src/OneScript.Core/Commons/RuntimeException.cs +++ b/src/OneScript.Core/Exceptions/RuntimeException.cs @@ -8,7 +8,7 @@ This Source Code Form is subject to the terms of the using System; using OneScript.Localization; -namespace OneScript.Commons +namespace OneScript.Exceptions { public class RuntimeException : BslCoreException { @@ -20,8 +20,6 @@ public RuntimeException(BilingualString message) : base(message) { } - - #region Static Factory Methods public static RuntimeException DeprecatedMethodCall(string name) diff --git a/src/OneScript.Core/Commons/TypeConversionException.cs b/src/OneScript.Core/Exceptions/TypeConversionException.cs similarity index 94% rename from src/OneScript.Core/Commons/TypeConversionException.cs rename to src/OneScript.Core/Exceptions/TypeConversionException.cs index ae3b145e9..98e330f34 100644 --- a/src/OneScript.Core/Commons/TypeConversionException.cs +++ b/src/OneScript.Core/Exceptions/TypeConversionException.cs @@ -7,7 +7,7 @@ This Source Code Form is subject to the terms of the using OneScript.Localization; -namespace OneScript.Commons +namespace OneScript.Exceptions { public class TypeConversionException : RuntimeException { diff --git a/src/OneScript.Core/Rcw/DispatchUtility.cs b/src/OneScript.Core/Rcw/DispatchUtility.cs index 2426dca43..08dd51882 100644 --- a/src/OneScript.Core/Rcw/DispatchUtility.cs +++ b/src/OneScript.Core/Rcw/DispatchUtility.cs @@ -98,9 +98,27 @@ public static bool TryGetDispId(object obj, string name, out int dispId) /// This can invoke a method or a property get accessor. /// public static object Invoke(object obj, int dispId, object[] args) + { + object result = Invoke(obj, dispId, args, null); + return result; + } + + /// + /// Invokes a member by DISPID. + /// + /// An object that implements IDispatch. + /// The DISPID of a member. This can be obtained using + /// . + /// The arguments to pass to the member. + /// ByRef modifiers + /// The member's return value. + /// + /// This can invoke a method or a property get accessor. + /// + public static object Invoke(object obj, int dispId, object[] args, ParameterModifier[] modifiers) { string memberName = "[DispId=" + dispId + "]"; - object result = Invoke(obj, memberName, args); + object result = Invoke(obj, memberName, args, modifiers); return result; } @@ -114,12 +132,12 @@ public static object Invoke(object obj, int dispId, object[] args) /// /// This can invoke a method or a property get accessor. /// - public static object Invoke(object obj, string memberName, object[] args) + public static object Invoke(object obj, string memberName, object[] args, ParameterModifier[] modifiers) { RequireReference(obj, "obj"); Type type = obj.GetType(); object result = type.InvokeMember(memberName, BindingFlags.InvokeMethod | BindingFlags.GetProperty, - null, obj, args, null); + null, obj, args, modifiers, null, null); return result; } diff --git a/src/OneScript.Core/Rcw/RcwMemberMetadata.cs b/src/OneScript.Core/Rcw/RcwMemberMetadata.cs index a784feb0b..2aff2f090 100644 --- a/src/OneScript.Core/Rcw/RcwMemberMetadata.cs +++ b/src/OneScript.Core/Rcw/RcwMemberMetadata.cs @@ -7,29 +7,6 @@ This Source Code Form is subject to the terms of the namespace OneScript.Rcw { - public class RcwMethodMetadata : RcwMemberMetadata - { - public bool? IsFunction { get; } - - public RcwMethodMetadata(string name, int dispId, bool? isFunc) : base(name, dispId) - { - IsFunction = isFunc; - } - } - - public class RcwPropertyMetadata : RcwMemberMetadata - { - public bool IsReadable { get; internal set; } - - public bool IsWritable { get; internal set; } - - public RcwPropertyMetadata(string name, int dispId) : base(name, dispId) - { - IsReadable = true; - IsWritable = true; - } - } - public abstract class RcwMemberMetadata { public int DispatchId { get; } diff --git a/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs b/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs index 28cf9d8a7..826162b36 100644 --- a/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs +++ b/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs @@ -13,9 +13,9 @@ namespace OneScript.Rcw { public class RcwMembersMetadataCollection where T : RcwMemberMetadata { - private readonly List _collection; - private readonly Dictionary _dispIds; - private readonly Dictionary _names; + private readonly List _collection = new List(); + private readonly Dictionary _dispIds = new Dictionary(); + private readonly Dictionary _names = new Dictionary(StringComparer.InvariantCultureIgnoreCase); public IReadOnlyDictionary DispatchIds => new ReadOnlyDictionary(_dispIds); @@ -23,13 +23,6 @@ public class RcwMembersMetadataCollection where T : RcwMemberMetadata public T this[int index] => _collection[index]; - public RcwMembersMetadataCollection() - { - _collection = new List(); - _dispIds = new Dictionary(); - _names = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - } - public int IndexOf(T item) => _collection.IndexOf(item); public void Add(T item) diff --git a/src/OneScript.Core/Rcw/RcwMetadata.cs b/src/OneScript.Core/Rcw/RcwMetadata.cs index c25b014b9..e4281775d 100644 --- a/src/OneScript.Core/Rcw/RcwMetadata.cs +++ b/src/OneScript.Core/Rcw/RcwMetadata.cs @@ -9,13 +9,12 @@ This Source Code Form is subject to the terms of the using System.Collections; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; -using OneScript.Rcw; using FUNCDESC = System.Runtime.InteropServices.ComTypes.FUNCDESC; using FUNCFLAGS = System.Runtime.InteropServices.ComTypes.FUNCFLAGS; using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR; using INVOKEKIND = System.Runtime.InteropServices.ComTypes.INVOKEKIND; -namespace ScriptEngine.Machine.Rcw +namespace OneScript.Rcw { public class RcwMetadata { diff --git a/src/OneScript.Core/Rcw/RcwMethodMetadata.cs b/src/OneScript.Core/Rcw/RcwMethodMetadata.cs new file mode 100644 index 000000000..53f806010 --- /dev/null +++ b/src/OneScript.Core/Rcw/RcwMethodMetadata.cs @@ -0,0 +1,19 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace OneScript.Rcw +{ + public class RcwMethodMetadata : RcwMemberMetadata + { + public bool? IsFunction { get; } + + public RcwMethodMetadata(string name, int dispId, bool? isFunc) : base(name, dispId) + { + IsFunction = isFunc; + } + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Rcw/RcwPropertyMetadata.cs b/src/OneScript.Core/Rcw/RcwPropertyMetadata.cs new file mode 100644 index 000000000..b2790a3e1 --- /dev/null +++ b/src/OneScript.Core/Rcw/RcwPropertyMetadata.cs @@ -0,0 +1,22 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace OneScript.Rcw +{ + public class RcwPropertyMetadata : RcwMemberMetadata + { + public bool IsReadable { get; internal set; } + + public bool IsWritable { get; internal set; } + + public RcwPropertyMetadata(string name, int dispId) : base(name, dispId) + { + IsReadable = true; + IsWritable = true; + } + } +} \ No newline at end of file diff --git a/src/OneScript.Core/TypeUtils.cs b/src/OneScript.Core/TypeUtils.cs index bf3f2ef11..1cb9bda5f 100644 --- a/src/OneScript.Core/TypeUtils.cs +++ b/src/OneScript.Core/TypeUtils.cs @@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using OneScript.Contexts; using OneScript.Values; namespace OneScript @@ -35,6 +36,8 @@ public static bool IsNumeric(this Type type) public static bool IsValue(this Type type) => typeof(BslValue).IsAssignableFrom(type); + public static bool IsContext(this Type type) => typeof(IRuntimeContextInstance).IsAssignableFrom(type); + public static bool IsObjectValue(this Type type) => typeof(BslObjectValue).IsAssignableFrom(type); } } \ No newline at end of file diff --git a/src/OneScript.Core/Values/BslBooleanValue.cs b/src/OneScript.Core/Values/BslBooleanValue.cs index 3d97ba981..e852331b0 100644 --- a/src/OneScript.Core/Values/BslBooleanValue.cs +++ b/src/OneScript.Core/Values/BslBooleanValue.cs @@ -6,7 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Localization; using OneScript.Types; diff --git a/src/OneScript.Core/Values/BslDateValue.cs b/src/OneScript.Core/Values/BslDateValue.cs index 93c025527..205dedd4a 100644 --- a/src/OneScript.Core/Values/BslDateValue.cs +++ b/src/OneScript.Core/Values/BslDateValue.cs @@ -7,7 +7,7 @@ This Source Code Form is subject to the terms of the using System; using System.Globalization; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; namespace OneScript.Values diff --git a/src/OneScript.Core/Values/BslNumericValue.cs b/src/OneScript.Core/Values/BslNumericValue.cs index 67426e215..f75d81561 100644 --- a/src/OneScript.Core/Values/BslNumericValue.cs +++ b/src/OneScript.Core/Values/BslNumericValue.cs @@ -8,7 +8,7 @@ This Source Code Form is subject to the terms of the using System; using System.Dynamic; using System.Globalization; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; namespace OneScript.Values diff --git a/src/OneScript.Core/Values/BslObjectValue.cs b/src/OneScript.Core/Values/BslObjectValue.cs index 4bfe1f555..10226630d 100644 --- a/src/OneScript.Core/Values/BslObjectValue.cs +++ b/src/OneScript.Core/Values/BslObjectValue.cs @@ -5,7 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Localization; namespace OneScript.Values diff --git a/src/OneScript.Core/Values/BslPrimitiveValue.cs b/src/OneScript.Core/Values/BslPrimitiveValue.cs index 162d93dc9..24bc8000d 100644 --- a/src/OneScript.Core/Values/BslPrimitiveValue.cs +++ b/src/OneScript.Core/Values/BslPrimitiveValue.cs @@ -6,7 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; +using OneScript.Exceptions; namespace OneScript.Values { diff --git a/src/OneScript.Core/Values/BslTypeValue.cs b/src/OneScript.Core/Values/BslTypeValue.cs index 2a1977633..dab5b65a0 100644 --- a/src/OneScript.Core/Values/BslTypeValue.cs +++ b/src/OneScript.Core/Values/BslTypeValue.cs @@ -17,7 +17,9 @@ public BslTypeValue(TypeDescriptor type) { _type = type; } - + + public static BslTypeValue Create(TypeDescriptor value) => new BslTypeValue(value); + public override TypeDescriptor SystemType => BasicTypes.Type; public override string ToString() diff --git a/src/OneScript.Core/Values/BslValue.cs b/src/OneScript.Core/Values/BslValue.cs index 523d96641..514bf5ec5 100644 --- a/src/OneScript.Core/Values/BslValue.cs +++ b/src/OneScript.Core/Values/BslValue.cs @@ -7,7 +7,7 @@ This Source Code Form is subject to the terms of the using System; using System.Dynamic; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.Core/Values/PropertyValueReference.cs b/src/OneScript.Core/Values/PropertyValueReference.cs index 67563cf4d..bead9213d 100644 --- a/src/OneScript.Core/Values/PropertyValueReference.cs +++ b/src/OneScript.Core/Values/PropertyValueReference.cs @@ -5,8 +5,8 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; namespace OneScript.Values diff --git a/src/OneScript.DebugProtocol/Abstractions/ICommunicationServer.cs b/src/OneScript.DebugProtocol/Abstractions/ICommunicationServer.cs index b964431db..f13e0418e 100644 --- a/src/OneScript.DebugProtocol/Abstractions/ICommunicationServer.cs +++ b/src/OneScript.DebugProtocol/Abstractions/ICommunicationServer.cs @@ -9,6 +9,9 @@ This Source Code Form is subject to the terms of the namespace OneScript.DebugProtocol.Abstractions { + /// + /// Сервис прослушивания сетевого канала и отправки в него сообщений + /// public interface ICommunicationServer { void Start(); diff --git a/src/OneScript.DebugProtocol/DebuggerSettings.cs b/src/OneScript.DebugProtocol/DebuggerSettings.cs index c89fe6025..fd3297aa5 100644 --- a/src/OneScript.DebugProtocol/DebuggerSettings.cs +++ b/src/OneScript.DebugProtocol/DebuggerSettings.cs @@ -4,11 +4,17 @@ This Source Code Form is subject to the terms of the was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ + +using System.Text; + namespace OneScript.DebugProtocol { public static class DebuggerSettings { public const int MAX_BUFFER_SIZE = 5000000; + public const int MAX_PRESENTATION_LENGTH = (int)(MAX_BUFFER_SIZE / 2.5); + + public static readonly Encoding DebugModeEncoding = Encoding.UTF8; } } \ No newline at end of file diff --git a/src/OneScript.DebugProtocol/IDebugEventListener.cs b/src/OneScript.DebugProtocol/IDebugEventListener.cs index 29c627639..def15c4bc 100644 --- a/src/OneScript.DebugProtocol/IDebugEventListener.cs +++ b/src/OneScript.DebugProtocol/IDebugEventListener.cs @@ -7,6 +7,9 @@ This Source Code Form is subject to the terms of the namespace OneScript.DebugProtocol { + /// + /// Интерфейс слушателя событий отладки (сообщений, инициируемых со стороны BSL) + /// public interface IDebugEventListener { void ThreadStopped(int threadId, ThreadStopReason reason); diff --git a/src/OneScript.DebugProtocol/IDebuggerService.cs b/src/OneScript.DebugProtocol/IDebuggerService.cs index 91c421d2b..84f7593f4 100644 --- a/src/OneScript.DebugProtocol/IDebuggerService.cs +++ b/src/OneScript.DebugProtocol/IDebuggerService.cs @@ -7,6 +7,9 @@ This Source Code Form is subject to the terms of the namespace OneScript.DebugProtocol { + /// + /// Сервис непосредственной работы с командами отладки, шагами, брейкпоинтами и пр. + /// public interface IDebuggerService { /// @@ -59,6 +62,12 @@ public interface IDebuggerService void StepOut(int threadId); + /// + /// Отключение сеанса отладки по инициативе IDE + /// + /// + void Disconnect(bool terminate); + int[] GetThreads(); int GetProcessId(); diff --git a/src/OneScript.DebugProtocol/TcpServer/BinaryChannel.cs b/src/OneScript.DebugProtocol/TcpServer/BinaryChannel.cs index b1e7cf70f..5f7b99a93 100644 --- a/src/OneScript.DebugProtocol/TcpServer/BinaryChannel.cs +++ b/src/OneScript.DebugProtocol/TcpServer/BinaryChannel.cs @@ -5,7 +5,6 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using System.IO; using System.Net.Sockets; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; @@ -13,6 +12,9 @@ This Source Code Form is subject to the terms of the namespace OneScript.DebugProtocol { + /// + /// TCP-канал, использующий стандартную Binary-сериализацию .NET + /// public class BinaryChannel : ICommunicationChannel { private readonly TcpClient _client; diff --git a/src/OneScript.DebugProtocol/TcpServer/DefaultMessageServer.cs b/src/OneScript.DebugProtocol/TcpServer/DefaultMessageServer.cs index 5d97d916c..3f70cff8a 100644 --- a/src/OneScript.DebugProtocol/TcpServer/DefaultMessageServer.cs +++ b/src/OneScript.DebugProtocol/TcpServer/DefaultMessageServer.cs @@ -21,6 +21,11 @@ public DefaultMessageServer(ICommunicationChannel protocolChannel) { _protocolChannel = protocolChannel; } + + /// + /// Имя, назначаемое потоку сервера. Полезно для отладки и диагностики. + /// + public string ServerThreadName { get; set; } public void Start() { @@ -79,11 +84,16 @@ private void RunCommandsLoop() catch (Exception) { _serverStopped = true; - break; } } }); + _messageThread.IsBackground = true; + if (ServerThreadName != default) + { + _messageThread.Name = ServerThreadName; + } + _messageThread.Start(); } @@ -97,6 +107,7 @@ public void Stop() if (_messageThread?.IsAlive == true) { _protocolChannel.Dispose(); + _messageThread.Interrupt(); } } diff --git a/src/OneScript.DebugProtocol/TcpServer/DispatchingServer.cs b/src/OneScript.DebugProtocol/TcpServer/DispatchingServer.cs index 13cace284..5d0ec7cd0 100644 --- a/src/OneScript.DebugProtocol/TcpServer/DispatchingServer.cs +++ b/src/OneScript.DebugProtocol/TcpServer/DispatchingServer.cs @@ -56,9 +56,14 @@ private void ProcessSuccess(RpcCall message, ICommunicationChannel responseChann try { var methodResult = _requestProcessor.Dispatch(_requestService, message.Id, message.Parameters); - if(methodResult != null) + if (methodResult != null) callResult = RpcCallResult.Respond(message, methodResult); } + catch (StopServiceException) + { + Stop(); + return; + } catch (Exception e) { callResult = RpcCallResult.Exception(message, e); diff --git a/src/OneScript.DebugProtocol/TcpServer/StopServiceException.cs b/src/OneScript.DebugProtocol/TcpServer/StopServiceException.cs new file mode 100644 index 000000000..359e4427f --- /dev/null +++ b/src/OneScript.DebugProtocol/TcpServer/StopServiceException.cs @@ -0,0 +1,18 @@ +/*---------------------------------------------------------- +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 OneScript.DebugProtocol.TcpServer +{ + /// + /// Прерывание сервера со стороны прикладного интерфейса. Кнопка "Выход" из диспетчера + /// + public class StopServiceException : ApplicationException + { + } +} \ No newline at end of file diff --git a/src/OneScript.DebugServices/BinaryTcpDebugServer.cs b/src/OneScript.DebugServices/BinaryTcpDebugServer.cs index c20c1d622..9648e4b4b 100644 --- a/src/OneScript.DebugServices/BinaryTcpDebugServer.cs +++ b/src/OneScript.DebugServices/BinaryTcpDebugServer.cs @@ -24,7 +24,10 @@ public IDebugController CreateDebugController() { var listener = TcpListener.Create(_port); var channel = new DelayedConnectionChannel(listener); - var ipcServer = new DefaultMessageServer(channel); + var ipcServer = new DefaultMessageServer(channel) + { + ServerThreadName = "debug-server" + }; var callback = new TcpEventCallbackChannel(channel); var threadManager = new ThreadManager(); var breakpoints = new DefaultBreakpointManager(); diff --git a/src/OneScript.DebugServices/DefaultBreakpointManager.cs b/src/OneScript.DebugServices/DefaultBreakpointManager.cs index 82745fdbf..ef74bb911 100644 --- a/src/OneScript.DebugServices/DefaultBreakpointManager.cs +++ b/src/OneScript.DebugServices/DefaultBreakpointManager.cs @@ -32,5 +32,10 @@ public bool Find(string module, int line) var found = _breakpoints.Find(x => x.Module.Equals(module) && x.LineNumber == line); return found != null; } + + public void Clear() + { + _breakpoints.Clear(); + } } } \ No newline at end of file diff --git a/src/OneScript.DebugServices/DefaultDebugController.cs b/src/OneScript.DebugServices/DefaultDebugController.cs index ea548d5bb..7c09b9a54 100644 --- a/src/OneScript.DebugServices/DefaultDebugController.cs +++ b/src/OneScript.DebugServices/DefaultDebugController.cs @@ -13,6 +13,11 @@ This Source Code Form is subject to the terms of the namespace OneScript.DebugServices { + /// + /// Простой односессионный контроллер отладки. Поддерживает только один сеанс отладки на процесс. + /// Также поддерживает только один BSL-процесс на приложение. При получении NotifyProcessExited отключает отладчик + /// и к нему нельзя подключиться еще раз. + /// public class DefaultDebugController : IDebugController { private readonly ICommunicationServer _server; diff --git a/src/OneScript.DebugServices/DefaultDebugService.cs b/src/OneScript.DebugServices/DefaultDebugService.cs index 51e727f46..c7b035baf 100644 --- a/src/OneScript.DebugServices/DefaultDebugService.cs +++ b/src/OneScript.DebugServices/DefaultDebugService.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Linq; using OneScript.Contexts; using OneScript.DebugProtocol; +using OneScript.DebugProtocol.TcpServer; using OneScript.Language; using ScriptEngine.Machine; using StackFrame = OneScript.DebugProtocol.StackFrame; @@ -50,7 +51,7 @@ public void Execute(int threadId) } } - public virtual Breakpoint[] SetMachineBreakpoints(Breakpoint[] breaksToSet) + public Breakpoint[] SetMachineBreakpoints(Breakpoint[] breaksToSet) { var confirmedBreakpoints = new List(); @@ -72,7 +73,6 @@ public virtual Breakpoint[] SetMachineBreakpoints(Breakpoint[] breaksToSet) Source = item.Key }); } - } // Уведомить все потоки о новых точках остановки @@ -84,7 +84,7 @@ public virtual Breakpoint[] SetMachineBreakpoints(Breakpoint[] breaksToSet) return confirmedBreakpoints.ToArray(); } - public virtual StackFrame[] GetStackFrames(int threadId) + public StackFrame[] GetStackFrames(int threadId) { var machine = _threadManager.GetTokenForThread(threadId).Machine; var frames = machine.GetExecutionFrames(); @@ -92,13 +92,14 @@ public virtual StackFrame[] GetStackFrames(int threadId) int index = 0; foreach (var frameInfo in frames) { - var frame = new StackFrame(); - frame.LineNumber = frameInfo.LineNumber; - frame.Index = index++; - frame.MethodName = frameInfo.MethodName; - frame.Source = frameInfo.Source; + var frame = new StackFrame + { + LineNumber = frameInfo.LineNumber, + Index = index++, + MethodName = frameInfo.MethodName, + Source = frameInfo.Source + }; result[frame.Index] = frame; - } return result; } @@ -113,7 +114,7 @@ private MachineInstance GetMachine(int threadId) return savedMachine; } - public virtual Variable[] GetVariables(int threadId, int frameIndex, int[] path) + public Variable[] GetVariables(int threadId, int frameIndex, int[] path) { var machine = GetMachine(threadId); @@ -128,13 +129,13 @@ public virtual Variable[] GetVariables(int threadId, int frameIndex, int[] path) return GetDebugVariables(locals); } - public virtual Variable[] GetEvaluatedVariables(string expression, int threadId, int frameIndex, int[] path) + public Variable[] GetEvaluatedVariables(string expression, int threadId, int frameIndex, int[] path) { IValue value; try { - value = GetMachine(threadId).Evaluate(expression, true); + value = GetMachine(threadId).EvaluateInFrame(expression, frameIndex); } catch (Exception e) { @@ -152,12 +153,12 @@ public virtual Variable[] GetEvaluatedVariables(string expression, int threadId, return GetDebugVariables(locals); } - public virtual Variable Evaluate(int threadId, int contextFrame, string expression) + public Variable Evaluate(int threadId, int contextFrame, string expression) { try { var value = GetMachine(threadId) - .Evaluate(expression, true) + .EvaluateInFrame(expression, contextFrame) .GetRawValue(); var variable = _visualizer.GetVariable(MachineVariable.Create(value, "$evalResult")); @@ -170,28 +171,36 @@ public virtual Variable Evaluate(int threadId, int contextFrame, string expressi } } - public virtual void Next(int threadId) + public void Next(int threadId) { var t = _threadManager.GetTokenForThread(threadId); t.Machine.StepOver(); t.Set(); } - public virtual void StepIn(int threadId) + public void StepIn(int threadId) { var t = _threadManager.GetTokenForThread(threadId); t.Machine.StepIn(); t.Set(); } - public virtual void StepOut(int threadId) + public void StepOut(int threadId) { var t = _threadManager.GetTokenForThread(threadId); t.Machine.StepOut(); t.Set(); } - public virtual int[] GetThreads() + public void Disconnect(bool terminate) + { + _breakpointManager.Clear(); + _threadManager.ReleaseAllThreads(); + + throw new StopServiceException(); + } + + public int[] GetThreads() { return _threadManager.GetAllThreadIds(); } diff --git a/src/OneScript.DebugServices/MachineWaitToken.cs b/src/OneScript.DebugServices/MachineWaitToken.cs index 732fa143a..ddb22b481 100644 --- a/src/OneScript.DebugServices/MachineWaitToken.cs +++ b/src/OneScript.DebugServices/MachineWaitToken.cs @@ -5,20 +5,16 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ +using System; using System.Threading; using ScriptEngine.Machine; namespace OneScript.DebugServices { - public class MachineWaitToken + public class MachineWaitToken: IDisposable { - private ManualResetEventSlim _threadEvent; + private ManualResetEventSlim _threadEvent = new ManualResetEventSlim(); - public MachineWaitToken() - { - _threadEvent = new ManualResetEventSlim(); - } - public MachineInstance Machine { get; set; } public void Wait() => _threadEvent.Wait(); @@ -26,5 +22,12 @@ public MachineWaitToken() public void Set() => _threadEvent.Set(); public void Reset() => _threadEvent.Reset(); + + public void Dispose() + { + Machine.UnsetDebugMode(); + _threadEvent.Set(); + _threadEvent.Dispose(); + } } } \ No newline at end of file diff --git a/src/OneScript.DebugServices/ThreadManager.cs b/src/OneScript.DebugServices/ThreadManager.cs index 06033ed85..2dc31f3fa 100644 --- a/src/OneScript.DebugServices/ThreadManager.cs +++ b/src/OneScript.DebugServices/ThreadManager.cs @@ -80,16 +80,22 @@ public int[] GetAllThreadIds() { return _machinesOnThreads.Keys.ToArray(); } - - public void Dispose() + + public void ReleaseAllThreads() { var tokens = GetAllTokens(); foreach (var machineWaitToken in tokens) { machineWaitToken.Machine.MachineStopped -= Machine_MachineStopped; + machineWaitToken.Dispose(); } _machinesOnThreads.Clear(); } + + public void Dispose() + { + ReleaseAllThreads(); + } } } \ No newline at end of file diff --git a/src/OneScript.Language/ErrorPositionInfo.cs b/src/OneScript.Language/ErrorPositionInfo.cs index 4f559c6d6..ed68a6272 100644 --- a/src/OneScript.Language/ErrorPositionInfo.cs +++ b/src/OneScript.Language/ErrorPositionInfo.cs @@ -22,5 +22,6 @@ public ErrorPositionInfo() public string Code { get; set; } public string ModuleName { get; set; } + public bool IsEmpty => LineNumber == OUT_OF_TEXT && ColumnNumber == OUT_OF_TEXT && ModuleName == default; } } diff --git a/src/OneScript.Language/IdentifiersTrie.cs b/src/OneScript.Language/IdentifiersTrie.cs index 6eb3bc0e0..df4b68a19 100644 --- a/src/OneScript.Language/IdentifiersTrie.cs +++ b/src/OneScript.Language/IdentifiersTrie.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; using System.Collections.Generic; @@ -12,14 +13,29 @@ namespace OneScript.Language { public class IdentifiersTrie : IDictionary { + private readonly TrieNode _root = new TrieNode(); + private class TrieNode { public char charL; public char charU; - public T value; public TrieNode sibl; public TrieNode next; + private T _value; + + public T Value + { + get => _value; + set + { + HasValue = true; + _value = value; + } + } + + public bool HasValue { get; private set; } + public TrieNode Find(char ch) { var node = sibl; @@ -31,13 +47,7 @@ public TrieNode Find(char ch) } return null; } - } - - private readonly TrieNode _root; - public IdentifiersTrie() - { - _root = new TrieNode(); } public void Add(string str, T val) @@ -52,7 +62,7 @@ public void Add(string str, T val) { charL = char.ToLower(ch), charU = char.ToUpper(ch), - value = default(T), + Value = default(T), sibl = node.sibl }; node.sibl = key; @@ -61,12 +71,23 @@ public void Add(string str, T val) node = key.next; } - node.value = val; + node.Value = val; } public bool ContainsKey(string key) { - throw new System.NotImplementedException(); + var node = _root; + foreach (char ch in key) + { + var keyNode = node.Find(ch); + if (keyNode == null) + { + return false; + } + node = keyNode.next; + } + + return node.next == null && node.HasValue; } public bool Remove(string key) @@ -85,8 +106,11 @@ public T Get(string str) node = key.next; } + + if (!node.HasValue) + throw new KeyNotFoundException(); - return node.value; + return node.Value; } public T this[string index] @@ -95,8 +119,8 @@ public T this[string index] set => Add(index, value); } - public ICollection Keys { get; } - public ICollection Values { get; } + public ICollection Keys => throw new NotSupportedException(); + public ICollection Values => throw new NotSupportedException(); public bool TryGetValue(string str, out T value) { @@ -106,14 +130,20 @@ public bool TryGetValue(string str, out T value) var key = node.Find(ch); if (key == null) { - value = default(T); + value = default; return false; } node = key.next; } - value = node.value; + if (!node.HasValue) + { + value = default; + return false; + } + + value = node.Value; return true; } diff --git a/src/OneScript.Language/ScriptException.cs b/src/OneScript.Language/ScriptException.cs index f438bfb13..ff5918106 100644 --- a/src/OneScript.Language/ScriptException.cs +++ b/src/OneScript.Language/ScriptException.cs @@ -15,12 +15,12 @@ public class ScriptException : ApplicationException { private readonly ErrorPositionInfo _codePosition; - public ScriptException(string message) - : this(new ErrorPositionInfo(), message, null) + public ScriptException(string message, Exception innerException = null) + : this(new ErrorPositionInfo(), message, innerException) { } - public ScriptException(ErrorPositionInfo errorInfo, string message, Exception innerException = null) + protected ScriptException(ErrorPositionInfo errorInfo, string message, Exception innerException = null) : base(message, innerException) { _codePosition = errorInfo ?? throw new ArgumentNullException(nameof(errorInfo)); @@ -104,5 +104,16 @@ public override string Message } public object RuntimeSpecificInfo { get; set; } + + public void SetPositionIfEmpty(ErrorPositionInfo newPosition) + { + if (!_codePosition.IsEmpty) + return; + + _codePosition.LineNumber = newPosition.LineNumber; + _codePosition.ColumnNumber = newPosition.ColumnNumber; + _codePosition.Code = newPosition.Code; + _codePosition.ModuleName = newPosition.ModuleName; + } } } diff --git a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs index 7bd4d26f3..b2f8b73fe 100644 --- a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs +++ b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs @@ -123,6 +123,9 @@ public static CodeError PreprocessorDefinitionExpected() => public static CodeError UseBuiltInFunctionAsProcedure() => Create("Использование встроенной функции, как процедуры", "Using build-in function as procedure"); + public static CodeError UseProcAsFunction() => + Create("Использование процедуры, как функции", "Procedure called as function"); + public static CodeError DuplicateVarDefinition(string varName) => Create($"Переменная {varName} уже определена", $"Variable {varName} already defined"); diff --git a/src/OneScript.Language/SyntaxAnalysis/PreprocessorHandlers.cs b/src/OneScript.Language/SyntaxAnalysis/PreprocessorHandlers.cs index 53b5c3ded..0649be80a 100644 --- a/src/OneScript.Language/SyntaxAnalysis/PreprocessorHandlers.cs +++ b/src/OneScript.Language/SyntaxAnalysis/PreprocessorHandlers.cs @@ -51,7 +51,7 @@ public PreprocessorHandlers Slice(Func predicate) { var slice = _handlers.Where(predicate).ToArray(); if (slice.Length == 0) - return default; + return new PreprocessorHandlers(); return new PreprocessorHandlers(slice); } diff --git a/src/OneScript.Native/Compiler/BinaryOperationCompiler.cs b/src/OneScript.Native/Compiler/BinaryOperationCompiler.cs index 439ec500a..76f47f7a8 100644 --- a/src/OneScript.Native/Compiler/BinaryOperationCompiler.cs +++ b/src/OneScript.Native/Compiler/BinaryOperationCompiler.cs @@ -10,8 +10,6 @@ This Source Code Form is subject to the terms of the using System.Linq.Expressions; using System.Reflection; using OneScript.Language.SyntaxAnalysis.AstNodes; -using OneScript.Native.Runtime; -using OneScript.Values; namespace OneScript.Native.Compiler { @@ -35,11 +33,6 @@ public Expression Compile(BinaryOperationNode node, Expression left, Expression private Expression CompileStaticOperation(Expression left, Expression right) { - if (IsEqualityOperation(_opCode)) - { - return MakeStaticEqualityOperation(left, right); - } - if (left.Type.IsNumeric()) { return MakeNumericOperation(left, right); @@ -52,15 +45,7 @@ private Expression CompileStaticOperation(Expression left, Expression right) if (left.Type == typeof(string)) { - if (_opCode == ExpressionType.Add) - return StringAddition(left, right); - - // Для строк допустимо сравнение со строками на < > - if (IsComparisonOperation(_opCode)) - { - // для простоты сделаем через BslValue.CompareTo - return MakeDynamicComparison(left, right); - } + return MakeStringOperation(left, right); } if (left.Type == typeof(bool)) @@ -71,9 +56,28 @@ private Expression CompileStaticOperation(Expression left, Expression right) throw NativeCompilerException.OperationNotDefined(_opCode, left.Type, right.Type); } - private Expression MakeStaticEqualityOperation(Expression left, Expression right) + private Expression MakeStringOperation(Expression left, Expression right) { - return Expression.MakeBinary(_opCode, left, right); + if (_opCode == ExpressionType.Add) + { + return StringAddition(left, right); + } + + // Для строк допустимо сравнение со строками на < > + if (IsComparisonOperation(_opCode)) + { + // для простоты сделаем через BslValue.CompareTo + return MakeDynamicComparison(left, right); + } + + if (IsEqualityOperation(_opCode)) + { + return right.Type == typeof(string) ? + Expression.MakeBinary(_opCode, left, right) + : MakeDynamicEquality(left, right); + } + + throw NativeCompilerException.OperationNotDefined(_opCode, left.Type, right.Type); } private Expression MakeNumericOperation(Expression left, Expression right) @@ -195,7 +199,7 @@ private Expression CompileDynamicOperation(Expression left, Expression right) case ExpressionType.OrElse: return MakeLogicalOperation(left, right); default: - throw new NativeCompilerException($"Operation {_opCode} is not defined for IValues"); + throw NativeCompilerException.OperationNotDefined(_opCode, left.Type, right.Type); } } diff --git a/src/OneScript.Native/Compiler/CompilerHelpers.cs b/src/OneScript.Native/Compiler/CompilerHelpers.cs index 3501e5509..2afe69439 100644 --- a/src/OneScript.Native/Compiler/CompilerHelpers.cs +++ b/src/OneScript.Native/Compiler/CompilerHelpers.cs @@ -28,6 +28,7 @@ public static BslPrimitiveValue ValueFromLiteral(in Lexem lex) LexemType.StringLiteral => BslStringValue.Create(lex.Content), LexemType.DateLiteral => BslDateValue.Parse(lex.Content), LexemType.UndefinedLiteral => BslUndefinedValue.Instance, + LexemType.NullLiteral => BslNullValue.Instance, _ => throw new NotImplementedException() }; } @@ -41,24 +42,23 @@ public static object ClrValueFromLiteral(in Lexem lex) LexemType.StringLiteral => (string)BslStringValue.Create(lex.Content), LexemType.DateLiteral => (DateTime)BslDateValue.Parse(lex.Content), LexemType.UndefinedLiteral => BslUndefinedValue.Instance, + LexemType.NullLiteral => BslNullValue.Instance, _ => throw new NotImplementedException() }; } - public static IEnumerable GetAnnotations(IEnumerable annotations) + public static IEnumerable GetAnnotations(IEnumerable annotations) { // Возможно будут какие-то маппинги на системные атрибуты, не только на BslAnnotation - // поэтому возвращаем object[] а не BslAnnotation[] + // поэтому возвращаем Attribute[] а не BslAnnotation[] - var mappedAnnotations = new List(); - foreach (var node in annotations) - { - var anno = new BslAnnotationAttribute(node.Name); - anno.SetParameters(GetAnnotationParameters(node)); - mappedAnnotations.Add(anno); - } - - return mappedAnnotations; + return annotations.Select(GetBslAnnotation).ToList(); + } + + public static BslAnnotationAttribute GetBslAnnotation(AnnotationNode node) + { + var parameters = GetAnnotationParameters(node); + return new BslAnnotationAttribute(node.Name, parameters); } public static Type GetClrType(TypeDescriptor type) @@ -83,10 +83,26 @@ public static Type GetClrType(TypeDescriptor type) private static IEnumerable GetAnnotationParameters(AnnotationNode node) { return node.Children.Cast() - .Select(param => new BslAnnotationParameter(param.Name, ValueFromLiteral(param.Value))) + .Select(MakeAnnotationParameter) .ToList(); } + private static BslAnnotationParameter MakeAnnotationParameter(AnnotationParameterNode param) + { + BslAnnotationParameter result; + if (param.Value.Type != LexemType.NotALexem) + { + var runtimeValue = ValueFromLiteral(param.Value); + result = new BslAnnotationParameter(param.Name, runtimeValue); + } + else + { + result = new BslAnnotationParameter(param.Name, null); + } + + return result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string GetIdentifier(this BslSyntaxNode node) { diff --git a/src/OneScript.Native/Compiler/DateOperations.cs b/src/OneScript.Native/Compiler/DateOperations.cs index 91ca2cd06..4627a2d2f 100644 --- a/src/OneScript.Native/Compiler/DateOperations.cs +++ b/src/OneScript.Native/Compiler/DateOperations.cs @@ -34,7 +34,7 @@ public static Expression DateOffsetOperation(Expression left, Expression right, { ExpressionType.Add => toDouble, ExpressionType.Subtract => Expression.Negate(toDouble), - _ => throw new NativeCompilerException($"Operation {opCode} is not defined for dates") + _ => throw NativeCompilerException.OperationNotDefined(opCode, left.Type, right.Type) }; return Expression.Call(left, adder, arg); diff --git a/src/OneScript.Native/Compiler/ExpressionHelpers.cs b/src/OneScript.Native/Compiler/ExpressionHelpers.cs index 0c69b630c..c141e641a 100644 --- a/src/OneScript.Native/Compiler/ExpressionHelpers.cs +++ b/src/OneScript.Native/Compiler/ExpressionHelpers.cs @@ -12,8 +12,10 @@ This Source Code Form is subject to the terms of the using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; using Microsoft.CSharp.RuntimeBinder; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Language.LexicalAnalysis; using OneScript.Localization; using OneScript.Native.Runtime; @@ -33,6 +35,9 @@ public static Expression DowncastDecimal(Expression decimalValue, Type targetTyp public static Expression CastToDecimal(Expression value) { + if (value.Type == typeof(decimal)) + return value; + return Expression.Convert(value, typeof(decimal)); } @@ -105,6 +110,11 @@ public static Expression ToBoolean(Expression right) if (right.Type.IsValue()) return ConvertBslValueToPrimitiveType(right, typeof(bool)); + + if (right.Type.IsNumeric()) + { + return Expression.NotEqual(right, Expression.Default(right.Type)); + } return Expression.Convert(right, typeof(bool)); } @@ -176,7 +186,7 @@ private static Expression ConvertBslValueToPrimitiveType(Expression right, Type { return TryConvertBslValueToPrimitiveType(right, type) ?? throw new NativeCompilerException( - new BilingualString( + BilingualString.Localize( $"Преобразование {right.Type} в тип {type} недоступно", $"Conversion from {right.Type} to {type} is unavailable") ); @@ -351,27 +361,25 @@ private static bool IsNullable(Type targetType) public static Expression CallCompareTo(Expression target, Expression argument) { var compareToMethod = OperationsCache.GetOrAdd( - typeof(IComparable), - nameof(IComparable.CompareTo), - BindingFlags.Instance | BindingFlags.Public + typeof(DynamicOperations), + nameof(DynamicOperations.Comparison) ); - var bslArgument = ConvertToBslValue(argument); + Debug.Assert(argument.Type.IsValue()); - return Expression.Call(target, compareToMethod, bslArgument); + return Expression.Call(compareToMethod, target, argument); } public static Expression CallEquals(Expression target, Expression argument) { var equalsMethod = OperationsCache.GetOrAdd( - typeof(IEquatable), - nameof(IEquatable.Equals), - BindingFlags.Instance | BindingFlags.Public + typeof(DynamicOperations), + nameof(DynamicOperations.Equality) ); - var bslArgument = ConvertToBslValue(argument); + Debug.Assert(argument.Type.IsValue()); - return Expression.Call(target, equalsMethod, bslArgument); + return Expression.Call(equalsMethod, target, argument); } public static Expression ConvertToBslValue(Expression value) @@ -382,7 +390,8 @@ public static Expression ConvertToBslValue(Expression value) var factoryClass = GetValueFactoryType(value.Type); if (factoryClass == null) { - if (value.Type == typeof(object)) + if (value.Type==typeof(IValue) || value.Type.IsSubclassOf(typeof(IValue)) + || value.Type == typeof(object)) { // это результат динамической операции // просто верим, что он BslValue @@ -391,7 +400,7 @@ public static Expression ConvertToBslValue(Expression value) nameof(DynamicOperations.WrapClrObjectToValue)); return Expression.Call(meth, value); } - throw new NativeCompilerException(new BilingualString( + throw new NativeCompilerException(BilingualString.Localize( $"Преобразование из типа {value.Type} в тип BslValue не поддерживается", $"Conversion from type {value.Type} into BslValue is not supported")); } @@ -404,6 +413,7 @@ public static Expression ConvertToBslValue(Expression value) var factory = OperationsCache.GetOrAdd(factoryClass, "Create"); return Expression.Call(factory, value); } + public static (Expression, Expression) ConvertToCompatibleBslValues(Expression value1, Expression value2) { value1 = ConvertToBslValue(value1); @@ -432,20 +442,18 @@ private static Type GetValueFactoryType(Type clrType) { factoryClass = typeof(BslBooleanValue); } - else if (clrType == typeof(decimal)) + else if (clrType.IsNumeric()) { - factoryClass = typeof(BslNumericValue); - } - else if (clrType == typeof(int) || - clrType == typeof(long) || - clrType == typeof(double)) - { - factoryClass = typeof(BslNumericValue); + factoryClass = typeof(BslNumericValue); } else if (clrType == typeof(DateTime)) { factoryClass = typeof(BslDateValue); } + else if (clrType == typeof(TypeDescriptor)) + { + factoryClass = typeof(BslTypeValue); + } return factoryClass; } @@ -484,7 +492,7 @@ public static Expression CreateAssignmentSource(Expression source, Type targetTy if (canBeCasted) return conversion; - throw new NativeCompilerException(new BilingualString( + throw new NativeCompilerException(BilingualString.Localize( $"Преобразование из типа {source.Type} в тип {targetType} не поддерживается", $"Conversion from type {source.Type} into {targetType} is not supported")); } @@ -508,12 +516,23 @@ public static Expression ConstructorCall(ITypeManager typeManager, Expression se public static Expression ConstructorCall(ITypeManager typeManager, Expression services, TypeDescriptor knownType, Expression[] argsArray) { - var genericMethod = OperationsCache.GetOrAdd( - typeof(DynamicOperations), - nameof(DynamicOperations.StrictConstructorCall)); + MethodInfo method; + + if (knownType.ImplementingClass.IsValue()) + { + var genericMethod = OperationsCache.GetOrAdd( + typeof(DynamicOperations), + nameof(DynamicOperations.StrictConstructorCall)); + + method = genericMethod.MakeGenericMethod(knownType.ImplementingClass); + } + else // подключенный сценарий + { + method = OperationsCache.GetOrAdd( + typeof(DynamicOperations), + nameof(DynamicOperations.ConstructorCall)); + } - var method = genericMethod.MakeGenericMethod(knownType.ImplementingClass); - var arrayOfArgs = Expression.NewArrayInit(typeof(BslValue), argsArray.Select(ConvertToBslValue)); return Expression.Call(method, @@ -526,20 +545,30 @@ public static Expression ConstructorCall(ITypeManager typeManager, Expression se public static Expression TypeByNameCall(ITypeManager manager, Expression argument) { var method = OperationsCache.GetOrAdd(typeof(DynamicOperations), nameof(DynamicOperations.GetTypeByName), - BindingFlags.Instance | BindingFlags.Public); + BindingFlags.Static | BindingFlags.Public); Debug.Assert(method != null); return Expression.Call(method, Expression.Constant(manager), argument); } - public static Expression GetExceptionInfo(ParameterExpression excVariable) + public static Expression GetExceptionInfo(Expression factory, ParameterExpression excVariable) { var method = OperationsCache.GetOrAdd( typeof(DynamicOperations), nameof(DynamicOperations.GetExceptionInfo)); - return Expression.Call(method, excVariable); + return Expression.Call(method, factory, excVariable); + } + + public static Expression CallOfInstanceMethod(Expression instance, string name, params Expression[] arguments) + { + var method = OperationsCache.GetOrAdd( + instance.Type, + name, + BindingFlags.Public | BindingFlags.Instance); + + return Expression.Call(instance, method, arguments); } public static Expression AccessModuleVariable(ParameterExpression thisArg, int variableIndex) @@ -566,11 +595,11 @@ public static Expression GetContextPropertyValue(IRuntimeContextInstance target, nameof(IRuntimeContextInstance.GetPropValue), BindingFlags.Instance | BindingFlags.Public); - return Expression.Call( + return Expression.Convert(Expression.Call( Expression.Constant(target), getter, Expression.Constant(propertyNumber) - ); + ), typeof(BslValue)); } public static Expression GetContextPropertyValue(Expression target, string propertyName) @@ -622,7 +651,7 @@ public static Expression InvokeBslNativeMethod(BslNativeMethodInfo nativeMethod, PackArgsToArgsArray(args)); } - private static Expression PackArgsToArgsArray(List args) + private static Expression PackArgsToArgsArray(IEnumerable args) { return Expression.NewArrayInit(typeof(BslValue), args.Select(ConvertToBslValue)); } @@ -675,5 +704,22 @@ private static bool IsModuleVariable(Expression counterVar) return memberExpr.Expression.Type == typeof(IVariable) && memberExpr.Member.Name == nameof(IVariable.BslValue); } + + public static Expression CallContextMethod(Expression target, string name, IEnumerable arguments) + { + var methodInfo = OperationsCache.GetOrAdd( + typeof(DynamicOperations), + nameof(DynamicOperations.CallContextMethod) + ); + + var argExpressions = new List + { + target, + Expression.Constant(name), + PackArgsToArgsArray(arguments) + }; + + return Expression.Call(methodInfo, argExpressions); + } } } diff --git a/src/OneScript.Native/Compiler/MethodCompiler.cs b/src/OneScript.Native/Compiler/MethodCompiler.cs index c5b83f2db..522bdeb3a 100644 --- a/src/OneScript.Native/Compiler/MethodCompiler.cs +++ b/src/OneScript.Native/Compiler/MethodCompiler.cs @@ -18,6 +18,7 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation.Binding; using OneScript.Contexts; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Language; using OneScript.Language.LexicalAnalysis; using OneScript.Language.SyntaxAnalysis; @@ -42,6 +43,7 @@ public class MethodCompiler : ExpressionTreeGeneratorBase private readonly BinaryOperationCompiler _binaryOperationCompiler = new BinaryOperationCompiler(); private ITypeManager _typeManager; + private IExceptionInfoFactory _exceptionInfoFactory; private readonly IServiceContainer _services; private readonly BuiltInFunctionsCache _builtInFunctions = new BuiltInFunctionsCache(); @@ -56,19 +58,20 @@ public MethodCompiler(BslWalkerContext walkContext, BslNativeMethodInfo method) _source = walkContext.Source; } - private ITypeManager CurrentTypeManager + private ITypeManager CurrentTypeManager => GetService(_services, ref _typeManager); + + private IExceptionInfoFactory ExceptionInfoFactory => GetService(_services, ref _exceptionInfoFactory); + + private static T GetService(IServiceContainer services, ref T value) where T : class { - get - { - if (_typeManager != default) - return _typeManager; + if (value != default) + return value; - _typeManager = _services.TryResolve(); - if (_typeManager == default) - throw new NotSupportedException("Type manager is not registered in services."); + value = services.TryResolve(); + if (value == default) + throw new NotSupportedException($"{typeof(T)} is not registered in services."); - return _typeManager; - } + return value; } public void CompileMethod(MethodNode methodNode) @@ -186,20 +189,21 @@ protected override void VisitStatement(BslSyntaxNode statement) catch (NativeCompilerException e) { RestoreNestingLevel(nestingLevel); - e.Position ??= ToCodePosition(statement.Location); + e.SetPositionIfEmpty(ToCodePosition(statement.Location)); AddError(new CodeError { Description = e.Message, - Position = e.Position, + Position = e.GetPosition(), ErrorId = nameof(NativeCompilerException) }); } catch (Exception e) { + RestoreNestingLevel(nestingLevel); if (e is NativeCompilerException ce) { - ce.Position ??= ToCodePosition(statement.Location); + ce.SetPositionIfEmpty(ToCodePosition(statement.Location)); throw; } @@ -660,13 +664,25 @@ private Expression CompileBinaryOp(Expression left, Expression right, BinaryOper protected override void VisitReturnNode(BslSyntaxNode node) { - Debug.Assert(node.Children.Count > 0); + if (_method.IsFunction() && node.Children.Count == 0) + { + AddError(LocalizedErrors.FuncEmptyReturnValue(), node.Location); + return; + } + var label = _blocks.GetCurrentBlock().MethodReturn; + + if (!_method.IsFunction() && node.Children.Count == 0) + { + var undefinedExpr = Expression.Constant(BslUndefinedValue.Instance); + _blocks.Add(Expression.Return(label, undefinedExpr)); + return; + } + VisitExpression(node.Children[0]); var resultExpr = _statementBuildParts.Pop(); - - var label = _blocks.GetCurrentBlock().MethodReturn; + if (!resultExpr.Type.IsValue()) resultExpr = ExpressionHelpers.ConvertToType(resultExpr, typeof(BslValue)); @@ -1023,15 +1039,13 @@ protected override void VisitRaiseNode(BslSyntaxNode node) else { VisitExpression(node.Children[0]); - var expression = Expression.Call( - _statementBuildParts.Pop(), - typeof(object).GetMethod("ToString")); + var raiseArgExpression = ExpressionHelpers.ToString(_statementBuildParts.Pop()); + + var exceptionExpression = ExpressionHelpers.CallOfInstanceMethod( + Expression.Constant(ExceptionInfoFactory), + nameof(IExceptionInfoFactory.Raise), + raiseArgExpression); - var exceptionType = typeof(RuntimeException); - var ctor = exceptionType.GetConstructor(new Type[] {typeof(BilingualString)}); - var exceptionExpression = Expression.New( - ctor, - Expression.Convert(expression, typeof(BilingualString))); _blocks.Add(Expression.Throw(exceptionExpression)); } base.VisitRaiseNode(node); @@ -1060,6 +1074,15 @@ protected override void VisitGlobalFunctionCall(CallNode node) _statementBuildParts.Push(CreateBuiltInFunctionCall(node)); return; } + + var methodExists = Symbols.TryFindMethod( + node.Identifier.GetIdentifier(), out var methodSymbol); + + if (methodExists && !methodSymbol.Method.IsFunction()) + { + AddError(LocalizedErrors.UseProcAsFunction(), node.Location); + } + var expression = CreateMethodCall(node); _statementBuildParts.Push(expression); } @@ -1100,7 +1123,7 @@ protected override void VisitObjectProcedureCall(BslSyntaxNode node) } else { - AddError(new BilingualString($"Тип {targetType} не является объектным типом.",$"Type {targetType} is not an object type."), node.Location); + AddError(NativeCompilerErrors.TypeIsNotAnObjectType(targetType), node.Location); } } @@ -1109,7 +1132,7 @@ private IEnumerable PrepareDynamicCallArguments(BslSyntaxNode argLis return argList.Children.Select(passedArg => passedArg.Children.Count > 0 ? ConvertToExpressionTree(passedArg.Children[0]) - : null); + : Expression.Constant(BslSkippedParameterValue.Instance)); } protected override void VisitObjectFunctionCall(BslSyntaxNode node) @@ -1124,7 +1147,7 @@ protected override void VisitObjectFunctionCall(BslSyntaxNode node) var methodInfo = FindMethodOfType(node, targetType, name); if (methodInfo.ReturnType == typeof(void)) { - throw new NativeCompilerException(new BilingualString( + throw new NativeCompilerException(BilingualString.Localize( $"Метод {targetType}.{name} не является функцией", $"Method {targetType}.{name} is not a function"), ToCodePosition(node.Location)); } @@ -1132,6 +1155,10 @@ protected override void VisitObjectFunctionCall(BslSyntaxNode node) var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters()); _statementBuildParts.Push(Expression.Call(target, methodInfo, args)); } + else if (targetType.IsContext()) + { + _statementBuildParts.Push(ExpressionHelpers.CallContextMethod(target, name, PrepareDynamicCallArguments(call.ArgumentList))); + } else if (targetType.IsValue() || target is DynamicExpression) { var args = new List(); @@ -1154,7 +1181,7 @@ protected override void VisitObjectFunctionCall(BslSyntaxNode node) } else { - AddError(new BilingualString($"Тип {targetType} не является объектным типом.",$"Type {targetType} is not an object type."), node.Location); + AddError(NativeCompilerErrors.TypeIsNotAnObjectType(targetType), node.Location); } } @@ -1167,7 +1194,7 @@ private MethodInfo FindMethodOfType(BslSyntaxNode node, Type targetType, string } catch (InvalidOperationException) { - throw new NativeCompilerException(new BilingualString( + throw new NativeCompilerException(BilingualString.Localize( $"Метод {name} не определен для типа {targetType}", $"Method {name} is not defined for type {targetType}"), ToCodePosition(node.Location)); } @@ -1199,7 +1226,7 @@ private PropertyInfo FindPropertyOfType(BslSyntaxNode node, Type targetType, str } catch (InvalidOperationException) { - throw new NativeCompilerException(new BilingualString( + throw new NativeCompilerException(BilingualString.Localize( $"Свойство {name} не определено для типа {targetType}", $"Property {name} is not defined for type {targetType}")); } @@ -1209,7 +1236,7 @@ private PropertyInfo FindPropertyOfType(BslSyntaxNode node, Type targetType, str private Expression CreateMethodCall(CallNode node) { - if (!Symbols.FindMethod(node.Identifier.GetIdentifier(), out var binding)) + if (!Symbols.TryFindMethodBinding(node.Identifier.GetIdentifier(), out var binding)) { AddError($"Unknown method {node.Identifier.GetIdentifier()}", node.Location); return null; @@ -1264,7 +1291,7 @@ private Expression CreateBuiltInFunctionCall(CallNode node) case Token.Type: CheckArgumentsCount(node.ArgumentList, 1); result = ExpressionHelpers.TypeByNameCall(CurrentTypeManager, - ConvertToExpressionTree(node.ArgumentList.Children[0])); + ConvertToExpressionTree(node.ArgumentList.Children[0].Children[0])); break; case Token.ExceptionInfo: CheckArgumentsCount(node.ArgumentList, 0); @@ -1295,20 +1322,37 @@ private Expression CreateBuiltInFunctionCall(CallNode node) private Expression GetRuntimeExceptionDescription() { - var excInfo = GetRuntimeExceptionObject(); - if (excInfo.Type == typeof(BslUndefinedValue)) - return excInfo; - - return Expression.Property(excInfo, nameof(ExceptionInfoClass.Description)); + var excVariable = _blocks.GetCurrentBlock().CurrentException; + Expression factoryArgument; + // нас вызвали вне попытки-исключения + factoryArgument = excVariable == null ? Expression.Constant(null, typeof(IRuntimeContextInstance)) : GetRuntimeExceptionObject(); + + var factory = Expression.Constant(ExceptionInfoFactory); + return ExpressionHelpers.CallOfInstanceMethod( + factory, + nameof(IExceptionInfoFactory.GetExceptionDescription), + factoryArgument); } private Expression GetRuntimeExceptionObject() { var excVariable = _blocks.GetCurrentBlock().CurrentException; + Expression factoryArgument; if (excVariable == null) - return Expression.Constant(BslUndefinedValue.Instance); - - return ExpressionHelpers.GetExceptionInfo(excVariable); + { + // нас вызвали вне попытки-исключения + factoryArgument = Expression.Constant(null, typeof(Exception)); + } + else + { + factoryArgument = excVariable; + } + + var factory = Expression.Constant(ExceptionInfoFactory); + return ExpressionHelpers.CallOfInstanceMethod( + factory, + nameof(IExceptionInfoFactory.GetExceptionInfo), + factoryArgument); } private void CheckArgumentsCount(BslSyntaxNode argList, int needed) @@ -1376,8 +1420,22 @@ private List PrepareCallArguments(BslSyntaxNode argList, ParameterIn } else { - var convertedOrDirect = PassSingleParameter(passedArg, declaredParam.ParameterType, argList.Location); - factArguments.Add(convertedOrDirect); + if (passedArg != null) + { + var convertedOrDirect = PassSingleParameter(passedArg, declaredParam.ParameterType, argList.Location); + factArguments.Add(convertedOrDirect); + } + else if (declaredParam.HasDefaultValue) + { + factArguments.Add(Expression.Constant(declaredParam.DefaultValue, declaredParam.ParameterType)); + } + else + { + var errText = new BilingualString( + $"Пропущен обязательный параметр {declaredParam.Position+1} '{declaredParam.Name}'", + $"Missing mandatory parameter {declaredParam.Position+1} '{declaredParam.Name}'"); + AddError(errText, argList.Location); + } } --parametersToProcess; @@ -1407,15 +1465,16 @@ private Expression PassSingleParameter(Expression passedArg, Type targetType, Co { if (passedArg == null) { - return Expression.Default(targetType); + return Expression.Constant(BslSkippedParameterValue.Instance); } - + var convertedOrDirect = ExpressionHelpers.TryConvertParameter(passedArg, targetType); if (convertedOrDirect == null) { AddError( new BilingualString( - $"Не удается выполнить преобразование из типа {passedArg.Type} в тип {targetType}"), + $"Не удается выполнить преобразование параметра из типа {passedArg.Type} в тип {targetType}", + $"Cannot convert parameter from type {passedArg.Type} to type {targetType}"), location); } @@ -1452,9 +1511,18 @@ protected override void VisitNewObjectCreation(NewObjectNode node) else { var typeNameString = node.TypeNameNode.GetIdentifier(); - var typeDef = CurrentTypeManager.GetTypeByName(typeNameString); - var call = ExpressionHelpers.ConstructorCall(CurrentTypeManager, services, typeDef, parameters); - _statementBuildParts.Push(call); + var isKnownType = CurrentTypeManager.TryGetType(typeNameString, out var typeDef); + if (isKnownType) + { + var call = ExpressionHelpers.ConstructorCall(CurrentTypeManager, services, typeDef, parameters); + _statementBuildParts.Push(call); + } + else // это может быть тип, подключенный через ПодключитьСценарий + { + var typeName = Expression.Constant(typeNameString); + var call = ExpressionHelpers.ConstructorCall(CurrentTypeManager, services, typeName, parameters); + _statementBuildParts.Push(call); + } } } diff --git a/src/OneScript.Native/Compiler/ModuleCompiler.cs b/src/OneScript.Native/Compiler/ModuleCompiler.cs index 7ea4733fc..07c200a31 100644 --- a/src/OneScript.Native/Compiler/ModuleCompiler.cs +++ b/src/OneScript.Native/Compiler/ModuleCompiler.cs @@ -10,7 +10,9 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation.Binding; using OneScript.Contexts; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Language; +using OneScript.Language.LexicalAnalysis; using OneScript.Language.SyntaxAnalysis; using OneScript.Language.SyntaxAnalysis.AstNodes; using OneScript.Native.Runtime; @@ -22,13 +24,16 @@ namespace OneScript.Native.Compiler public class ModuleCompiler : ExpressionTreeGeneratorBase { private readonly IServiceContainer _runtimeServices; + private readonly ICompileTimeDependencyResolver _dependencyResolver; private DynamicModule _module; private readonly BslMethodInfoFactory _methodsFactory; - public ModuleCompiler(IErrorSink errors, IServiceContainer runtimeServices) : base(errors) + public ModuleCompiler(IErrorSink errors, IServiceContainer runtimeServices, ICompileTimeDependencyResolver dependencyResolver) : base(errors) { _runtimeServices = runtimeServices; + _dependencyResolver = dependencyResolver; _methodsFactory = new BslMethodInfoFactory(() => new BslNativeMethodInfo()); + } public DynamicModule Compile( @@ -73,14 +78,14 @@ private void RegisterLocalMethods(BslSyntaxNode module) foreach (var methodNode in methodsSection.Children.Cast()) { var signature = methodNode.Signature; - if (Symbols.FindMethod(signature.MethodName, out _)) + if (Symbols.TryFindMethodBinding(signature.MethodName, out _)) { AddError(LocalizedErrors.DuplicateMethodDefinition(signature.MethodName), signature.Location); continue; } var builder = _methodsFactory.NewMethod(); - builder.SetAnnotations(methodNode.Annotations); + builder.SetAnnotations(CompilerHelpers.GetAnnotations(methodNode.Annotations)); builder.SetDispatchingIndex(ownMethodsCount++); VisitMethodSignature(builder, methodNode.Signature); @@ -186,5 +191,51 @@ protected override void VisitModuleBody(BslSyntaxNode moduleBody) var methCompiler = new MethodCompiler(context, method); methCompiler.CompileModuleBody(moduleBody); } + + protected override void VisitModuleAnnotation(AnnotationNode node) + { + if (node.Kind == NodeKind.Import) + { + HandleImportClause(node); + } + + var annotation = CompilerHelpers.GetBslAnnotation(node); + _module.ModuleAttributes.Add(annotation); + } + + private void HandleImportClause(AnnotationNode node) + { + var libName = node.Children + .Cast() + .First() + .Value + .Content; + + try + { + _dependencyResolver.Resolve(_module.Source, libName); + } + catch (DependencyResolveException e) + { + var error = new CodeError + { + Description = e.Message, + Position = MakeCodePosition(node.Location), + ErrorId = nameof(CompilerException) + }; + AddError(error); + } + } + + private ErrorPositionInfo MakeCodePosition(CodeRange range) + { + return new ErrorPositionInfo + { + Code = _module.Source.GetCodeLine(range.LineNumber), + LineNumber = range.LineNumber, + ColumnNumber = range.ColumnNumber, + ModuleName = _module.Source.Name + }; + } } } \ No newline at end of file diff --git a/src/OneScript.Native/Compiler/NativeCompilerErrors.cs b/src/OneScript.Native/Compiler/NativeCompilerErrors.cs new file mode 100644 index 000000000..5f484a2ca --- /dev/null +++ b/src/OneScript.Native/Compiler/NativeCompilerErrors.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 System; +using System.Runtime.CompilerServices; +using OneScript.Language; +using OneScript.Localization; + +namespace OneScript.Native.Compiler +{ + public class NativeCompilerErrors + { + public static CodeError TypeIsNotAnObjectType(Type targetType) => + Create($"Тип {targetType} не является объектным типом.",$"Type {targetType} is not an object type."); + + private static CodeError Create(string ru, string en, [CallerMemberName] string errorId = default) + { + return new CodeError + { + ErrorId = errorId, + Description = BilingualString.Localize(ru, en) + }; + } + } +} \ No newline at end of file diff --git a/src/OneScript.Native/Compiler/NativeCompilerException.cs b/src/OneScript.Native/Compiler/NativeCompilerException.cs index 795b2a9ba..534fce904 100644 --- a/src/OneScript.Native/Compiler/NativeCompilerException.cs +++ b/src/OneScript.Native/Compiler/NativeCompilerException.cs @@ -7,33 +7,26 @@ This Source Code Form is subject to the terms of the using System; using System.Linq.Expressions; -using OneScript.Commons; +using OneScript.Compilation; +using OneScript.Exceptions; using OneScript.Language; using OneScript.Localization; namespace OneScript.Native.Compiler { - public class NativeCompilerException : BslCoreException + public class NativeCompilerException : CompilerException { - public ErrorPositionInfo Position { get; set; } - - public NativeCompilerException(BilingualString message) : base(message) - { - } - - public NativeCompilerException(BilingualString message, ErrorPositionInfo position) : base(message) + public NativeCompilerException(string message) : base(message) { - Position = position; } - public NativeCompilerException(BilingualString message, ErrorPositionInfo position, Exception innerException) : base(message, innerException) + public NativeCompilerException(string message, ErrorPositionInfo position) : base(message, position) { - Position = position; } public static NativeCompilerException OperationNotDefined(ExpressionType opCode, Type left, Type right) => new NativeCompilerException( - new BilingualString( + BilingualString.Localize( $"Операция {opCode} не определена для типов {left} и {right}", $"Operation {opCode} is not defined for {left} and {right}") ); diff --git a/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs b/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs index 25936a87e..6ff0b9183 100644 --- a/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs +++ b/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs @@ -27,19 +27,19 @@ public NativeRuntimeAnnotationHandler(IErrorSink errorSink) : base(errorSink) } public static string NativeDirectiveName => "native"; + public static string StackRuntimeDirectiveName => "stack"; protected override bool DirectiveSupported(string directive) { - return string.Equals(directive, NativeDirectiveName, StringComparison.CurrentCultureIgnoreCase); + return string.Equals(directive, NativeDirectiveName, StringComparison.CurrentCultureIgnoreCase) || + string.Equals(directive, StackRuntimeDirectiveName, StringComparison.CurrentCultureIgnoreCase); } protected override void ParseAnnotationInternal(ref Lexem lastExtractedLexem, ILexer lexer, ParserContext parserContext) { var node = new AnnotationNode(NodeKind.Annotation, lastExtractedLexem); _allLineContentLexer.Iterator = lexer.Iterator; - - var child = new TerminalNode(NodeKind.Unknown, lastExtractedLexem); - node.AddChild(child); + parserContext.AddChild(node); // после ничего не должно находиться diff --git a/src/OneScript.Native/Runtime/BslNativeMethodInfo.cs b/src/OneScript.Native/Runtime/BslNativeMethodInfo.cs index b3bf5f184..c7dcce459 100644 --- a/src/OneScript.Native/Runtime/BslNativeMethodInfo.cs +++ b/src/OneScript.Native/Runtime/BslNativeMethodInfo.cs @@ -5,14 +5,11 @@ 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.Globalization; -using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Threading; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; namespace OneScript.Native.Runtime @@ -45,10 +42,26 @@ private CallableMethod CreateCallable() public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { - var bslArguments = new List(parameters.Length); - bslArguments.AddRange(parameters.Cast()); + // FIXME: Из стековой машины дефолтные значения могут прийти, как null или Skipped + // здесь мы принудительно проставляем пропущенные параметры + var bslArguments = new BslValue[parameters.Length]; + for (int i = 0; i < bslArguments.Length; i++) + { + var param = parameters[i]; + if (param == null || param == BslSkippedParameterValue.Instance) + { + if (_parameters[i].HasDefaultValue) + bslArguments[i] = (BslValue)_parameters[i].DefaultValue; + else + throw RuntimeException.MissedArgument(); + } + else + { + bslArguments[i] = (BslValue)param; + } + } - return _callable.Invoke(obj, bslArguments.ToArray()); + return _callable.Invoke(obj, bslArguments); } } diff --git a/src/OneScript.Native/Runtime/BuiltInFunctions.cs b/src/OneScript.Native/Runtime/BuiltInFunctions.cs index 3f5283b7b..37320fa11 100644 --- a/src/OneScript.Native/Runtime/BuiltInFunctions.cs +++ b/src/OneScript.Native/Runtime/BuiltInFunctions.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Runtime.CompilerServices; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; namespace OneScript.Native.Runtime @@ -90,7 +91,7 @@ public static string Mid(string str, int start, int len = -1) } [ContextMethod("Найти", "Find")] - public static int StrPos(string needle, string haystack) + public static int StrPos(string haystack, string needle) { var result = haystack.IndexOf(needle, StringComparison.Ordinal) + 1; return result; diff --git a/src/OneScript.Native/Runtime/DynamicOperations.cs b/src/OneScript.Native/Runtime/DynamicOperations.cs index 1ce717098..246c350a6 100644 --- a/src/OneScript.Native/Runtime/DynamicOperations.cs +++ b/src/OneScript.Native/Runtime/DynamicOperations.cs @@ -7,15 +7,18 @@ This Source Code Form is subject to the terms of the using System; using System.Linq; -using OneScript.Commons; +using System.Runtime.CompilerServices; using OneScript.Contexts; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Language; using OneScript.Localization; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; +[assembly: InternalsVisibleTo("OneScript.Dynamic.Tests")] + namespace OneScript.Native.Runtime { internal static class DynamicOperations @@ -88,6 +91,30 @@ public static string ToString(BslValue value) return (string)value; } + // FIXME: тут не должно быть Null, но из-за несовершенства мира они тут бывают. Когда задолбает - надо починить и убрать отсюда проверки на null + public static bool Equality(BslValue left, BslValue right) + { + if (ReferenceEquals(left, right)) + return true; + + if (left == null || right == null) + return false; + + return left.Equals(right); + } + + // FIXME: тут не должно быть Null, но из-за несовершенства мира они тут бывают. Когда задолбает - надо починить и убрать отсюда проверки на null + public static int Comparison(BslValue left, BslValue right) + { + if (left == null && right == null) + return 0; + + if (left != null) + return left.CompareTo(right); + + return BslUndefinedValue.Instance.CompareTo(right); + } + public static BslValue WrapClrObjectToValue(object value) { return value switch @@ -95,11 +122,20 @@ public static BslValue WrapClrObjectToValue(object value) null => BslUndefinedValue.Instance, string s => BslStringValue.Create(s), decimal d => BslNumericValue.Create(d), + int n => BslNumericValue.Create(n), + uint n => BslNumericValue.Create(n), + short n => BslNumericValue.Create(n), + ushort n => BslNumericValue.Create(n), + byte n => BslNumericValue.Create(n), + sbyte n => BslNumericValue.Create(n), long l => BslNumericValue.Create(l), + ulong l => BslNumericValue.Create(l), + double dbl => BslNumericValue.Create((decimal) dbl), bool boolean => BslBooleanValue.Create(boolean), DateTime date => BslDateValue.Create(date), + BslValue bslValue => bslValue, _ => throw new TypeConversionException(new BilingualString( $"Невозможно преобразовать {value.GetType()} в тип {nameof(BslValue)}", $"Can't Convert {value.GetType()} to {nameof(BslValue)}")) @@ -127,27 +163,15 @@ public static T StrictConstructorCall(ITypeManager typeManager, IServiceConta return (T) ConstructorCall(typeManager, services, typeName, args); } - public static ExceptionInfoClass GetExceptionInfo(Exception e) + public static BslObjectValue GetExceptionInfo(IExceptionInfoFactory factory, Exception e) { - if (e is ScriptException s) - return new ExceptionInfoClass(s); - - var wrapper = new ExternalSystemException(e); - - return new ExceptionInfoClass(wrapper); + return factory.GetExceptionInfo(e); } - public static TypeDescriptor GetTypeByName(ITypeManager manager, string name) + public static BslTypeValue GetTypeByName(ITypeManager manager, string name) { - var firstTry = manager.GetTypeByName(name); - - // костыль подмены типа для Тип("ИнформацияОбОшибке") - if (firstTry.Name == ExceptionInfoClass.LanguageType.Name) - { - return ExceptionInfoClass.LanguageType; - } - - return firstTry; + var foundType = manager.GetTypeByName(name); + return new BslTypeValue(foundType); } public static BslValue GetIndexedValue(object target, BslValue index) @@ -170,7 +194,7 @@ public static void SetIndexedValue(object target, BslValue index, BslValue value context.SetIndexedValue(index, value); } - public static BslValue GetPropertyValue(BslValue target, string propertyName) + public static BslValue GetPropertyValue(object target, string propertyName) { if (!(target is IRuntimeContextInstance context)) throw BslExceptions.ValueIsNotObjectException(); @@ -178,5 +202,12 @@ public static BslValue GetPropertyValue(BslValue target, string propertyName) var propIndex = context.GetPropertyNumber(propertyName); return (BslValue)context.GetPropValue(propIndex); } + + public static BslValue CallContextMethod(IRuntimeContextInstance instance, string methodName, BslValue[] arguments) + { + var idx = instance.GetMethodNumber(methodName); + instance.CallAsFunction(idx, arguments, out var result); + return (BslValue)result; + } } } \ No newline at end of file diff --git a/src/OneScript.Native/Runtime/ExceptionInfoClass.cs b/src/OneScript.Native/Runtime/ExceptionInfoClass.cs deleted file mode 100644 index 365995626..000000000 --- a/src/OneScript.Native/Runtime/ExceptionInfoClass.cs +++ /dev/null @@ -1,89 +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/. -----------------------------------------------------------*/ - -using System; -using OneScript.Contexts; -using OneScript.Language; -using OneScript.Types; -using OneScript.Values; - -namespace OneScript.Native.Runtime -{ - public class ExceptionInfoClass : BslObjectValue - { - private static TypeDescriptor type = new TypeDescriptor( - new Guid("9783123B-DF0D-4821-A2B9-A9244A3530F5"), - "ИнформацияОбОшибке", - "ErrorInfo", - typeof(ExceptionInfoClass)); - - public static TypeDescriptor LanguageType => type; - - private ErrorPositionInfo _errorPosition; - private Exception _exc; - private Lazy _innerException; - - public ExceptionInfoClass(ScriptException lineAwareException) - : this(lineAwareException, lineAwareException.GetPosition()) - { - } - - public ExceptionInfoClass(Exception externalException, ErrorPositionInfo position) - { - _errorPosition = position; - _exc = externalException; - _innerException = new Lazy(WrapInnerException); - } - - public override TypeDescriptor SystemType => type; - - /// - /// Содержит краткое описание ошибки. Эквивалент Exception.Message в C# - /// - [ContextProperty("Описание", "Description")] - public string Description => - _exc switch - { - ScriptException s => s.MessageWithoutCodeFragment, - _ => _exc.Message - }; - - /// - /// Имя модуля, вызвавшего исключение. - /// - [ContextProperty("ИмяМодуля", "ModuleName")] - public string ModuleName => _errorPosition.ModuleName ?? string.Empty; - - /// - /// Номер строки, вызвавшей исключение. - /// - [ContextProperty("НомерСтроки", "LineNumber")] - public int LineNumber => _errorPosition.LineNumber; - - /// - /// Строка исходного кода, вызвавшего исключение. - /// - [ContextProperty("ИсходнаяСтрока", "SourceLine")] - public string SourceLine => _errorPosition.Code ?? string.Empty; - - /// - /// Содержит вложенное исключение, если таковое было. Эквивалент Exception.InnerException в C# - /// - [ContextProperty("Причина", "Cause")] - public ExceptionInfoClass InnerException => _innerException.Value; - - private ExceptionInfoClass WrapInnerException() - { - if (_exc.InnerException == null) - return null; - - var position = _exc.InnerException is ScriptException scr ? scr.GetPosition() : _errorPosition; - - return new ExceptionInfoClass(_exc.InnerException, position); - } - } -} \ No newline at end of file diff --git a/src/OneScript.Native/Runtime/ExternalSystemException.cs b/src/OneScript.Native/Runtime/ExternalSystemException.cs deleted file mode 100644 index 42c2ac7f0..000000000 --- a/src/OneScript.Native/Runtime/ExternalSystemException.cs +++ /dev/null @@ -1,20 +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/. -----------------------------------------------------------*/ - -using System; -using OneScript.Language; - -namespace OneScript.Native.Runtime -{ - public class ExternalSystemException : ScriptException - { - public ExternalSystemException(Exception reason) - : base(new ErrorPositionInfo(), $"Внешнее исключение ({reason.GetType().FullName}): {reason.Message}", reason) - { - } - } -} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs b/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs index 218e29f52..07321e0a3 100644 --- a/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs +++ b/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Linq; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Binary/BinaryDataContext.cs b/src/OneScript.StandardLibrary/Binary/BinaryDataContext.cs index 7332aa17c..abe63ec88 100644 --- a/src/OneScript.StandardLibrary/Binary/BinaryDataContext.cs +++ b/src/OneScript.StandardLibrary/Binary/BinaryDataContext.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using System.Diagnostics; using System.IO; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Binary/DataReader.cs b/src/OneScript.StandardLibrary/Binary/DataReader.cs index a6f29186d..efa3be574 100644 --- a/src/OneScript.StandardLibrary/Binary/DataReader.cs +++ b/src/OneScript.StandardLibrary/Binary/DataReader.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Text; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Text; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Binary/DataWriter.cs b/src/OneScript.StandardLibrary/Binary/DataWriter.cs index a9bfbfab8..e0d0669ea 100644 --- a/src/OneScript.StandardLibrary/Binary/DataWriter.cs +++ b/src/OneScript.StandardLibrary/Binary/DataWriter.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Text; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Text; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Binary/GenericStreamImpl.cs b/src/OneScript.StandardLibrary/Binary/GenericStreamImpl.cs index a0ffa7dfb..385081d6a 100644 --- a/src/OneScript.StandardLibrary/Binary/GenericStreamImpl.cs +++ b/src/OneScript.StandardLibrary/Binary/GenericStreamImpl.cs @@ -6,7 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.IO; -using OneScript.Commons; +using OneScript.Exceptions; using ScriptEngine.Machine; namespace OneScript.StandardLibrary.Binary diff --git a/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs b/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs index 71251dd21..458cdd030 100644 --- a/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs +++ b/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.Text; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.Binary diff --git a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs index 2f0f70f13..b9a6fcf76 100644 --- a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Collections/FixedArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/FixedArrayImpl.cs index c38e93e79..5a8d1e8a1 100644 --- a/src/OneScript.StandardLibrary/Collections/FixedArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/FixedArrayImpl.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/FixedMapImpl.cs b/src/OneScript.StandardLibrary/Collections/FixedMapImpl.cs index 5718cb435..63f07d21e 100644 --- a/src/OneScript.StandardLibrary/Collections/FixedMapImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/FixedMapImpl.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/FixedStructureImpl.cs b/src/OneScript.StandardLibrary/Collections/FixedStructureImpl.cs index 4ccf23153..4c7c208b0 100644 --- a/src/OneScript.StandardLibrary/Collections/FixedStructureImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/FixedStructureImpl.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/MapImpl.cs b/src/OneScript.StandardLibrary/Collections/MapImpl.cs index 6888d8c9b..4ba66aae1 100644 --- a/src/OneScript.StandardLibrary/Collections/MapImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/MapImpl.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/StructureImpl.cs b/src/OneScript.StandardLibrary/Collections/StructureImpl.cs index 62af03daf..c520aa6a3 100644 --- a/src/OneScript.StandardLibrary/Collections/StructureImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/StructureImpl.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index d8e799944..2cc898256 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs index a52462df3..eb52b0a8f 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs index f07499b7c..5c9ce285c 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs index 10f1fdd9d..578e6b01a 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs index 0cad12a2a..7a127fa96 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs @@ -5,8 +5,8 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs index 6be65dd0a..62c0d7350 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRow.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRow.cs index 50b5c743c..b0ce73dd9 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRow.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRow.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs index 506b1a74a..bcacce1d5 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/DelegateAction.cs b/src/OneScript.StandardLibrary/DelegateAction.cs index 2e0510254..017b7844f 100644 --- a/src/OneScript.StandardLibrary/DelegateAction.cs +++ b/src/OneScript.StandardLibrary/DelegateAction.cs @@ -42,7 +42,8 @@ public DelegateAction(Func action) public DelegateAction(Func action) { - _action = parameters => (IValue)action(parameters.Cast().ToArray()); + _action = parameters => action( parameters.Select(x=>x.GetRawValue()) + .Cast().ToArray() ); } public override bool DynamicMethodSignatures => true; @@ -67,6 +68,7 @@ public override BslMethodInfo GetMethodInfo(int methodNumber) { return BslMethodBuilder.Create() .SetNames(MethodName_Ru, MethodName_En) + .ReturnType(typeof(BslValue)) .Build(); } diff --git a/src/OneScript.StandardLibrary/DynamicLoadingFunctions.cs b/src/OneScript.StandardLibrary/DynamicLoadingFunctions.cs index 9fc74e7ae..51745e97e 100644 --- a/src/OneScript.StandardLibrary/DynamicLoadingFunctions.cs +++ b/src/OneScript.StandardLibrary/DynamicLoadingFunctions.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using OneScript.Commons; using OneScript.Compilation; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Language; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.NativeApi; diff --git a/src/OneScript.StandardLibrary/GlobalBitFunctions.cs b/src/OneScript.StandardLibrary/GlobalBitFunctions.cs index 285ef46a7..302950b5a 100644 --- a/src/OneScript.StandardLibrary/GlobalBitFunctions.cs +++ b/src/OneScript.StandardLibrary/GlobalBitFunctions.cs @@ -5,8 +5,8 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary diff --git a/src/OneScript.StandardLibrary/GuidWrapper.cs b/src/OneScript.StandardLibrary/GuidWrapper.cs index 61cd024a0..78f754950 100644 --- a/src/OneScript.StandardLibrary/GuidWrapper.cs +++ b/src/OneScript.StandardLibrary/GuidWrapper.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Reflection; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Hash/HashImpl.cs b/src/OneScript.StandardLibrary/Hash/HashImpl.cs index 6ca4065bd..99008ba20 100644 --- a/src/OneScript.StandardLibrary/Hash/HashImpl.cs +++ b/src/OneScript.StandardLibrary/Hash/HashImpl.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Security.Cryptography; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using OneScript.Values; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Http/HttpConnectionContext.cs b/src/OneScript.StandardLibrary/Http/HttpConnectionContext.cs index be91599d4..3b9ab8ab2 100644 --- a/src/OneScript.StandardLibrary/Http/HttpConnectionContext.cs +++ b/src/OneScript.StandardLibrary/Http/HttpConnectionContext.cs @@ -11,8 +11,8 @@ This Source Code Form is subject to the terms of the using System.Net; using System.Reflection; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.Types; using RegExp = System.Text.RegularExpressions; diff --git a/src/OneScript.StandardLibrary/Http/HttpRequestContext.cs b/src/OneScript.StandardLibrary/Http/HttpRequestContext.cs index 46b7c0571..c3fada9ce 100644 --- a/src/OneScript.StandardLibrary/Http/HttpRequestContext.cs +++ b/src/OneScript.StandardLibrary/Http/HttpRequestContext.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.IO; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.Text; diff --git a/src/OneScript.StandardLibrary/Http/InternetProxyContext.cs b/src/OneScript.StandardLibrary/Http/InternetProxyContext.cs index ea79041d9..36433cbc4 100644 --- a/src/OneScript.StandardLibrary/Http/InternetProxyContext.cs +++ b/src/OneScript.StandardLibrary/Http/InternetProxyContext.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Net; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Json/GlobalJsonFunctions.cs b/src/OneScript.StandardLibrary/Json/GlobalJsonFunctions.cs index cd6224d61..939c2d02d 100644 --- a/src/OneScript.StandardLibrary/Json/GlobalJsonFunctions.cs +++ b/src/OneScript.StandardLibrary/Json/GlobalJsonFunctions.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using Newtonsoft.Json; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Json/JSONDataExtractor.cs b/src/OneScript.StandardLibrary/Json/JSONDataExtractor.cs index 47da1907d..71721f391 100644 --- a/src/OneScript.StandardLibrary/Json/JSONDataExtractor.cs +++ b/src/OneScript.StandardLibrary/Json/JSONDataExtractor.cs @@ -1,536 +1,535 @@ -/*---------------------------------------------------------- -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 System.Text; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; -using OneScript.Commons; -using OneScript.Contexts; -using OneScript.Types; -using OneScript.StandardLibrary; -using OneScript.StandardLibrary.Collections; -using OneScript.StandardLibrary.Text; -using OneScript.StandardLibrary.Binary; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace OneScript.StandardLibrary.Json -{ - /// - /// Предоставляет методы для извлечения данных из JSON по запросу JSON-path - /// - [ContextClass("ИзвлечениеДанныхJSON", "JSONDataExtractor")] - public class JSONDataExtractor : AutoContext - { - private JToken _jsonData; - - /// - /// Устанавливает строку JSON для последующей обработки - /// - /// Строка. Строка JSON. - [ContextMethod("УстановитьСтроку", "SetString")] - public void SetString(string JSONString) - { - - _jsonData = JToken.Parse(JSONString); - - } - - /// - /// Читает файл, содержащий данные JSON для последующей обработки - /// - /// Строка. Путь к файлу. - /// КодировкаТекста. кодировка файла. - [ContextMethod("ОткрытьФайл", "OpenFile")] - public void OpenFile(string JSONFileName, IValue encoding = null) - { - - StreamReader _fileReader; - - try - { - if (encoding == null) - _fileReader = FileOpener.OpenReader(JSONFileName, Encoding.Default); - else - _fileReader = FileOpener.OpenReader(JSONFileName, TextEncodingEnum.GetEncoding(encoding)); - } - catch (Exception e) - { - throw new RuntimeException(e.Message, e); - } - - _jsonData = JToken.Parse(_fileReader.ReadToEnd()); - - _fileReader.Close(); - - } - - /// - /// Читает данные из потока JSON для последующей обработки - /// - /// Поток. поток с данными JSON. - /// КодировкаТекста. кодировка файла. - [ContextMethod("ОткрытьПоток", "OpenStream")] - public void OpenStream(IValue JSONStream, IValue encoding = null) - { - - string _JSONString = "{}"; - Encoding _encoding; - - if (encoding == null) - _encoding = Encoding.Default; - else - _encoding = TextEncodingEnum.GetEncoding(encoding); - - using (Stream _underlyingStream = ((IStreamWrapper)JSONStream).GetUnderlyingStream()) - { - byte[] buffer = new byte[1000]; - StringBuilder builder = new StringBuilder(); - int read = -1; - - while (true) - { - AutoResetEvent gotInput = new AutoResetEvent(false); - Thread inputThread = new Thread(() => - { - try - { - read = _underlyingStream.Read(buffer, 0, buffer.Length); - gotInput.Set(); - } - catch (ThreadAbortException) - { - Thread.ResetAbort(); - } - }) - { - IsBackground = true - }; - - inputThread.Start(); - - // Timeout expired? - if (!gotInput.WaitOne(100)) - { - inputThread.Abort(); - break; - } - - // End of stream? - if (read == 0) - { - _JSONString = builder.ToString(); - break; - } - - // Got data - builder.Append(_encoding.GetString(buffer, 0, read)); - } - } - - string _BOMMarkUTF8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); - - if (_JSONString.StartsWith(_BOMMarkUTF8, StringComparison.Ordinal)) - _JSONString = _JSONString.Remove(0, _BOMMarkUTF8.Length); - - _jsonData = JToken.Parse(_JSONString.Trim()); - - } - - /// - /// Выполняет выборку из JSON по указанному JSON-path - /// - /// Строка. JSON-path. - /// Булево. Если результирующий массив содержит единственное значение, то: - /// Истина - будет возвращено значение; - /// Ложь - будет возвращен массив. - /// Булево. Истина - объекты будут возвращены в виде строки JSON; - /// Ложь - Объекты будут возвращены в виде соответствия. - /// Строка - Выбранные данные - [ContextMethod("Выбрать", "Select")] - public IValue Select(string path, bool extractSingleValue = true, bool getObjectAsJSON = true) - { - IValue result; - - AggregateFuncEnum aggregateFunc = GetAggregateFunc(path, out path); - - List parseResult = _jsonData.SelectTokens(path).ToList(); - - if (parseResult.Count() == 0) - { - result = ValueFactory.Create(); - } - else - { - StringBuilder sb = new StringBuilder(); - StringWriter sw = new StringWriter(sb); - - using (JsonWriter writer = new JsonTextWriter(sw)) - { - writer.Formatting = Formatting.Indented; - - writer.WriteStartArray(); - foreach (JToken token in parseResult) - { - writer.WriteToken(token.CreateReader(), true); - } - writer.WriteEndArray(); - } - result = JSONToDataStructure(sb.ToString()); - } - - if (aggregateFunc != AggregateFuncEnum.none) - result = CalculateAggregateFunc(result, aggregateFunc); - - if (result is ArrayImpl && ((ArrayImpl)result.AsObject()).Count() == 1 && extractSingleValue) - { - result = ((ArrayImpl)result.AsObject()).Get(0); - } - - if ((result is ArrayImpl || result is MapImpl) && getObjectAsJSON) - { - result = ValueFactory.Create(DataStructureToJSON(result)); - } - - return result; - } - - #region JSON conversion - - /// - /// Преобразует строку JSON в соответствие или массив - /// - /// Строка. Строка JSON. - /// Соответствие, Массив - Результат преобразования строки JSON в соответствие или массив - private IValue JSONToDataStructure(string JSONString) - { - JSONReader reader = new JSONReader(); - reader.SetString(JSONString); - - return ((GlobalJsonFunctions)GlobalJsonFunctions.CreateInstance()).ReadJSONInMap(reader); - } - - /// - /// Преобразует соответствие или массив в строку JSON - /// - /// Соответствие, Массив. Соответствие или массив для преобразования в строку JSON. - /// Строка - Результат преобразования соответствия или массива в строку JSON - private string DataStructureToJSON(IValue inputStruct) - { - JSONWriter writer = new JSONWriter(); - writer.SetString(); - - ((GlobalJsonFunctions)GlobalJsonFunctions.CreateInstance()).WriteJSON(writer, inputStruct); - - return writer.Close(); - } - - #endregion - - #region Aggregate calculation - - /// - /// Вычисляет агрегатную функцию над переданными данными - /// - /// Соответствие, Массив. Соответствие или массив для вычисления агрегатной функции. - /// Агрегатнаная функция. - /// Строка - Результат вычисления функции - private IValue CalculateAggregateFunc(IValue sourceData, AggregateFuncEnum aggregateFunc) - { - - IValue result; - - if (aggregateFunc == AggregateFuncEnum.length) - result = CalculateLength(sourceData); - else if (aggregateFunc == AggregateFuncEnum.sum) - result = CalculateSum(sourceData); - else if (aggregateFunc == AggregateFuncEnum.avg) - result = CalculateAvg(sourceData); - else if (aggregateFunc == AggregateFuncEnum.min) - result = CalculateMin(sourceData); - else if (aggregateFunc == AggregateFuncEnum.max) - result = CalculateMax(sourceData); - else if (aggregateFunc == AggregateFuncEnum.first) - result = CalculateFirst(sourceData); - else if (aggregateFunc == AggregateFuncEnum.last) - result = CalculateLast(sourceData); - else if (aggregateFunc == AggregateFuncEnum.keys) - result = CalculateKeys(sourceData); - else - result = sourceData; - - return result; - } - - /// - /// Вычисляет размер переданного массива или соответствия - /// - /// Соответствие, Массив. Соответствие или массив для обработки. - /// Число - Размер переданного массива или соответствия - private IValue CalculateLength(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (sourceData is ArrayImpl) - result = ValueFactory.Create(((ArrayImpl)sourceData).Count()); - else if (sourceData is MapImpl) - result = ValueFactory.Create(((MapImpl)sourceData).Count()); - - return result; - } - - /// - /// Вычисляет сумму чисел в переданном массиве - /// - /// Массив. Соответствие или массив для обработки. - /// Число - Сумма чисел в переданном массиве - private IValue CalculateSum(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - decimal fullSum = 0; - - foreach (IValue value in (ArrayImpl)sourceData) - fullSum += value.AsNumber(); - - result = ValueFactory.Create(fullSum); - - return result; - } - - /// - /// Вычисляет среднее значение в переданном массиве - /// - /// Массив. Соответствие или массив для обработки. - /// Число - Среднее значение в переданном массиве - private IValue CalculateAvg(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (!(sourceData is ArrayImpl)) - return result; - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - decimal fullSum = 0; - - foreach (IValue value in (ArrayImpl)sourceData) - fullSum += value.AsNumber(); - - result = ValueFactory.Create(fullSum / ((ArrayImpl)sourceData).Count()); - - return result; - } - - /// - /// Вычисляет минимально значение в переданном массиве - /// - /// Массив. Соответствие или массив для обработки. - /// Число - Минимальное значение в переданном массиве - private IValue CalculateMin(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (!(sourceData is ArrayImpl)) - return result; - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - decimal numericResult = ((ArrayImpl)sourceData).Get(0).AsNumber(); - - foreach (IValue value in (ArrayImpl)sourceData) - numericResult = value.AsNumber() < numericResult ? value.AsNumber() : numericResult; - - result = ValueFactory.Create(numericResult); - - return result; - } - - /// - /// Вычисляет максимальное значение в переданном массиве - /// - /// Массив. Соответствие или массив для обработки. - /// Число - Максимальное значение в переданном массиве - private IValue CalculateMax(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (!(sourceData is ArrayImpl)) - return result; - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - decimal numericResult = ((ArrayImpl)sourceData).Get(0).AsNumber(); - - foreach (IValue value in (ArrayImpl)sourceData) - numericResult = value.AsNumber() > numericResult ? value.AsNumber() : numericResult; - - result = ValueFactory.Create(numericResult); - - return result; - } - - /// - /// Получает первое значение из переданного массива - /// - /// Массив. Массив для обработки. - /// Произвольный - Первое значение из переданного массива - private IValue CalculateFirst(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (!(sourceData is ArrayImpl)) - return result; - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - result = ((ArrayImpl)sourceData).Get(0); - - return result; - } - - /// - /// Получает последнее значение из переданного массива - /// - /// Массив. Массив для обработки. - /// Произвольный - Последнее значение из переданного массива - private IValue CalculateLast(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (!(sourceData is ArrayImpl)) - return result; - - if (((ArrayImpl)sourceData).Count() == 0) - return result; - - int lastIndex = ((ArrayImpl)sourceData).UpperBound(); - result = ((ArrayImpl)sourceData).Get(lastIndex); - - return result; - } - - /// - /// Получает массив ключей из переданного соответствия или массив индексов из переданного массива - /// если переданный массив содержит единственное соответствие, то возвращаются ключи соответствия - /// - /// Соответствие, Массив. Соответствие или массив для обработки. - /// Массив - Ключи соответствия или индексы массива - private IValue CalculateKeys(IValue sourceData) - { - - IValue result = ValueFactory.Create(); - - if (sourceData is ArrayImpl && ((ArrayImpl)sourceData).Count() == 1) - sourceData = ((ArrayImpl)sourceData).Get(0); - - if (!(sourceData is MapImpl)) - return result; - - ArrayImpl keyArray = new ArrayImpl(); - if (sourceData is MapImpl) - foreach (KeyAndValueImpl KeyValue in (MapImpl)sourceData) - keyArray.Add(KeyValue.Key); - else if (sourceData is ArrayImpl) - for (int i = 0; i < ((ArrayImpl)sourceData).Count(); i++) - keyArray.Add(ValueFactory.Create(i)); - - return keyArray; - } - - /// - /// Доступные агрегатные функции - /// - private enum AggregateFuncEnum - { - none, - length, - sum, - avg, - min, - max, - first, - last, - keys - } - - /// - /// Получает используемую агрегатную функцию из переданного пути JSON path - /// - /// Строка. исходный путь JSON-path. - /// Строка. путь JSON-path без агрегатной функции. - /// AggregateFuncEnum - используемуя агрегатная функция - private AggregateFuncEnum GetAggregateFunc(string path, out string mainPath) - { - Dictionary aggregateFuncs = new Dictionary(); - aggregateFuncs.Add("count", AggregateFuncEnum.length); - aggregateFuncs.Add("length", AggregateFuncEnum.length); - aggregateFuncs.Add("sum", AggregateFuncEnum.sum); - aggregateFuncs.Add("avg", AggregateFuncEnum.avg); - aggregateFuncs.Add("min", AggregateFuncEnum.min); - aggregateFuncs.Add("max", AggregateFuncEnum.max); - aggregateFuncs.Add("first", AggregateFuncEnum.first); - aggregateFuncs.Add("last", AggregateFuncEnum.last); - aggregateFuncs.Add("keys", AggregateFuncEnum.keys); - - AggregateFuncEnum result = AggregateFuncEnum.none; - mainPath = path; - - string[] parts = path.Split('.'); - - if (parts.Length == 0) - return result; - - string aggregateFunc = parts[parts.GetUpperBound(0)].Trim(); - - if (!aggregateFunc.Trim().EndsWith("()")) - return result; - - aggregateFunc = aggregateFunc.Substring(0, aggregateFunc.Length - 2); - - if (aggregateFuncs.TryGetValue(aggregateFunc.ToLower(), out result)) - { - mainPath = String.Join(".", parts, 0, parts.Length - 1); - return result; - } - - return result; - } - - #endregion - - /// - /// Создает ИзвлечениеДанныхJSON - /// - /// ИзвлечениеДанныхJSON - [ScriptConstructor] - public static IRuntimeContextInstance Constructor() - { - return new JSONDataExtractor(); - } - - } -} +/*---------------------------------------------------------- +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 System.Text; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; +using OneScript.Commons; +using OneScript.Contexts; +using OneScript.StandardLibrary.Collections; +using OneScript.StandardLibrary.Text; +using OneScript.StandardLibrary.Binary; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OneScript.Exceptions; + +namespace OneScript.StandardLibrary.Json +{ + /// + /// Предоставляет методы для извлечения данных из JSON по запросу JSON-path + /// + [ContextClass("ИзвлечениеДанныхJSON", "JSONDataExtractor")] + public class JSONDataExtractor : AutoContext + { + private JToken _jsonData; + + /// + /// Устанавливает строку JSON для последующей обработки + /// + /// Строка. Строка JSON. + [ContextMethod("УстановитьСтроку", "SetString")] + public void SetString(string JSONString) + { + + _jsonData = JToken.Parse(JSONString); + + } + + /// + /// Читает файл, содержащий данные JSON для последующей обработки + /// + /// Строка. Путь к файлу. + /// КодировкаТекста. кодировка файла. + [ContextMethod("ОткрытьФайл", "OpenFile")] + public void OpenFile(string JSONFileName, IValue encoding = null) + { + + StreamReader _fileReader; + + try + { + if (encoding == null) + _fileReader = FileOpener.OpenReader(JSONFileName, Encoding.Default); + else + _fileReader = FileOpener.OpenReader(JSONFileName, TextEncodingEnum.GetEncoding(encoding)); + } + catch (Exception e) + { + throw new RuntimeException(e.Message, e); + } + + _jsonData = JToken.Parse(_fileReader.ReadToEnd()); + + _fileReader.Close(); + + } + + /// + /// Читает данные из потока JSON для последующей обработки + /// + /// Поток. поток с данными JSON. + /// КодировкаТекста. кодировка файла. + [ContextMethod("ОткрытьПоток", "OpenStream")] + public void OpenStream(IValue JSONStream, IValue encoding = null) + { + + string _JSONString = "{}"; + Encoding _encoding; + + if (encoding == null) + _encoding = Encoding.Default; + else + _encoding = TextEncodingEnum.GetEncoding(encoding); + + using (Stream _underlyingStream = ((IStreamWrapper)JSONStream).GetUnderlyingStream()) + { + byte[] buffer = new byte[1000]; + StringBuilder builder = new StringBuilder(); + int read = -1; + + while (true) + { + AutoResetEvent gotInput = new AutoResetEvent(false); + Thread inputThread = new Thread(() => + { + try + { + read = _underlyingStream.Read(buffer, 0, buffer.Length); + gotInput.Set(); + } + catch (ThreadAbortException) + { + Thread.ResetAbort(); + } + }) + { + IsBackground = true + }; + + inputThread.Start(); + + // Timeout expired? + if (!gotInput.WaitOne(100)) + { + inputThread.Abort(); + break; + } + + // End of stream? + if (read == 0) + { + _JSONString = builder.ToString(); + break; + } + + // Got data + builder.Append(_encoding.GetString(buffer, 0, read)); + } + } + + string _BOMMarkUTF8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); + + if (_JSONString.StartsWith(_BOMMarkUTF8, StringComparison.Ordinal)) + _JSONString = _JSONString.Remove(0, _BOMMarkUTF8.Length); + + _jsonData = JToken.Parse(_JSONString.Trim()); + + } + + /// + /// Выполняет выборку из JSON по указанному JSON-path + /// + /// Строка. JSON-path. + /// Булево. Если результирующий массив содержит единственное значение, то: + /// Истина - будет возвращено значение; + /// Ложь - будет возвращен массив. + /// Булево. Истина - объекты будут возвращены в виде строки JSON; + /// Ложь - Объекты будут возвращены в виде соответствия. + /// Строка - Выбранные данные + [ContextMethod("Выбрать", "Select")] + public IValue Select(string path, bool extractSingleValue = true, bool getObjectAsJSON = true) + { + IValue result; + + AggregateFuncEnum aggregateFunc = GetAggregateFunc(path, out path); + + List parseResult = _jsonData.SelectTokens(path).ToList(); + + if (parseResult.Count() == 0) + { + result = ValueFactory.Create(); + } + else + { + StringBuilder sb = new StringBuilder(); + StringWriter sw = new StringWriter(sb); + + using (JsonWriter writer = new JsonTextWriter(sw)) + { + writer.Formatting = Formatting.Indented; + + writer.WriteStartArray(); + foreach (JToken token in parseResult) + { + writer.WriteToken(token.CreateReader(), true); + } + writer.WriteEndArray(); + } + result = JSONToDataStructure(sb.ToString()); + } + + if (aggregateFunc != AggregateFuncEnum.none) + result = CalculateAggregateFunc(result, aggregateFunc); + + if (result is ArrayImpl && ((ArrayImpl)result.AsObject()).Count() == 1 && extractSingleValue) + { + result = ((ArrayImpl)result.AsObject()).Get(0); + } + + if ((result is ArrayImpl || result is MapImpl) && getObjectAsJSON) + { + result = ValueFactory.Create(DataStructureToJSON(result)); + } + + return result; + } + + #region JSON conversion + + /// + /// Преобразует строку JSON в соответствие или массив + /// + /// Строка. Строка JSON. + /// Соответствие, Массив - Результат преобразования строки JSON в соответствие или массив + private IValue JSONToDataStructure(string JSONString) + { + JSONReader reader = new JSONReader(); + reader.SetString(JSONString); + + return ((GlobalJsonFunctions)GlobalJsonFunctions.CreateInstance()).ReadJSONInMap(reader); + } + + /// + /// Преобразует соответствие или массив в строку JSON + /// + /// Соответствие, Массив. Соответствие или массив для преобразования в строку JSON. + /// Строка - Результат преобразования соответствия или массива в строку JSON + private string DataStructureToJSON(IValue inputStruct) + { + JSONWriter writer = new JSONWriter(); + writer.SetString(); + + ((GlobalJsonFunctions)GlobalJsonFunctions.CreateInstance()).WriteJSON(writer, inputStruct); + + return writer.Close(); + } + + #endregion + + #region Aggregate calculation + + /// + /// Вычисляет агрегатную функцию над переданными данными + /// + /// Соответствие, Массив. Соответствие или массив для вычисления агрегатной функции. + /// Агрегатнаная функция. + /// Строка - Результат вычисления функции + private IValue CalculateAggregateFunc(IValue sourceData, AggregateFuncEnum aggregateFunc) + { + + IValue result; + + if (aggregateFunc == AggregateFuncEnum.length) + result = CalculateLength(sourceData); + else if (aggregateFunc == AggregateFuncEnum.sum) + result = CalculateSum(sourceData); + else if (aggregateFunc == AggregateFuncEnum.avg) + result = CalculateAvg(sourceData); + else if (aggregateFunc == AggregateFuncEnum.min) + result = CalculateMin(sourceData); + else if (aggregateFunc == AggregateFuncEnum.max) + result = CalculateMax(sourceData); + else if (aggregateFunc == AggregateFuncEnum.first) + result = CalculateFirst(sourceData); + else if (aggregateFunc == AggregateFuncEnum.last) + result = CalculateLast(sourceData); + else if (aggregateFunc == AggregateFuncEnum.keys) + result = CalculateKeys(sourceData); + else + result = sourceData; + + return result; + } + + /// + /// Вычисляет размер переданного массива или соответствия + /// + /// Соответствие, Массив. Соответствие или массив для обработки. + /// Число - Размер переданного массива или соответствия + private IValue CalculateLength(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (sourceData is ArrayImpl) + result = ValueFactory.Create(((ArrayImpl)sourceData).Count()); + else if (sourceData is MapImpl) + result = ValueFactory.Create(((MapImpl)sourceData).Count()); + + return result; + } + + /// + /// Вычисляет сумму чисел в переданном массиве + /// + /// Массив. Соответствие или массив для обработки. + /// Число - Сумма чисел в переданном массиве + private IValue CalculateSum(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + decimal fullSum = 0; + + foreach (IValue value in (ArrayImpl)sourceData) + fullSum += value.AsNumber(); + + result = ValueFactory.Create(fullSum); + + return result; + } + + /// + /// Вычисляет среднее значение в переданном массиве + /// + /// Массив. Соответствие или массив для обработки. + /// Число - Среднее значение в переданном массиве + private IValue CalculateAvg(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (!(sourceData is ArrayImpl)) + return result; + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + decimal fullSum = 0; + + foreach (IValue value in (ArrayImpl)sourceData) + fullSum += value.AsNumber(); + + result = ValueFactory.Create(fullSum / ((ArrayImpl)sourceData).Count()); + + return result; + } + + /// + /// Вычисляет минимально значение в переданном массиве + /// + /// Массив. Соответствие или массив для обработки. + /// Число - Минимальное значение в переданном массиве + private IValue CalculateMin(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (!(sourceData is ArrayImpl)) + return result; + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + decimal numericResult = ((ArrayImpl)sourceData).Get(0).AsNumber(); + + foreach (IValue value in (ArrayImpl)sourceData) + numericResult = value.AsNumber() < numericResult ? value.AsNumber() : numericResult; + + result = ValueFactory.Create(numericResult); + + return result; + } + + /// + /// Вычисляет максимальное значение в переданном массиве + /// + /// Массив. Соответствие или массив для обработки. + /// Число - Максимальное значение в переданном массиве + private IValue CalculateMax(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (!(sourceData is ArrayImpl)) + return result; + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + decimal numericResult = ((ArrayImpl)sourceData).Get(0).AsNumber(); + + foreach (IValue value in (ArrayImpl)sourceData) + numericResult = value.AsNumber() > numericResult ? value.AsNumber() : numericResult; + + result = ValueFactory.Create(numericResult); + + return result; + } + + /// + /// Получает первое значение из переданного массива + /// + /// Массив. Массив для обработки. + /// Произвольный - Первое значение из переданного массива + private IValue CalculateFirst(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (!(sourceData is ArrayImpl)) + return result; + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + result = ((ArrayImpl)sourceData).Get(0); + + return result; + } + + /// + /// Получает последнее значение из переданного массива + /// + /// Массив. Массив для обработки. + /// Произвольный - Последнее значение из переданного массива + private IValue CalculateLast(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (!(sourceData is ArrayImpl)) + return result; + + if (((ArrayImpl)sourceData).Count() == 0) + return result; + + int lastIndex = ((ArrayImpl)sourceData).UpperBound(); + result = ((ArrayImpl)sourceData).Get(lastIndex); + + return result; + } + + /// + /// Получает массив ключей из переданного соответствия или массив индексов из переданного массива + /// если переданный массив содержит единственное соответствие, то возвращаются ключи соответствия + /// + /// Соответствие, Массив. Соответствие или массив для обработки. + /// Массив - Ключи соответствия или индексы массива + private IValue CalculateKeys(IValue sourceData) + { + + IValue result = ValueFactory.Create(); + + if (sourceData is ArrayImpl && ((ArrayImpl)sourceData).Count() == 1) + sourceData = ((ArrayImpl)sourceData).Get(0); + + if (!(sourceData is MapImpl)) + return result; + + ArrayImpl keyArray = new ArrayImpl(); + if (sourceData is MapImpl) + foreach (KeyAndValueImpl KeyValue in (MapImpl)sourceData) + keyArray.Add(KeyValue.Key); + else if (sourceData is ArrayImpl) + for (int i = 0; i < ((ArrayImpl)sourceData).Count(); i++) + keyArray.Add(ValueFactory.Create(i)); + + return keyArray; + } + + /// + /// Доступные агрегатные функции + /// + private enum AggregateFuncEnum + { + none, + length, + sum, + avg, + min, + max, + first, + last, + keys + } + + /// + /// Получает используемую агрегатную функцию из переданного пути JSON path + /// + /// Строка. исходный путь JSON-path. + /// Строка. путь JSON-path без агрегатной функции. + /// AggregateFuncEnum - используемуя агрегатная функция + private AggregateFuncEnum GetAggregateFunc(string path, out string mainPath) + { + Dictionary aggregateFuncs = new Dictionary(); + aggregateFuncs.Add("count", AggregateFuncEnum.length); + aggregateFuncs.Add("length", AggregateFuncEnum.length); + aggregateFuncs.Add("sum", AggregateFuncEnum.sum); + aggregateFuncs.Add("avg", AggregateFuncEnum.avg); + aggregateFuncs.Add("min", AggregateFuncEnum.min); + aggregateFuncs.Add("max", AggregateFuncEnum.max); + aggregateFuncs.Add("first", AggregateFuncEnum.first); + aggregateFuncs.Add("last", AggregateFuncEnum.last); + aggregateFuncs.Add("keys", AggregateFuncEnum.keys); + + AggregateFuncEnum result = AggregateFuncEnum.none; + mainPath = path; + + string[] parts = path.Split('.'); + + if (parts.Length == 0) + return result; + + string aggregateFunc = parts[parts.GetUpperBound(0)].Trim(); + + if (!aggregateFunc.Trim().EndsWith("()")) + return result; + + aggregateFunc = aggregateFunc.Substring(0, aggregateFunc.Length - 2); + + if (aggregateFuncs.TryGetValue(aggregateFunc.ToLower(), out result)) + { + mainPath = String.Join(".", parts, 0, parts.Length - 1); + return result; + } + + return result; + } + + #endregion + + /// + /// Создает ИзвлечениеДанныхJSON + /// + /// ИзвлечениеДанныхJSON + [ScriptConstructor] + public static IRuntimeContextInstance Constructor() + { + return new JSONDataExtractor(); + } + + } +} diff --git a/src/OneScript.StandardLibrary/Json/JSONReader.cs b/src/OneScript.StandardLibrary/Json/JSONReader.cs index 3ff73e0b3..9eb28fedd 100644 --- a/src/OneScript.StandardLibrary/Json/JSONReader.cs +++ b/src/OneScript.StandardLibrary/Json/JSONReader.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using Newtonsoft.Json; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Text; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Json/JSONWriter.cs b/src/OneScript.StandardLibrary/Json/JSONWriter.cs index c558f21aa..db3b9bc31 100644 --- a/src/OneScript.StandardLibrary/Json/JSONWriter.cs +++ b/src/OneScript.StandardLibrary/Json/JSONWriter.cs @@ -12,8 +12,8 @@ This Source Code Form is subject to the terms of the using Newtonsoft.Json; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Text; -using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Native/CompiledBlock.cs b/src/OneScript.StandardLibrary/Native/CompiledBlock.cs index 447104c16..1f4e9fc52 100644 --- a/src/OneScript.StandardLibrary/Native/CompiledBlock.cs +++ b/src/OneScript.StandardLibrary/Native/CompiledBlock.cs @@ -14,6 +14,7 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation.Binding; using OneScript.Contexts; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Language; using OneScript.Language.LexicalAnalysis; using OneScript.Language.SyntaxAnalysis; diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs index 9eed43ae2..217932042 100644 --- a/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs +++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs index 139c74383..43462570e 100644 --- a/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs +++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs @@ -9,7 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiPackage.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiPackage.cs index 268e63d52..1c8cdc09b 100644 --- a/src/OneScript.StandardLibrary/NativeApi/NativeApiPackage.cs +++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiPackage.cs @@ -9,7 +9,7 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Xml; using Ionic.Zip; -using OneScript.Commons; +using OneScript.Exceptions; namespace OneScript.StandardLibrary.NativeApi { diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiValue.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiValue.cs index eaad39100..125323a66 100644 --- a/src/OneScript.StandardLibrary/NativeApi/NativeApiValue.cs +++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiValue.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs b/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs new file mode 100644 index 000000000..88e22b283 --- /dev/null +++ b/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs @@ -0,0 +1,101 @@ +/*---------------------------------------------------------- +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.Text; + +namespace OneScript.StandardLibrary.Processes +{ + public class ArgumentsParser + { + private readonly string _input; + private readonly List _quotes; + private readonly List _arguments; + private readonly StringBuilder _currentArgument; + + private char _currentQuote; + private bool _isInQuotes; + + public ArgumentsParser(string input) + { + _input = input; + _currentArgument = new StringBuilder(); + _arguments = new List(); + _quotes = new List { '\'', '"' }; + } + + public string[] GetArguments() + { + if (string.IsNullOrWhiteSpace(_input)) + { + return Array.Empty(); + } + + if (_arguments.Count > 0) + { + return _arguments.ToArray(); + } + + _currentArgument.Clear(); + + foreach (var currentChar in _input) + { + if (char.IsWhiteSpace(currentChar) && !_isInQuotes) + { + PushArgument(); + } + else if (_quotes.Contains(currentChar)) + { + HandleQuotes(currentChar); + } + else + { + PushChar(currentChar); + } + } + + PushArgument(); + + return _arguments.ToArray(); + } + + private void HandleQuotes(char quoteChar) + { + if (!_isInQuotes) + { + _isInQuotes = true; + _currentQuote = quoteChar; + } + else if (quoteChar == _currentQuote) + { + _isInQuotes = false; + _currentQuote = default; + } + else + { + PushChar(quoteChar); + } + } + + private void PushChar(char ch) + { + _currentArgument.Append(ch); + } + + private void PushArgument() + { + if (_currentArgument.Length == 0) + { + return; + } + + _arguments.Add(_currentArgument.ToString()); + _currentArgument.Clear(); + } + } +} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Processes/ProcessContext.cs b/src/OneScript.StandardLibrary/Processes/ProcessContext.cs index c2ae44819..a0ae09708 100644 --- a/src/OneScript.StandardLibrary/Processes/ProcessContext.cs +++ b/src/OneScript.StandardLibrary/Processes/ProcessContext.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Diagnostics; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.Text; using ScriptEngine.Machine; @@ -270,13 +270,23 @@ public static ProcessStartInfo PrepareProcessStartupInfo(string cmdLine, string var sInfo = new ProcessStartInfo(); int argsPosition; + sInfo.UseShellExecute = true; sInfo.FileName = ExtractExecutableName(cmdLine, out argsPosition); - sInfo.Arguments = argsPosition >= cmdLine.Length ? "" : cmdLine.Substring(argsPosition); if (currentDir != null) sInfo.WorkingDirectory = currentDir; + + var arguments = argsPosition >= cmdLine.Length + ? Array.Empty() + : new ArgumentsParser(cmdLine[argsPosition..]).GetArguments(); + + foreach (var argument in arguments) + { + sInfo.ArgumentList.Add(argument); + } + return sInfo; } - + private static string ExtractExecutableName(string cmdLine, out int argsPosition) { bool inQuotes = false; diff --git a/src/OneScript.StandardLibrary/RandomNumberGenerator.cs b/src/OneScript.StandardLibrary/RandomNumberGenerator.cs index 450a806db..1a284cc48 100644 --- a/src/OneScript.StandardLibrary/RandomNumberGenerator.cs +++ b/src/OneScript.StandardLibrary/RandomNumberGenerator.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Reflector.cs b/src/OneScript.StandardLibrary/Reflector.cs index f7c27d4f1..fdb6e3ac3 100644 --- a/src/OneScript.StandardLibrary/Reflector.cs +++ b/src/OneScript.StandardLibrary/Reflector.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Reflection; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.Collections.ValueTable; diff --git a/src/OneScript.StandardLibrary/StandardGlobalContext.cs b/src/OneScript.StandardLibrary/StandardGlobalContext.cs index 97dba0789..015ecc7a7 100644 --- a/src/OneScript.StandardLibrary/StandardGlobalContext.cs +++ b/src/OneScript.StandardLibrary/StandardGlobalContext.cs @@ -9,8 +9,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; @@ -93,7 +93,7 @@ public string BriefErrorDescription(ExceptionInfoContext errInfo) [ContextMethod("ПодробноеПредставлениеОшибки", "DetailErrorDescription")] public string DetailErrorDescription(ExceptionInfoContext errInfo) { - return errInfo.DetailedDescription; + return errInfo.GetDetailedDescription(); } [ContextMethod("ТекущаяУниверсальнаяДата", "CurrentUniversalDate")] diff --git a/src/OneScript.StandardLibrary/StringOperations.cs b/src/OneScript.StandardLibrary/StringOperations.cs index f11a6cd73..c8321077f 100644 --- a/src/OneScript.StandardLibrary/StringOperations.cs +++ b/src/OneScript.StandardLibrary/StringOperations.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using OneScript.Commons; using OneScript.Contexts; using OneScript.Contexts.Enums; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs b/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs index 4d0bb299b..fd57231a2 100644 --- a/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs +++ b/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Reflection; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using ScriptEngine; using ScriptEngine.HostedScript.Library; diff --git a/src/OneScript.StandardLibrary/Tasks/BackgroundTask.cs b/src/OneScript.StandardLibrary/Tasks/BackgroundTask.cs index ad667d873..fdf1793ce 100644 --- a/src/OneScript.StandardLibrary/Tasks/BackgroundTask.cs +++ b/src/OneScript.StandardLibrary/Tasks/BackgroundTask.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Threading.Tasks; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Language; using OneScript.StandardLibrary.Collections; using ScriptEngine.Machine; @@ -112,11 +113,6 @@ public void ExecuteOnCurrentThread() State = TaskStateEnum.CompletedWithErrors; ExceptionInfo = new ExceptionInfoContext(exception); } - catch (BslCoreException exception) - { - State = TaskStateEnum.CompletedWithErrors; - ExceptionInfo = new ExceptionInfoContext(new ScriptException(exception)); - } } } } diff --git a/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs b/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs index 106e6ae04..b29110e35 100644 --- a/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs +++ b/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs @@ -12,6 +12,7 @@ This Source Code Form is subject to the terms of the using System.Threading.Tasks; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/Text/ConsoleColorEnum.cs b/src/OneScript.StandardLibrary/Text/ConsoleColorEnum.cs index 74b0722d5..adc8b984b 100644 --- a/src/OneScript.StandardLibrary/Text/ConsoleColorEnum.cs +++ b/src/OneScript.StandardLibrary/Text/ConsoleColorEnum.cs @@ -26,15 +26,23 @@ public static ConsoleColorEnum CreateInstance(ITypeManager typeManager) typeManager, (t,v) => new ConsoleColorEnum(t,v)); - instance.WrapClrValue("Белый", "White", ConsoleColor.White); instance.WrapClrValue("Черный", "Black", ConsoleColor.Black); + instance.WrapClrValue("ТемноСиний", "DarkBlue", ConsoleColor.DarkBlue); + instance.WrapClrValue("ТемноЗеленый", "DarkGreen", ConsoleColor.DarkGreen); + instance.WrapClrValue("ТемноБирюзовый", "DarkCyan", ConsoleColor.DarkCyan); + instance.WrapClrValue("ТемноКрасный", "DarkRed", ConsoleColor.DarkRed); + instance.WrapClrValue("ТемноМалиновый", "DarkMagenta", ConsoleColor.DarkMagenta); + instance.WrapClrValue("ТемноЖелтый", "DarkYellow", ConsoleColor.DarkYellow); + instance.WrapClrValue("Серый", "Gray", ConsoleColor.Gray); + + instance.WrapClrValue("ТемноСерый", "DarkGray", ConsoleColor.DarkGray); instance.WrapClrValue("Синий", "Blue", ConsoleColor.Blue); - instance.WrapClrValue("Желтый", "Yellow", ConsoleColor.Yellow); - instance.WrapClrValue("Красный", "Red", ConsoleColor.Red); instance.WrapClrValue("Зеленый", "Green", ConsoleColor.Green); instance.WrapClrValue("Бирюза", "Cyan", ConsoleColor.Cyan); + instance.WrapClrValue("Красный", "Red", ConsoleColor.Red); instance.WrapClrValue("Малиновый", "Magenta", ConsoleColor.Magenta); - instance.WrapClrValue("Серый", "Gray", ConsoleColor.Gray); + instance.WrapClrValue("Желтый", "Yellow", ConsoleColor.Yellow); + instance.WrapClrValue("Белый", "White", ConsoleColor.White); OnInstanceCreation(instance); diff --git a/src/OneScript.StandardLibrary/Text/ConsoleContext.cs b/src/OneScript.StandardLibrary/Text/ConsoleContext.cs index 2d0ae2f46..2bab12cf9 100644 --- a/src/OneScript.StandardLibrary/Text/ConsoleContext.cs +++ b/src/OneScript.StandardLibrary/Text/ConsoleContext.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.IO; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Text/TextDocumentContext.cs b/src/OneScript.StandardLibrary/Text/TextDocumentContext.cs index 5e7281fee..21ca9b1e1 100644 --- a/src/OneScript.StandardLibrary/Text/TextDocumentContext.cs +++ b/src/OneScript.StandardLibrary/Text/TextDocumentContext.cs @@ -12,6 +12,7 @@ This Source Code Form is subject to the terms of the using System.Text; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Text/TextEncodingEnum.cs b/src/OneScript.StandardLibrary/Text/TextEncodingEnum.cs index 9a95af6fe..46ccd36a6 100644 --- a/src/OneScript.StandardLibrary/Text/TextEncodingEnum.cs +++ b/src/OneScript.StandardLibrary/Text/TextEncodingEnum.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Text; -using OneScript.Commons; using OneScript.Contexts.Enums; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -75,7 +75,7 @@ public EnumerationValue GetValue(Encoding encoding) public static TextEncodingEnum CreateInstance(ITypeManager typeManager) { - var instance = EnumContextHelper.CreateClrEnumInstance( + var instance = EnumContextHelper.CreateClrEnumInstance( typeManager, (t, v) => new TextEncodingEnum(t, v)); diff --git a/src/OneScript.StandardLibrary/Text/TextReadImpl.cs b/src/OneScript.StandardLibrary/Text/TextReadImpl.cs index 049f2bfda..b66f5c5af 100644 --- a/src/OneScript.StandardLibrary/Text/TextReadImpl.cs +++ b/src/OneScript.StandardLibrary/Text/TextReadImpl.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Text; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Text/TextWriteImpl.cs b/src/OneScript.StandardLibrary/Text/TextWriteImpl.cs index aa93fabda..98d51b5d1 100644 --- a/src/OneScript.StandardLibrary/Text/TextWriteImpl.cs +++ b/src/OneScript.StandardLibrary/Text/TextWriteImpl.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.IO; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Timezones/GlobalTimezoneFunctions.cs b/src/OneScript.StandardLibrary/Timezones/GlobalTimezoneFunctions.cs index d8b17176a..5e7cbee32 100644 --- a/src/OneScript.StandardLibrary/Timezones/GlobalTimezoneFunctions.cs +++ b/src/OneScript.StandardLibrary/Timezones/GlobalTimezoneFunctions.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/BooleanTypeAdjuster.cs b/src/OneScript.StandardLibrary/TypeDescriptions/BooleanTypeAdjuster.cs index 58c6227f1..4ca274a7c 100644 --- a/src/OneScript.StandardLibrary/TypeDescriptions/BooleanTypeAdjuster.cs +++ b/src/OneScript.StandardLibrary/TypeDescriptions/BooleanTypeAdjuster.cs @@ -5,7 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/NumberQualifiers.cs b/src/OneScript.StandardLibrary/TypeDescriptions/NumberQualifiers.cs index a65cb14b9..96ea0a8bf 100644 --- a/src/OneScript.StandardLibrary/TypeDescriptions/NumberQualifiers.cs +++ b/src/OneScript.StandardLibrary/TypeDescriptions/NumberQualifiers.cs @@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/TypeComparer.cs b/src/OneScript.StandardLibrary/TypeDescriptions/TypeComparer.cs new file mode 100644 index 000000000..b48b568aa --- /dev/null +++ b/src/OneScript.StandardLibrary/TypeDescriptions/TypeComparer.cs @@ -0,0 +1,66 @@ +/*---------------------------------------------------------- +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 OneScript.Types; +using OneScript.Values; + +namespace OneScript.StandardLibrary.TypeDescriptions +{ + internal class TypeComparer : IComparer + { + private const string TYPE_BINARYDATA_NAME = "ДвоичныеДанные"; + private static readonly IDictionary primitives = new Dictionary(); + + public int Compare(BslTypeValue x, BslTypeValue y) + { + if (x.TypeValue.Equals(y)) return 0; + + var primitiveX = PrimitiveIndex(x); + var primitiveY = PrimitiveIndex(y); + + if (primitiveX != -1) + { + if (primitiveY != -1) + return primitiveX - primitiveY; + + return -1; + } + + if (primitiveY != -1) + return 1; + + return x.TypeValue.Id.CompareTo(y.TypeValue.Id); + } + + private int PrimitiveIndex(BslTypeValue type) + { + if (StringComparer.CurrentCultureIgnoreCase.Equals(type.TypeValue.Name, TYPE_BINARYDATA_NAME)) + { + // Пора двоичным данным стать примитивом + return 1; + } + + if (primitives.TryGetValue(type.TypeValue, out var index)) + return index; + + return -1; + } + + static TypeComparer() + { + primitives.Add(BasicTypes.Boolean, 0); + primitives.Add(BasicTypes.String, 2); + primitives.Add(BasicTypes.Date, 3); + primitives.Add(BasicTypes.Null, 4); + primitives.Add(BasicTypes.Number, 5); + primitives.Add(BasicTypes.Type, 6); + } + + } +} + \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs index 5822b2796..0f9c3b164 100644 --- a/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs +++ b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs @@ -5,10 +5,11 @@ 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.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.Types; using OneScript.Values; @@ -22,27 +23,34 @@ public class TypeDescription : AutoContext { private readonly List _types = new List(); - private const string TYPE_BINARYDATA_NAME = "ДвоичныеДанные"; + public TypeDescription(IEnumerable types = null) + { + if (types != null) + { + _types.AddRange(types); + } + + NumberQualifiers = new NumberQualifiers(); + StringQualifiers = new StringQualifiers(); + DateQualifiers = new DateQualifiers(); + BinaryDataQualifiers = new BinaryDataQualifiers(); + } - public TypeDescription(IEnumerable types = null, - NumberQualifiers numberQualifiers = null, - StringQualifiers stringQualifiers = null, - DateQualifiers dateQualifiers = null, - BinaryDataQualifiers binaryDataQualifiers = null) + internal TypeDescription(IEnumerable types, + NumberQualifiers numberQualifiers, + StringQualifiers stringQualifiers, + DateQualifiers dateQualifiers, + BinaryDataQualifiers binaryDataQualifiers) { if (types != null) { _types.AddRange(types); } - NumberQualifiers = numberQualifiers != null && _types.Contains(TypeNumber()) ? - numberQualifiers : new NumberQualifiers(); - StringQualifiers = stringQualifiers != null && _types.Contains(TypeString()) ? - stringQualifiers : new StringQualifiers(); - DateQualifiers = dateQualifiers != null && _types.Contains(TypeDate()) ? - dateQualifiers : new DateQualifiers(); - BinaryDataQualifiers = binaryDataQualifiers != null && _types.Any(x => x.TypeValue.Name == TYPE_BINARYDATA_NAME) ? - binaryDataQualifiers : new BinaryDataQualifiers(); + NumberQualifiers = numberQualifiers; + StringQualifiers = stringQualifiers; + DateQualifiers = dateQualifiers; + BinaryDataQualifiers = binaryDataQualifiers; } [ContextProperty("КвалификаторыЧисла", "NumberQualifiers")] @@ -70,16 +78,30 @@ public ArrayImpl Types() return result; } + internal IEnumerable TypesInternal() + { + return _types; + } + [ContextMethod("СодержитТип", "ContainsType")] public bool ContainsType(IValue type) { if (type is BslTypeValue typeVal) + { + if (typeVal.TypeValue.Equals(BasicTypes.Undefined)) + { + // тип "Неопределено" содержится в любом явно определенном составном типе + // и не содержится в типе Произвольный (когда явно не указан состав типов) + // или когда указан один конкретный тип + return (_types.Count > 1); + } return _types.Contains(typeVal); + } throw RuntimeException.InvalidArgumentType(nameof(type)); } - IValueAdjuster GetAdjusterForType(BslTypeValue type) + private IValueAdjuster GetAdjusterForType(BslTypeValue type) { var value = type.TypeValue; @@ -95,158 +117,63 @@ IValueAdjuster GetAdjusterForType(BslTypeValue type) if (value.Equals(BasicTypes.Boolean)) return new BooleanTypeAdjuster(); + if (value.Equals(BasicTypes.Undefined)) + return new UndefinedTypeAdjuster(); + return null; } [ContextMethod("ПривестиЗначение", "AdjustValue")] - public IValue AdjustValue(IValue value = null) + public IValue AdjustValue(IValue pValue = null) { - + var value = pValue?.GetRawValue(); if (_types.Count == 0) { return value ?? ValueFactory.Create(); } - BslTypeValue typeToCast = null; - - if (value != null && value.SystemType != BasicTypes.Undefined) + if (value != null) { var valueType = new BslTypeValue(value.SystemType); - if (_types.Contains(valueType)) + if (ContainsType(valueType)) { // Если такой тип у нас есть - typeToCast = valueType; + var adjuster = GetAdjusterForType(valueType); + var adjustedValue = adjuster?.Adjust(value) ?? value; + return adjustedValue; } } - if (typeToCast == null) - { - // Если типа нет, то нужно брать значение по-умолчанию - if (_types.Count != 1) - { - // много типов - Неопределено - return ValueFactory.Create(); - } - - typeToCast = _types[0]; - } - - var adjuster = GetAdjusterForType(typeToCast); - - return adjuster?.Adjust(value) ?? ValueFactory.Create(); - } - - private static IList ConstructTypeList(ITypeManager typeManager, IValue types) - { - var typesList = new List(); - if (types == null) - return typesList; - - types = types.GetRawValue(); - if (types.SystemType == BasicTypes.String) - { - var typeNames = types.AsString().Split(','); - foreach (var typeName in typeNames) - { - if (string.IsNullOrWhiteSpace(typeName)) - continue; - - var typeValue = new BslTypeValue(typeManager.GetTypeByName(typeName.Trim())); - if (!typesList.Contains(typeValue)) - typesList.Add(typeValue); - } - } else if (types is ArrayImpl arrayOfTypes) - { - foreach (var type in arrayOfTypes) - { - var rawType = type.GetRawValue() as BslTypeValue; - if (rawType == null) - continue; - - if (!typesList.Contains(rawType)) - typesList.Add(rawType); - } - } - else if (types.SystemType != BasicTypes.Undefined) + foreach (var type in _types) { - return null; // далее будет исключение + var adjuster = GetAdjusterForType(type); + var adjustedValue = adjuster?.Adjust(value); + if (adjustedValue != null) + return adjustedValue; } - // для Неопределено возвращается пустой список - return typesList; - } - - static BslTypeValue TypeNumber() - { - return new BslTypeValue(BasicTypes.Number); - } - - static BslTypeValue TypeBoolean() - { - return new BslTypeValue(BasicTypes.Boolean); - } - - static BslTypeValue TypeString() - { - return new BslTypeValue(BasicTypes.String); - } - - static BslTypeValue TypeDate() - { - return new BslTypeValue(BasicTypes.Date); + return ValueFactory.Create(); } public static TypeDescription StringType(int length = 0, - AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) + AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) { - var stringQualifier = new StringQualifiers(length, allowedLength); - return new TypeDescription(new BslTypeValue[] { TypeString() }, null, stringQualifier); + return TypeDescriptionBuilder.OfType(BasicTypes.String) + .SetStringQualifiers(new StringQualifiers(length, allowedLength)) + .Build(); } public static TypeDescription IntegerType(int length = 10, - AllowedSignEnum allowedSign = AllowedSignEnum.Any) + AllowedSignEnum allowedSign = AllowedSignEnum.Any) { - var numberQualifier = new NumberQualifiers(length, 0, allowedSign); - return new TypeDescription(new BslTypeValue[] { TypeNumber() }, numberQualifier); + return TypeDescriptionBuilder.OfType(BasicTypes.Number) + .SetNumberQualifiers(new NumberQualifiers(length, 0, allowedSign)) + .Build(); } public static TypeDescription BooleanType() { - return new TypeDescription(new BslTypeValue[] { TypeBoolean() }); - } - - - private class TypeQualifiersSet - { - public readonly NumberQualifiers numberQualifiers = null; - public readonly StringQualifiers stringQualifiers = null; - public readonly DateQualifiers dateQualifiers = null; - public readonly BinaryDataQualifiers binaryDataQualifiers = null; - - public TypeQualifiersSet(IValue p2, IValue p3, IValue p4, IValue p5, IValue p6, IValue p7) - { - int nParam = 1; - foreach (var qual in new[] { p2, p3, p4, p5, p6, p7 }) - { - nParam++; - - if (qual == null || qual.Equals(BslUndefinedValue.Instance)) - continue; - - switch (qual.GetRawValue()) - { - case NumberQualifiers nq: numberQualifiers = nq; break; - - case StringQualifiers sq: stringQualifiers = sq; break; - - case DateQualifiers dq: dateQualifiers = dq; break; - - case BinaryDataQualifiers bdq: binaryDataQualifiers = bdq; break; - - default: throw RuntimeException.InvalidNthArgumentType(nParam); - } - } - } + return TypeDescriptionBuilder.OfType(BasicTypes.Boolean).Build(); } [ScriptConstructor] @@ -260,90 +187,153 @@ public static TypeDescription Constructor( IValue p6 = null, IValue p7 = null) { + var builder = new TypeDescriptionBuilder(); + + // параметры, которые заведомо не квалификаторы, заменяем на null, но оставляем, + // чтобы указать номер параметра при выводе ошибки несоответствия типа + var qualifiers = new[] { null, p2, p3, p4, p5, p6, p7 }; + var rawSource = source?.GetRawValue(); - - if (rawSource == null || rawSource.SystemType == BasicTypes.Undefined) + if (rawSource != null && rawSource.SystemType != BasicTypes.Undefined) { - // пустой первый параметр - нет объекта-основания - // добавляемые/вычитаемые типы не допускаются, квалификаторы игнорируются + if (rawSource is TypeDescription typeDesc) + { + // Если 1 парарметр - ОписаниеТипов, то 2 - добавляемые типы, 3 - убираемые типы, + builder.SourceDescription(typeDesc); - // только для контроля типов - var _ = new TypeQualifiersSet(p2, p3, p4, p5, p6, p7); + var typesToAdd = CheckAndParseTypeList(context.TypeManager, p2, 2); + var typesToRemove = CheckAndParseTypeList(context.TypeManager, p3, 3); - return new TypeDescription(); - } + builder.RemoveTypes(typesToRemove); + builder.AddTypes(typesToAdd); - if (rawSource is TypeDescription) + qualifiers[1] = null; // эти параметры не квалификаторы + qualifiers[2] = null; // эти параметры не квалификаторы + } + else if (rawSource.SystemType == BasicTypes.String || rawSource is ArrayImpl) + { + // Если 1 парарметр - Массив или строка, то это набор конкретных типов + // остальные параметры (2 и далее) - клвалификаторы в произвольном порядке + var typesList = CheckAndParseTypeList(context.TypeManager, rawSource, 1); + builder.AddTypes(typesList); + } + else + throw RuntimeException.InvalidArgumentValue(); + } /* else + пустой первый параметр - нет объекта-основания + добавляемые/вычитаемые типы не допускаются, квалификаторы игнорируются + квалификакторы передаются только для контроля типов + */ + CheckAndAddQualifiers(builder, qualifiers); + return builder.Build(); + } + + /// + /// Преобразует входящий параметр в список типов. + /// + /// В качестве типов могут быть переданы Строка или Массив Типов + /// Номер параметра, который будет указан в исключении, если параметр typeList задан неверно + /// Если typeList не может быть разобран как набор типов + /// Список переданных типов, приведенный к конкретным TypeTypeValue + private static List CheckAndParseTypeList(ITypeManager typeManager, IValue types, int nParam) + { + types = types?.GetRawValue(); + if (types == null || types.SystemType == BasicTypes.Undefined) + return new List(); + + if (types.SystemType == BasicTypes.String) { - return ConstructByOtherDescription(context.TypeManager, rawSource, p2, p3, p4, p5, p6, p7); + return FromTypeNames(typeManager, types.AsString()); } - - if (rawSource.SystemType == BasicTypes.String || rawSource is ArrayImpl) + if (types is ArrayImpl arrayOfTypes) { - return ConstructByQualifiers(context.TypeManager, rawSource, p2, p3, p4, p5, p6, p7); + return FromArrayOfTypes(arrayOfTypes); } - throw RuntimeException.InvalidArgumentValue(); + throw RuntimeException.InvalidNthArgumentType(nParam); } - public static TypeDescription ConstructByQualifiers(ITypeManager typeManager, IValue types, - IValue p2 = null, - IValue p3 = null, - IValue p4 = null, - IValue p5 = null, - IValue p6 = null, - IValue p7 = null) + private static List FromTypeNames(ITypeManager typeManager, string types) { - var typesList = ConstructTypeList(typeManager, types); - if (typesList == null) - throw RuntimeException.InvalidNthArgumentType(1); + var typeNames = types.Split(','); + var typesList = new List(); + foreach (var typeName in typeNames) + { + if (string.IsNullOrWhiteSpace(typeName)) + continue; - var qualSet = new TypeQualifiersSet(p2,p3,p4,p5,p6,p7); + var typeValue = new BslTypeValue(typeManager.GetTypeByName(typeName.Trim())); + if (!typesList.Contains(typeValue)) + typesList.Add(typeValue); + } - return new TypeDescription(typesList, - qualSet.numberQualifiers, - qualSet.stringQualifiers, - qualSet.dateQualifiers, - qualSet.binaryDataQualifiers); + return typesList; } - public static TypeDescription ConstructByOtherDescription(ITypeManager typeManager, - IValue typeDescription = null, - IValue addTypes = null, - IValue removeTypes = null, - IValue p4 = null, - IValue p5 = null, - IValue p6 = null, - IValue p7 = null) + private static List FromArrayOfTypes(ArrayImpl arrayOfTypes) { - var removeTypesList = ConstructTypeList(typeManager, removeTypes); - if (removeTypesList == null) - throw RuntimeException.InvalidNthArgumentType(3); - var typesList = new List(); - if (typeDescription is TypeDescription typeDesc) + foreach (var type in arrayOfTypes) { - foreach (var type in typeDesc._types) + if (type.GetRawValue() is BslTypeValue rawType) { - if (!removeTypesList.Contains(type)) - { - typesList.Add(type); - } + typesList.Add(rawType); } } + return typesList; + } - var addTypesList = ConstructTypeList(typeManager, addTypes); - if (addTypesList == null) - throw RuntimeException.InvalidNthArgumentType(2); - typesList.AddRange(addTypesList); + private static void CheckAndAddQualifiers(TypeDescriptionBuilder builder, IValue[] parameters) + { + for (var i = 0; i < parameters.Length; i++) + { + var rawQualifier = parameters[i]?.GetRawValue(); + if (rawQualifier != null && !rawQualifier.Equals(ValueFactory.Create())) + { + CheckAndAddOneQualifier(builder, rawQualifier, i + 1); + } + } + } + + /// + /// Проверяет, что переданный параметр является квалификатором типа. + /// Если тип параметра не является квалификатором, бросает исключение с указанием номера параметра. + /// + /// Построитель описания типов, которому будет присвоен квалификатор + /// Проверяемый входящий параметр + /// Порядковый номер параметра для выброса исключения + /// Если qualifier не является квалификатором типа + private static void CheckAndAddOneQualifier(TypeDescriptionBuilder builder, IValue qualifier, int nParam) + { + switch (qualifier) + { + case NumberQualifiers nq: + builder.SetNumberQualifiers(nq); + break; + + case StringQualifiers sq: + builder.SetStringQualifiers(sq); + break; - var qualSet = new TypeQualifiersSet(null, null, p4, p5, p6, p7); + case DateQualifiers dq: + builder.SetDateQualifiers(dq); + break; - return new TypeDescription(typesList, - qualSet.numberQualifiers, - qualSet.stringQualifiers, - qualSet.dateQualifiers, - qualSet.binaryDataQualifiers); + case BinaryDataQualifiers bdq: + builder.SetBinaryDataQualifiers(bdq); + break; + + default: + throw RuntimeException.InvalidNthArgumentType(nParam); + } + } + } + + internal class UndefinedTypeAdjuster : IValueAdjuster + { + public IValue Adjust(IValue value) + { + return ValueFactory.Create(); } } } diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescriptionBuilder.cs b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescriptionBuilder.cs new file mode 100644 index 000000000..551d8e7d0 --- /dev/null +++ b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescriptionBuilder.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.Collections.Generic; +using System.Linq; +using OneScript.Types; +using OneScript.Values; + +namespace OneScript.StandardLibrary.TypeDescriptions +{ + internal class TypeDescriptionBuilder + { + private NumberQualifiers _numberQualifiers; + private StringQualifiers _stringQualifiers; + private DateQualifiers _dateQualifiers; + private BinaryDataQualifiers _binaryDataQualifiers; + + private const string TYPE_BINARYDATA_NAME = "ДвоичныеДанные"; + + private List _types = new List(); + + internal TypeDescriptionBuilder() + { + } + + public TypeDescriptionBuilder SourceDescription(TypeDescription source) + { + _numberQualifiers = source.NumberQualifiers; + _stringQualifiers = source.StringQualifiers; + _dateQualifiers = source.DateQualifiers; + _binaryDataQualifiers = source.BinaryDataQualifiers; + return AddTypes(source.TypesInternal()); + } + + public TypeDescriptionBuilder AddTypes(IEnumerable types) + { + _types.AddRange(types); + return this; + } + + public TypeDescriptionBuilder RemoveTypes(IEnumerable types) + { + _types.RemoveAll(types.Contains); + return this; + } + + public TypeDescriptionBuilder SetNumberQualifiers(NumberQualifiers nq) + { + _numberQualifiers = nq; + return this; + } + + public TypeDescriptionBuilder SetStringQualifiers(StringQualifiers sq) + { + _stringQualifiers = sq; + return this; + } + + public TypeDescriptionBuilder SetDateQualifiers(DateQualifiers dq) + { + _dateQualifiers = dq; + return this; + } + + public TypeDescriptionBuilder SetBinaryDataQualifiers(BinaryDataQualifiers bq) + { + _binaryDataQualifiers = bq; + return this; + } + + public TypeDescription Build() + { + _types = new List(_types.Distinct()); + _types.RemoveAll(type => type.TypeValue.ImplementingClass == typeof(BslUndefinedValue)); + _types.Sort(new TypeComparer()); + var hasNumber = _types.Any(type => type.TypeValue == BasicTypes.Number); + var hasString =_types.Any(type => type.TypeValue == BasicTypes.String); + var hasDate = _types.Any(type => type.TypeValue == BasicTypes.Date); + var hasBinaryData = _types.Any(x => x.TypeValue.Name == TYPE_BINARYDATA_NAME); + + if (!hasNumber || _numberQualifiers == null) _numberQualifiers = new NumberQualifiers(); + if (!hasString || _stringQualifiers == null) _stringQualifiers = new StringQualifiers(); + if (!hasDate || _dateQualifiers == null) _dateQualifiers = new DateQualifiers(); + if (!hasBinaryData || _binaryDataQualifiers == null) _binaryDataQualifiers = new BinaryDataQualifiers(); + + return new TypeDescription(_types, + _numberQualifiers, + _stringQualifiers, + _dateQualifiers, + _binaryDataQualifiers + ); + + } + + public static TypeDescriptionBuilder OfType(TypeDescriptor commonType) + { + var builder = new TypeDescriptionBuilder(); + builder.AddTypes(new[] { new BslTypeValue(commonType) }); + return builder; + } + } +} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs b/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs index 4e2eec232..9655f91ac 100644 --- a/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs +++ b/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Xml; using OneScript.Types; using OneScript.Values; @@ -20,7 +20,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XDTO { [ContextClass("СериализаторXDTO", "XDTOSerializer")] - public class XDTOSerializer : AutoContext + public sealed class XDTOSerializer : AutoContext { private readonly ITypeManager _typeManager; private readonly XmlGlobalFunctions _xmlGlobalFunctions; @@ -223,7 +223,7 @@ public IValue ReadXML(XmlReaderImpl xmlReader, IValue valueType = null) } else if (xsiNil.SystemType == BasicTypes.String) typeValue = new BslTypeValue(BasicTypes.Undefined); - }; + } if (typeValue == null) throw RuntimeException.InvalidArgumentValue(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XMLSchemaSet.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XMLSchemaSet.cs index 9b0e5b6d0..78a55450f 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XMLSchemaSet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XMLSchemaSet.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; using ScriptEngine; using ScriptEngine.Machine; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("НаборСхемXML", "XMLSchemaSet")] - public class XMLSchemaSet : AutoCollectionContext + public sealed class XMLSchemaSet : AutoCollectionContext { private readonly XmlSchemaSet _schemaSet; private readonly List _items; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComplexFinalUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComplexFinalUnion.cs index 15a1fe5cf..3ca016b24 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComplexFinalUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComplexFinalUnion.cs @@ -16,7 +16,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеЗавершенностиСоставногоТипаXS", "XSComplexFinalUnion")] - public class XSComplexFinalUnion : AutoContext + public sealed class XSComplexFinalUnion : AutoContext { private readonly ArrayImpl _values; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentFixedList.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentFixedList.cs index 183332a63..962311a1a 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentFixedList.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentFixedList.cs @@ -14,13 +14,15 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ФиксированныйСписокКомпонентXS", "XSComponentFixedList")] - public class XSComponentFixedList : AutoCollectionContext + public sealed class XSComponentFixedList : AutoCollectionContext { private readonly List _items; public XSComponentFixedList() => _items = new List(); + public static XSComponentFixedList EmptyList() => new XSComponentFixedList(); + public void Add(IXSComponent value) => _items.Add(value); public void Remove(IXSComponent value) => _items.Remove(value); public void Clear() => _items.Clear(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentList.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentList.cs index 9f20fbdec..6041a6f8b 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentList.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSComponentList.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Interfaces; using OneScript.Values; using ScriptEngine.Machine; @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("СписокКомпонентXS", "XSComponentList")] - public class XSComponentList : AutoCollectionContext + public sealed class XSComponentList : AutoCollectionContext { private readonly List _items; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSDisallowedSubstitutionsUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSDisallowedSubstitutionsUnion.cs index 2e7605838..a663f4538 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSDisallowedSubstitutionsUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSDisallowedSubstitutionsUnion.cs @@ -10,20 +10,19 @@ This Source Code Form is subject to the terms of the using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.Types; -using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеНедопустимыхПодстановкиXS", "XSDisallowedSubstitutionsUnion")] - public class XsDisallowedSubstitutionsUnion : AutoContext + public sealed class XsDisallowedSubstitutionsUnion : AutoContext { - private ArrayImpl _values; + private readonly ArrayImpl _values; private bool Contains(XmlSchemaDerivationMethod value) { - XSDisallowedSubstitutions enumValue = EnumerationXSDisallowedSubstitutions.FromNativeValue(value); - IValue idx = _values.Find(enumValue); + var enumValue = EnumerationXSDisallowedSubstitutions.FromNativeValue(value); + var idx = _values.Find(enumValue); return (idx.SystemType != BasicTypes.Undefined); } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSNamedComponentMap.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSNamedComponentMap.cs index ad13233ca..49e1ff972 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSNamedComponentMap.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSNamedComponentMap.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Interfaces; using OneScript.Types; using ScriptEngine.Machine; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("КоллекцияИменованныхКомпонентXS", "XSNamedComponentMap")] - public class XSNamedComponentMap : AutoCollectionContext + public sealed class XSNamedComponentMap : AutoCollectionContext { private readonly List _items; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSProhibitedSubstitutionsUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSProhibitedSubstitutionsUnion.cs index 9763acb30..04e19508b 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSProhibitedSubstitutionsUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSProhibitedSubstitutionsUnion.cs @@ -16,7 +16,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеЗапрещенныхПодстановокXS", "XSProhibitedSubstitutionsUnion")] - public class XsProhibitedSubstitutionsUnion : AutoContext + public sealed class XsProhibitedSubstitutionsUnion : AutoContext { private readonly ArrayImpl _values; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSchemaFinalUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSchemaFinalUnion.cs index d333e0b98..28644c629 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSchemaFinalUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSchemaFinalUnion.cs @@ -10,20 +10,19 @@ This Source Code Form is subject to the terms of the using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.Types; -using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеЗавершенностиСхемыXS", "XSSchemaFinalUnion")] - public class XSSchemaFinalUnion : AutoContext + public sealed class XSSchemaFinalUnion : AutoContext { - private ArrayImpl _values; + private readonly ArrayImpl _values; private bool Contains(XmlSchemaDerivationMethod value) { var enumValue = EnumerationXSSchemaFinal.Instance.FromNativeValue(value); - IValue idx = _values.Find(enumValue); + var idx = _values.Find(enumValue); return (idx.SystemType != BasicTypes.Undefined); } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSimpleFinalUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSimpleFinalUnion.cs index 81490fc81..1cd14e6aa 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSimpleFinalUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSimpleFinalUnion.cs @@ -10,20 +10,19 @@ This Source Code Form is subject to the terms of the using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.Types; -using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеЗавершенностиПростогоТипаXS", "XSSimpleFinalUnion")] - public class XSSimpleFinalUnion : AutoContext + public sealed class XSSimpleFinalUnion : AutoContext { private ArrayImpl _values; private bool Contains(XmlSchemaDerivationMethod _value) { - XSSimpleFinal enumValue = EnumerationXSSimpleFinal.FromNativeValue(_value); - IValue idx = _values.Find(enumValue); + var enumValue = EnumerationXSSimpleFinal.FromNativeValue(_value); + var idx = _values.Find(enumValue); return idx.SystemType != BasicTypes.Undefined; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSubstitutionGroupExclusionsUnion.cs b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSubstitutionGroupExclusionsUnion.cs index 078f35d4a..489c33adf 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSubstitutionGroupExclusionsUnion.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Collections/XSSubstitutionGroupExclusionsUnion.cs @@ -16,7 +16,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Collections { [ContextClass("ОбъединениеИсключенийГруппПодстановкиXS", "XSSubstitutionGroupExclusionsUnion")] - public class XsSubstitutionGroupExclusionsUnion : AutoContext + public sealed class XsSubstitutionGroupExclusionsUnion : AutoContext { private readonly ArrayImpl _values; private bool Contains(XmlSchemaDerivationMethod value) diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSComplexFinal.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSComplexFinal.cs index 63311e279..dbdab2a8d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSComplexFinal.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSComplexFinal.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSComplexFinal : EnumerationValue + public sealed class XSComplexFinal : EnumerationValue { private readonly XmlSchemaDerivationMethod _derivationMethod; public XSComplexFinal(EnumerationContext owner, XmlSchemaDerivationMethod derivationMethod) @@ -28,7 +28,7 @@ public static XmlSchemaDerivationMethod ToNativeValue(XSComplexFinal wrapper) } [SystemEnum("ЗавершенностьСоставногоТипаXS", "XSComplexFinal")] - public class EnumerationXSComplexFinal : EnumerationContext + public sealed class EnumerationXSComplexFinal : EnumerationContext { private readonly Dictionary _valuesCache; @@ -70,6 +70,4 @@ public static EnumerationXSComplexFinal CreateInstance(ITypeManager typeManager) } } - - -} \ No newline at end of file +} diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSContentModel.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSContentModel.cs index 4ef13998b..1b65c3801 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSContentModel.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSContentModel.cs @@ -18,9 +18,15 @@ public enum XSContentModel [EnumValue("EmptyRef", "ПустаяСсылка")] EmptyRef, + /// + /// Простая модель содержания. + /// [EnumValue("Simple", "Простая")] Simple, + /// + /// Составная модель содержания. + /// [EnumValue("Complex", "Составная")] Complex } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSDisallowedSubstitutions.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSDisallowedSubstitutions.cs index 65f06a242..9a52f923c 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSDisallowedSubstitutions.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSDisallowedSubstitutions.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSDisallowedSubstitutions : ClrEnumValueWrapper + public sealed class XSDisallowedSubstitutions : ClrEnumValueWrapper { internal XSDisallowedSubstitutions(EnumerationXSDisallowedSubstitutions instance, XmlSchemaDerivationMethod realValue) : base(instance, realValue) @@ -29,7 +29,7 @@ public static XmlSchemaDerivationMethod ToNativeValue(XSDisallowedSubstitutions } [SystemEnum("НедопустимыеПодстановкиXS", "XSDisallowedSubstitutions")] - public class EnumerationXSDisallowedSubstitutions : EnumerationContext + public sealed class EnumerationXSDisallowedSubstitutions : EnumerationContext { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSForm.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSForm.cs index 9e9c4b18f..29b8ee707 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSForm.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSForm.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSForm : ClrEnumValueWrapper + public sealed class XSForm : ClrEnumValueWrapper { internal XSForm(EnumerationXSForm instance, XmlSchemaForm realValue) : base(instance, realValue ) { @@ -26,7 +26,7 @@ internal XSForm(EnumerationXSForm instance, XmlSchemaForm realValue) : base(inst } [SystemEnum("ФормаПредставленияXS", "XSForm")] - public class EnumerationXSForm : EnumerationContext + public sealed class EnumerationXSForm : EnumerationContext { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSProhibitedSubstitutions.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSProhibitedSubstitutions.cs index 344a85e16..e60bd06a4 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSProhibitedSubstitutions.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSProhibitedSubstitutions.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSProhibitedSubstitutions : ClrEnumValueWrapper + public sealed class XSProhibitedSubstitutions : ClrEnumValueWrapper { internal XSProhibitedSubstitutions(EnumerationXSProhibitedSubstitutions instance, XmlSchemaDerivationMethod realValue) : base(instance, realValue) @@ -29,7 +29,7 @@ public static XmlSchemaDerivationMethod ToNativeValue(XSProhibitedSubstitutions } [SystemEnum("ЗапрещенныеПодстановкиXS", "EnumerationXSProhibitedSubstitutions")] - public class EnumerationXSProhibitedSubstitutions : EnumerationContext + public sealed class EnumerationXSProhibitedSubstitutions : EnumerationContext { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSchemaFinal.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSchemaFinal.cs index 8d56229db..998213398 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSchemaFinal.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSchemaFinal.cs @@ -13,7 +13,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSSchemaFinal : ClrEnumValueWrapper + public sealed class XSSchemaFinal : ClrEnumValueWrapper { internal XSSchemaFinal(EnumerationXSSchemaFinal instance, XmlSchemaDerivationMethod realValue) : base(instance, realValue) @@ -22,7 +22,7 @@ internal XSSchemaFinal(EnumerationXSSchemaFinal instance, XmlSchemaDerivationMet } [SystemEnum("ЗавершенностьСхемыXS", "XSSchemaFinal")] - public class EnumerationXSSchemaFinal : ClrEnumWrapper + public sealed class EnumerationXSSchemaFinal : ClrEnumWrapper { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSimpleFinal.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSimpleFinal.cs index 8010da761..281563283 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSimpleFinal.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSimpleFinal.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSSimpleFinal : ClrEnumValueWrapper + public sealed class XSSimpleFinal : ClrEnumValueWrapper { internal XSSimpleFinal(EnumerationXSSimpleFinal instance, XmlSchemaDerivationMethod realValue) : base(instance, realValue) @@ -29,7 +29,7 @@ public static XmlSchemaDerivationMethod ToNativeValue(XSSimpleFinal wrapper) } [SystemEnum("ЗавершенностьПростогоТипаXS", "XSSimpleFinal")] - public class EnumerationXSSimpleFinal : EnumerationContext + public sealed class EnumerationXSSimpleFinal : EnumerationContext { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSubstitutionGroupExclusions.cs b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSubstitutionGroupExclusions.cs index 333d62ad6..a90644bb3 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSubstitutionGroupExclusions.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Enumerations/XSSubstitutionGroupExclusions.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Enumerations { - public class XSSubstitutionGroupExclusions : ClrEnumValueWrapper + public sealed class XSSubstitutionGroupExclusions : ClrEnumValueWrapper { internal XSSubstitutionGroupExclusions(EnumerationXSSubstitutionGroupExclusions instance, XmlSchemaDerivationMethod realValue) : base(instance, realValue) @@ -29,7 +29,7 @@ public static XmlSchemaDerivationMethod ToNativeValue(XSSubstitutionGroupExclusi } [SystemEnum("ИсключенияГруппПодстановкиXS", "XSSubstitutionGroupExclusions")] - public class EnumerationXSSubstitutionGroupExclusions : EnumerationContext + public sealed class EnumerationXSSubstitutionGroupExclusions : EnumerationContext { private readonly Dictionary _valuesCache; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Interfaces/IXSType.cs b/src/OneScript.StandardLibrary/XMLSchema/Interfaces/IXSType.cs index b374ee757..8929e2d14 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Interfaces/IXSType.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Interfaces/IXSType.cs @@ -9,5 +9,7 @@ namespace OneScript.StandardLibrary.XMLSchema.Interfaces { public interface IXSType : IXSAnnotated { + string NamespaceURI { get; } + string Name { get; set; } } } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchema.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchema.cs index 84d422759..524eaf759 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchema.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchema.cs @@ -10,8 +10,8 @@ This Source Code Form is subject to the terms of the using System.Text; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XDTO; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Collections; @@ -25,13 +25,15 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("СхемаXML", "XMLSchema")] - public class XMLSchema : AutoContext, IXSComponent, IXDTOSerializableXML + public sealed class XMLSchema : AutoContext, IXSComponent, IXDTOSerializableXML { private readonly XmlSchema _schema; - private XMLSchema() + private XMLSchema() : this(new XmlSchema()) { } + + public XMLSchema(XmlSchema xmlSchema) { - _schema = new XmlSchema(); + _schema = xmlSchema; Components = new XSComponentFixedList(); Annotations = new XSComponentFixedList(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchemaSerializer.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchemaSerializer.cs index 96dad80b7..80421b16d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchemaSerializer.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XMLSchemaSerializer.cs @@ -7,13 +7,13 @@ This Source Code Form is subject to the terms of the using System.Xml; using System.Xml.Schema; -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Interfaces; namespace OneScript.StandardLibrary.XMLSchema.Objects { - internal class XMLSchemaSerializer + internal static class XMLSchemaSerializer { internal static IXSComponent CreateInstance(XmlSchemaObject xmlSchemaObject) { @@ -93,7 +93,8 @@ private static IXSComponent CreateIXSAnnotated(XmlSchemaAnnotated xmlAnnotated) else if (xmlAnnotated is XmlSchemaGroup xmlGroup) return new XSModelGroupDefinition(xmlGroup); - + else if (xmlAnnotated is XmlSchemaXPath xmlPath) + return new XSXPathDefinition(xmlPath); else throw RuntimeException.InvalidArgumentType(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAnnotation.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAnnotation.cs index 8f5219b99..c063335a3 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAnnotation.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAnnotation.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.StandardLibrary.XMLSchema.Interfaces; @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("АннотацияXS", "XSAnnotation")] - public class XSAnnotation : AutoContext, IXSComponent + public sealed class XSAnnotation : AutoContext, IXSComponent { internal readonly XmlSchemaAnnotation InternalObject; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs index 5abfc37bf..a1b64664e 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ИнформацияДляПриложенияXS", "XSAppInfo")] - public class XSAppInfo : AutoContext, IXSAnnotationItem + public sealed class XSAppInfo : AutoContext, IXSAnnotationItem { private readonly XmlSchemaAppInfo _appInfo; @@ -34,7 +34,7 @@ public class XSAppInfo : AutoContext, IXSAnnotationItem public XSAnnotation Annotation => null; [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -60,7 +60,7 @@ public string Source #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeDeclaration.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeDeclaration.cs index 85cacaa0b..a548df57d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeDeclaration.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeDeclaration.cs @@ -19,7 +19,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОбъявлениеАтрибутаXS", "XSAttributeDeclaration")] - public class XSAttributeDeclaration : AutoContext, IXSAnnotated, IXSAttribute, IXSNamedComponent + public sealed class XSAttributeDeclaration : AutoContext, IXSAnnotated, IXSAttribute, IXSNamedComponent { private readonly XmlSchemaAttribute _attribute; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeGroupDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeGroupDefinition.cs index 77875b644..578d100c9 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeGroupDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeGroupDefinition.cs @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределениеГруппыАтрибутовXS", "XSAttributeGroupDefinition")] - public class XSAttributeGroupDefinition : AutoContext, IXSAnnotated, IXSNamedComponent + public sealed class XSAttributeGroupDefinition : AutoContext, IXSAnnotated, IXSNamedComponent { private XmlSchemaAnnotated _attributeGroup; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeUse.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeUse.cs index 4777b5c02..9a3d11754 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeUse.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAttributeUse.cs @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ИспользованиеАтрибутаXS", "XSAttributeUse")] - public class XSAttributeUse : AutoContext, IXSComponent + public sealed class XSAttributeUse : AutoContext, IXSComponent { private IValue _value; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs index 225b042a1..616f09d09 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Collections; @@ -20,9 +20,11 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределениеСоставногоТипаXS", "XSComplexTypeDefinition")] - public class XSComplexTypeDefinition : AutoContext, IXSType, IXSNamedComponent + public sealed class XSComplexTypeDefinition : AutoContext, IXSType, IXSNamedComponent { private readonly XmlSchemaComplexType _type; + private readonly XSComponentFixedList _components = new XSComponentFixedList(); + private readonly XSComponentList _attributes = new XSComponentList(); private XSAnnotation _annotation; private XSAnnotation _contentModelAnnotation; private XSAnnotation _derivationAnnotation; @@ -32,17 +34,9 @@ public class XSComplexTypeDefinition : AutoContext, IXS private XSDerivationMethod _derivationMethod; private XSContentModel _contentModel; - private XSComplexTypeDefinition() - { - _type = new XmlSchemaComplexType(); - Components = new XSComponentFixedList(); - Attributes = new XSComponentList(); - Attributes.Inserted += Attributes_Inserted; - Attributes.Cleared += Attributes_Cleared; - } + private XSComplexTypeDefinition() : this(new XmlSchemaComplexType()) { } internal XSComplexTypeDefinition(XmlSchemaComplexType complexType) - : this() { _type = complexType; @@ -52,86 +46,99 @@ internal XSComplexTypeDefinition(XmlSchemaComplexType complexType) _annotation.BindToContainer(RootContainer, this); } - if (_type.ContentModel is XmlSchemaSimpleContent simpleContent) - { - _contentModel = XSContentModel.Simple; - if (simpleContent.Content is XmlSchemaSimpleContentExtension contentExtension) - { - _derivationMethod = XSDerivationMethod.Extension; - if (contentExtension.BaseTypeName is XmlQualifiedName qualifiedName) - _baseTypeName = XMLSchemaSerializer.CreateXMLExpandedName(qualifiedName); - - if (contentExtension.AnyAttribute is XmlSchemaAnyAttribute anyAttribute) - _attributeWildcard = XMLSchemaSerializer.CreateXSWildcard(anyAttribute); - } - else if (simpleContent.Content is XmlSchemaSimpleContentRestriction contentRestriction) - { - _derivationMethod = XSDerivationMethod.Restriction; - if (contentRestriction.BaseTypeName is XmlQualifiedName qualifiedName) - _baseTypeName = XMLSchemaSerializer.CreateXMLExpandedName(qualifiedName); - - if (contentRestriction.AnyAttribute is XmlSchemaAnyAttribute anyAttribute) - _attributeWildcard = XMLSchemaSerializer.CreateXSWildcard(anyAttribute); - } - else - _derivationMethod = XSDerivationMethod.EmptyRef; + InitContentModel(); - if (_type.Particle is XmlSchemaParticle particle) - _content = XMLSchemaSerializer.CreateInstance(particle); + foreach (XmlSchemaObject item in _type.Attributes) + { + IXSComponent component = XMLSchemaSerializer.CreateInstance(item); + component.BindToContainer(RootContainer, this); + _attributes.Add(component); + _components.Add(component); } + _attributes.Inserted += Attributes_Inserted; + _attributes.Cleared += Attributes_Cleared; + } + + private void InitContentModel() + { + if (_type.ContentModel is XmlSchemaSimpleContent simpleContent) + InitSimpleContent(simpleContent); + else if (_type.ContentModel is XmlSchemaComplexContent complexContent) - { - _contentModel = XSContentModel.Complex; - - if (complexContent.Content is XmlSchemaComplexContentExtension contentExtension) - { - _derivationMethod = XSDerivationMethod.Extension; - if (contentExtension.BaseTypeName is XmlQualifiedName qualifiedName) - _baseTypeName = XMLSchemaSerializer.CreateXMLExpandedName(qualifiedName); - - if (contentExtension.Particle is XmlSchemaParticle particle) - _content = XMLSchemaSerializer.CreateInstance(particle); - - if (contentExtension.AnyAttribute is XmlSchemaAnyAttribute anyAttribute) - _attributeWildcard = XMLSchemaSerializer.CreateXSWildcard(anyAttribute); - } - else if (complexContent.Content is XmlSchemaComplexContentRestriction contentRestriction) - { - _derivationMethod = XSDerivationMethod.Restriction; - if (contentRestriction.BaseTypeName is XmlQualifiedName qualifiedName) - _baseTypeName = XMLSchemaSerializer.CreateXMLExpandedName(qualifiedName); - - if (contentRestriction.Particle is XmlSchemaParticle particle) - _content = XMLSchemaSerializer.CreateInstance(particle); - - if (contentRestriction.AnyAttribute is XmlSchemaAnyAttribute anyAttribute) - _attributeWildcard = XMLSchemaSerializer.CreateXSWildcard(anyAttribute); - } - else - { - _derivationMethod = XSDerivationMethod.EmptyRef; + InitComplexContent(complexContent); + + else + InitEmptyContent(); + } - if (_type.Particle is XmlSchemaParticle particle) - _content = XMLSchemaSerializer.CreateInstance(particle); - } + private void InitSimpleContent(XmlSchemaSimpleContent simpleContent) + { + _contentModel = XSContentModel.Simple; + if (simpleContent.Content is XmlSchemaSimpleContentExtension contentExtension) + { + _derivationMethod = XSDerivationMethod.Extension; + InitBaseTypeName(contentExtension.BaseTypeName); + InitAttributeWildcard(contentExtension.AnyAttribute); + } + else if (simpleContent.Content is XmlSchemaSimpleContentRestriction contentRestriction) + { + _derivationMethod = XSDerivationMethod.Restriction; + InitBaseTypeName(contentRestriction.BaseTypeName); + InitAttributeWildcard(contentRestriction.AnyAttribute); } else { - _contentModel = XSContentModel.EmptyRef; - - if (_type.Particle is XmlSchemaParticle particle) - _content = XMLSchemaSerializer.CreateInstance(particle); + _derivationMethod = XSDerivationMethod.EmptyRef; + InitContent(_type.Particle); } - - Attributes.Inserted -= Attributes_Inserted; - foreach (XmlSchemaObject item in _type.Attributes) + } + + private void InitComplexContent(XmlSchemaComplexContent complexContent) + { + _contentModel = XSContentModel.Complex; + if (complexContent.Content is XmlSchemaComplexContentExtension contentExtension) { - IXSComponent component = XMLSchemaSerializer.CreateInstance(item); - component.BindToContainer(RootContainer, this); - Attributes.Add(component); - Components.Add(component); + _derivationMethod = XSDerivationMethod.Extension; + InitBaseTypeName(contentExtension.BaseTypeName); + InitContent(contentExtension.Particle); + InitAttributeWildcard(contentExtension.AnyAttribute); } - Attributes.Inserted += Attributes_Inserted; + else if (complexContent.Content is XmlSchemaComplexContentRestriction contentRestriction) + { + _derivationMethod = XSDerivationMethod.Restriction; + InitBaseTypeName(contentRestriction.BaseTypeName); + InitContent(contentRestriction.Particle); + InitAttributeWildcard(contentRestriction.AnyAttribute); + } + else + { + _derivationMethod = XSDerivationMethod.EmptyRef; + InitContent(_type.Particle); + } + } + + private void InitEmptyContent() + { + _contentModel = XSContentModel.EmptyRef; + InitContent(_type.Particle); + } + + private void InitBaseTypeName(XmlQualifiedName xmlQualifiedName) + { + if (xmlQualifiedName is XmlQualifiedName qualifiedName) + _baseTypeName = XMLSchemaSerializer.CreateXMLExpandedName(qualifiedName); + } + + private void InitAttributeWildcard(XmlSchemaAnyAttribute xmlAnyAttribute) + { + if (xmlAnyAttribute is XmlSchemaAnyAttribute anyAttribute) + _attributeWildcard = XMLSchemaSerializer.CreateXSWildcard(anyAttribute); + } + + private void InitContent(XmlSchemaParticle xmlParticle) + { + if (xmlParticle is XmlSchemaParticle particle) + _content = XMLSchemaSerializer.CreateInstance(particle); } private void OnSetContentModelDerivation() @@ -293,7 +300,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components { get; } + public XSComponentFixedList Components => _components; [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -311,7 +318,7 @@ public XSAnnotation Annotation public IValue DOMElement => ValueFactory.Create(); [ContextProperty("URIПространстваИмен", "NamespaceURI")] - public string URIПространстваИмен => _type.SourceUri; + public string NamespaceURI => _type.SourceUri; [ContextProperty("Имя", "Name")] public string Name @@ -358,7 +365,7 @@ public XSAnnotation DerivationAnnotation } [ContextProperty("Атрибуты", "Attributes")] - public XSComponentList Attributes { get; } + public XSComponentList Attributes => _attributes; [ContextProperty("Блокировка", "Block")] public XsProhibitedSubstitutionsUnion Block { get; } @@ -417,7 +424,7 @@ public XSContentModel ContentModel //ОпределениеБазовогоТипа(BaseTypeDefinition) [ContextProperty("Смешанный", "Mixed")] - public bool Mixed => _type.ContentModel is XmlSchemaComplexContent complexContent ? complexContent.IsMixed : false; + public bool Mixed => _type.ContentModel is XmlSchemaComplexContent complexContent && complexContent.IsMixed; [ContextProperty("Содержимое", "Content")] public IXSComponent Content @@ -438,13 +445,13 @@ public IXSComponent Content #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); [ContextMethod("Содержит", "Contains")] - public bool Contains(IXSComponent component) => Components.Contains(component); + public bool Contains(IXSComponent component) => _components.Contains(component); [ContextMethod("ЭтоОпределениеЗациклено", "IsCircular")] public bool IsCircular() => throw new NotImplementedException(); @@ -481,18 +488,16 @@ public void BindToContainer(IXSComponent rootContainer, IXSComponent container) private void Attributes_Inserted(object sender, XSComponentListEventArgs e) { IXSComponent component = e.Component; - if (!(component is IXSAttribute) && (!(component is XSAttributeGroupDefinition))) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires((component is IXSAttribute) || (component is XSAttributeGroupDefinition)); component.BindToContainer(RootContainer, this); - Components.Add(component); + _components.Add(component); _type.Attributes.Add(component.SchemaObject); } private void Attributes_Cleared(object sender, EventArgs e) { - Components.RemoveAll(x => (x is IXSAttribute)); + _components.RemoveAll(x => (x is IXSAttribute)); _type.Attributes.Clear(); } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs index 7bc8fe6ae..efbcebb8a 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ДокументацияXS", "XSDocumentation")] - public class XSDocumentation : AutoContext, IXSAnnotationItem + public sealed class XSDocumentation : AutoContext, IXSAnnotationItem { private readonly XmlSchemaDocumentation _documentation; @@ -34,7 +34,7 @@ public class XSDocumentation : AutoContext, IXSAnnotationItem public XSAnnotation Annotation => null; [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -67,7 +67,7 @@ public string Language #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSElementDeclaration.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSElementDeclaration.cs index 69fe0eb6c..45f1fd7d4 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSElementDeclaration.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSElementDeclaration.cs @@ -19,7 +19,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОбъявлениеЭлементаXS", "XSElementDeclaration")] - public class XSElementDeclaration : AutoContext, IXSFragment, IXSNamedComponent + public sealed class XSElementDeclaration : AutoContext, IXSFragment, IXSNamedComponent { private readonly XmlSchemaElement _element; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs index 0ea561255..3a299bd23 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетПеречисленияXS", "XSEnumerationFacet")] - public class XSEnumerationFacet : AutoContext, IXSFacet + public sealed class XSEnumerationFacet : AutoContext, IXSFacet { private readonly XmlSchemaEnumerationFacet _facet; private XSAnnotation _annotation; @@ -55,7 +55,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -106,7 +106,7 @@ public IValue Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -131,9 +131,7 @@ public IValue Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs index 14857b168..5a7217d0b 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетКоличестваРазрядовДробнойЧастиXS", "XSFractionDigitsFacet")] - public class XSFractionDigitsFacet : AutoContext, IXSFacet + public sealed class XSFractionDigitsFacet : AutoContext, IXSFacet { private readonly XmlSchemaFractionDigitsFacet _facet; private XSAnnotation _annotation; @@ -53,7 +53,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -96,7 +96,7 @@ public decimal Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -121,9 +121,7 @@ public decimal Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSIdentityConstraintDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSIdentityConstraintDefinition.cs index 444d023ad..d14c2c391 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSIdentityConstraintDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSIdentityConstraintDefinition.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределениеОграниченияИдентичностиXS", "XSIdentityConstraintDefinition")] - public class XSIdentityConstraintDefinition : AutoContext, IXSAnnotated, IXSNamedComponent + public sealed class XSIdentityConstraintDefinition : AutoContext, IXSAnnotated, IXSNamedComponent { private XmlSchemaIdentityConstraint _constraint; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSImport.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSImport.cs index f894fc9af..5a62e242d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSImport.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSImport.cs @@ -21,16 +21,17 @@ namespace OneScript.StandardLibrary.XMLSchema.Objects /// /// [ContextClass("ИмпортXS", "XSImport")] - public class XSImport : AutoContext, IXSDirective + public sealed class XSImport : AutoContext, IXSDirective { private readonly XmlSchemaImport _import; + private XMLSchema _resolvedSchema; - private XSImport() => _import = new XmlSchemaImport(); + private XSImport() : this(new XmlSchemaImport()) { } internal XSImport(XmlSchemaImport import) - : this() { _import = import; + _resolvedSchema = new XMLSchema(_import.Schema); } #region OneScript @@ -41,7 +42,7 @@ internal XSImport(XmlSchemaImport import) public XSAnnotation Annotation => null; [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -56,10 +57,13 @@ internal XSImport(XmlSchemaImport import) public XSComponentType ComponentType => XSComponentType.Import; [ContextProperty("РазрешеннаяСхема", "ResolvedSchema")] - public XMLSchema ResolvedSchema - { - get => ResolvedSchema; - set => ResolvedSchema = value; + public XMLSchema ResolvedSchema + { + get => _resolvedSchema; + set { + _resolvedSchema = value; + _import.Schema = _resolvedSchema.SchemaObject; + } } [ContextProperty("РасположениеСхемы", "SchemaLocation")] diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs index 380776fce..b759a6059 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs @@ -16,17 +16,18 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ВключениеXS", "XSInclude")] - public class XSInclude : AutoContext, IXSDirective + public sealed class XSInclude : AutoContext, IXSDirective { private readonly XmlSchemaInclude _include; + private XMLSchema _resolvedSchema; - private XSInclude() => _include = new XmlSchemaInclude(); + private XSInclude() : this(new XmlSchemaInclude()) { } internal XSInclude(XmlSchemaInclude include) - : this() { _include = include; + _resolvedSchema = new XMLSchema(_include.Schema); } #region OneScript @@ -37,7 +38,7 @@ internal XSInclude(XmlSchemaInclude include) public XSAnnotation Annotation => null; [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -54,8 +55,12 @@ internal XSInclude(XmlSchemaInclude include) [ContextProperty("РазрешеннаяСхема", "ResolvedSchema")] public XMLSchema ResolvedSchema { - get => ResolvedSchema; - set => ResolvedSchema = value; + get => _resolvedSchema; + set + { + _resolvedSchema = value; + _include.Schema = _resolvedSchema.SchemaObject; + } } [ContextProperty("РасположениеСхемы", "SchemaLocation")] @@ -70,7 +75,7 @@ public string SchemaLocation #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = false) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs index a7cc337b3..58d9751de 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетДлиныXS", "XSLengthFacet")] - public class XSLengthFacet : AutoContext, IXSFacet + public sealed class XSLengthFacet : AutoContext, IXSFacet { private readonly XmlSchemaLengthFacet _facet; private XSAnnotation _annotation; @@ -53,7 +53,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -96,7 +96,7 @@ public decimal Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -121,9 +121,7 @@ public decimal Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs index df0941834..0d89d09b3 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМаксимальногоИсключающегоЗначенияXS", "XSMaxExclusiveFacet")] - public class XSMaxExclusiveFacet : AutoContext, IXSFacet + public sealed class XSMaxExclusiveFacet : AutoContext, IXSFacet { private readonly XmlSchemaMaxExclusiveFacet _facet; private XSAnnotation _annotation; @@ -55,7 +55,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -112,7 +112,7 @@ public IValue Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -137,9 +137,7 @@ public IValue Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs index 54f8c7d8a..d1aab68db 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs @@ -6,9 +6,10 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.StandardLibrary.XMLSchema.Interfaces; @@ -18,7 +19,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМаксимальногоВключающегоЗначенияXS", "XSMaxInclusiveFacet")] - public class XSMaxInclusiveFacet : AutoContext, IXSFacet + public sealed class XSMaxInclusiveFacet : AutoContext, IXSFacet { private readonly XmlSchemaMaxInclusiveFacet _facet; private XSAnnotation _annotation; @@ -55,7 +56,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -112,7 +113,7 @@ public IValue Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -137,9 +138,7 @@ public IValue Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs index 4543d276e..397c0344d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМаксимальнойДлиныXS", "XSMaxLengthFacet")] - public class XSMaxLengthFacet : AutoContext, IXSFacet + public sealed class XSMaxLengthFacet : AutoContext, IXSFacet { private readonly XmlSchemaMaxLengthFacet _facet; private XSAnnotation _annotation; @@ -53,7 +53,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -96,7 +96,7 @@ public decimal Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -121,9 +121,7 @@ public decimal Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs index 11d28d4c7..98a5d88b1 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,13 +18,14 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМинимальногоИсключающегоЗначенияXS", "XSMinExclusiveFacet")] - public class XSMinExclusiveFacet : AutoContext, IXSFacet + public sealed class XSMinExclusiveFacet : AutoContext, IXSFacet { private readonly XmlSchemaMinExclusiveFacet _facet; private XSAnnotation _annotation; private IValue _value; private XSMinExclusiveFacet() => _facet = new XmlSchemaMinExclusiveFacet(); + internal XSMinExclusiveFacet(XmlSchemaMinExclusiveFacet minExclusiveFace) { _facet = minExclusiveFace; @@ -36,6 +37,7 @@ internal XSMinExclusiveFacet(XmlSchemaMinExclusiveFacet minExclusiveFace) _annotation.BindToContainer(RootContainer, this); } } + #region OneScript #region Properties @@ -53,7 +55,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -110,7 +112,7 @@ public IValue Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -135,9 +137,7 @@ public IValue Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs index 57e328fd8..d4c83e859 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,13 +18,14 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМинимальногоВключающегоЗначенияXS", "XSMinInclusiveFacet")] - public class XSMinInclusiveFacet : AutoContext, IXSFacet + public sealed class XSMinInclusiveFacet : AutoContext, IXSFacet { private readonly XmlSchemaMinInclusiveFacet _facet; private XSAnnotation _annotation; private IValue _value; private XSMinInclusiveFacet() => _facet = new XmlSchemaMinInclusiveFacet(); + internal XSMinInclusiveFacet(XmlSchemaMinInclusiveFacet minInclusiveFacet) { _facet = minInclusiveFacet; @@ -54,7 +55,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -111,7 +112,7 @@ public IValue Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -136,9 +137,7 @@ public IValue Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs index dd22c808d..322763457 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетМинимальнойДлиныXS", "XSMinLengthFacet")] - public class XSMinLengthFacet : AutoContext, IXSFacet + public sealed class XSMinLengthFacet : AutoContext, IXSFacet { private readonly XmlSchemaMinLengthFacet _facet; private XSAnnotation _annotation; @@ -53,7 +53,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -96,7 +96,7 @@ public decimal Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -121,9 +121,7 @@ public decimal Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroup.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroup.cs index e3903fa1a..ed4905be5 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroup.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroup.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.StandardLibrary.XMLSchema.Interfaces; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ГруппаМоделиXS", "XSModelGroup")] - public class XSModelGroup : AutoContext, IXSFragment + public sealed class XSModelGroup : AutoContext, IXSFragment { private XmlSchemaGroupBase _group; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs index ab072beb6..c12979632 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -19,7 +19,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределениеГруппыМоделиXS", "XSModelGroupDefinition")] - public class XSModelGroupDefinition : AutoContext, IXSFragment, IXSNamedComponent + public sealed class XSModelGroupDefinition : AutoContext, IXSFragment, IXSNamedComponent { private XmlSchemaAnnotated _group; private string _name; @@ -42,7 +42,7 @@ internal XSModelGroupDefinition(XmlSchemaGroup xmlGroup) if (xmlGroup.Particle is XmlSchemaGroupBase xmlGroupBase) { - IXSComponent component = XMLSchemaSerializer.CreateInstance(xmlGroupBase); + var component = XMLSchemaSerializer.CreateInstance(xmlGroupBase); if (component is XSParticle particle) _modelGroup = particle; @@ -52,7 +52,7 @@ internal XSModelGroupDefinition(XmlSchemaGroup xmlGroup) } } - internal XSModelGroupDefinition(XmlSchemaGroupRef xmlGroupRef) + internal XSModelGroupDefinition(in XmlSchemaGroupRef xmlGroupRef) { _group = xmlGroupRef; @@ -83,7 +83,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -162,7 +162,7 @@ public XMLExpandedName Reference #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSNotationDeclaration.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSNotationDeclaration.cs index f245270a3..a12229e61 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSNotationDeclaration.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSNotationDeclaration.cs @@ -16,7 +16,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОбъявлениеНотацииXS", "XSNotationDeclaration")] - public class XSNotationDeclaration : AutoContext, IXSAnnotated, IXSNamedComponent + public sealed class XSNotationDeclaration : AutoContext, IXSAnnotated, IXSNamedComponent { private readonly XmlSchemaNotation _notation; private XSAnnotation _annotation; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSParticle.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSParticle.cs index b74c6036a..adc340feb 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSParticle.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSParticle.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; using OneScript.StandardLibrary.XMLSchema.Interfaces; @@ -19,7 +19,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФрагментXS", "XSParticle")] - public class XSParticle : AutoContext, IXSComponent + public sealed class XSParticle : AutoContext, IXSComponent { private IXSFragment _term; private IValue _minOccurs; diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs index 67c8f6892..53792aa9c 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетОбразцаXS", "XSPatternFacet")] - public class XSPatternFacet : AutoContext, IXSFacet + public sealed class XSPatternFacet : AutoContext, IXSFacet { private readonly XmlSchemaPatternFacet _facet; private XSAnnotation _annotation; @@ -52,7 +52,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -95,7 +95,7 @@ public string Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -120,9 +120,7 @@ public string Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSRedefine.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSRedefine.cs index 06769c0c2..752d39371 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSRedefine.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSRedefine.cs @@ -16,25 +16,21 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ПереопределениеXS", "XSRedefine")] - public class XSRedefine : AutoContext, IXSDirective + public sealed class XSRedefine : AutoContext, IXSDirective { private readonly XmlSchemaRedefine _redefine; + private XMLSchema _resolvedSchema; - private XSRedefine() - { - _redefine = new XmlSchemaRedefine(); - Components = new XSComponentFixedList(); - - Content = new XSComponentList(); - Content.Inserted += Content_Inserted; - Content.Cleared += Content_Cleared; - } + private XSRedefine() : this (new XmlSchemaRedefine()) { } internal XSRedefine(XmlSchemaRedefine redefine) - : this() { _redefine = redefine; + _resolvedSchema = new XMLSchema(_redefine.Schema); + + Components = new XSComponentFixedList(); + Content = new XSComponentList(); Content.Inserted -= Content_Inserted; Content.Cleared -= Content_Cleared; @@ -47,7 +43,7 @@ internal XSRedefine(XmlSchemaRedefine redefine) Components.Add(component); Content.Add(component); } - + Content.Inserted += Content_Inserted; Content.Cleared += Content_Cleared; } @@ -77,8 +73,12 @@ internal XSRedefine(XmlSchemaRedefine redefine) [ContextProperty("РазрешеннаяСхема", "ResolvedSchema")] public XMLSchema ResolvedSchema { - get => ResolvedSchema; - set => ResolvedSchema = value; + get => _resolvedSchema; + set + { + _resolvedSchema = value; + _redefine.Schema = _resolvedSchema.SchemaObject; + } } [ContextProperty("РасположениеСхемы", "SchemaLocation")] diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs index 4b8203354..bbafd61c4 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.Xml; using OneScript.StandardLibrary.XMLSchema.Collections; @@ -20,31 +20,21 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределениеПростогоТипаXS", "XSSimpleTypeDefinition")] - public class XSSimpleTypeDefinition : AutoContext, IXSType, IXSNamedComponent + public sealed class XSSimpleTypeDefinition : AutoContext, IXSType, IXSNamedComponent { private readonly XmlSchemaSimpleType _type; + private readonly XSComponentFixedList _components = new XSComponentFixedList(); + private readonly XSComponentList _typeDefinitions = new XSComponentList(); + private readonly XSComponentList _facets = new XSComponentList(); + private XSAnnotation _annotation; private XMLExpandedName _baseTypeName; private XMLExpandedName _itemTypeName; private XSSimpleTypeVariety _variety; - private XSSimpleTypeDefinition() - { - _type = new XmlSchemaSimpleType(); - Facets = new XSComponentList(); - Facets.Inserted += Facets_Inserted; - Facets.Cleared += Facets_Cleared; - - MemberTypeDefinitions = new XSComponentList(); - MemberTypeDefinitions.Inserted += MemberTypeDefinitions_Inserted; - MemberTypeDefinitions.Cleared += MemberTypeDefinitions_Cleared; - - Components = new XSComponentFixedList(); - Variety = XSSimpleTypeVariety.Atomic; - } + private XSSimpleTypeDefinition() : this(new XmlSchemaSimpleType()) { } internal XSSimpleTypeDefinition(XmlSchemaSimpleType simpleType) - : this() { _type = simpleType; @@ -54,47 +44,126 @@ internal XSSimpleTypeDefinition(XmlSchemaSimpleType simpleType) _annotation.BindToContainer(RootContainer, this); } + InitContentTypeVariety(); + + _facets.Inserted += Facets_Inserted; + _facets.Cleared += Facets_Cleared; + + _typeDefinitions.Inserted += MemberTypeDefinitions_Inserted; + _typeDefinitions.Cleared += MemberTypeDefinitions_Cleared; + } + + private void InitContentTypeVariety() + { if (_type.Content is XmlSchemaSimpleTypeList typeList) - { - _variety = XSSimpleTypeVariety.List; + InitListVariety(typeList); + + else if (_type.Content is XmlSchemaSimpleTypeUnion typeUnion) + InitUnionVariety(typeUnion); - if (typeList.ItemTypeName is XmlQualifiedName qualifiedName) - _itemTypeName = new XMLExpandedName(qualifiedName); + else if (_type.Content is XmlSchemaSimpleTypeRestriction typeRestriction) + InitAtomicVariety(typeRestriction); + else + { + var newRestriction = new XmlSchemaSimpleTypeRestriction(); + _type.Content = newRestriction; + InitAtomicVariety(newRestriction); } - else if (_type.Content is XmlSchemaSimpleTypeUnion typeUnion) + } + + private void InitListVariety(XmlSchemaSimpleTypeList typeList) + { + _variety = XSSimpleTypeVariety.List; + InitItemTypeName(typeList.ItemTypeName); + } + + private void InitUnionVariety(XmlSchemaSimpleTypeUnion typeUnion) + { + _variety = XSSimpleTypeVariety.Union; + foreach (var item in typeUnion.BaseTypes) { - _variety = XSSimpleTypeVariety.Union; - - MemberTypeDefinitions.Inserted -= MemberTypeDefinitions_Inserted; - foreach (XmlSchemaObject item in typeUnion.BaseTypes) - { - IXSComponent component = XMLSchemaSerializer.CreateInstance(item); - component.BindToContainer(RootContainer, this); - MemberTypeDefinitions.Add(component); - Components.Add(component); - } - MemberTypeDefinitions.Inserted += MemberTypeDefinitions_Inserted; + var component = XMLSchemaSerializer.CreateInstance(item); + component.BindToContainer(RootContainer, this); + _typeDefinitions.Add(component); + _components.Add(component); + } + } + + private void InitAtomicVariety(XmlSchemaSimpleTypeRestriction typeRestriction) + { + _variety = XSSimpleTypeVariety.Atomic; + InitBaseTypeName(typeRestriction.BaseTypeName); + + foreach (var item in typeRestriction.Facets) + { + var component = XMLSchemaSerializer.CreateInstance(item); + component.BindToContainer(RootContainer, this); + _facets.Add(component); + _components.Add(component); } - else if (_type.Content is XmlSchemaSimpleTypeRestriction typeRestriction) + } + + private void InitItemTypeName(XmlQualifiedName xmlQualifiedName) + { + if (xmlQualifiedName is XmlQualifiedName qualifiedName) + _itemTypeName = new XMLExpandedName(qualifiedName); + } + + private void InitBaseTypeName(XmlQualifiedName xmlQualifiedName) + { + if (xmlQualifiedName is XmlQualifiedName qualifiedName) + _baseTypeName = new XMLExpandedName(qualifiedName); + } + + private void SetContentTypeVariety(XSSimpleTypeVariety value) + { + if (_variety == value) return; + _variety = value; + + switch (_variety) { - _variety = XSSimpleTypeVariety.Atomic; - - if (typeRestriction.BaseTypeName is XmlQualifiedName qualifiedName) - _baseTypeName = new XMLExpandedName(qualifiedName); - - Facets.Inserted -= Facets_Inserted; - foreach (XmlSchemaObject item in typeRestriction.Facets) - { - IXSComponent component = XMLSchemaSerializer.CreateInstance(item); - component.BindToContainer(RootContainer, this); - Facets.Add(component); - Components.Add(component); - } - Facets.Inserted += Facets_Inserted; + case XSSimpleTypeVariety.List: + _type.Content = new XmlSchemaSimpleTypeList(); + _itemTypeName = default; + break; + + case XSSimpleTypeVariety.Union: + _type.Content = new XmlSchemaSimpleTypeUnion(); + _typeDefinitions.Clear(); + break; + + case XSSimpleTypeVariety.Atomic: + _type.Content = new XmlSchemaSimpleTypeRestriction(); + _baseTypeName = default; + _facets.Clear(); + break; + + default: + break; } } + private void SetBaseTypeName(XMLExpandedName value) + { + if (_baseTypeName == value) return; + Contract.Requires(Variety == XSSimpleTypeVariety.Atomic); + _baseTypeName = value; + + var content = _type.Content as XmlSchemaSimpleTypeRestriction; + content.BaseTypeName = _baseTypeName?.NativeValue; + } + + private void SetItemTypeName(XMLExpandedName value) + { + if (_itemTypeName == value) return; + Contract.Requires(Variety == XSSimpleTypeVariety.List); + _itemTypeName = value; + + var content = _type.Content as XmlSchemaSimpleTypeList; + content.ItemTypeName = _itemTypeName?.NativeValue; + } + #region OneScript #region Properties @@ -112,7 +181,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components { get; } + public XSComponentFixedList Components => _components; [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -130,7 +199,7 @@ public XSAnnotation Annotation public IValue DOMElement => ValueFactory.Create(); [ContextProperty("URIПространстваИмен", "NamespaceURI")] - public string URIПространстваИмен => _type.SourceUri; + public string NamespaceURI => _type.SourceUri; [ContextProperty("Имя", "Name")] public string Name @@ -152,19 +221,7 @@ public string Name public XSSimpleTypeVariety Variety { get => _variety; - set - { - _variety = value; - - if (_variety == XSSimpleTypeVariety.List) - _type.Content = new XmlSchemaSimpleTypeList(); - - else if (_variety == XSSimpleTypeVariety.Union) - _type.Content = new XmlSchemaSimpleTypeUnion(); - - else - _type.Content = new XmlSchemaSimpleTypeRestriction(); - } + set => SetContentTypeVariety(value); } [ContextProperty("Завершенность", "Final")] @@ -177,32 +234,14 @@ public XSSimpleTypeVariety Variety public XMLExpandedName BaseTypeName { get => _baseTypeName; - set - { - _baseTypeName = value; - if (Variety == XSSimpleTypeVariety.Atomic) - { - XmlSchemaSimpleTypeRestriction content = _type.Content as XmlSchemaSimpleTypeRestriction; - content.BaseTypeName = _baseTypeName.NativeValue; - } - else - throw RuntimeException.InvalidArgumentValue(); - } + set => SetBaseTypeName(value); } [ContextProperty("ИмяТипаЭлемента", "ItemTypeName")] public XMLExpandedName ItemTypeName { get => _itemTypeName; - set - { - _itemTypeName = value; - if (Variety == XSSimpleTypeVariety.List) - { - XmlSchemaSimpleTypeList content = (XmlSchemaSimpleTypeList)_type.Content; - content.ItemTypeName = _itemTypeName.NativeValue; - } - } + set => SetItemTypeName(value); } [ContextProperty("ОпределениеБазовогоТипа", "BaseTypeDefinition")] @@ -215,17 +254,17 @@ public XMLExpandedName ItemTypeName public XSSimpleTypeDefinition ItemTypeDefinition { get; set; } [ContextProperty("ОпределенияТиповОбъединения", "MemberTypeDefinitions")] - public XSComponentList MemberTypeDefinitions { get; } + public XSComponentList MemberTypeDefinitions => _typeDefinitions; [ContextProperty("Фасеты", "Facets")] - public XSComponentList Facets { get; } + public XSComponentList Facets => _facets; #endregion #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -264,46 +303,46 @@ public void BindToContainer(IXSComponent rootContainer, IXSComponent container) private void Facets_Inserted(object sender, XSComponentListEventArgs e) { - IXSComponent component = e.Component; - - if (!(component is IXSFacet)) - throw RuntimeException.InvalidArgumentType(); + var component = e.Component; + Contract.Requires(_variety == XSSimpleTypeVariety.Atomic); + Contract.Requires(component is IXSFacet); component.BindToContainer(RootContainer, this); - Components.Add(component); + _components.Add(component); - if (_type.Content is XmlSchemaSimpleTypeRestriction content) - content.Facets.Add(component.SchemaObject); + var content = _type.Content as XmlSchemaSimpleTypeRestriction; + content.Facets.Add(component.SchemaObject); } private void Facets_Cleared(object sender, EventArgs e) { - Components.Clear(); + Contract.Requires(_variety == XSSimpleTypeVariety.Atomic); + _components.Clear(); - if (_type.Content is XmlSchemaSimpleTypeRestriction content) - content.Facets.Clear(); + var content = _type.Content as XmlSchemaSimpleTypeRestriction; + content.Facets.Clear(); } private void MemberTypeDefinitions_Inserted(object sender, XSComponentListEventArgs e) { - IXSComponent component = e.Component; - - if (!(component is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); + var component = e.Component; + Contract.Requires(_variety == XSSimpleTypeVariety.Union); + Contract.Requires(component is XSSimpleTypeDefinition); component.BindToContainer(RootContainer, this); - Components.Add(component); + _components.Add(component); - if (_type.Content is XmlSchemaSimpleTypeUnion content) - content.BaseTypes.Add(component.SchemaObject); + var content = _type.Content as XmlSchemaSimpleTypeUnion; + content.BaseTypes.Add(component.SchemaObject); } private void MemberTypeDefinitions_Cleared(object sender, EventArgs e) { - Components.Clear(); + Contract.Requires(_variety == XSSimpleTypeVariety.Union); + _components.Clear(); - if (_type.Content is XmlSchemaSimpleTypeUnion content) - content.BaseTypes.Clear(); + var content = _type.Content as XmlSchemaSimpleTypeUnion; + content.BaseTypes.Clear(); } #endregion diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs index 70d06b54d..498bae27d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs @@ -6,9 +6,9 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетОбщегоКоличестваРазрядовXS", "XSTotalDigitsFacet")] - public class XSTotalDigitsFacet : AutoContext, IXSFacet + public sealed class XSTotalDigitsFacet : AutoContext, IXSFacet { private readonly XmlSchemaTotalDigitsFacet _facet; private XSAnnotation _annotation; @@ -53,7 +53,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -96,7 +96,7 @@ public decimal Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -121,9 +121,7 @@ public decimal Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs index f071416dc..a71ce3216 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Diagnostics.Contracts; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -17,7 +17,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ФасетПробельныхСимволовXS", "XSWhitespaceFacet")] - public class XSWhitespaceFacet : AutoContext, IXSFacet + public sealed class XSWhitespaceFacet : AutoContext, IXSFacet { private readonly XmlSchemaWhiteSpaceFacet _facet; private XSAnnotation _annotation; @@ -52,7 +52,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container => SimpleTypeDefinition; @@ -131,7 +131,7 @@ public XSWhitespaceHandling Value #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); @@ -156,9 +156,7 @@ public XSWhitespaceHandling Value void IXSComponent.BindToContainer(IXSComponent rootContainer, IXSComponent container) { - if (!(container is XSSimpleTypeDefinition)) - throw RuntimeException.InvalidArgumentType(); - + Contract.Requires(container is XSSimpleTypeDefinition); RootContainer = rootContainer; SimpleTypeDefinition = container as XSSimpleTypeDefinition; } diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs index 33798f228..f5718511d 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Xml.Schema; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.XMLSchema.Collections; using OneScript.StandardLibrary.XMLSchema.Enumerations; @@ -18,7 +18,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("МаскаXS", "XSWildcard")] - public class XSWildcard : AutoContext, IXSAnnotated, IXSFragment + public sealed class XSWildcard : AutoContext, IXSFragment { private XmlSchemaAnnotated _wildcard; private XSAnnotation _annotation; @@ -43,6 +43,7 @@ internal XSWildcard(XmlSchemaAny xmlAny) SetNamespaceConstraint(); } + internal XSWildcard(XmlSchemaAnyAttribute xmlAnyAttribute) { _wildcard = xmlAnyAttribute; @@ -120,7 +121,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } @@ -164,7 +165,7 @@ public string LexicalNamespaceConstraint #region Methods [ContextMethod("КлонироватьКомпоненту", "CloneComponent")] - public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException(); + public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException(); [ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")] public void UpdateDOMElement() => throw new NotImplementedException(); diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSXPathDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSXPathDefinition.cs index a2616af9c..9377abadd 100644 --- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSXPathDefinition.cs +++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSXPathDefinition.cs @@ -16,13 +16,15 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.XMLSchema.Objects { [ContextClass("ОпределенияXPathXS", "XSXPathDefinition")] - public class XSXPathDefinition : AutoContext, IXSAnnotated, IXSNamedComponent + public sealed class XSXPathDefinition : AutoContext, IXSAnnotated, IXSNamedComponent { private readonly XmlSchemaXPath _xpath; private XSAnnotation _annotation; private XSXPathDefinition() => _xpath = new XmlSchemaXPath(); - + + internal XSXPathDefinition(XmlSchemaXPath xpath) => _xpath = xpath; + #region OneScript #region Properties @@ -39,7 +41,7 @@ public XSAnnotation Annotation } [ContextProperty("Компоненты", "Components")] - public XSComponentFixedList Components => null; + public XSComponentFixedList Components => XSComponentFixedList.EmptyList(); [ContextProperty("Контейнер", "Container")] public IXSComponent Container { get; private set; } diff --git a/src/OneScript.StandardLibrary/Xml/XSLTransform.cs b/src/OneScript.StandardLibrary/Xml/XSLTransform.cs index f07ad7c9f..a352bfdfd 100644 --- a/src/OneScript.StandardLibrary/Xml/XSLTransform.cs +++ b/src/OneScript.StandardLibrary/Xml/XSLTransform.cs @@ -1,220 +1,218 @@ -/*---------------------------------------------------------- -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.Xml; -using System.Xml.Xsl; -using OneScript.Commons; -using OneScript.Contexts; -using OneScript.Types; -using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; - -namespace OneScript.StandardLibrary.Xml -{ - /// - /// Предназначен для преобразования текстов XML. - /// - [ContextClass("ПреобразованиеXSL", "XSLTransform")] - public class XSLTransform : AutoContext - { - private XslCompiledTransform _xslTransform; - private XsltArgumentList _argumentList; - - /// - /// Загружает таблицу стилей XSL - /// - /// ЧтениеXML. Объект чтения XML, из которого будет загружена таблица стилей XSL. - [ContextMethod("ЗагрузитьТаблицуСтилей", "LoadXSLStylesheet")] - public void LoadXSLStylesheet(XmlReaderImpl xmlReader) - { - _xslTransform.Load(xmlReader.GetNativeReader()); - } - - /// - /// Загружает таблицу стилей XSL - /// - /// Строка. Строка, содержащая описание преобразования XSL. - [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзСтроки", "LoadXSLStylesheetFromString")] - public void LoadXSLStylesheetFromString(string xmlString) - { - XmlReaderImpl _reader = new XmlReaderImpl(); - - _reader.SetString(xmlString); - - LoadXSLStylesheet(_reader); - } - - /// - /// Загружает описание преобразования XSL из узла DOM. - /// - /// УзелDOM. Узел DOM, представляющий собой шаблон XSL. - [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзУзла", "LoadXSLStylesheetFromNode")] - public void LoadXSLStylesheetFromNode(IValue xmlNode) - { - throw new NotImplementedException(); - } - - /// - /// Загружает описание преобразования XSL из файла. - /// - /// Строка. Имя файла, из которого должно быть загружено описание преобразования XSL. - [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзФайла", "LoadXSLStylesheetFromFile")] - public void LoadXSLStylesheetFromFile(string fileName) - { - XmlReaderImpl _reader = new XmlReaderImpl(); - - _reader.OpenFile(fileName); - - LoadXSLStylesheet(_reader); - } - - /// - /// Очищает внутреннее состояние. - /// - [ContextMethod("Очистить", "Clear")] - public void Clear() - { - _xslTransform = new XslCompiledTransform(); - _argumentList = new XsltArgumentList(); - } - - /// - /// Выполняет преобразование XML-документа. - /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. - /// - /// ЧтениеXML. Объект чтения XML, из которого будет прочитан исходный XML документ для преобразования. - /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. - [ContextMethod("Преобразовать", "Transform")] - public void Transform(XmlReaderImpl xmlReader, XmlWriterImpl xmlWriter) - { - - XmlReader _reader = xmlReader.GetNativeReader(); - XmlWriter _writer = xmlWriter.GetNativeWriter(); - - _xslTransform.Transform(_reader, _argumentList, _writer); - } - - /// - /// Выполняет преобразование XML-документа. - /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. - /// - /// Строка. Строка, в которой находится XML-документ. - /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. - /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. - /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, - /// возвращаемое значение в данном случае будет отсутствовать. - /// Строка. Результат преобразования. - [ContextMethod("ПреобразоватьИзСтроки", "TransformFromString")] - public string TransformFromString(string xmlString, XmlWriterImpl xmlWriter = null) - { - XmlReaderImpl _reader = new XmlReaderImpl(); - - _reader.SetString(xmlString); - - XmlWriterImpl _writer = new XmlWriterImpl(); - _writer.SetString(); - - Transform(_reader, _writer); - - string result = _writer.Close().ToString(); - - if (xmlWriter != null) - xmlWriter.WriteRaw(result); - - return result; - } - - /// - /// Выполняет преобразование XML-документа. - /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. - /// - /// УзелDOM. Узел DOM - исходное дерево для преобразования XSL. - /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. - /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. - /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, - /// возвращаемое значение в данном случае будет отсутствовать. - /// Строка. Результат преобразования. - [ContextMethod("ПреобразоватьИзУзла", "TransformFromNode")] - public string TransformFromNode(IValue xmlNode, XmlWriterImpl xmlWriter = null) - { - throw new NotImplementedException(); - } - - /// - /// Выполняет преобразование XML-документа. - /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. - /// - /// Строка. Имя файла, в котором находится преобразуемый XML-документ. - /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. - /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. - /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, - /// возвращаемое значение в данном случае будет отсутствовать. - /// Строка. Результат преобразования. - [ContextMethod("ПреобразоватьИзФайла", "TransformFromFile")] - public string TransformFromFile(string fileName, XmlWriterImpl xmlWriter = null) - { - XmlReaderImpl _reader = new XmlReaderImpl(); - - _reader.OpenFile(fileName); - - XmlWriterImpl _writer = new XmlWriterImpl(); - _writer.SetString(); - - Transform(_reader, _writer); - - string result = _writer.Close().ToString(); - - if (xmlWriter != null) - xmlWriter.WriteRaw(result); - - return result; - } - - /// - /// Добавляет значение параметра преобразования. - /// - /// Строка. Полное имя параметра. - /// Булево, Число, Строка. Значение параметра. - [ContextMethod("ДобавитьПараметр", "AddParameter")] - public void AddParameter(string fullName, IValue value) - { - var _value = ContextValuesMarshaller.ConvertToClrObject(value); - _argumentList.AddParam(fullName, "", _value); - } - - /// - /// Удаляет значение параметра преобразования. - /// - /// Строка. Полное имя параметра. - [ContextMethod("УдалитьПараметр", "RemoveParameter")] - public void RemoveParameter(string fullName) - { - _argumentList.RemoveParam(fullName, ""); - } - - /// - /// Создает XSLTransform - /// - /// XSLTransform - public XSLTransform() - { - _xslTransform = new XslCompiledTransform(); - _argumentList = new XsltArgumentList(); - } - - /// - /// Создает ПреобразованиеXSL - /// - /// ПреобразованиеXSL - [ScriptConstructor] - public static IRuntimeContextInstance Constructor() - { - return new XSLTransform(); - } - } +/*---------------------------------------------------------- +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.Xml; +using System.Xml.Xsl; +using OneScript.Contexts; +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace OneScript.StandardLibrary.Xml +{ + /// + /// Предназначен для преобразования текстов XML. + /// + [ContextClass("ПреобразованиеXSL", "XSLTransform")] + public class XSLTransform : AutoContext + { + private XslCompiledTransform _xslTransform; + private XsltArgumentList _argumentList; + + /// + /// Загружает таблицу стилей XSL + /// + /// ЧтениеXML. Объект чтения XML, из которого будет загружена таблица стилей XSL. + [ContextMethod("ЗагрузитьТаблицуСтилей", "LoadXSLStylesheet")] + public void LoadXSLStylesheet(XmlReaderImpl xmlReader) + { + _xslTransform.Load(xmlReader.GetNativeReader()); + } + + /// + /// Загружает таблицу стилей XSL + /// + /// Строка. Строка, содержащая описание преобразования XSL. + [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзСтроки", "LoadXSLStylesheetFromString")] + public void LoadXSLStylesheetFromString(string xmlString) + { + XmlReaderImpl _reader = new XmlReaderImpl(); + + _reader.SetString(xmlString); + + LoadXSLStylesheet(_reader); + } + + /// + /// Загружает описание преобразования XSL из узла DOM. + /// + /// УзелDOM. Узел DOM, представляющий собой шаблон XSL. + [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзУзла", "LoadXSLStylesheetFromNode")] + public void LoadXSLStylesheetFromNode(IValue xmlNode) + { + throw new NotImplementedException(); + } + + /// + /// Загружает описание преобразования XSL из файла. + /// + /// Строка. Имя файла, из которого должно быть загружено описание преобразования XSL. + [ContextMethod("ЗагрузитьТаблицуСтилейXSLИзФайла", "LoadXSLStylesheetFromFile")] + public void LoadXSLStylesheetFromFile(string fileName) + { + XmlReaderImpl _reader = new XmlReaderImpl(); + + _reader.OpenFile(fileName); + + LoadXSLStylesheet(_reader); + } + + /// + /// Очищает внутреннее состояние. + /// + [ContextMethod("Очистить", "Clear")] + public void Clear() + { + _xslTransform = new XslCompiledTransform(); + _argumentList = new XsltArgumentList(); + } + + /// + /// Выполняет преобразование XML-документа. + /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. + /// + /// ЧтениеXML. Объект чтения XML, из которого будет прочитан исходный XML документ для преобразования. + /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. + [ContextMethod("Преобразовать", "Transform")] + public void Transform(XmlReaderImpl xmlReader, XmlWriterImpl xmlWriter) + { + + XmlReader _reader = xmlReader.GetNativeReader(); + XmlWriter _writer = xmlWriter.GetNativeWriter(); + + _xslTransform.Transform(_reader, _argumentList, _writer); + } + + /// + /// Выполняет преобразование XML-документа. + /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. + /// + /// Строка. Строка, в которой находится XML-документ. + /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. + /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. + /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, + /// возвращаемое значение в данном случае будет отсутствовать. + /// Строка. Результат преобразования. + [ContextMethod("ПреобразоватьИзСтроки", "TransformFromString")] + public string TransformFromString(string xmlString, XmlWriterImpl xmlWriter = null) + { + XmlReaderImpl _reader = new XmlReaderImpl(); + + _reader.SetString(xmlString); + + XmlWriterImpl _writer = new XmlWriterImpl(); + _writer.SetString(); + + Transform(_reader, _writer); + + string result = _writer.Close().ToString(); + + if (xmlWriter != null) + xmlWriter.WriteRaw(result); + + return result; + } + + /// + /// Выполняет преобразование XML-документа. + /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. + /// + /// УзелDOM. Узел DOM - исходное дерево для преобразования XSL. + /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. + /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. + /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, + /// возвращаемое значение в данном случае будет отсутствовать. + /// Строка. Результат преобразования. + [ContextMethod("ПреобразоватьИзУзла", "TransformFromNode")] + public string TransformFromNode(IValue xmlNode, XmlWriterImpl xmlWriter = null) + { + throw new NotImplementedException(); + } + + /// + /// Выполняет преобразование XML-документа. + /// Используется описание преобразования и значения параметров, ранее установленные в данном объекте. + /// + /// Строка. Имя файла, в котором находится преобразуемый XML-документ. + /// ЗаписьXML. Объект записи XML, в который будет записан результат преобразования. + /// Указание данного параметра имеет смысл, если преобразование выполняется в документ XML. + /// При указании данного параметра результат преобразования будет записываться в объект ЗаписьXML, + /// возвращаемое значение в данном случае будет отсутствовать. + /// Строка. Результат преобразования. + [ContextMethod("ПреобразоватьИзФайла", "TransformFromFile")] + public string TransformFromFile(string fileName, XmlWriterImpl xmlWriter = null) + { + XmlReaderImpl _reader = new XmlReaderImpl(); + + _reader.OpenFile(fileName); + + XmlWriterImpl _writer = new XmlWriterImpl(); + _writer.SetString(); + + Transform(_reader, _writer); + + string result = _writer.Close().ToString(); + + if (xmlWriter != null) + xmlWriter.WriteRaw(result); + + return result; + } + + /// + /// Добавляет значение параметра преобразования. + /// + /// Строка. Полное имя параметра. + /// Булево, Число, Строка. Значение параметра. + [ContextMethod("ДобавитьПараметр", "AddParameter")] + public void AddParameter(string fullName, IValue value) + { + var _value = ContextValuesMarshaller.ConvertToClrObject(value); + _argumentList.AddParam(fullName, "", _value); + } + + /// + /// Удаляет значение параметра преобразования. + /// + /// Строка. Полное имя параметра. + [ContextMethod("УдалитьПараметр", "RemoveParameter")] + public void RemoveParameter(string fullName) + { + _argumentList.RemoveParam(fullName, ""); + } + + /// + /// Создает XSLTransform + /// + /// XSLTransform + public XSLTransform() + { + _xslTransform = new XslCompiledTransform(); + _argumentList = new XsltArgumentList(); + } + + /// + /// Создает ПреобразованиеXSL + /// + /// ПреобразованиеXSL + [ScriptConstructor] + public static IRuntimeContextInstance Constructor() + { + return new XSLTransform(); + } + } } \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs b/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs index 1408014d6..48acbc43b 100644 --- a/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs +++ b/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs @@ -6,13 +6,16 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Xml; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; +using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using OneScript.Values; +using ScriptEngine; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -21,10 +24,43 @@ namespace OneScript.StandardLibrary.Xml [GlobalContext(Category="Функции работы с XML")] public class XmlGlobalFunctions : GlobalContextBase { + private static readonly Dictionary _allowedEnums + = new Dictionary(); + + private XmlGlobalFunctions(IGlobalsManager mgr) + { + lock (_allowedEnums) + { + _allowedEnums.Clear(); + foreach (var e in new[] { + (typeof(ClrEnumValueWrapper), typeof(AllowedSignEnum)), + (typeof(ClrEnumValueWrapper), typeof(AllowedLengthEnum)), + (typeof(ClrEnumValueWrapper), typeof(DateFractionsEnum)) + }) + { + _allowedEnums.Add(e.Item1, (EnumerationContext)mgr.GetInstance(e.Item2)); + } + } + } + + /// + /// Получает XML представление значения для помещения в текст элемента или значение атрибута XML. + /// + /// + /// Значение. Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные, + /// Неопределено, Null, а также значения перечислений ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты + /// + /// + /// Строковое представление значения. Для двоичных данных - строка в формате Вase64. + /// При недопустимом типе значения выбрасывается исключение + /// + /// [ContextMethod("XMLСтрока", "XMLString")] public string XMLString(IValue value) { - if (value.SystemType == BasicTypes.Undefined) + if (value.SystemType == BasicTypes.String) + return value.AsString(); + else if (value.SystemType == BasicTypes.Undefined || value.SystemType == BasicTypes.Null) return ""; else if(value.SystemType == BasicTypes.Boolean) return XmlConvert.ToString(value.AsBoolean()); @@ -34,23 +70,47 @@ public string XMLString(IValue value) return XmlConvert.ToString(value.AsNumber()); else { - if(value.GetRawValue() is BinaryDataContext bdc) + var rawValue = value.GetRawValue(); + if(rawValue is BinaryDataContext bdc) { return Convert.ToBase64String(bdc.Buffer, Base64FormattingOptions.InsertLineBreaks); } - else + if(rawValue is GuidWrapper guid) + { + return guid.AsString(); + } + else if (_allowedEnums.ContainsKey(rawValue.GetType())) { - return value.GetRawValue().AsString(); + return rawValue.AsString(); } } + + throw RuntimeException.InvalidArgumentValue(); } + /// + /// Выполняет преобразование из строки, полученной из текста элемента или значения атрибута XML, + /// в значение в соответствии с указанным типом. Действие, обратное действию метода XMLСтрока + /// + /// + /// Тип, значение которого надо получить при преобразовании из строкового представления XML. + /// Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные, + /// Неопределено, Null, перечисления ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты + /// + /// + /// Строка, содержащая строковое представление значения соответствующего типа + /// + /// + /// Значение заданного типа. + /// При недопустимом типе или неправильном строковом представлении выбрасывается исключение + /// + /// [ContextMethod("XMLЗначение", "XMLValue")] public IValue XMLValue(IValue givenType, string presentation) { if (givenType.GetRawValue().SystemType != BasicTypes.Type) { - throw new ArgumentException(nameof(givenType)); + throw RuntimeException.InvalidNthArgumentType(1); } var dataType = givenType.GetRawValue() as BslTypeValue; @@ -74,25 +134,54 @@ public IValue XMLValue(IValue givenType, string presentation) { return ValueFactory.Create(presentation); } - else if (typeValue.Equals(BasicTypes.Undefined) && presentation == "") + else if (typeValue.Equals(BasicTypes.Undefined)) + { + if (presentation.Trim() == "") + return ValueFactory.Create(); + + throw RuntimeException.InvalidNthArgumentValue(2); + } + else if (typeValue.Equals(BasicTypes.Null)) { - return ValueFactory.Create(); + if (presentation.Trim() == "") + return ValueFactory.CreateNullValue(); + + throw RuntimeException.InvalidNthArgumentValue(2); + } + else if (typeValue.ImplementingClass == typeof(GuidWrapper)) + { + try + { + return new GuidWrapper(presentation); + } + catch + { + throw RuntimeException.InvalidNthArgumentValue(2); + } } else if (typeValue.ImplementingClass == typeof(BinaryDataContext)) { byte[] bytes = Convert.FromBase64String(presentation); return new BinaryDataContext(bytes); } - else + else if (_allowedEnums.TryGetValue(typeValue.ImplementingClass, out var enumerationContext)) { - throw RuntimeException.InvalidArgumentValue(); + try + { + return enumerationContext[presentation]; + } + catch (RuntimeException) + { + throw RuntimeException.InvalidNthArgumentValue(2); + } } - + + throw RuntimeException.InvalidNthArgumentType(1); } - public static IAttachableContext CreateInstance() + public static IAttachableContext CreateInstance(IGlobalsManager mgr) { - return new XmlGlobalFunctions(); + return new XmlGlobalFunctions(mgr); } } diff --git a/src/OneScript.StandardLibrary/Xml/XmlReaderImpl.cs b/src/OneScript.StandardLibrary/Xml/XmlReaderImpl.cs index 5a944cc51..4b9de8d2f 100644 --- a/src/OneScript.StandardLibrary/Xml/XmlReaderImpl.cs +++ b/src/OneScript.StandardLibrary/Xml/XmlReaderImpl.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.IO; using System.Xml; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Xml/XmlSpaceEnum.cs b/src/OneScript.StandardLibrary/Xml/XmlSpaceEnum.cs index 744f9edf4..671f629ee 100644 --- a/src/OneScript.StandardLibrary/Xml/XmlSpaceEnum.cs +++ b/src/OneScript.StandardLibrary/Xml/XmlSpaceEnum.cs @@ -5,12 +5,9 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using System.Collections.Generic; -using System.Linq; using System.Xml; using OneScript.Contexts.Enums; using OneScript.Types; -using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.Xml diff --git a/src/OneScript.StandardLibrary/Xml/XmlWriterImpl.cs b/src/OneScript.StandardLibrary/Xml/XmlWriterImpl.cs index c43b2eee1..a6b72ce14 100644 --- a/src/OneScript.StandardLibrary/Xml/XmlWriterImpl.cs +++ b/src/OneScript.StandardLibrary/Xml/XmlWriterImpl.cs @@ -11,8 +11,8 @@ This Source Code Form is subject to the terms of the using System.Linq; using System.Text; using System.Xml; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/OneScript.StandardLibrary/Zip/ZipReader.cs b/src/OneScript.StandardLibrary/Zip/ZipReader.cs index 64701220b..4e7cb1a61 100644 --- a/src/OneScript.StandardLibrary/Zip/ZipReader.cs +++ b/src/OneScript.StandardLibrary/Zip/ZipReader.cs @@ -11,8 +11,8 @@ This Source Code Form is subject to the terms of the using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System.IO; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using OneScript.Types; diff --git a/src/OneScript.StandardLibrary/Zip/ZipWriter.cs b/src/OneScript.StandardLibrary/Zip/ZipWriter.cs index 733d300bb..856593a40 100644 --- a/src/OneScript.StandardLibrary/Zip/ZipWriter.cs +++ b/src/OneScript.StandardLibrary/Zip/ZipWriter.cs @@ -11,8 +11,8 @@ This Source Code Form is subject to the terms of the using System.Text; using Ionic.Zip; using Ionic.Zlib; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/ScriptEngine.HostedScript/CfgFileConfigProvider.cs b/src/ScriptEngine.HostedScript/CfgFileConfigProvider.cs index f4ad3259b..68e14bf92 100644 --- a/src/ScriptEngine.HostedScript/CfgFileConfigProvider.cs +++ b/src/ScriptEngine.HostedScript/CfgFileConfigProvider.cs @@ -17,17 +17,32 @@ public class CfgFileConfigProvider : IConfigProvider public const string CONFIG_FILE_NAME = "oscript.cfg"; public string FilePath { get; set; } - + + public bool Required { get; set; } + public Func> GetProvider() { var localCopy = FilePath; return () => ReadConfigFile(localCopy); } - private static IDictionary ReadConfigFile(string configPath) + private IDictionary ReadConfigFile(string configPath) { var conf = new Dictionary(); - using (var reader = new StreamReader(configPath, true)) + StreamReader reader; + try + { + reader = new StreamReader(configPath, true); + } + catch (IOException) + { + if (!Required) + return conf; + + throw; + } + + using (reader) { while (!reader.EndOfStream) { diff --git a/src/ScriptEngine.HostedScript/DefaultEventProcessor.cs b/src/ScriptEngine.HostedScript/DefaultEventProcessor.cs index 9f055cf0f..aceb67955 100644 --- a/src/ScriptEngine.HostedScript/DefaultEventProcessor.cs +++ b/src/ScriptEngine.HostedScript/DefaultEventProcessor.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections; using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs b/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs index 5e01f4251..7ffcb1f17 100644 --- a/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs +++ b/src/ScriptEngine.HostedScript/Extensions/EngineBuilderExtensions.cs @@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.IO; +using OneScript.Contexts; using OneScript.Native.Extensions; using ScriptEngine.Hosting; using ScriptEngine.Machine; @@ -15,13 +16,14 @@ namespace ScriptEngine.HostedScript.Extensions { public static class EngineBuilderExtensions { - public static ConfigurationProviders UseConfigFile(this ConfigurationProviders providers, string configFile) + public static ConfigurationProviders UseConfigFile(this ConfigurationProviders providers, string configFile, bool required = true) { - if (System.IO.File.Exists(configFile)) + if (File.Exists(configFile)) { var reader = new CfgFileConfigProvider { - FilePath = configFile + FilePath = configFile, + Required = required }; providers.Add(reader.GetProvider()); } @@ -35,22 +37,22 @@ public static ConfigurationProviders UseSystemConfigFile(this ConfigurationProvi if (string.IsNullOrEmpty(asmLocation)) asmLocation = System.Reflection.Assembly.GetEntryAssembly()?.Location; - var pathPrefix = !string.IsNullOrWhiteSpace(asmLocation) ? - System.IO.Path.GetDirectoryName(asmLocation) : - System.Environment.CurrentDirectory; + var pathPrefix = (!string.IsNullOrWhiteSpace(asmLocation) ? + Path.GetDirectoryName(asmLocation) : + System.Environment.CurrentDirectory) ?? ""; - var configFile = System.IO.Path.Combine(pathPrefix, CfgFileConfigProvider.CONFIG_FILE_NAME); + var configFile = Path.Combine(pathPrefix, CfgFileConfigProvider.CONFIG_FILE_NAME); return providers.UseConfigFile(configFile); } public static ConfigurationProviders UseEntrypointConfigFile(this ConfigurationProviders providers, string entryPoint) { - var dir = System.IO.Path.GetDirectoryName(entryPoint); - var cfgPath = System.IO.Path.Combine(dir, CfgFileConfigProvider.CONFIG_FILE_NAME); - if (System.IO.File.Exists(cfgPath)) + var dir = Path.GetDirectoryName(entryPoint) ?? ""; + var cfgPath = Path.GetFullPath(Path.Combine(dir, CfgFileConfigProvider.CONFIG_FILE_NAME)); + if (File.Exists(cfgPath)) { - return providers.UseConfigFile(cfgPath); + return providers.UseConfigFile(cfgPath, false); } return providers; @@ -75,9 +77,7 @@ public static IEngineBuilder UseFileSystemLibraries(this IEngineBuilder b) { b.Services.RegisterSingleton(sp => { - var config = sp.Resolve(); - - var libOptions = new OneScriptLibraryOptions(config); + var libOptions = sp.Resolve(); var searchDirs = new List(); var sysDir = libOptions.SystemLibraryDir; @@ -119,7 +119,9 @@ public static ExecutionContext UseTemplateFactory(this ExecutionContext env, ITe public static IEngineBuilder UseNativeRuntime(this IEngineBuilder builder) { + builder.Services.Register(); builder.Services.UseNativeRuntime(); + return builder; } } diff --git a/src/ScriptEngine.HostedScript/Extensions/NativeScriptInfoFactory.cs b/src/ScriptEngine.HostedScript/Extensions/NativeScriptInfoFactory.cs new file mode 100644 index 000000000..f7a4075ca --- /dev/null +++ b/src/ScriptEngine.HostedScript/Extensions/NativeScriptInfoFactory.cs @@ -0,0 +1,22 @@ +/*---------------------------------------------------------- +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.Contexts; +using OneScript.Sources; +using OneScript.Values; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Extensions +{ + public class NativeScriptInfoFactory : IScriptInformationFactory + { + public BslObjectValue GetInfo(SourceCode source) + { + return new ScriptInformationContext(source); + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/FileSystemDependencyResolver.cs b/src/ScriptEngine.HostedScript/FileSystemDependencyResolver.cs index aa71ab66e..5549026c4 100644 --- a/src/ScriptEngine.HostedScript/FileSystemDependencyResolver.cs +++ b/src/ScriptEngine.HostedScript/FileSystemDependencyResolver.cs @@ -10,8 +10,9 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Linq; using System.Text; -using OneScript.Commons; using OneScript.Compilation; +using OneScript.Exceptions; +using OneScript.Localization; using OneScript.Sources; namespace ScriptEngine.HostedScript @@ -56,7 +57,7 @@ public void Initialize(ScriptingEngine engine) Engine = engine; } - public ExternalLibraryDef Resolve(SourceCode module, string libraryName) + public void Resolve(SourceCode module, string libraryName) { bool quoted = PrepareQuoted(ref libraryName); bool loaded; @@ -67,8 +68,6 @@ public ExternalLibraryDef Resolve(SourceCode module, string libraryName) if(!loaded) throw new CompilerException(String.Format("Библиотека не найдена: '{0}'", libraryName)); - - return default; } private bool LoadByName(string libraryName) @@ -181,8 +180,10 @@ private bool LoadLibraryInternal(string libraryPath) if (existedLib.state == ProcessingState.Discovered) { string libStack = ListToStringStack(_libs, id); - throw new RuntimeException($"Ошибка загрузки библиотеки {id}. Обнаружены циклические зависимости.\n" + - $"{libStack}"); + throw new DependencyResolveException( + new BilingualString( + $"Ошибка загрузки библиотеки {id}. Обнаружены циклические зависимости.\n", + $"Error loading library {id}. Circular dependencies found.\n") + libStack); } return true; @@ -232,10 +233,7 @@ private static string ListToStringStack(IEnumerable libs, string stopTo builder.Append("-> "); builder.AppendLine(library.id); offset += " "; - if (library.id == stopToken) - { - break; - } + offset += " "; } return builder.ToString(); diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 8e1422b22..f41496ce5 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -26,16 +26,14 @@ public class HostedScriptEngine : IDisposable private readonly RuntimeEnvironment _env; private bool _isInitialized; - private readonly Lazy _workingConfig; - - private CodeStatProcessor _codeStat; + private readonly OneScriptLibraryOptions _workingConfig; public HostedScriptEngine(ScriptingEngine engine) { _engine = engine; _env = _engine.Environment; _engine.AttachAssembly(typeof(HostedScriptEngine).Assembly); - _workingConfig = new Lazy(InitWorkingConfig); + _workingConfig = _engine.Services.Resolve(); SetGlobalContexts(engine.GlobalsManager); } @@ -55,19 +53,6 @@ private void SetGlobalContexts(IGlobalsManager manager) _env.InjectGlobalProperty(bgTasksManager, "ФоновыеЗадания", "BackgroundJobs", true); } - private OneScriptLibraryOptions GetWorkingConfig() - { - return _workingConfig.Value; - } - - private OneScriptLibraryOptions InitWorkingConfig() - { - var cfgAccessor = _engine.GlobalsManager.GetInstance(); - cfgAccessor.Refresh(); - - return new OneScriptLibraryOptions(cfgAccessor.GetConfig()); - } - public void Initialize() { if (!_isInitialized) @@ -77,7 +62,7 @@ public void Initialize() } // System language - var systemLanguageCfg = GetWorkingConfig().SystemLanguage; + var systemLanguageCfg = _workingConfig.SystemLanguage; Locale.SystemLanguageISOName = systemLanguageCfg ?? System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName; } @@ -130,7 +115,7 @@ public Process CreateProcess(IHostApplication host, SourceCode src) private void DefineConstants(ICompilerFrontend compilerSvc) { - var definitions = GetWorkingConfig().PreprocessorDefinitions; + var definitions = _workingConfig.PreprocessorDefinitions; foreach (var val in definitions) { compilerSvc.PreprocessorDefinitions.Add(val); @@ -156,22 +141,10 @@ private Process InitProcess(IHostApplication host, IExecutableModule module) var process = new Process(host, module, _engine); return process; } - - public void EnableCodeStatistics() - { - _codeStat = new CodeStatProcessor(); - _engine.SetCodeStatisticsCollector(_codeStat); - } - - public CodeStatDataCollection GetCodeStatData() - { - return _codeStat.GetStatData(); - } public void Dispose() { _engine?.Dispose(); - _codeStat?.EndCodeStat(); } } } diff --git a/src/ScriptEngine.HostedScript/LibraryLoader.cs b/src/ScriptEngine.HostedScript/LibraryLoader.cs index a02ad4f1a..f0227b1ec 100644 --- a/src/ScriptEngine.HostedScript/LibraryLoader.cs +++ b/src/ScriptEngine.HostedScript/LibraryLoader.cs @@ -13,6 +13,7 @@ This Source Code Form is subject to the terms of the using System.Linq; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; namespace ScriptEngine.HostedScript diff --git a/src/ScriptEngine.HostedScript/SystemConfigAccessor.cs b/src/ScriptEngine.HostedScript/SystemConfigAccessor.cs index 64e34c67c..619e6f6f6 100644 --- a/src/ScriptEngine.HostedScript/SystemConfigAccessor.cs +++ b/src/ScriptEngine.HostedScript/SystemConfigAccessor.cs @@ -16,27 +16,21 @@ namespace ScriptEngine.HostedScript.Library public class SystemConfigAccessor : GlobalContextBase { private KeyValueConfig _config; + private readonly ConfigurationProviders _providers; - internal ConfigurationProviders Provider { get; set; } - - public SystemConfigAccessor() + public SystemConfigAccessor(ConfigurationProviders providers) { + _providers = providers; Refresh(); } - internal KeyValueConfig GetConfig() - { - return _config; - } - /// /// Метод обновляет текущие настройки значениями из файла oscript.cfg /// [ContextMethod("ОбновитьНастройкиСистемы", "RefreshSystemConfig")] public void Refresh() { - if (Provider != null) - _config = Provider.CreateConfig(); + _config = _providers.CreateConfig(); } /// @@ -61,10 +55,7 @@ public IValue GetSystemOptionValue(string optionKey) public static IAttachableContext CreateInstance(ConfigurationProviders providers) { - return new SystemConfigAccessor - { - Provider = providers - }; + return new SystemConfigAccessor(providers); } } } diff --git a/src/ScriptEngine.HostedScript/SystemGlobalContext.cs b/src/ScriptEngine.HostedScript/SystemGlobalContext.cs index 32a6a6dc6..cfe970db5 100644 --- a/src/ScriptEngine.HostedScript/SystemGlobalContext.cs +++ b/src/ScriptEngine.HostedScript/SystemGlobalContext.cs @@ -5,8 +5,6 @@ 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.Linq; using OneScript.Contexts; using OneScript.StandardLibrary; using OneScript.StandardLibrary.Collections; diff --git a/src/ScriptEngine.HostedScript/TemplateStorage.cs b/src/ScriptEngine.HostedScript/TemplateStorage.cs index 9af73082b..0c41bd64e 100644 --- a/src/ScriptEngine.HostedScript/TemplateStorage.cs +++ b/src/ScriptEngine.HostedScript/TemplateStorage.cs @@ -7,9 +7,9 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; using OneScript.Contexts.Enums; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/ScriptEngine.NativeApi/build.sh b/src/ScriptEngine.NativeApi/build.sh old mode 100644 new mode 100755 index 4a911d356..a2aaacc80 --- a/src/ScriptEngine.NativeApi/build.sh +++ b/src/ScriptEngine.NativeApi/build.sh @@ -11,5 +11,6 @@ cmake -E make_directory build64 cd build64 cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=OFF --build .. cmake --build . +chmod +x *.so cp *.so .. cd .. diff --git a/src/ScriptEngine/Compiler/CompilerBackendSelector.cs b/src/ScriptEngine/Compiler/CompilerBackendSelector.cs index 7ea0d6e5c..edaf320ff 100644 --- a/src/ScriptEngine/Compiler/CompilerBackendSelector.cs +++ b/src/ScriptEngine/Compiler/CompilerBackendSelector.cs @@ -17,6 +17,12 @@ namespace ScriptEngine.Compiler public class CompilerBackendSelector : BslSyntaxWalker { private bool _isNative; + private bool _isNativeDefault; + + public CompilerBackendSelector(OneScriptCoreOptions options) + { + _isNativeDefault = options.UseNativeAsDefaultRuntime; + } public Func StackBackendInitializer { get; set; } @@ -40,6 +46,15 @@ protected override void VisitModuleAnnotation(AnnotationNode node) { _isNative = true; } + else if (string.Equals(node.Name, NativeRuntimeAnnotationHandler.StackRuntimeDirectiveName, + StringComparison.CurrentCultureIgnoreCase)) + { + _isNative = false; + } + else + { + _isNative = _isNativeDefault; + } } protected override void VisitModule(ModuleNode node) diff --git a/src/ScriptEngine/Compiler/CompilerErrors.cs b/src/ScriptEngine/Compiler/CompilerErrors.cs index 6f411444a..1f6ea3e2d 100644 --- a/src/ScriptEngine/Compiler/CompilerErrors.cs +++ b/src/ScriptEngine/Compiler/CompilerErrors.cs @@ -21,7 +21,10 @@ public static CodeError TooFewArgumentsPassed() => public static CodeError TooManyArgumentsPassed() => Create("Слишком много фактических параметров", "Too many actual parameters"); - + + public static CodeError MissedArgument() => + Create("Пропущен обязательный параметр", "Missed mandatory parameter"); + private static CodeError Create(string ru, string en, [CallerMemberName] string errorId = default) { return new CodeError diff --git a/src/ScriptEngine/Compiler/CompilerFrontend.cs b/src/ScriptEngine/Compiler/CompilerFrontend.cs index 95f70658e..1c6fe1db8 100644 --- a/src/ScriptEngine/Compiler/CompilerFrontend.cs +++ b/src/ScriptEngine/Compiler/CompilerFrontend.cs @@ -28,7 +28,7 @@ public CompilerFrontend( IDependencyResolver dependencyResolver) : base(handlers, errorSink, services) { _dependencyResolver = dependencyResolver; - _backendSelector = new CompilerBackendSelector(); + _backendSelector = services.Resolve(); _backendSelector.NativeBackendInitializer = NativeInitializer; _backendSelector.StackBackendInitializer = StackInitializer; diff --git a/src/ScriptEngine/Compiler/ModuleDumpWriter.cs b/src/ScriptEngine/Compiler/ModuleDumpWriter.cs index 5418e8a7d..bfc981242 100644 --- a/src/ScriptEngine/Compiler/ModuleDumpWriter.cs +++ b/src/ScriptEngine/Compiler/ModuleDumpWriter.cs @@ -8,10 +8,14 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.IO; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using OneScript.Commons; using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Native.Compiler; +using OneScript.Native.Runtime; using OneScript.Sources; using ScriptEngine.Machine; @@ -28,10 +32,78 @@ public ModuleDumpWriter(ICompilerFrontend compilerService) public void Write(TextWriter output, SourceCode source) { - var module = (StackRuntimeModule)_compiler.Compile(source); + var compilerResult = _compiler.Compile(source); + if (compilerResult is StackRuntimeModule stackModule) + { + var module = stackModule; + WriteImage(output, module); + } + else + { + WriteNativeModule(output, (DynamicModule)compilerResult); + } - WriteImage(output, module); + } + private void WriteNativeModule(TextWriter output, DynamicModule compilerResult) + { + foreach (var attribute in compilerResult.ModuleAttributes) + { + output.WriteLine($"[{attribute.Name}]"); + } + output.WriteLine("class DynamicModule"); + output.WriteLine("{"); + output.WriteLine(".fields"); + foreach (var field in compilerResult.Fields) + { + PrintField(output, field); + } + + output.WriteLine(".properties"); + foreach (var prop in compilerResult.Properties) + { + PrintProperty(output, prop); + } + + output.WriteLine(".methods"); + foreach (var method in compilerResult.Methods) + { + PrintMethod(output, (BslNativeMethodInfo)method); + } + + output.WriteLine("}"); + } + + private void PrintProperty(TextWriter output, BslPropertyInfo prop) + { + output.WriteLine(); + foreach (var attribute in prop.GetAnnotations()) + { + output.WriteLine($"[{attribute.Name}]"); + } + output.WriteLine($"{prop.PropertyType} {prop.Name}"); + } + + private void PrintMethod(TextWriter output, BslNativeMethodInfo method) + { + output.WriteLine(); + foreach (var attribute in method.GetAnnotations()) + { + output.WriteLine($"[{attribute.Name}]"); + } + + var propertyInfo = typeof(Expression).GetProperty("DebugView", BindingFlags.Instance | BindingFlags.NonPublic); + output.WriteLine(propertyInfo.GetValue(method.Implementation) as string); + } + + private void PrintField(TextWriter output, BslFieldInfo field) + { + output.WriteLine(); + foreach (var attribute in field.GetAnnotations()) + { + output.WriteLine($"[{attribute.Name}]"); + } + output.WriteLine($"{field.FieldType} {field.Name}"); } public void Write(TextWriter output, StackRuntimeModule module) diff --git a/src/ScriptEngine/Compiler/NativeCompilerBackend.cs b/src/ScriptEngine/Compiler/NativeCompilerBackend.cs index 57fc098a9..6c6bb9344 100644 --- a/src/ScriptEngine/Compiler/NativeCompilerBackend.cs +++ b/src/ScriptEngine/Compiler/NativeCompilerBackend.cs @@ -21,7 +21,7 @@ public class NativeCompilerBackend : ICompilerBackend public NativeCompilerBackend(IErrorSink errorSink, IServiceContainer services) { - _codeGen = new ModuleCompiler(errorSink, services); + _codeGen = new ModuleCompiler(errorSink, services, services.Resolve()); } public bool GenerateDebugCode { get; set; } diff --git a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs index 6c73404d0..c37e0938b 100644 --- a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs +++ b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs @@ -14,6 +14,7 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.Language; using OneScript.Language.Extensions; @@ -99,14 +100,12 @@ private void HandleImportClause(AnnotationNode node) // if(_ctx is ModuleCompilerContext moduleContext) // moduleContext.Update(); } - catch (CompilerException e) + catch (DependencyResolveException e) { var error = new CodeError { Description = e.Message, - Position = e.GetPosition()?.LineNumber == default - ? MakeCodePosition(node.Location) - : e.GetPosition(), + Position = MakeCodePosition(node.Location), ErrorId = nameof(CompilerException) }; AddError(error); @@ -119,7 +118,7 @@ private void CheckForwardedDeclarations() { foreach (var item in _forwardedMethods) { - if (!_ctx.FindMethod(item.identifier, out var methN)) + if (!_ctx.TryFindMethodBinding(item.identifier, out var methN)) { AddError(LocalizedErrors.SymbolNotFound(item.identifier), item.location); continue; @@ -605,7 +604,7 @@ private void BuiltInFunctionCall(CallNode node) else { var parameters = BuiltinFunctions.ParametersInfo(funcId); - CheckFactArguments(parameters, node.ArgumentList); + FullCheckFactArguments(parameters, node.ArgumentList); } AddCommand(funcId, argsPassed); @@ -630,7 +629,34 @@ private void CheckFactArguments(BslMethodInfo method, BslSyntaxNode argList) { CheckFactArguments(method.GetParameters(), argList); } - + + private void FullCheckFactArguments(ParameterInfo[] parameters, BslSyntaxNode argList) + { + var argsPassed = argList.Children.Count; + if (argsPassed > parameters.Length) + { + AddError(CompilerErrors.TooManyArgumentsPassed(), argList.Location); + return; + } + + int i = 0; + for (; i < argsPassed; i++) + { + if (!parameters[i].HasDefaultValue && argList.Children[i].Children.Count == 0) + { + AddError(CompilerErrors.MissedArgument(), argList.Location); + } + } + for (; i < parameters.Length; i++) + { + if (!parameters[i].HasDefaultValue) + { + AddError(CompilerErrors.TooFewArgumentsPassed(), argList.Location); + return; + } + } + } + protected override void VisitGlobalProcedureCall(CallNode node) { if (LanguageDef.IsBuiltInFunction(node.Identifier.Lexem.Token)) @@ -722,7 +748,7 @@ private void GlobalCall(CallNode call, bool asFunction) var identifier = identifierNode.Lexem.Content; - var hasMethod = _ctx.FindMethod(identifier, out var methBinding); + var hasMethod = _ctx.TryFindMethodBinding(identifier, out var methBinding); if (hasMethod) { var scope = _ctx.GetScope(methBinding.ScopeNumber); @@ -875,7 +901,7 @@ protected override void VisitHandlerOperation(BslSyntaxNode node) { var terminal = handlerNode.AsTerminal(); var identifier = terminal.GetIdentifier(); - if (_ctx.FindMethod(identifier, out _)) + if (_ctx.TryFindMethodBinding(identifier, out _)) { var lex = terminal.Lexem; lex.Type = LexemType.StringLiteral; @@ -1062,9 +1088,9 @@ private void VisitConstant(in Lexem constant) AddCommand(OperationCode.PushConst, num); } - private IEnumerable GetAnnotationAttributes(AnnotatableNode node) + private IEnumerable GetAnnotationAttributes(AnnotatableNode node) { - var mappedAnnotations = new List(); + var mappedAnnotations = new List(); foreach (var annotation in node.Annotations) { var anno = new BslAnnotationAttribute(annotation.Name); diff --git a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs index d116223af..ccb3981a8 100644 --- a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs +++ b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs @@ -9,11 +9,11 @@ This Source Code Form is subject to the terms of the using System.Diagnostics.CodeAnalysis; using OneScript.Compilation; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.Language; using OneScript.Language.SyntaxAnalysis; using OneScript.Types; -using ScriptEngine.Compiler; using ScriptEngine.Machine; namespace ScriptEngine.Hosting @@ -49,6 +49,7 @@ public static IEngineBuilder SetDefaultOptions(this IEngineBuilder builder) services.RegisterSingleton(); services.RegisterSingleton(); services.RegisterSingleton(svc => new ThrowingErrorSink(CompilerException.FromCodeError)); + services.RegisterSingleton(); services.Register(); services.Register(); diff --git a/src/ScriptEngine/ICompilerService.cs b/src/ScriptEngine/ICompilerService.cs index 3b5cc8047..452a1b872 100644 --- a/src/ScriptEngine/ICompilerService.cs +++ b/src/ScriptEngine/ICompilerService.cs @@ -6,7 +6,6 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Compilation.Binding; using OneScript.Contexts; using OneScript.Execution; using ScriptEngine.Machine; diff --git a/src/ScriptEngine/IDependencyResolver.cs b/src/ScriptEngine/IDependencyResolver.cs index c72719ee4..291e36ad0 100644 --- a/src/ScriptEngine/IDependencyResolver.cs +++ b/src/ScriptEngine/IDependencyResolver.cs @@ -5,14 +5,12 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Sources; +using OneScript.Compilation; namespace ScriptEngine { - public interface IDependencyResolver + public interface IDependencyResolver : ICompileTimeDependencyResolver { - ExternalLibraryDef Resolve(SourceCode module, string libraryName); - void Initialize(ScriptingEngine engine); } } \ No newline at end of file diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index cee7b1f86..15be6508f 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -1,94 +1,90 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ - -using System.Diagnostics; -using System.Collections.Generic; - -namespace ScriptEngine.Machine -{ - public class CodeStatProcessor : ICodeStatCollector - { - private Dictionary _codeStat = new Dictionary(); - private Dictionary _watchers = new Dictionary(); - private Stopwatch _activeStopwatch = null; - private HashSet _preparedScripts = new HashSet(); - - public CodeStatProcessor() - { - } - - public bool IsPrepared(string ScriptFileName) - { - return _preparedScripts.Contains(ScriptFileName); - } - - public void MarkEntryReached(CodeStatEntry entry, int count = 1) - { - int oldValue = 0; - _codeStat.TryGetValue(entry, out oldValue); - _codeStat[entry] = oldValue + count; - - if (count == 0) - { - if (!_watchers.ContainsKey(entry)) - { - _watchers.Add(entry, new Stopwatch()); - } - } - else - { - _activeStopwatch?.Stop(); - _activeStopwatch = _watchers[entry]; - _activeStopwatch.Start(); - } - } - - public void MarkPrepared(string scriptFileName) - { - _preparedScripts.Add(scriptFileName); - } - - public CodeStatDataCollection GetStatData() - { - CodeStatDataCollection data = new CodeStatDataCollection(); - foreach (var item in _codeStat) - { - if (!IsPrepared(item.Key.ScriptFileName)) - { - continue; - } - data.Add(new CodeStatData(item.Key, _watchers[item.Key].ElapsedMilliseconds, item.Value)); - } - - return data; - } - - public void EndCodeStat() - { - _activeStopwatch?.Stop(); - } - - public void StopWatch(CodeStatEntry entry) - { - if (_watchers.ContainsKey(entry)) - { - _watchers[entry].Stop(); - } - } - - public void ResumeWatch(CodeStatEntry entry) - { - _activeStopwatch?.Stop(); - - if (_watchers.ContainsKey(entry)) - { - _activeStopwatch = _watchers[entry]; - _activeStopwatch.Start(); - } - } - } -} +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using System.Diagnostics; +using System.Collections.Generic; + +namespace ScriptEngine.Machine +{ + public class CodeStatProcessor : ICodeStatCollector + { + private Dictionary _codeStat = new Dictionary(); + private Dictionary _watchers = new Dictionary(); + private Stopwatch _activeStopwatch = null; + private HashSet _preparedScripts = new HashSet(); + + public bool IsPrepared(string ScriptFileName) + { + return _preparedScripts.Contains(ScriptFileName); + } + + public void MarkEntryReached(CodeStatEntry entry, int count = 1) + { + int oldValue = 0; + _codeStat.TryGetValue(entry, out oldValue); + _codeStat[entry] = oldValue + count; + + if (count == 0) + { + if (!_watchers.ContainsKey(entry)) + { + _watchers.Add(entry, new Stopwatch()); + } + } + else + { + _activeStopwatch?.Stop(); + _activeStopwatch = _watchers[entry]; + _activeStopwatch.Start(); + } + } + + public void MarkPrepared(string scriptFileName) + { + _preparedScripts.Add(scriptFileName); + } + + public CodeStatDataCollection GetStatData() + { + CodeStatDataCollection data = new CodeStatDataCollection(); + foreach (var item in _codeStat) + { + if (!IsPrepared(item.Key.ScriptFileName)) + { + continue; + } + data.Add(new CodeStatData(item.Key, _watchers[item.Key].ElapsedMilliseconds, item.Value)); + } + + return data; + } + + public void EndCodeStat() + { + _activeStopwatch?.Stop(); + } + + public void StopWatch(CodeStatEntry entry) + { + if (_watchers.ContainsKey(entry)) + { + _watchers[entry].Stop(); + } + } + + public void ResumeWatch(CodeStatEntry entry) + { + _activeStopwatch?.Stop(); + + if (_watchers.ContainsKey(entry)) + { + _activeStopwatch = _watchers[entry]; + _activeStopwatch.Start(); + } + } + } +} diff --git a/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs b/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs index 613f8b847..8db869186 100644 --- a/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs +++ b/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs @@ -9,6 +9,9 @@ This Source Code Form is subject to the terms of the using System.Linq; using System.Reflection; using OneScript.Commons; +using OneScript.Contexts; +using OneScript.Exceptions; +using ScriptEngine.Machine.Contexts; namespace ScriptEngine.Machine { diff --git a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs index aed9b8341..8412de908 100755 --- a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs +++ b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs @@ -13,6 +13,7 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.Types; diff --git a/src/ScriptEngine/Machine/Contexts/AutoContext.cs b/src/ScriptEngine/Machine/Contexts/AutoContext.cs index a29ba9559..ba81e2639 100644 --- a/src/ScriptEngine/Machine/Contexts/AutoContext.cs +++ b/src/ScriptEngine/Machine/Contexts/AutoContext.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Diagnostics; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/AutoScriptDrivenObject.cs b/src/ScriptEngine/Machine/Contexts/AutoScriptDrivenObject.cs index 8c360a660..520eaa9ae 100644 --- a/src/ScriptEngine/Machine/Contexts/AutoScriptDrivenObject.cs +++ b/src/ScriptEngine/Machine/Contexts/AutoScriptDrivenObject.cs @@ -6,11 +6,10 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using System.Collections.Generic; -using OneScript.Commons; using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.Sources; diff --git a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs index c93b7221a..80f620dda 100644 --- a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs @@ -1,4 +1,4 @@ -/*---------------------------------------------------------- +/*---------------------------------------------------------- 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 @@ -10,9 +10,11 @@ This Source Code Form is subject to the terms of the using System.Linq; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Types; +using System.Reflection; namespace ScriptEngine.Machine.Contexts { @@ -83,7 +85,7 @@ private static COMWrapperContext Create(string progId, IValue[] arguments) type = type.MakeGenericType(genericTypes.ToArray()); } - object instance = Activator.CreateInstance(type, MarshalArguments(arguments)); + object instance = Activator.CreateInstance(type, MarshalArguments(arguments).values); return InitByInstance(type, instance); } @@ -122,10 +124,23 @@ private static bool TypeIsRuntimeCallableWrapper(Type type) return type.FullName == "System.__ComObject" || type.BaseType.FullName == "System.__ComObject"; // string, cause it's hidden type } - public static object[] MarshalArguments(IValue[] arguments) + protected static (object[] values, ParameterModifier[] flags) MarshalArguments(IValue[] arguments) { - var args = arguments.Select(x => MarshalIValue(x)).ToArray(); - return args; + var values = new object[arguments.Length]; + ParameterModifier[] flagsArray = null; + if (arguments.Length > 0) + { + var flags = new ParameterModifier(arguments.Length); + for (int i = 0; i < arguments.Length; i++) + { + values[i] = MarshalIValue(arguments[i]); + flags[i] = arguments[i] is IVariable; + } + + flagsArray = new[] { flags }; + } + + return (values, flagsArray); } public static object MarshalIValue(IValue val) diff --git a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs index 622cec3fa..2404915e1 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs @@ -1,331 +1,320 @@ -/*---------------------------------------------------------- -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.Dynamic; -using System.Linq; -using OneScript.Commons; -using OneScript.Contexts; -using OneScript.Types; -using OneScript.Values; - -namespace ScriptEngine.Machine.Contexts -{ - public abstract class ContextIValueImpl : BslObjectValue, IRuntimeContextInstance, ISystemTypeAcceptor - { - private TypeDescriptor _type; - - protected ContextIValueImpl() : this(BasicTypes.UnknownType) - { - } - - protected ContextIValueImpl(TypeDescriptor type) - { - _type = type; - } - - void ISystemTypeAcceptor.AssignType(TypeDescriptor type) - { - _type = type; - } - - protected void DefineType(TypeDescriptor type) - { - _type = type; - } - - public override string ToString() - { - if (_type == BasicTypes.UnknownType) - TryDetermineOwnType(); - - return _type.Name; - } - - #region IValue Members - - public override TypeDescriptor SystemType - { - get - { - if (_type != BasicTypes.UnknownType) - return _type; - - if (!TryDetermineOwnType()) - { - throw new InvalidOperationException($"Type {GetType()} is not defined"); - } - - return _type; - } - } - - private bool TryDetermineOwnType() - { - var mgr = MachineInstance.Current?.TypeManager; - if (mgr?.IsKnownType(GetType()) ?? false) - { - _type = mgr.GetTypeByFrameworkType(GetType()); - return true; - } - - return false; - } - - #endregion - - #region IComparable Members - - public override int CompareTo(IValue other) - { - if (other.SystemType.Equals(this.SystemType)) - { - if (this.Equals(other)) - { - return 0; - } - else - { - throw RuntimeException.ComparisonNotSupportedException(); - } - } - else - { - return this.SystemType.ToString().CompareTo(other.SystemType.ToString()); - } - } - - #endregion - - #region IEquatable Members - - public override bool Equals(IValue other) - { - if (!(other is BslObjectValue _)) - return false; - - return ReferenceEquals(this, other); - } - - #endregion - - #region IRuntimeContextInstance Members - - public virtual bool IsIndexed => false; - - public virtual bool DynamicMethodSignatures => false; - - public virtual IValue GetIndexedValue(IValue index) - { - throw new NotImplementedException(); - } - - public virtual void SetIndexedValue(IValue index, IValue val) - { - throw new NotImplementedException(); - } - - public virtual int GetPropertyNumber(string name) - { - throw PropertyAccessException.PropNotFoundException(name); - } - public virtual bool IsPropReadable(int propNum) - { - throw new NotImplementedException(); - } - - public virtual bool IsPropWritable(int propNum) - { - throw new NotImplementedException(); - } - public virtual IValue GetPropValue(int propNum) - { - throw new NotImplementedException(); - } - public virtual void SetPropValue(int propNum, IValue newVal) - { - throw new NotImplementedException(); - } - - public virtual int GetPropCount() - { - throw new NotImplementedException(); - } - - public virtual string GetPropName(int propNum) - { - throw new NotImplementedException(); - } - - public virtual int GetMethodsCount() - { - throw new NotImplementedException(); - } - - public virtual int GetMethodNumber(string name) - { - throw RuntimeException.MethodNotFoundException(name); - } - - public virtual BslMethodInfo GetMethodInfo(int methodNumber) - { - throw new NotImplementedException(); - } - - public virtual BslPropertyInfo GetPropertyInfo(int propertyNumber) - { - throw new NotImplementedException(); - } - - public virtual void CallAsProcedure(int methodNumber, IValue[] arguments) - { - throw new NotImplementedException(); - } - public virtual void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retValue) - { - throw new NotImplementedException(); - } - - #endregion - - #region DynamicObject members - - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - try - { - var propIdx = GetPropertyNumber(binder.Name); - if (!IsPropReadable(propIdx)) - { - result = null; - return false; - } - - result = ContextValuesMarshaller.ConvertToClrObject(GetPropValue(propIdx)); - return true; - } - catch (PropertyAccessException) - { - result = null; - return false; - } - catch (ValueMarshallingException) - { - result = null; - return false; - } - } - - public override bool TrySetMember(SetMemberBinder binder, object value) - { - try - { - var propIdx = GetPropertyNumber(binder.Name); - if (!IsPropWritable(propIdx)) - { - return false; - } - - SetPropValue(propIdx, ContextValuesMarshaller.ConvertDynamicValue(value)); - return true; - } - catch (PropertyAccessException) - { - return false; - } - catch (NotSupportedException) - { - return false; - } - } - - public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) - { - if (!IsIndexed) - { - result = null; - return false; - } - - var index = ContextValuesMarshaller.ConvertDynamicIndex(indexes[0]); - result = ContextValuesMarshaller.ConvertToClrObject(GetIndexedValue(index)); - return true; - } - - public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) - { - if (!IsIndexed) - { - return false; - } - - var index = ContextValuesMarshaller.ConvertDynamicIndex(indexes[0]); - SetIndexedValue(index, ContextValuesMarshaller.ConvertDynamicValue(value)); - return true; - } - - public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) - { - int methIdx; - try - { - methIdx = GetMethodNumber(binder.Name); - } - catch (MethodAccessException) - { - result = null; - return false; - } - - var parameters = GetMethodInfo(methIdx).GetParameters(); - var valueArgs = new IValue[parameters.Length]; - var passedArgs = args.Select(x => ContextValuesMarshaller.ConvertDynamicValue(x)).ToArray(); - - for (int i = 0; i < valueArgs.Length; i++) - { - if (i < passedArgs.Length) - valueArgs[i] = passedArgs[i]; - else - valueArgs[i] = ValueFactory.CreateInvalidValueMarker(); - } - - CallAsFunction(methIdx, valueArgs, out IValue methResult); - result = methResult == null ? null : ContextValuesMarshaller.ConvertToClrObject(methResult); - - return true; - } - - #endregion - - public override int CompareTo(BslValue other) - { - if (other.GetType() == GetType()) - { - if (this.Equals(other)) - { - return 0; - } - else - { - throw RuntimeException.ComparisonNotSupportedException(); - } - } - else - { - return this.GetType().ToString().CompareTo(other.GetType().ToString()); - } - } - - public override bool Equals(BslValue other) - { - if (other == null) - return false; - - return ReferenceEquals(this, other); - } - } - -} +/*---------------------------------------------------------- +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.Dynamic; +using System.Linq; +using OneScript.Contexts; +using OneScript.Exceptions; +using OneScript.Types; +using OneScript.Values; + +namespace ScriptEngine.Machine.Contexts +{ + public abstract class ContextIValueImpl : BslObjectValue, IRuntimeContextInstance, ISystemTypeAcceptor + { + private TypeDescriptor _type; + + protected ContextIValueImpl() : this(BasicTypes.UnknownType) + { + } + + protected ContextIValueImpl(TypeDescriptor type) + { + _type = type; + } + + void ISystemTypeAcceptor.AssignType(TypeDescriptor type) + { + _type = type; + } + + protected void DefineType(TypeDescriptor type) + { + _type = type; + } + + public override string ToString() + { + if (_type == BasicTypes.UnknownType) + TryDetermineOwnType(); + + return _type.Name; + } + + #region IValue Members + + public override TypeDescriptor SystemType + { + get + { + if (_type != BasicTypes.UnknownType) + return _type; + + if (!TryDetermineOwnType()) + { + throw new InvalidOperationException($"Type {GetType()} is not defined"); + } + + return _type; + } + } + + private bool TryDetermineOwnType() + { + var mgr = MachineInstance.Current?.TypeManager; + if (mgr?.IsKnownType(GetType()) ?? false) + { + _type = mgr.GetTypeByFrameworkType(GetType()); + return true; + } + + return false; + } + + #endregion + + #region IComparable Members + + public override int CompareTo(IValue other) + { + throw RuntimeException.ComparisonNotSupportedException(); + } + + #endregion + + #region IEquatable Members + + public override bool Equals(IValue other) + { + if (!(other is BslObjectValue _)) + return false; + + return ReferenceEquals(this, other); + } + + #endregion + + #region IRuntimeContextInstance Members + + public virtual bool IsIndexed => false; + + public virtual bool DynamicMethodSignatures => false; + + public virtual IValue GetIndexedValue(IValue index) + { + throw new NotImplementedException(); + } + + public virtual void SetIndexedValue(IValue index, IValue val) + { + throw new NotImplementedException(); + } + + public virtual int GetPropertyNumber(string name) + { + throw PropertyAccessException.PropNotFoundException(name); + } + public virtual bool IsPropReadable(int propNum) + { + throw new NotImplementedException(); + } + + public virtual bool IsPropWritable(int propNum) + { + throw new NotImplementedException(); + } + public virtual IValue GetPropValue(int propNum) + { + throw new NotImplementedException(); + } + public virtual void SetPropValue(int propNum, IValue newVal) + { + throw new NotImplementedException(); + } + + public virtual int GetPropCount() + { + throw new NotImplementedException(); + } + + public virtual string GetPropName(int propNum) + { + throw new NotImplementedException(); + } + + public virtual int GetMethodsCount() + { + throw new NotImplementedException(); + } + + public virtual int GetMethodNumber(string name) + { + throw RuntimeException.MethodNotFoundException(name); + } + + public virtual BslMethodInfo GetMethodInfo(int methodNumber) + { + throw new NotImplementedException(); + } + + public virtual BslPropertyInfo GetPropertyInfo(int propertyNumber) + { + throw new NotImplementedException(); + } + + public virtual void CallAsProcedure(int methodNumber, IValue[] arguments) + { + throw new NotImplementedException(); + } + public virtual void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retValue) + { + throw new NotImplementedException(); + } + + #endregion + + #region DynamicObject members + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + try + { + var propIdx = GetPropertyNumber(binder.Name); + if (!IsPropReadable(propIdx)) + { + result = null; + return false; + } + + result = ContextValuesMarshaller.ConvertToClrObject(GetPropValue(propIdx)); + return true; + } + catch (PropertyAccessException) + { + result = null; + return false; + } + catch (ValueMarshallingException) + { + result = null; + return false; + } + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + try + { + var propIdx = GetPropertyNumber(binder.Name); + if (!IsPropWritable(propIdx)) + { + return false; + } + + SetPropValue(propIdx, ContextValuesMarshaller.ConvertDynamicValue(value)); + return true; + } + catch (PropertyAccessException) + { + return false; + } + catch (NotSupportedException) + { + return false; + } + } + + public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) + { + if (!IsIndexed) + { + result = null; + return false; + } + + var index = ContextValuesMarshaller.ConvertDynamicIndex(indexes[0]); + result = ContextValuesMarshaller.ConvertToClrObject(GetIndexedValue(index)); + return true; + } + + public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) + { + if (!IsIndexed) + { + return false; + } + + var index = ContextValuesMarshaller.ConvertDynamicIndex(indexes[0]); + SetIndexedValue(index, ContextValuesMarshaller.ConvertDynamicValue(value)); + return true; + } + + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + int methIdx; + try + { + methIdx = GetMethodNumber(binder.Name); + } + catch (MethodAccessException) + { + result = null; + return false; + } + + var parameters = GetMethodInfo(methIdx).GetParameters(); + if (args.Length > parameters.Length) + throw RuntimeException.TooManyArgumentsPassed(); + + var valueArgs = new IValue[parameters.Length]; + var passedArgs = args.Select(x => ContextValuesMarshaller.ConvertDynamicValue(x)).ToArray(); + + for (int i = 0; i < valueArgs.Length; i++) + { + if (i < passedArgs.Length) + valueArgs[i] = passedArgs[i]; + else + valueArgs[i] = ValueFactory.CreateInvalidValueMarker(); + } + + CallAsFunction(methIdx, valueArgs, out IValue methResult); + result = methResult == null ? null : ContextValuesMarshaller.ConvertToClrObject(methResult); + + return true; + } + + #endregion + + public override int CompareTo(BslValue other) + { + if (other.GetType() == GetType()) + { + if (this.Equals(other)) + { + return 0; + } + else + { + throw RuntimeException.ComparisonNotSupportedException(); + } + } + else + { + return this.GetType().ToString().CompareTo(other.GetType().ToString()); + } + } + + public override bool Equals(BslValue other) + { + if (other == null) + return false; + + return ReferenceEquals(this, other); + } + } + +} diff --git a/src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs b/src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs index e199a4db2..1967c74ca 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs @@ -10,8 +10,8 @@ This Source Code Form is subject to the terms of the using System.Linq; using System.Linq.Expressions; using System.Reflection; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Language; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/ContextPropertyMapper.cs b/src/ScriptEngine/Machine/Contexts/ContextPropertyMapper.cs index b1ae1a721..faef57057 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextPropertyMapper.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextPropertyMapper.cs @@ -1,188 +1,188 @@ -/*---------------------------------------------------------- -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.Linq; -using System.Reflection; -using OneScript.Commons; -using OneScript.Contexts; - -namespace ScriptEngine.Machine.Contexts -{ - public class PropertyTarget - { - private readonly BslPropertyInfo _propertyInfo; - - public PropertyTarget(PropertyInfo propInfo) - { - _propertyInfo = new ContextPropertyInfo(propInfo); - Name = _propertyInfo.Name; - Alias = _propertyInfo.Alias; - - if (string.IsNullOrEmpty(Alias)) - Alias = propInfo.Name; - - IValue CantReadAction(TInstance inst) - { - throw PropertyAccessException.PropIsNotReadableException(Name); - } - - void CantWriteAction(TInstance inst, IValue val) - { - throw PropertyAccessException.PropIsNotWritableException(Name); - } - - if (_propertyInfo.CanRead) - { - var getMethodInfo = propInfo.GetGetMethod(); - if (getMethodInfo == null) - { - Getter = CantReadAction; - } - else - { - var genericGetter = typeof(PropertyTarget).GetMembers(BindingFlags.NonPublic | BindingFlags.Instance) - .Where(x => x.MemberType == MemberTypes.Method && x.Name == nameof(CreateGetter)) - .Select(x => (MethodInfo)x) - .First(); - - var resolvedGetter = genericGetter.MakeGenericMethod(propInfo.PropertyType); - - Getter = (Func)resolvedGetter.Invoke(this, new object[] { getMethodInfo }); - } - } - else - { - Getter = CantReadAction; - } - - if (_propertyInfo.CanWrite) - { - var setMethodInfo = propInfo.GetSetMethod(); - if (setMethodInfo == null) - { - Setter = CantWriteAction; - } - else - { - var genericSetter = typeof(PropertyTarget).GetMembers(BindingFlags.NonPublic | BindingFlags.Instance) - .Where(x => x.MemberType == MemberTypes.Method && x.Name == nameof(CreateSetter)) - .Select(x => (MethodInfo)x) - .First(); - - var resolvedSetter = genericSetter.MakeGenericMethod(propInfo.PropertyType); - - Setter = (Action)resolvedSetter.Invoke(this, new object[] { setMethodInfo }); - } - } - else - { - Setter = CantWriteAction; - } - } - - public Func Getter { get; } - - public Action Setter { get; } - - public string Name { get; } - - public string Alias { get; } - - public bool CanRead => _propertyInfo.CanRead; - public bool CanWrite => _propertyInfo.CanWrite; - - public BslPropertyInfo PropertyInfo => _propertyInfo; - - private Func CreateGetter(MethodInfo methInfo) - { - var method = (Func)Delegate.CreateDelegate(typeof(Func), methInfo); - return inst => ConvertReturnValue(method(inst)); - } - - private Action CreateSetter(MethodInfo methInfo) - { - var method = (Action)Delegate.CreateDelegate(typeof(Action), methInfo); - return (inst, val) => method(inst, ConvertParam(val)); - } - - private T ConvertParam(IValue value) - { - return ContextValuesMarshaller.ConvertParam(value); - } - - private IValue ConvertReturnValue(TRet param) - { - return ContextValuesMarshaller.ConvertReturnValue(param); - } - - } - - public class ContextPropertyMapper - { - private List> _properties; - private readonly object _locker = new object(); - - private void Init() - { - if (_properties != null) - return; - - lock (_locker) - { - if (_properties == null) - { - _properties = FindProperties(); - } - } - } - - private List> FindProperties() - { - return typeof(TInstance).GetProperties() - .Where(x => x.GetCustomAttributes(typeof(ContextPropertyAttribute), false).Any()) - .Select(x => new PropertyTarget(x)).ToList(); - } - - public bool ContainsProperty(string name) - { - return GetPropertyIndex(name) >= 0; - } - - public int FindProperty(string name) - { - var idx = GetPropertyIndex(name); - if (idx < 0) - throw PropertyAccessException.PropNotFoundException(name); - - return idx; - } - - public PropertyTarget GetProperty(int index) - { - Init(); - return _properties[index]; - } - - public int Count - { - get - { - Init(); - return _properties.Count; - } - } - - private int GetPropertyIndex(string name) - { - Init(); - return _properties.FindIndex(x => String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) - || String.Equals(x.Alias, name, StringComparison.OrdinalIgnoreCase)); - } - } -} +/*---------------------------------------------------------- +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.Linq; +using System.Reflection; +using OneScript.Contexts; +using OneScript.Exceptions; + +namespace ScriptEngine.Machine.Contexts +{ + public class PropertyTarget + { + private readonly BslPropertyInfo _propertyInfo; + + public PropertyTarget(PropertyInfo propInfo) + { + _propertyInfo = new ContextPropertyInfo(propInfo); + Name = _propertyInfo.Name; + Alias = _propertyInfo.Alias; + + if (string.IsNullOrEmpty(Alias)) + Alias = propInfo.Name; + + IValue CantReadAction(TInstance inst) + { + throw PropertyAccessException.PropIsNotReadableException(Name); + } + + void CantWriteAction(TInstance inst, IValue val) + { + throw PropertyAccessException.PropIsNotWritableException(Name); + } + + if (_propertyInfo.CanRead) + { + var getMethodInfo = propInfo.GetGetMethod(); + if (getMethodInfo == null) + { + Getter = CantReadAction; + } + else + { + var genericGetter = typeof(PropertyTarget).GetMembers(BindingFlags.NonPublic | BindingFlags.Instance) + .Where(x => x.MemberType == MemberTypes.Method && x.Name == nameof(CreateGetter)) + .Select(x => (MethodInfo)x) + .First(); + + var resolvedGetter = genericGetter.MakeGenericMethod(propInfo.PropertyType); + + Getter = (Func)resolvedGetter.Invoke(this, new object[] { getMethodInfo }); + } + } + else + { + Getter = CantReadAction; + } + + if (_propertyInfo.CanWrite) + { + var setMethodInfo = propInfo.GetSetMethod(); + if (setMethodInfo == null) + { + Setter = CantWriteAction; + } + else + { + var genericSetter = typeof(PropertyTarget).GetMembers(BindingFlags.NonPublic | BindingFlags.Instance) + .Where(x => x.MemberType == MemberTypes.Method && x.Name == nameof(CreateSetter)) + .Select(x => (MethodInfo)x) + .First(); + + var resolvedSetter = genericSetter.MakeGenericMethod(propInfo.PropertyType); + + Setter = (Action)resolvedSetter.Invoke(this, new object[] { setMethodInfo }); + } + } + else + { + Setter = CantWriteAction; + } + } + + public Func Getter { get; } + + public Action Setter { get; } + + public string Name { get; } + + public string Alias { get; } + + public bool CanRead => _propertyInfo.CanRead; + public bool CanWrite => _propertyInfo.CanWrite; + + public BslPropertyInfo PropertyInfo => _propertyInfo; + + private Func CreateGetter(MethodInfo methInfo) + { + var method = (Func)Delegate.CreateDelegate(typeof(Func), methInfo); + return inst => ConvertReturnValue(method(inst)); + } + + private Action CreateSetter(MethodInfo methInfo) + { + var method = (Action)Delegate.CreateDelegate(typeof(Action), methInfo); + return (inst, val) => method(inst, ConvertParam(val)); + } + + private T ConvertParam(IValue value) + { + return ContextValuesMarshaller.ConvertParam(value); + } + + private IValue ConvertReturnValue(TRet param) + { + return ContextValuesMarshaller.ConvertReturnValue(param); + } + + } + + public class ContextPropertyMapper + { + private List> _properties; + private readonly object _locker = new object(); + + private void Init() + { + if (_properties != null) + return; + + lock (_locker) + { + if (_properties == null) + { + _properties = FindProperties(); + } + } + } + + private List> FindProperties() + { + return typeof(TInstance).GetProperties() + .Where(x => x.GetCustomAttributes(typeof(ContextPropertyAttribute), false).Any()) + .Select(x => new PropertyTarget(x)).ToList(); + } + + public bool ContainsProperty(string name) + { + return GetPropertyIndex(name) >= 0; + } + + public int FindProperty(string name) + { + var idx = GetPropertyIndex(name); + if (idx < 0) + throw PropertyAccessException.PropNotFoundException(name); + + return idx; + } + + public PropertyTarget GetProperty(int index) + { + Init(); + return _properties[index]; + } + + public int Count + { + get + { + Init(); + return _properties.Count; + } + } + + private int GetPropertyIndex(string name) + { + Init(); + return _properties.FindIndex(x => String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) + || String.Equals(x.Alias, name, StringComparison.OrdinalIgnoreCase)); + } + } +} diff --git a/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs b/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs index 6213b3184..8f5de8357 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using OneScript.Commons; using OneScript.Contexts; using OneScript.Contexts.Enums; +using OneScript.Exceptions; using OneScript.Values; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/DynamicPropertiesAccessor.cs b/src/ScriptEngine/Machine/Contexts/DynamicPropertiesAccessor.cs index 128110dfc..ca4096b06 100644 --- a/src/ScriptEngine/Machine/Contexts/DynamicPropertiesAccessor.cs +++ b/src/ScriptEngine/Machine/Contexts/DynamicPropertiesAccessor.cs @@ -6,7 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System.Collections.Generic; -using OneScript.Commons; +using OneScript.Exceptions; namespace ScriptEngine.Machine.Contexts { diff --git a/src/ScriptEngine/Machine/Contexts/DynamicPropertiesHolder.cs b/src/ScriptEngine/Machine/Contexts/DynamicPropertiesHolder.cs index df7159490..34642871a 100644 --- a/src/ScriptEngine/Machine/Contexts/DynamicPropertiesHolder.cs +++ b/src/ScriptEngine/Machine/Contexts/DynamicPropertiesHolder.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; namespace ScriptEngine.Machine.Contexts { diff --git a/src/ScriptEngine/Machine/Contexts/EnumerationValue.cs b/src/ScriptEngine/Machine/Contexts/EnumerationValue.cs index 855adf8db..ae3c79d4a 100644 --- a/src/ScriptEngine/Machine/Contexts/EnumerationValue.cs +++ b/src/ScriptEngine/Machine/Contexts/EnumerationValue.cs @@ -5,7 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; @@ -49,23 +49,7 @@ public override IValue GetRawValue() public override int CompareTo(BslValue other) { - if (other != null) - { - if (other is EnumerationValue) - { - int thisIdx = _owner.IndexOf(this); - int otherIdx = _owner.IndexOf((EnumerationValue)other); - return thisIdx - otherIdx; - } - else - { - throw RuntimeException.ComparisonNotSupportedException(); - } - } - else - { - return 1; - } + throw RuntimeException.ComparisonNotSupportedException(); } public override bool Equals(BslValue other) diff --git a/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs b/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs index 051bbf1bd..ce73700d3 100644 --- a/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs +++ b/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs @@ -1,189 +1,222 @@ -/*---------------------------------------------------------- -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.Text; -using OneScript.Commons; -using OneScript.Contexts; -using OneScript.Language; - -namespace ScriptEngine.Machine.Contexts -{ - /// - /// Класс позволяет узнать информацию о произошедшем исключении. - /// - [ContextClass("ИнформацияОбОшибке", "ErrorInfo")] - public class ExceptionInfoContext : AutoContext - { - readonly ScriptException _exc; - IValue _innerException; - - public ExceptionInfoContext(ScriptException source) - { - _exc = source ?? throw new ArgumentNullException(); - if (source.InnerException is ParametrizedRuntimeException pre) - { - Parameters = pre.Parameter; - } - } - - /// - /// Значение, переданное при создании исключения в конструкторе объекта ИнформацияОбОшибке. - /// - [ContextProperty("Параметры", "Parameters", CanWrite = false)] - public IValue Parameters - { - get; - private set; - } - - /// - /// Содержит краткое описание ошибки. Эквивалент Exception.Message в C# - /// - [ContextProperty("Описание", "Description")] - public string Description - { - get { return _exc.ErrorDescription; } - } - - public string MessageWithoutCodeFragment - { - get { return _exc.MessageWithoutCodeFragment; } - } - - public string DetailedDescription - { - get - { - var sb = new StringBuilder(_exc.Message); - var inner = _exc.InnerException; - while (inner != default) - { - sb.AppendLine(); - sb.AppendLine(Locale.NStr("ru = 'по причине:';en = 'caused by:'")); - sb.AppendLine(inner.Message); - inner = inner.InnerException; - } - - return sb.ToString(); - } - } - - /// - /// Имя модуля, вызвавшего исключение. - /// - [ContextProperty("ИмяМодуля", "ModuleName")] - public string ModuleName => _exc.ModuleName ?? string.Empty; - - /// - /// Номер строки, вызвавшей исключение. - /// - [ContextProperty("НомерСтроки", "LineNumber")] - public int LineNumber => _exc.LineNumber; - - /// - /// Строка исходного кода, вызвавшего исключение. - /// - [ContextProperty("ИсходнаяСтрока", "SourceLine")] - public string SourceLine => _exc.Code ?? string.Empty; - - /// - /// Предоставляет доступ к стеку вызовов процедур. - /// Подробнее см. класс КоллекцияКадровСтекаВызовов - /// - /// - [ContextMethod("ПолучитьСтекВызовов", "GetStackTrace")] - public IValue GetStackTrace() - { - if (_exc.RuntimeSpecificInfo is IList frames) - { - // var frames = rte.CallStackFrames; - // if (frames == null) - // return ValueFactory.Create(); - return new StackTraceCollectionContext(frames); - } - return ValueFactory.Create(); - } - - /// - /// Содержит вложенное исключение, если таковое было. Эквивалент Exception.InnerException в C# - /// - [ContextProperty("Причина", "Cause")] - public IValue InnerException - { - get - { - if (_innerException == null) - _innerException = CreateInnerExceptionInfo(); - - return _innerException; - } - } - - private IValue CreateInnerExceptionInfo() - { - if (_exc.InnerException == null) - return ValueFactory.Create(); - - bool alreadyWrapped = _exc is ExternalSystemException; - if (!alreadyWrapped) - { - ScriptException inner; - inner = _exc.InnerException as ScriptException; - if (inner == null) - { - inner = new ExternalSystemException(_exc.InnerException); - } - if (inner.ModuleName == null) - inner.ModuleName = _exc.ModuleName; - if (inner.Code == null) - inner.Code = _exc.Code; - return new ExceptionInfoContext(inner); - } - else - { - if (_exc.InnerException.InnerException == null) - return ValueFactory.Create(); - - var inner = new ExternalSystemException(_exc.InnerException.InnerException); - if (inner.LineNumber == ErrorPositionInfo.OUT_OF_TEXT) - { - inner.ModuleName = this.ModuleName; - inner.Code = this.SourceLine; - inner.LineNumber = this.LineNumber; - } - - return new ExceptionInfoContext(inner); - } - } - - /// - /// Содержит подробное описание исключения, включая стек вызовов среды исполнения CLR. - /// т.е. не стек вызовов скрипта, а стек вызовов скриптового движка. - /// Эквивалентно функции Exception.ToString() в C#. - /// - /// Строка. - [ContextMethod("ПодробноеОписаниеОшибки", "DetailedDescription")] - public string GetDescription() - { - return _exc.ToString(); - } - - public override string ToString() - { - return Description; - } - - - [ScriptConstructor(Name = "С возможностью передачи параметров")] - public static ExceptionTemplate Create(IValue msg, IValue parameter) - { - return new ExceptionTemplate(msg.AsString(), parameter); - } - - } -} +/*---------------------------------------------------------- +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.Text; +using OneScript.Commons; +using OneScript.Contexts; +using OneScript.Exceptions; +using OneScript.Language; +using OneScript.Localization; +using OneScript.Types; +using ScriptEngine.Types; + +namespace ScriptEngine.Machine.Contexts +{ + /// + /// Класс позволяет узнать информацию о произошедшем исключении. + /// + [ContextClass("ИнформацияОбОшибке", "ErrorInfo", TypeUUID = "E0EDED59-D37A-42E7-9796-D6C061934B5D")] + public class ExceptionInfoContext : AutoContext + { + private static readonly TypeDescriptor ObjectType = typeof(ExceptionInfoContext).GetTypeFromClassMarkup(); + + private ScriptException _exc; + private IValue _innerException; + + public ExceptionInfoContext(ScriptException source) : base(ObjectType) + { + SetActualException(source); + } + + private ExceptionInfoContext(string message, IValue parameters) : base(ObjectType) + { + Description = message; + Parameters = parameters; + } + + public bool IsErrorTemplate => _exc == null; + + private void SetActualException(ScriptException exception) + { + _exc = exception ?? throw new ArgumentNullException(); + Description = _exc.ErrorDescription; + if (exception is ParametrizedRuntimeException pre) + { + Parameters = pre.Parameter; + } + } + + private ScriptException ActualException() + { + if (IsErrorTemplate) + { + throw new RuntimeException(BilingualString.Localize( + "Эта ИнформацияОбОшибке еще не была выброшена оператором ВызватьИсключение", + "This ErrorInfo is not have been thrown by Raise operator yet")); + } + + return _exc; + } + + /// + /// Значение, переданное при создании исключения в конструкторе объекта ИнформацияОбОшибке. + /// + [ContextProperty("Параметры", "Parameters", CanWrite = false)] + public IValue Parameters + { + get; + private set; + } + + /// + /// Содержит краткое описание ошибки. Эквивалент Exception.Message в C# + /// + [ContextProperty("Описание", "Description")] + public string Description { get; private set; } + + public string MessageWithoutCodeFragment => ActualException().MessageWithoutCodeFragment; + + public string GetDetailedDescription() + { + var exc = ActualException(); + var sb = new StringBuilder(exc.Message); + var inner = exc.InnerException; + while (inner != default) + { + sb.AppendLine(); + sb.AppendLine(Locale.NStr("ru = 'по причине:';en = 'caused by:'")); + sb.AppendLine(inner.Message); + inner = inner.InnerException; + } + + return sb.ToString(); + } + + /// + /// Имя модуля, вызвавшего исключение. + /// + [ContextProperty("ИмяМодуля", "ModuleName")] + public string ModuleName => ActualException().ModuleName ?? string.Empty; + + /// + /// Номер строки, вызвавшей исключение. + /// + [ContextProperty("НомерСтроки", "LineNumber")] + public int LineNumber => ActualException().LineNumber; + + /// + /// Строка исходного кода, вызвавшего исключение. + /// + [ContextProperty("ИсходнаяСтрока", "SourceLine")] + public string SourceLine => ActualException().Code ?? string.Empty; + + /// + /// Предоставляет доступ к стеку вызовов процедур. + /// Подробнее см. класс КоллекцияКадровСтекаВызовов + /// + /// + [ContextMethod("ПолучитьСтекВызовов", "GetStackTrace")] + public IValue GetStackTrace() + { + if (ActualException().RuntimeSpecificInfo is IList frames) + { + return new StackTraceCollectionContext(frames); + } + return ValueFactory.Create(); + } + + /// + /// Содержит вложенное исключение, если таковое было. Эквивалент Exception.InnerException в C# + /// + [ContextProperty("Причина", "Cause")] + public IValue InnerException + { + get + { + if (_innerException == null) + _innerException = CreateInnerExceptionInfo(); + + return _innerException; + } + } + + private IValue CreateInnerExceptionInfo() + { + var exc = ActualException(); + if (exc.InnerException == null) + return ValueFactory.Create(); + + var alreadyWrapped = ActualException() is ExternalSystemException; + if (!alreadyWrapped) + { + var inner = exc.InnerException as ScriptException ?? new ExternalSystemException(exc.InnerException); + inner.ModuleName ??= exc.ModuleName; + inner.Code ??= exc.Code; + return new ExceptionInfoContext(inner); + } + else + { + if (exc.InnerException.InnerException == null) + return ValueFactory.Create(); + + var inner = new ExternalSystemException(exc.InnerException.InnerException); + if (inner.LineNumber == ErrorPositionInfo.OUT_OF_TEXT) + { + inner.ModuleName = this.ModuleName; + inner.Code = this.SourceLine; + inner.LineNumber = this.LineNumber; + } + + return new ExceptionInfoContext(inner); + } + } + + /// + /// Содержит подробное описание исключения, включая стек вызовов среды исполнения CLR. + /// т.е. не стек вызовов скрипта, а стек вызовов скриптового движка. + /// Эквивалентно функции Exception.ToString() в C#. + /// + /// Строка. + [ContextMethod("ПодробноеОписаниеОшибки", "DetailedDescription")] + public string GetDescription() + { + return ActualException().ToString(); + } + + public override string ToString() + { + return Description; + } + + + [ScriptConstructor(Name = "С возможностью передачи параметров")] + public static ExceptionInfoContext Create(IValue msg, IValue parameter) + { + return new ExceptionInfoContext(msg.AsString(), parameter); + } + + public static ExceptionInfoContext EmptyExceptionInfo() + { + return new ExceptionInfoContext(EmptyScriptException.Instance); + } + + private class EmptyScriptException : ScriptException + { + public static EmptyScriptException Instance = new EmptyScriptException(); + private EmptyScriptException() : base("") + { + LineNumber = 0; + ColumnNumber = 0; + } + + public override string Message => ""; + + public override string ToString() => ""; + } + } +} diff --git a/src/ScriptEngine/Machine/Contexts/ExceptionTemplate.cs b/src/ScriptEngine/Machine/Contexts/ExceptionTemplate.cs deleted file mode 100644 index 484553d1b..000000000 --- a/src/ScriptEngine/Machine/Contexts/ExceptionTemplate.cs +++ /dev/null @@ -1,35 +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/. -----------------------------------------------------------*/ - -using OneScript.Contexts; -using OneScript.Types; -using ScriptEngine.Types; - -namespace ScriptEngine.Machine.Contexts -{ - /// - /// Служебный класс, создаваемый конструктором объекта "ИнформацияОбОшибке". - /// Превращается в полноценный объект ИнформацияОбОшибке в момент выброса исключения. - /// - /// Данный класс предназначен для создания параметризованных исключений. - /// - /// ВызватьИсключение Новый ИнформацияОбОшибке("Текст ошибки", ДополнительныеДанные); - [ContextClass("ИнформацияОбОшибкеШаблон", "ExceptionInfoTemplate", TypeUUID = "E0EDED59-D37A-42E7-9796-D6C061934B5D")] - public class ExceptionTemplate : ContextIValueImpl - { - private static readonly TypeDescriptor _objectType = typeof(ExceptionTemplate).GetTypeFromClassMarkup(); - - public string Message { get; private set; } - public IValue Parameter { get; private set; } - - public ExceptionTemplate(string msg, IValue parameter) : base(_objectType) - { - this.Message = msg; - this.Parameter = parameter; - } - } -} diff --git a/src/ScriptEngine/Machine/Contexts/ManagedCOMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/ManagedCOMWrapperContext.cs index 299b1e9da..b60cfd6b8 100644 --- a/src/ScriptEngine/Machine/Contexts/ManagedCOMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/ManagedCOMWrapperContext.cs @@ -11,8 +11,8 @@ This Source Code Form is subject to the terms of the using System.Diagnostics; using System.Linq; using System.Reflection; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/PropertyNameIndexAccessor.cs b/src/ScriptEngine/Machine/Contexts/PropertyNameIndexAccessor.cs index edd4f14cb..e5cf19a79 100644 --- a/src/ScriptEngine/Machine/Contexts/PropertyNameIndexAccessor.cs +++ b/src/ScriptEngine/Machine/Contexts/PropertyNameIndexAccessor.cs @@ -5,7 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; +using OneScript.Exceptions; using OneScript.Types; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs b/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs index ea5ec0df8..7f475506f 100644 --- a/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs +++ b/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs @@ -8,8 +8,8 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; namespace ScriptEngine.Machine.Contexts diff --git a/src/ScriptEngine/Machine/Contexts/ThisAwareScriptedObjectBase.cs b/src/ScriptEngine/Machine/Contexts/ThisAwareScriptedObjectBase.cs index 8c51f2267..de802eeed 100644 --- a/src/ScriptEngine/Machine/Contexts/ThisAwareScriptedObjectBase.cs +++ b/src/ScriptEngine/Machine/Contexts/ThisAwareScriptedObjectBase.cs @@ -6,7 +6,6 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using System.Collections.Generic; using OneScript.Commons; using OneScript.Compilation; using OneScript.Compilation.Binding; diff --git a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs index 2546f9892..058ed8715 100644 --- a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs @@ -9,18 +9,16 @@ This Source Code Form is subject to the terms of the using System.Collections; using System.Collections.Generic; using System.Linq; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Rcw; using OneScript.Values; -using ScriptEngine.Machine.Rcw; +using System.Reflection; namespace ScriptEngine.Machine.Contexts { public class UnmanagedCOMWrapperContext : COMWrapperContext, IDebugPresentationAcceptor { - private const uint E_DISP_MEMBERNOTFOUND = 0x80020003; - private readonly RcwMembersMetadataCollection _props; private readonly RcwMembersMetadataCollection _methods; private readonly bool _isCollection; @@ -158,11 +156,11 @@ public override void SetPropValue(int propNum, IValue newVal) } catch (System.MissingMemberException) { - throw OneScript.Commons.PropertyAccessException.PropNotFoundException(prop.Name); + throw PropertyAccessException.PropNotFoundException(prop.Name); } catch (System.MemberAccessException) { - throw OneScript.Commons.PropertyAccessException.PropIsNotWritableException(prop.Name); + throw PropertyAccessException.PropIsNotWritableException(prop.Name); } } @@ -196,7 +194,11 @@ public override void CallAsProcedure(int methodNumber, IValue[] arguments) { try { - DispatchUtility.Invoke(Instance, dispId, MarshalArguments(arguments)); + var argsData = MarshalArguments(arguments); + var initialValues = new object[argsData.values.Length]; + Array.Copy(argsData.values, initialValues, initialValues.Length); + DispatchUtility.Invoke(Instance, dispId, argsData.values, argsData.flags); + RemapOutputParams(arguments, argsData.values, argsData.flags[0], initialValues); } catch (System.Reflection.TargetInvocationException e) { @@ -222,7 +224,11 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV { try { - var result = DispatchUtility.Invoke(Instance, dispId, MarshalArguments(arguments)); + var argsData = MarshalArguments(arguments); + var initialValues = new object[argsData.values.Length]; + Array.Copy(argsData.values, initialValues, initialValues.Length); + var result = DispatchUtility.Invoke(Instance, dispId, argsData.values, argsData.flags); + RemapOutputParams(arguments, argsData.values, argsData.flags[0], initialValues); retValue = CreateIValue(result); } catch (System.Reflection.TargetInvocationException e) @@ -235,6 +241,19 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV throw RuntimeException.MethodNotFoundException(method.Name); } } + + private void RemapOutputParams(IValue[] arguments, object[] values, ParameterModifier flags, + object[] initialValues) + { + for (int i = 0; i < arguments.Length; i++) + { + if (flags[i] && !initialValues[i].Equals(values[i])) + { + var variable = (IVariable)arguments[i]; + variable.Value = CreateIValue(values[i]); + } + } + } private bool TryFindMethod(string name, out RcwMethodMetadata md) { diff --git a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs index e61dd271b..0d715d8cd 100644 --- a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs +++ b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs @@ -12,6 +12,7 @@ This Source Code Form is subject to the terms of the using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Execution; using OneScript.Types; using OneScript.Values; @@ -302,17 +303,25 @@ protected override string ConvertToString() void IDebugPresentationAcceptor.Accept(IDebugValueVisitor visitor) { - var thisId = GetPropertyNumber(THISOBJ_RU); - var total = GetPropCount(); - var props = new List(total); - for (int i = 0; i < total; i++) - { - if (i != thisId) - { - props.Add(Variable.Create(GetPropValue(i), GetPropName(i))); - } - } - + var instanceProps = Module + .Properties + .OfType() + .OrderBy(x => x.DispatchId) + .ToDictionary(x => x.Name, x => x.DispatchId); + + var instanceFields = Module + .Fields + .OfType() + .OrderBy(x => x.DispatchId) + .Where(x => !instanceProps.ContainsKey(x.Name)) + .ToDictionary(x => $"${x.Name}", x => x.DispatchId); + + var props = instanceProps + .Concat(instanceFields) + .Select(x => + Variable.Create(GetPropValue(x.Value), x.Key)) + .ToList(); + visitor.ShowCustom(props); } } diff --git a/src/ScriptEngine/Machine/DefaultTypeManager.cs b/src/ScriptEngine/Machine/DefaultTypeManager.cs index 34865ec74..3be4bd521 100644 --- a/src/ScriptEngine/Machine/DefaultTypeManager.cs +++ b/src/ScriptEngine/Machine/DefaultTypeManager.cs @@ -11,6 +11,7 @@ This Source Code Form is subject to the terms of the using System.Reflection; using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using ScriptEngine.Machine.Contexts; using ScriptEngine.Types; diff --git a/src/ScriptEngine/Machine/ExceptionInfoFactory.cs b/src/ScriptEngine/Machine/ExceptionInfoFactory.cs new file mode 100644 index 000000000..1afa05c39 --- /dev/null +++ b/src/ScriptEngine/Machine/ExceptionInfoFactory.cs @@ -0,0 +1,57 @@ +/*---------------------------------------------------------- +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 OneScript.Contexts; +using OneScript.Exceptions; +using OneScript.Language; +using OneScript.Values; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.Machine +{ + /// + /// Уровень косвенности между нативным рантаймом и ExceptionInfoContext, который тот не видит. + /// + public class ExceptionInfoFactory : IExceptionInfoFactory + { + public BslObjectValue GetExceptionInfo(Exception exception) + { + if (exception == null) + { + return ExceptionInfoContext.EmptyExceptionInfo(); + } + + if (exception is ScriptException script) + return new ExceptionInfoContext(script); + + return new ExceptionInfoContext(new ExternalSystemException(exception)); + } + + public string GetExceptionDescription(IRuntimeContextInstance exceptionInfo) + { + if (exceptionInfo == null) + { + return ""; + } + + var info = (ExceptionInfoContext)exceptionInfo; + return info.MessageWithoutCodeFragment; + } + + public Exception Raise(object raiseValue) + { + return raiseValue switch + { + ExceptionInfoContext { IsErrorTemplate: true } excInfo => + new ParametrizedRuntimeException(excInfo.Description, excInfo.Parameters), + BslValue bslVal => new RuntimeException(bslVal.AsString()), + _ => new RuntimeException(raiseValue.ToString()) + }; + } + } +} \ No newline at end of file diff --git a/src/ScriptEngine/Machine/IDebugController.cs b/src/ScriptEngine/Machine/IDebugController.cs index fae8a2812..e3801e3ac 100644 --- a/src/ScriptEngine/Machine/IDebugController.cs +++ b/src/ScriptEngine/Machine/IDebugController.cs @@ -27,5 +27,7 @@ public interface IBreakpointManager void SetLineStops(string module, int[] lines); bool Find(string module, int line); + + void Clear(); } } diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index fbc1d395f..966b8d9be 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -1,4 +1,4 @@ -/*---------------------------------------------------------- +/*---------------------------------------------------------- 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 @@ -15,6 +15,7 @@ This Source Code Form is subject to the terms of the using OneScript.Commons; using OneScript.Compilation.Binding; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Language; using OneScript.Sources; using OneScript.Types; @@ -42,6 +43,7 @@ public class MachineInstance // для отладчика. // актуален в момент останова машины private IList _fullCallstackCache; + private ScriptInformationContext _debugInfo; private MachineInstance() { @@ -50,20 +52,7 @@ private MachineInstance() } public event EventHandler MachineStopped; - - private class EmptyExceptionInfo : ScriptException - { - public EmptyExceptionInfo() : base("") - { - LineNumber = 0; - ColumnNumber = 0; - } - - public override string Message => ""; - public override string ToString() => ""; - } - public void AttachContext(IAttachableContext context) { _scopes.Add(CreateModuleScope(context)); @@ -107,6 +96,7 @@ public void SetMemory(ExecutionContext memory) ContextsAttached(); _mem = memory; + _codeStatCollector = _mem.Services.TryResolve(); } internal MachineStoredState SaveState() @@ -118,7 +108,6 @@ internal MachineStoredState SaveState() CallStack = _callStack, OperationStack = _operationStack, StopManager = _stopManager, - CodeStatCollector = _codeStatCollector, Memory = _mem }; } @@ -131,7 +120,6 @@ internal void RestoreState(MachineStoredState state) _callStack = state.CallStack; _exceptionsStack = state.ExceptionsStack; _stopManager = state.StopManager; - _codeStatCollector = state.CodeStatCollector; _mem = state.Memory; SetFrame(_callStack.Peek()); @@ -311,52 +299,88 @@ public void PrepareDebugContinuation() _stopManager.Continue(); } - public IValue Evaluate(string expression, bool separate = false) + public IValue Evaluate(string expression) { var code = CompileCached(expression, CompileExpressionModule); - MachineInstance runner; - MachineInstance currentMachine; - if (separate) + var localScope = new Scope + { + Instance = new UserScriptContextInstance(code), + Methods = new BslMethodInfo[0], + Variables = _currentFrame.Locals + }; + _scopes.Add(localScope); + + var frame = new ExecutionFrame + { + MethodName = code.Source.Name, + Module = code, + ModuleScope = localScope, + ModuleLoadIndex = _scopes.Count - 1, + Locals = new IVariable[0], + InstructionPointer = 0, + }; + + try { - runner = new MachineInstance(); - runner._mem = _mem; - runner._scopes = new List(_scopes); - currentMachine = Current; - SetCurrentMachineInstance(runner); + PushFrame(frame); + MainCommandLoop(); } - else + finally { - currentMachine = null; - runner = this; + PopFrame(); + _scopes.RemoveAt(_scopes.Count - 1); } - ExecutionFrame frame; + return _operationStack.Pop(); + } + + public IValue EvaluateInFrame(string expression, int frameId) + { + System.Diagnostics.Debug.Assert(_fullCallstackCache != null); + if (frameId < 0 || frameId >= _fullCallstackCache.Count) + throw new ScriptException("Wrong stackframe"); + + ExecutionFrame selectedFrame = _fullCallstackCache[frameId].FrameObject; + MachineInstance currentMachine; + MachineInstance runner = new MachineInstance + { + _mem = this._mem, + _scopes = new List(this._scopes.GetRange(0, selectedFrame.ModuleLoadIndex + 1)), + _debugInfo = CurrentScript + }; + currentMachine = Current; + SetCurrentMachineInstance(runner); + + runner.SetFrame(selectedFrame); + + ExecutionFrame frame; try { - var mlocals = new Scope(); - mlocals.Instance = new UserScriptContextInstance(code); - mlocals.Methods = TopScope.Methods; - mlocals.Variables = _currentFrame.Locals; - runner._scopes.Add(mlocals); + var code = runner.CompileExpressionModule(expression); + + var localScope = new Scope + { + Instance = new UserScriptContextInstance(code), + Methods = new BslMethodInfo[0], + Variables = selectedFrame.Locals + }; + runner._scopes.Add(localScope); frame = new ExecutionFrame { MethodName = code.Source.Name, + Module = code, + ModuleScope = localScope, + ModuleLoadIndex = runner._scopes.Count - 1, Locals = new IVariable[0], InstructionPointer = 0, - Module = code, - ModuleScope = mlocals, - ModuleLoadIndex = runner._scopes.Count - 1 }; } catch { - if (separate) - { - SetCurrentMachineInstance(currentMachine); - } + SetCurrentMachineInstance(currentMachine); throw; } @@ -367,18 +391,10 @@ public IValue Evaluate(string expression, bool separate = false) } finally { - if (!separate) - { - PopFrame(); - _scopes.RemoveAt(_scopes.Count - 1); - } - else - { - SetCurrentMachineInstance(currentMachine); - } + SetCurrentMachineInstance(currentMachine); } - return runner._operationStack.Pop(); + return runner._operationStack.Pop().GetRawValue(); } private StackRuntimeModule CompileCached(string code, Func compile) @@ -503,8 +519,7 @@ private void ExecuteCode() } catch (ScriptException exc) { - if(exc.LineNumber == ErrorPositionInfo.OUT_OF_TEXT) - SetScriptExceptionSource(exc); + SetScriptExceptionSource(exc); if (ShouldRethrowException(exc)) throw; @@ -555,11 +570,6 @@ private bool ShouldRethrowException(ScriptException exc) return false; } - public void SetCodeStatisticsCollector(ICodeStatCollector collector) - { - _codeStatCollector = collector; - } - private CodeStatEntry CurrentCodeEntry() { return new CodeStatEntry(CurrentScript?.Source, _currentFrame.MethodName, _currentFrame.LineNumber); @@ -598,14 +608,12 @@ private void MainCommandLoop() { throw; } - catch (ScriptException) + catch (ScriptException exc) { + exc.SetPositionIfEmpty(GetPositionInfo()); + throw; } - catch (BslCoreException exc) - { - throw new ScriptException(GetPositionInfo(), exc); - } catch (Exception exc) { var excWrapper = new ExternalSystemException(exc); @@ -633,10 +641,7 @@ private ErrorPositionInfo GetPositionInfo() private void SetScriptExceptionSource(ScriptException exc) { - var epi = GetPositionInfo(); - exc.Code = epi.Code; - exc.LineNumber = epi.LineNumber; - exc.ModuleName = epi.ModuleName; + exc.SetPositionIfEmpty(GetPositionInfo()); } #region Commands @@ -1143,7 +1148,7 @@ private void PrepareContextCallArguments(int arg, out IRuntimeContextInstance co var argValue = factArgs[i]; if (!argValue.IsSkippedArgument()) { - argValues[i] = argValue.GetRawValue(); + argValues[i] = argValue; } } } @@ -1163,7 +1168,9 @@ private void PrepareContextCallArguments(int arg, out IRuntimeContextInstance co if (!argValue.IsSkippedArgument()) { if (methodParams[i].IsByRef()) - argValues[i] = argValue; + { + argValues[i] = argValue is IVariable? argValue : Variable.Create(argValue, ""); + } else argValues[i] = argValue.GetRawValue(); } @@ -1378,9 +1385,9 @@ private void RaiseException(int arg) else { var exceptionValue = _operationStack.Pop().GetRawValue(); - if (exceptionValue is ExceptionTemplate excInfo) + if (exceptionValue is ExceptionInfoContext { IsErrorTemplate: true } excInfo) { - throw new ParametrizedRuntimeException(excInfo.Message, excInfo.Parameter); + throw new ParametrizedRuntimeException(excInfo.Description, excInfo.Parameters); } else { @@ -1452,13 +1459,19 @@ private void Execute(int arg) { var code = _operationStack.Pop().AsString(); var module = CompileCached(code, CompileExecutionBatchModule); - PrepareCodeStatisticsData(module); + if (module.Methods.Count() == 0) + { + NextInstruction(); + return; + } - var mlocals = new Scope(); - mlocals.Instance = new UserScriptContextInstance(module); - mlocals.Methods = TopScope.Methods; - mlocals.Variables = _currentFrame.Locals; - _scopes.Add(mlocals); + var localScope = new Scope + { + Instance = new UserScriptContextInstance(module), + Methods = new BslMethodInfo[0], + Variables = _currentFrame.Locals + }; + _scopes.Add(localScope); var mi = (MachineMethodInfo)module.Methods[0]; var method = mi.GetRuntimeMethod(); @@ -1466,7 +1479,7 @@ private void Execute(int arg) { Module = module, MethodName = mi.Name, - ModuleScope = mlocals, + ModuleScope = localScope, ModuleLoadIndex = _scopes.Count - 1, Locals = new IVariable[method.LocalVariables.Length], InstructionPointer = 0 @@ -1477,14 +1490,14 @@ private void Execute(int arg) locals[i] = Variable.Create(ValueFactory.Create(), method.LocalVariables[i]); } + PushFrame(frame); try { - PushFrame(frame); - MainCommandLoop(); + ExecuteCode(); + PopFrame(); } finally { - PopFrame(); _scopes.RemoveAt(_scopes.Count - 1); } @@ -2425,8 +2438,7 @@ private void ExceptionInfo(int arg) } else { - var noDataException = new EmptyExceptionInfo(); - _operationStack.Push(new ExceptionInfoContext(noDataException)); + _operationStack.Push(ExceptionInfoContext.EmptyExceptionInfo()); } NextInstruction(); } @@ -2447,14 +2459,21 @@ private void ExceptionDescr(int arg) private void ModuleInfo(int arg) { - var currentScript = this.CurrentScript; - if (currentScript != null) + if (_debugInfo != null) { - _operationStack.Push(currentScript); + _operationStack.Push(_debugInfo); } else { - _operationStack.Push(ValueFactory.Create()); + var currentScript = this.CurrentScript; + if (currentScript != null) + { + _operationStack.Push(currentScript); + } + else + { + _operationStack.Push(ValueFactory.Create()); + } } NextInstruction(); } @@ -2501,16 +2520,16 @@ private void NewFunc(int argCount) private StackRuntimeModule CompileExpressionModule(string expression) { var ctx = ExtractCompilerContext(); + var entryId = CurrentCodeEntry().ToString(); var stringSource = SourceCodeBuilder.Create() .FromString(expression) - .WithName("") + .WithName($"{entryId}:") .Build(); - + var compiler = _mem.Services.Resolve(); compiler.SharedSymbols = ctx; var module = (StackRuntimeModule)compiler.CompileExpression(stringSource); - return module; } @@ -2543,9 +2562,14 @@ private SymbolTable ExtractCompilerContext() } foreach (var variable in scope.Variables) { - // TODO тут возможна двуязычность у свойств (приаттаченых, как IVariable) - // пока костыль в виде одного имени - symbolScope.DefineVariable(new LocalVariableSymbol(variable.Name)); + if (variable.SystemType.Alias != null) + { + symbolScope.DefineVariable(new AliasedVariableSymbol(variable.Name, variable.SystemType.Alias)); + } + else + { + symbolScope.DefineVariable(new LocalVariableSymbol(variable.Name)); + } } ctx.PushScope(symbolScope, scope.Instance); diff --git a/src/ScriptEngine/Machine/ParametrizedRuntimeException.cs b/src/ScriptEngine/Machine/ParametrizedRuntimeException.cs index b80eee270..22f5e4e0b 100644 --- a/src/ScriptEngine/Machine/ParametrizedRuntimeException.cs +++ b/src/ScriptEngine/Machine/ParametrizedRuntimeException.cs @@ -5,7 +5,7 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using OneScript.Commons; +using OneScript.Exceptions; namespace ScriptEngine.Machine { diff --git a/src/ScriptEngine/Machine/RciHelperExtensions.cs b/src/ScriptEngine/Machine/RciHelperExtensions.cs index 871c70c84..d4943a4f3 100644 --- a/src/ScriptEngine/Machine/RciHelperExtensions.cs +++ b/src/ScriptEngine/Machine/RciHelperExtensions.cs @@ -7,8 +7,8 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; namespace ScriptEngine.Machine { diff --git a/src/ScriptEngine/Machine/RuntimeExceptions.cs b/src/ScriptEngine/Machine/RuntimeExceptions.cs index ff706ec96..20aea0343 100644 --- a/src/ScriptEngine/Machine/RuntimeExceptions.cs +++ b/src/ScriptEngine/Machine/RuntimeExceptions.cs @@ -1,69 +1,70 @@ -/*---------------------------------------------------------- -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 OneScript.Commons; - -namespace ScriptEngine.Machine -{ - public class WrongStackConditionException : ApplicationException - { - public WrongStackConditionException() - : base("Внутренняя ошибка: неверное состояние стека") - { - - } - } - - public class ValueMarshallingException : RuntimeException - { - public ValueMarshallingException() : this("Неклассифицированная ошибка маршаллинга значений") - { - } - - public ValueMarshallingException(string message) : base(message) - { - } - - public static ValueMarshallingException TypeNotSupported(Type type) - { - return new ValueMarshallingException(string.Format(Locale.NStr - ("ru='Возвращаемый тип {0} не поддерживается'; en='Return type {0} is not supported'"), type)); - } - - public static ValueMarshallingException InvalidEnum(Type type) - { - return new ValueMarshallingException(string.Format(Locale.NStr - ("ru = 'Некорректный тип конвертируемого перечисления: {0}'; en = 'Invalid enum return type: {0}'"), type)); - } - - public static ValueMarshallingException EnumWithNoAttribute(Type type) - { - return new ValueMarshallingException(string.Format(Locale.NStr - ("ru='Значение перечисления {0} должно быть помечено атрибутом EnumItemAttribute';" - + "en='An enumeration value {0} must be marked with the EnumItemAttribute attribute"), type)); - } - - public static ValueMarshallingException NoConversionToCLR(Type type) - { - return new ValueMarshallingException(string.Format(Locale.NStr - ("ru='Тип {0} не поддерживает преобразование в CLR-объект';" - +"en='Type {0} does not support conversion to CLR object'"), type)); - } - public static ValueMarshallingException InvalidNullValue() - { - return new ValueMarshallingException(Locale.NStr - ("ru = 'Значение не может быть null'; en = 'Value cannot be null'")); - } - - public static ValueMarshallingException InvalidNullIndex() - { - return new ValueMarshallingException(Locale.NStr - ("ru = 'Индекс не может быть null'; en = 'Index cannot be null'")); - } - - } -} +/*---------------------------------------------------------- +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 OneScript.Commons; +using OneScript.Exceptions; + +namespace ScriptEngine.Machine +{ + public class WrongStackConditionException : ApplicationException + { + public WrongStackConditionException() + : base("Внутренняя ошибка: неверное состояние стека") + { + + } + } + + public class ValueMarshallingException : RuntimeException + { + public ValueMarshallingException() : this("Неклассифицированная ошибка маршаллинга значений") + { + } + + public ValueMarshallingException(string message) : base(message) + { + } + + public static ValueMarshallingException TypeNotSupported(Type type) + { + return new ValueMarshallingException(string.Format(Locale.NStr + ("ru='Возвращаемый тип {0} не поддерживается'; en='Return type {0} is not supported'"), type)); + } + + public static ValueMarshallingException InvalidEnum(Type type) + { + return new ValueMarshallingException(string.Format(Locale.NStr + ("ru = 'Некорректный тип конвертируемого перечисления: {0}'; en = 'Invalid enum return type: {0}'"), type)); + } + + public static ValueMarshallingException EnumWithNoAttribute(Type type) + { + return new ValueMarshallingException(string.Format(Locale.NStr + ("ru='Значение перечисления {0} должно быть помечено атрибутом EnumItemAttribute';" + + "en='An enumeration value {0} must be marked with the EnumItemAttribute attribute"), type)); + } + + public static ValueMarshallingException NoConversionToCLR(Type type) + { + return new ValueMarshallingException(string.Format(Locale.NStr + ("ru='Тип {0} не поддерживает преобразование в CLR-объект';" + +"en='Type {0} does not support conversion to CLR object'"), type)); + } + public static ValueMarshallingException InvalidNullValue() + { + return new ValueMarshallingException(Locale.NStr + ("ru = 'Значение не может быть null'; en = 'Value cannot be null'")); + } + + public static ValueMarshallingException InvalidNullIndex() + { + return new ValueMarshallingException(Locale.NStr + ("ru = 'Индекс не может быть null'; en = 'Index cannot be null'")); + } + + } +} diff --git a/src/ScriptEngine/Machine/TypeFactory.cs b/src/ScriptEngine/Machine/TypeFactory.cs index 39e398bc4..b6c365068 100644 --- a/src/ScriptEngine/Machine/TypeFactory.cs +++ b/src/ScriptEngine/Machine/TypeFactory.cs @@ -12,8 +12,8 @@ This Source Code Form is subject to the terms of the using System.Linq; using System.Linq.Expressions; using OneScript.Types; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Types; using Refl = System.Reflection; diff --git a/src/ScriptEngine/Machine/ValueAdoptionExtensions.cs b/src/ScriptEngine/Machine/ValueAdoptionExtensions.cs index b53cc9ac5..6887efedf 100644 --- a/src/ScriptEngine/Machine/ValueAdoptionExtensions.cs +++ b/src/ScriptEngine/Machine/ValueAdoptionExtensions.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Values; using ScriptEngine.Machine.Contexts; diff --git a/src/ScriptEngine/Machine/ValueFactory.cs b/src/ScriptEngine/Machine/ValueFactory.cs index 81dea903e..86fc2e10a 100644 --- a/src/ScriptEngine/Machine/ValueFactory.cs +++ b/src/ScriptEngine/Machine/ValueFactory.cs @@ -6,8 +6,8 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; using System.Diagnostics; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; diff --git a/src/ScriptEngine/NullDependencyResolver.cs b/src/ScriptEngine/NullDependencyResolver.cs index b83c94ef5..5f2b205d1 100644 --- a/src/ScriptEngine/NullDependencyResolver.cs +++ b/src/ScriptEngine/NullDependencyResolver.cs @@ -12,9 +12,8 @@ namespace ScriptEngine // ReSharper disable once ClassNeverInstantiated.Global internal class NullDependencyResolver : IDependencyResolver { - public ExternalLibraryDef Resolve(SourceCode module, string libraryName) + public void Resolve(SourceCode module, string libraryName) { - return new ExternalLibraryDef(libraryName); } public void Initialize(ScriptingEngine engine) diff --git a/src/ScriptEngine/OneScriptCoreOptions.cs b/src/ScriptEngine/OneScriptCoreOptions.cs index d615bfe8c..222ef74a2 100644 --- a/src/ScriptEngine/OneScriptCoreOptions.cs +++ b/src/ScriptEngine/OneScriptCoreOptions.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Text; using OneScript.Commons; +using OneScript.Native.Compiler; using ScriptEngine.Hosting; namespace ScriptEngine @@ -18,22 +19,30 @@ public class OneScriptCoreOptions private const string FILE_READER_ENCODING = "encoding.script"; 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]; FileReaderEncoding = SetupEncoding(config[FILE_READER_ENCODING]); PreprocessorDefinitions = SetupDefinitions(config[PREPROCESSOR_DEFINITIONS_KEY]); + UseNativeAsDefaultRuntime = SetupDefaultRuntime(config[DEFAULT_RUNTIME_KEY]); } + public string SystemLanguage { get; } + + public Encoding FileReaderEncoding { get; } + + public bool UseNativeAsDefaultRuntime { get; } + public IEnumerable PreprocessorDefinitions { get; set; } - private IEnumerable SetupDefinitions(string s) + private static IEnumerable SetupDefinitions(string s) { - return s?.Split(',') ?? new string[0]; + return s?.Split(',') ?? Array.Empty(); } - private Encoding SetupEncoding(string openerEncoding) + private static Encoding SetupEncoding(string openerEncoding) { if (string.IsNullOrWhiteSpace(openerEncoding)) return Encoding.UTF8; @@ -43,9 +52,10 @@ private Encoding SetupEncoding(string openerEncoding) else return Encoding.GetEncoding(openerEncoding); } - - public string SystemLanguage { get; set; } - - public Encoding FileReaderEncoding { get; set; } + + private static bool SetupDefaultRuntime(string runtimeId) + { + return runtimeId == NativeRuntimeAnnotationHandler.NativeDirectiveName; + } } } \ No newline at end of file diff --git a/src/ScriptEngine/ScriptingEngine.cs b/src/ScriptEngine/ScriptingEngine.cs index 6dddaf100..3388bdf0a 100644 --- a/src/ScriptEngine/ScriptingEngine.cs +++ b/src/ScriptEngine/ScriptingEngine.cs @@ -1,4 +1,4 @@ -/*---------------------------------------------------------- +/*---------------------------------------------------------- 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 @@ -15,7 +15,6 @@ This Source Code Form is subject to the terms of the using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using ScriptEngine.Compiler; -using ScriptEngine.Hosting; namespace ScriptEngine { @@ -27,7 +26,7 @@ public class ScriptingEngine : IDisposable public ScriptingEngine(ITypeManager types, IGlobalsManager globals, RuntimeEnvironment env, - ConfigurationProviders configurationProviders, + OneScriptCoreOptions options, IServiceContainer services) { TypeManager = types; @@ -40,18 +39,11 @@ public ScriptingEngine(ITypeManager types, Services = services; ContextDiscoverer = new ContextDiscoverer(types, globals, services); DebugController = services.TryResolve(); - ApplyConfiguration(configurationProviders.CreateConfig()); + Loader.ReaderEncoding = options.FileReaderEncoding; } public IServiceContainer Services { get; } - private void ApplyConfiguration(KeyValueConfig config) - { - var options = new OneScriptCoreOptions(config); - - Loader.ReaderEncoding = options.FileReaderEncoding; - } - private ContextDiscoverer ContextDiscoverer { get; } public RuntimeEnvironment Environment { get; set; } @@ -91,7 +83,7 @@ public void AttachExternalAssembly(System.Reflection.Assembly asm) public void Initialize() { SetDefaultEnvironmentIfNeeded(); - + EnableCodeStatistics(); UpdateContexts(); _attachedScriptsFactory = new AttachedScriptsFactory(this); @@ -194,16 +186,20 @@ private set } } - public void SetCodeStatisticsCollector(ICodeStatCollector collector) + private void EnableCodeStatistics() { + var collector = Services.TryResolve(); + if (collector == default) + return; + ProduceExtraCode |= CodeGenerationFlags.CodeStatistics; - MachineInstance.Current.SetCodeStatisticsCollector(collector); } #region IDisposable Members public void Dispose() { + DebugController?.Dispose(); AttachedScriptsFactory.SetInstance(null); } diff --git a/src/TestApp/MainWindow.xaml.cs b/src/TestApp/MainWindow.xaml.cs index 6926006ec..ab3e80b53 100644 --- a/src/TestApp/MainWindow.xaml.cs +++ b/src/TestApp/MainWindow.xaml.cs @@ -136,6 +136,7 @@ private HostedScriptEngine CreateEngine() var builder = DefaultEngineBuilder .Create() .SetDefaultOptions() + .UseNativeRuntime() .SetupEnvironment(e => e.AddStandardLibrary()) .SetupConfiguration(x => { diff --git a/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs b/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs new file mode 100644 index 000000000..cbca74f67 --- /dev/null +++ b/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs @@ -0,0 +1,31 @@ +/*---------------------------------------------------------- +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 FluentAssertions; +using OneScript.StandardLibrary.Processes; +using Xunit; + +namespace OneScript.Core.Tests; + +public class ArgumentParserTests +{ + [Theory] + [InlineData("-c 'oscript -version'", "-c", "oscript -version")] + [InlineData("-c oscript -version", "-c", "oscript", "-version")] + [InlineData("-c '\"oscript\" -version'", "-c", "\"oscript\" -version")] + [InlineData("-c \"'oscript' -version\"", "-c", "'oscript' -version")] + [InlineData("'aaa\"", "aaa\"")] + [InlineData(" ")] + public void Should_Parse_Arguments(string input, params string[] expected) + { + var parser = new ArgumentsParser(input); + + var actual = parser.GetArguments(); + + actual.Should().Equal(expected); + } +} \ No newline at end of file diff --git a/src/Tests/OneScript.Core.Tests/NativeCompilerTest.cs b/src/Tests/OneScript.Core.Tests/NativeCompilerTest.cs index 26380b06c..caa492b65 100644 --- a/src/Tests/OneScript.Core.Tests/NativeCompilerTest.cs +++ b/src/Tests/OneScript.Core.Tests/NativeCompilerTest.cs @@ -10,9 +10,9 @@ This Source Code Form is subject to the terms of the using System.Linq; using System.Linq.Expressions; using FluentAssertions; -using Microsoft.VisualBasic; using OneScript.Compilation.Binding; using OneScript.DependencyInjection; +using OneScript.Exceptions; using OneScript.Native.Runtime; using OneScript.StandardLibrary; using OneScript.StandardLibrary.Collections; @@ -25,6 +25,7 @@ This Source Code Form is subject to the terms of the using OneScript.Values; using ScriptEngine.Hosting; using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; using ScriptEngine.Types; using Xunit; @@ -46,6 +47,7 @@ private CompiledBlock GetCompiler(ITypeManager tm) { var services = new TinyIocImplementation(); services.Register(tm); + services.Register(); return new CompiledBlock(services.CreateContainer()); } @@ -404,6 +406,23 @@ public void EqualityOperators_With_BslValue_On_Right(TypeDescriptor type) statements[0].NodeType.Should().Be(ExpressionType.Assign); statements[1].NodeType.Should().Be(ExpressionType.Assign); } + + [Fact] + public void ClrIntegers_Can_Be_Used_As_Bsl_Numbers() + { + var block = new CompiledBlock(default); + block.CodeBlock = + @"Равенство = (Найти(""123"",""2"") = 0); + Неравенство = (КодСимвола(""А"") <> 0)"; + + var statements = block.MakeExpression() + .Body + .As() + .Expressions; + + statements[0].NodeType.Should().Be(ExpressionType.Assign); + statements[1].NodeType.Should().Be(ExpressionType.Assign); + } public static IEnumerable TypesForTestEqualityOperators() { @@ -645,7 +664,9 @@ public void Can_Do_ForEachLoop() [Fact] public void Can_Do_TryExcept() { - var block = new CompiledBlock(default); + var services = new TinyIocImplementation(); + services.Register(); + var block = new CompiledBlock(services); block.Parameters.Insert("Ф", new BslTypeValue(BasicTypes.Number)); block.CodeBlock = "Попытка Если Ф = 1 Тогда Возврат 1; КонецЕсли;" + @@ -699,7 +720,7 @@ Если Массив[индекс] Тогда tm.RegisterClass(typeof(ArrayImpl)); var blockCompiler = new CompiledBlock(default); - var N = 5000; + var N = 50000; var arr = new ArrayImpl(); for (int i = 0; i < N; i++) { @@ -995,7 +1016,7 @@ public void ExceptionInfo_ReturnsUndefined_OutsideOfCatch() block.CodeBlock = "А = ИнформацияОбОшибке();"; var lambda = block.MakeExpression(); - lambda.Body.As().Expressions[0].Type.Should().Be(typeof(BslValue)); + lambda.Body.As().Expressions[0].Type.Should().BeAssignableTo(); } [Fact] @@ -1013,7 +1034,7 @@ public void ExceptionInfo_ReturnsClass_InCatch() tryBlock.Handlers.First().Body.As().Expressions[0].Type .Should() - .Be(typeof(ExceptionInfoClass)); + .Be(typeof(BslObjectValue)); } [Fact] @@ -1038,7 +1059,7 @@ public void LazyBoolAnd() { var tm = new DefaultTypeManager(); var objectType = tm.RegisterClass(typeof(StructureImpl)); - var block = GetCompiler(new DefaultTypeManager()); + var block = GetCompiler(tm); block.Parameters.Insert("Ф", new BslTypeValue(objectType)); block.CodeBlock = "Возврат Ложь И Ф;"; // Ф не должен быть вычислен @@ -1049,5 +1070,37 @@ public void LazyBoolAnd() ((bool)(BslBooleanValue)func.DynamicInvoke(new object[] { testData })).Should().Be(false); } + + [Fact] + public void TypeFuncValue_Is_BslTypeValue() + { + var tm = new DefaultTypeManager(); + var objectType = tm.RegisterClass(typeof(StructureImpl)); + var block = GetCompiler(tm); + block.CodeBlock = "Возврат Тип(\"Структура\");"; + + var lambda = block.MakeExpression(); + var func = lambda.Compile(); + + var testType = new BslTypeValue(objectType); + var result = func.DynamicInvoke(); + + result.Should().BeOfType().And.Be(testType); + } + + [Fact] + public void TypeOfFuncValue_Is_BslTypeValue() + { + var block = GetCompiler(new DefaultTypeManager()); + block.CodeBlock = "Возврат ТипЗнч(42);"; + + var lambda = block.MakeExpression(); + var func = lambda.Compile(); + + var testType = new BslTypeValue(BasicTypes.Number); + var result = func.DynamicInvoke(); + + result.Should().BeOfType().And.Be(testType); + } } } \ No newline at end of file diff --git a/src/Tests/OneScript.Core.Tests/ObsoleteMethodAttributeTest.cs b/src/Tests/OneScript.Core.Tests/ObsoleteMethodAttributeTest.cs index 995071a0b..2deae0ae4 100644 --- a/src/Tests/OneScript.Core.Tests/ObsoleteMethodAttributeTest.cs +++ b/src/Tests/OneScript.Core.Tests/ObsoleteMethodAttributeTest.cs @@ -9,7 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using FluentAssertions; using Moq; -using OneScript.Commons; +using OneScript.Exceptions; using ScriptEngine; using Xunit; diff --git a/src/Tests/OneScript.Core.Tests/TestUserScriptProperties.cs b/src/Tests/OneScript.Core.Tests/TestUserScriptProperties.cs index 1a00839c1..2a728ba1a 100644 --- a/src/Tests/OneScript.Core.Tests/TestUserScriptProperties.cs +++ b/src/Tests/OneScript.Core.Tests/TestUserScriptProperties.cs @@ -11,7 +11,6 @@ This Source Code Form is subject to the terms of the using OneScript.Values; using ScriptEngine.Hosting; using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; using Xunit; namespace OneScript.Core.Tests diff --git a/src/Tests/OneScript.Core.Tests/ValuesTest.cs b/src/Tests/OneScript.Core.Tests/ValuesTest.cs index 31cbf4c60..9aeca7058 100644 --- a/src/Tests/OneScript.Core.Tests/ValuesTest.cs +++ b/src/Tests/OneScript.Core.Tests/ValuesTest.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using FluentAssertions; using Moq; using OneScript.Commons; +using OneScript.Exceptions; using OneScript.StandardLibrary; using OneScript.Types; using OneScript.Values; diff --git a/src/Tests/OneScript.Dynamic.Tests/CompileHelper.cs b/src/Tests/OneScript.Dynamic.Tests/CompileHelper.cs index 585851b69..e1e3ab13b 100644 --- a/src/Tests/OneScript.Dynamic.Tests/CompileHelper.cs +++ b/src/Tests/OneScript.Dynamic.Tests/CompileHelper.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using OneScript.Commons; +using OneScript.Compilation; using OneScript.Compilation.Binding; using OneScript.DependencyInjection; using OneScript.Language; @@ -16,6 +17,7 @@ This Source Code Form is subject to the terms of the using OneScript.Language.SyntaxAnalysis.AstNodes; using OneScript.Native.Compiler; using OneScript.Sources; +using ScriptEngine.Hosting; namespace OneScript.Dynamic.Tests { @@ -33,7 +35,7 @@ public CompileHelper(IServiceContainer services) public CompileHelper() { - _services = default; + _services = new TinyIocImplementation(); } public IEnumerable Errors => _errors.Errors; @@ -79,7 +81,8 @@ private DefaultBslParser GetBslParser(string code) .CreateIterator(); _codeIndexer = lexer.Iterator.Source; - var parser = new DefaultBslParser(lexer, _errors, new PreprocessorHandlers()); + var providers = _services.ResolveEnumerable(); + var parser = new DefaultBslParser(lexer, _errors, new PreprocessorHandlers(providers)); return parser; } @@ -87,8 +90,15 @@ public DynamicModule Compile(SymbolTable scopes) { if (scopes.ScopeCount == 0) scopes.PushScope(new SymbolScope(), null); - var compiler = new ModuleCompiler(_errors, _services); + var compiler = new ModuleCompiler(_errors, _services, new DependencyResolverMock()); return compiler.Compile(_codeIndexer, _module, scopes); } + + private class DependencyResolverMock : ICompileTimeDependencyResolver + { + public void Resolve(SourceCode module, string libraryName) + { + } + } } } diff --git a/src/Tests/OneScript.Dynamic.Tests/CompilerTestBase.cs b/src/Tests/OneScript.Dynamic.Tests/CompilerTestBase.cs new file mode 100644 index 000000000..c7e1b6392 --- /dev/null +++ b/src/Tests/OneScript.Dynamic.Tests/CompilerTestBase.cs @@ -0,0 +1,34 @@ +/*---------------------------------------------------------- +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.Collections.Generic; +using OneScript.Compilation.Binding; +using OneScript.Language; +using OneScript.Native.Compiler; + +namespace OneScript.Dynamic.Tests; + +public class CompilerTestBase +{ + protected DynamicModule CreateModule(string code) + { + var helper = new CompileHelper(); + helper.ParseModule(code); + var result = helper.Compile(new SymbolTable()); + helper.ThrowOnErrors(); + return result; + } + + protected DynamicModule CreateModule(string code, List errors) + { + var helper = new CompileHelper(); + helper.ParseModule(code); + var result = helper.Compile(new SymbolTable()); + errors.AddRange(helper.Errors); + return result; + } +} \ No newline at end of file diff --git a/src/Tests/OneScript.Dynamic.Tests/Compiler_Api_Tests.cs b/src/Tests/OneScript.Dynamic.Tests/Compiler_Api_Tests.cs index 72e4df766..c44e603d2 100644 --- a/src/Tests/OneScript.Dynamic.Tests/Compiler_Api_Tests.cs +++ b/src/Tests/OneScript.Dynamic.Tests/Compiler_Api_Tests.cs @@ -7,15 +7,13 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using FluentAssertions; -using OneScript.Compilation.Binding; using OneScript.Language; using OneScript.Language.SyntaxAnalysis; -using OneScript.Native.Compiler; using Xunit; namespace OneScript.Dynamic.Tests { - public class Compiler_Api_Tests + public class Compiler_Api_Tests : CompilerTestBase { [Fact] public void CanCompile_Empty_Module() @@ -135,28 +133,64 @@ public void Test_Min_Max_Functions() errors.Should().BeEmpty(); } + + [Fact] + public void CanCompile_Func() + { + var code = @" + Функция Тест() + Возврат 123; + КонецФункции - private DynamicModule CreateModule(string code) + а = Тест();"; + + var errors = new List(); + CreateModule(code, errors); + + errors.Should().BeEmpty(); + } + + [Fact] + public void CanCompile_Proc_With_Return() { - var helper = new CompileHelper(); - helper.ParseModule(code); - return helper.Compile(new SymbolTable()); + var code = @" + Процедура Тест() + Возврат; + КонецПроцедуры + + Тест();"; + + var errors = new List(); + CreateModule(code, errors); + + errors.Should().BeEmpty(); } - private DynamicModule CreateModule(string code, List errors) + [Fact] + public void Detects_Proc_As_Func_Invoke() { - var helper = new CompileHelper(); - helper.ParseModule(code); - var result = helper.Compile(new SymbolTable()); - errors.AddRange(helper.Errors); - return result; + var code = @" + Процедура Тест() + + КонецПроцедуры + + a = Тест();"; + + var errors = new List(); + CreateModule(code, errors); + + errors.Should().HaveCount(1); + errors[0].ErrorId.Should().Be(nameof(LocalizedErrors.UseProcAsFunction)); } - private DynamicModule CreateModule(string code, SymbolTable scopes) + [Fact] + public void Test_Conversion_To_Boolean_For_Decimals_In_BooleanExpressions() { - var helper = new CompileHelper(); - helper.ParseBatch(code); - return helper.Compile(scopes); + var code = @" + Номер = 0; + Операнд = 2=2 И Номер+1;"; + + CreateModule(code); } } } \ No newline at end of file diff --git a/src/Tests/OneScript.Dynamic.Tests/DynamicOperationsTest.cs b/src/Tests/OneScript.Dynamic.Tests/DynamicOperationsTest.cs new file mode 100644 index 000000000..9fa15c9cd --- /dev/null +++ b/src/Tests/OneScript.Dynamic.Tests/DynamicOperationsTest.cs @@ -0,0 +1,47 @@ +/*---------------------------------------------------------- +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.Collections.Generic; +using FluentAssertions; +using OneScript.Exceptions; +using OneScript.Native.Runtime; +using OneScript.Values; +using Xunit; + +namespace OneScript.Dynamic.Tests; + +public class DynamicOperationsTest +{ + [Theory] + [MemberData(nameof(ArgsForEqualityOperators))] + public void DynamicEquality(BslValue left, BslValue right, bool expected) + { + var result = DynamicOperations.Equality(left, right); + result.Should().Be(expected); + } + + [Fact] + public void DynamicAdditionForNulls() + { + Assert.Throws(() => DynamicOperations.Add(null, null)); + } + + [Fact] + public void DynamicSubtractionForNulls() + { + Assert.Throws(() => DynamicOperations.Subtract(null, null)); + } + + public static IEnumerable ArgsForEqualityOperators() + { + yield return new object[] { BslBooleanValue.True, BslBooleanValue.True, true }; + yield return new object[] { BslBooleanValue.True, null, false }; + yield return new object[] { null, BslBooleanValue.True, false }; + yield return new object[] { BslBooleanValue.True, BslUndefinedValue.Instance, false }; + // TODO: расширить по мере возможности + } +} \ No newline at end of file diff --git a/src/Tests/OneScript.Dynamic.Tests/NativeSdoTests.cs b/src/Tests/OneScript.Dynamic.Tests/NativeSdoTests.cs index 3351057f0..91e859cf3 100644 --- a/src/Tests/OneScript.Dynamic.Tests/NativeSdoTests.cs +++ b/src/Tests/OneScript.Dynamic.Tests/NativeSdoTests.cs @@ -11,6 +11,8 @@ This Source Code Form is subject to the terms of the using OneScript.DependencyInjection; using OneScript.Execution; using OneScript.Language; +using OneScript.Language.LexicalAnalysis; +using OneScript.Language.SyntaxAnalysis; using OneScript.Native.Compiler; using OneScript.Native.Extensions; using OneScript.Native.Runtime; @@ -18,6 +20,7 @@ This Source Code Form is subject to the terms of the using OneScript.StandardLibrary; using OneScript.StandardLibrary.Collections; using OneScript.StandardLibrary.Collections.ValueTable; +using OneScript.StandardLibrary.Regex; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine; @@ -49,9 +52,28 @@ public NativeSdoTests() testServices.RegisterSingleton(); testServices.RegisterSingleton(); testServices.RegisterSingleton(); + testServices.RegisterEnumerable(); + testServices.Register(); testServices.UseImports(); } - + + // ReSharper disable once ClassNeverInstantiated.Local + private class EmptyDirectiveHandler : IDirectiveHandler + { + public void OnModuleEnter() + { + } + + public void OnModuleLeave() + { + } + + public bool HandleDirective(ref Lexem lastExtractedLexem, ILexer lexer) + { + return false; + } + } + [Fact] public void Test_Can_Instantiate_Sdo_With_NativeModule() { @@ -162,7 +184,6 @@ Процедура А() Экспорт [Fact] public void CanSelectNativeCompiler() { - testServices.Register(); testServices.UseNativeRuntime(); var code = @@ -378,6 +399,40 @@ Функция Тест(Условие) val1.AsNumber().Should().Be(1); } + [Fact] + public void Can_Instantiate_Native_Class_With_Args() + { + var code = @"#native + + Перем РегулярноеВыражение; + + Процедура ПриСозданииОбъекта(ТекстРегулярки) + РегулярноеВыражение = Новый РегулярноеВыражение(ТекстРегулярки); + КонецПроцедуры + + Функция НайтиСовпадения(Текст) Экспорт + + КоллекцияСовпадений = РегулярноеВыражение.НайтиСовпадения(Текст); + + Возврат КоллекцияСовпадений; + + КонецФункции"; + + var symbols = new SymbolTable(); + + testServices.UseNativeRuntime(); + var serviceContainer = testServices.CreateContainer(); + var discoverer = serviceContainer.Resolve(); + discoverer.DiscoverClasses(typeof(RegExpImpl).Assembly); + var module = CreateModule(code, serviceContainer, symbols); + + var sdo = new UserScriptContextInstance(module, + new TypeDescriptor(new Guid(), "TestClass", default, typeof(UserScriptContextInstance)), + new IValue[] { new RegExpImpl(".") }); + sdo.InitOwnData(); + sdo.Initialize(); + } + private DynamicModule CreateModule(string code) => CreateModule(code, testServices.CreateContainer(), new SymbolTable()); private DynamicModule CreateModule(string code, IServiceContainer services, SymbolTable symbols) diff --git a/src/Tests/OneScript.Language.Tests/TrieTests.cs b/src/Tests/OneScript.Language.Tests/TrieTests.cs index af81bc852..f6c137daa 100644 --- a/src/Tests/OneScript.Language.Tests/TrieTests.cs +++ b/src/Tests/OneScript.Language.Tests/TrieTests.cs @@ -35,5 +35,28 @@ public void Tokens() Assert.Equal(2, t.Get("ИначеЕсли")); Assert.Equal(1, t.Get("Иначе")); } + + [Fact] + public void IdentifiersTrie_Inclusive_Test_ContainsKey() + { + var t = new IdentifiersTrie(); + + t.Add("ЕслиИначе", true); + Assert.False(t.ContainsKey("Если")); + Assert.True(t.ContainsKey("ЕслиИначе")); + } + + [Fact] + public void IdentifiersTrie_Inclusive_Test_TryGetValue() + { + var t = new IdentifiersTrie(); + + t.Add("МетодОдин", 1); + t.Add("МетодОдинИДва", 2); + + var exist = t.TryGetValue("Метод", out _); + + Assert.False(exist); + } } } \ No newline at end of file diff --git a/src/VSCode.DebugAdapter/DebugSession.cs b/src/VSCode.DebugAdapter/DebugSession.cs index c78b7a0c5..ced5ff0e3 100644 --- a/src/VSCode.DebugAdapter/DebugSession.cs +++ b/src/VSCode.DebugAdapter/DebugSession.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.IO; +using Serilog; using VSCode.DebugAdapter; namespace VSCodeDebug @@ -180,6 +181,7 @@ public class Capabilities : ResponseBody { public bool supportsConditionalBreakpoints; public bool supportsEvaluateForHovers; public dynamic[] exceptionBreakpointFilters; + public bool supportTerminateDebuggee; } public class ErrorResponseBody : ResponseBody { @@ -449,7 +451,6 @@ public virtual void SetExceptionBreakpoints(Response response, dynamic arguments protected virtual void OnRequestError(Exception e) { - SessionLog.WriteLine(e.ToString()); } public abstract void SetBreakpoints(Response response, dynamic arguments); diff --git a/src/VSCode.DebugAdapter/DebugeeProcess.cs b/src/VSCode.DebugAdapter/DebugeeProcess.cs index 2a7e31bb6..e6071a512 100644 --- a/src/VSCode.DebugAdapter/DebugeeProcess.cs +++ b/src/VSCode.DebugAdapter/DebugeeProcess.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Linq; +using Serilog; using StackFrame = OneScript.DebugProtocol.StackFrame; namespace VSCode.DebugAdapter @@ -21,6 +22,7 @@ internal abstract class DebugeeProcess private bool _terminated; private bool _stdoutEOF; private bool _stderrEOF; + private bool _attachMode; private IDebuggerService _debugger; @@ -46,16 +48,28 @@ public void Start() psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; + psi.StandardErrorEncoding = DebuggerSettings.DebugModeEncoding; + psi.StandardOutputEncoding = DebuggerSettings.DebugModeEncoding; + _process.EnableRaisingEvents = true; _process.OutputDataReceived += Process_OutputDataReceived; _process.ErrorDataReceived += Process_ErrorDataReceived; _process.Exited += Process_Exited; - + _attachMode = false; _process.Start(); System.Threading.Thread.Sleep(1500); _process.BeginOutputReadLine(); _process.BeginErrorReadLine(); } + + public void InitAttached() + { + var pid = _debugger.GetProcessId(); + _process = Process.GetProcessById(pid); + _attachMode = true; + _process.EnableRaisingEvents = true; + _process.Exited += Process_Exited; + } public void Init(JObject args) { @@ -136,14 +150,30 @@ private void Terminate() } } - public void Kill() + public void HandleDisconnect(bool terminate) { - if (_process != null && !_process.HasExited) + if (_debugger == null) + { + Log.Debug("Debugger is not connected. Nothing to disconnect"); + return; + } + _debugger.Disconnect(terminate); + + var mustKill = terminate || !_attachMode; + + if (mustKill && _process != null && !_process.HasExited) { - _process.Kill(); + if (!_process.WaitForExit(2000)) + _process.Kill(); } } + public void Kill() + { + _process.Kill(); + _process.WaitForExit(1500); + } + public Breakpoint[] SetBreakpoints(IEnumerable breakpoints) { var confirmedBreaks = _debugger.SetMachineBreakpoints(breakpoints.ToArray()); @@ -213,13 +243,5 @@ public int[] GetThreads() { return _debugger.GetThreads(); } - - public void InitAttached() - { - var pid = _debugger.GetProcessId(); - _process = Process.GetProcessById(pid); - _process.EnableRaisingEvents = true; - _process.Exited += Process_Exited; - } } } diff --git a/src/VSCode.DebugAdapter/OscriptDebugSession.cs b/src/VSCode.DebugAdapter/OscriptDebugSession.cs index 3ab3db32e..7cc50e153 100644 --- a/src/VSCode.DebugAdapter/OscriptDebugSession.cs +++ b/src/VSCode.DebugAdapter/OscriptDebugSession.cs @@ -7,7 +7,10 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; +using Newtonsoft.Json; using OneScript.DebugProtocol; +using Serilog; using VSCodeDebug; @@ -19,6 +22,8 @@ internal class OscriptDebugSession : DebugSession, IDebugEventListener private bool _startupPerformed = false; private readonly Handles _framesHandles; private readonly Handles _variableHandles; + + private static readonly ILogger Log = Serilog.Log.ForContext(); public OscriptDebugSession() : base(true, false) { @@ -30,18 +35,19 @@ public OscriptDebugSession() : base(true, false) public override void Initialize(Response response, dynamic args) { - SessionLog.WriteLine("Initialize:" + args); + LogCommandReceived(); AdapterID = (string) args.adapterID; _process = DebugeeFactory.CreateProcess(AdapterID, PathStrategy); - SendResponse(response, new Capabilities() + SendResponse(response, new Capabilities { supportsConditionalBreakpoints = false, supportsFunctionBreakpoints = false, supportsConfigurationDoneRequest = true, exceptionBreakpointFilters = new dynamic[0], - supportsEvaluateForHovers = true + supportsEvaluateForHovers = true, + supportTerminateDebuggee = true }); SendEvent(new InitializedEvent()); @@ -49,38 +55,38 @@ public override void Initialize(Response response, dynamic args) public override void Launch(Response response, dynamic args) { - SessionLog.WriteLine("Launch command accepted"); - + LogCommandReceived(); try { _process.Init(args); } catch (InvalidDebugeeOptionsException e) { + Log.Error(e, "Wrong options received {ErrorCode}: {Message}", e.ErrorCode, e.Message); SendErrorResponse(response, e.ErrorCode, e.Message); return; } _process.OutputReceived += (s, e) => { - SessionLog.WriteLine("output received: " + e.Content); + Log.Debug("Output received {Output}", e.Content); SendOutput(e.Category, e.Content); }; _process.ProcessExited += (s, e) => { - SessionLog.WriteLine("_process exited"); + Log.Information("Debuggee has exited"); SendEvent(new TerminatedEvent()); }; try { _process.Start(); - SessionLog.WriteLine("Debuggee started"); + Log.Information("Debuggee started"); } catch (Exception e) { - SessionLog.WriteLine(e.ToString()); + Log.Error(e, "Can't launch debuggee"); SendErrorResponse(response, 3012, "Can't launch debugee ({reason}).", new { reason = e.Message }); return; } @@ -88,7 +94,7 @@ public override void Launch(Response response, dynamic args) try { IDebuggerService service; - var tcpConnector = new TcpDebugConnector(_process.DebugPort, this); + var tcpConnector = new TcpDebugServerClient(_process.DebugPort, this); tcpConnector.Connect(); service = tcpConnector; @@ -97,8 +103,8 @@ public override void Launch(Response response, dynamic args) catch (Exception e) { _process.Kill(); - _process = null; - SessionLog.WriteLine(e.ToString()); + SendEvent(new TerminatedEvent()); + Log.Error(e, "Can't connect to debug server"); SendErrorResponse(response, 4550, "Can't connect: " + e.ToString()); return; } @@ -109,20 +115,20 @@ public override void Launch(Response response, dynamic args) public override void Attach(Response response, dynamic arguments) { - SessionLog.WriteLine("Attach command received"); + LogCommandReceived(); _process.DebugPort = getInt(arguments, "debugPort", 2801); _process.ProcessExited += (s, e) => { - SessionLog.WriteLine("_process exited"); + Log.Information("Debuggee has exited"); SendEvent(new TerminatedEvent()); }; try { IDebuggerService service; - var tcpConnector = new TcpDebugConnector(_process.DebugPort, this); + var tcpConnector = new TcpDebugServerClient(_process.DebugPort, this); tcpConnector.Connect(); - SessionLog.WriteLine($"Connected to host on port {_process.DebugPort}"); + Log.Debug("Connected to debuggee on port {Port}", _process.DebugPort); service = tcpConnector; _process.SetConnection(service); @@ -130,7 +136,7 @@ public override void Attach(Response response, dynamic arguments) } catch (Exception e) { - SessionLog.WriteLine(e.ToString()); + Log.Error(e, "Can't connect debuggee"); SendErrorResponse(response, 4550, "Can't connect: " + e.ToString()); return; } @@ -140,14 +146,18 @@ public override void Attach(Response response, dynamic arguments) public override void Disconnect(Response response, dynamic arguments) { - _process.Kill(); + LogCommandReceived(arguments); + bool terminateDebuggee = arguments.terminateDebuggee == true; + + _process.HandleDisconnect(terminateDebuggee); SendResponse(response); } public override void SetBreakpoints(Response response, dynamic arguments) { - SessionLog.WriteLine($"Set breakpoints command accepted {arguments}"); - + LogCommandReceived(); + Log.Debug("Breakpoints: {Data}", JsonConvert.SerializeObject(arguments)); + if ((bool)arguments.sourceModified) { if (_startupPerformed) @@ -207,7 +217,7 @@ private string NormalizeDriveLetter(string path) public void ThreadStopped(int threadId, ThreadStopReason reason) { - SessionLog.WriteLine("thread stopped"); + LogEventOccured(); _framesHandles.Reset(); _variableHandles.Reset(); SendEvent(new StoppedEvent(threadId, reason.ToString())); @@ -215,7 +225,7 @@ public void ThreadStopped(int threadId, ThreadStopReason reason) public void ProcessExited(int exitCode) { - SessionLog.WriteLine("Exited event recieved"); + LogEventOccured(); SendEvent(new ExitedEvent(exitCode)); } @@ -223,11 +233,11 @@ public override void ConfigurationDone(Response response, dynamic args) { if (_process == null) { - SessionLog.WriteLine("Config Done. Process is not started"); + Log.Debug("Config Done. Process is not started"); SendResponse(response); return; } - SessionLog.WriteLine("Config Done. Process is started"); + Log.Debug("Config Done. Process is started, sending Execute"); _process.BeginExecution(-1); _startupPerformed = true; SendResponse(response); @@ -235,12 +245,14 @@ public override void ConfigurationDone(Response response, dynamic args) public override void Continue(Response response, dynamic arguments) { + LogCommandReceived(); SendResponse(response); _process.BeginExecution(-1); } public override void Next(Response response, dynamic arguments) { + LogCommandReceived(); SendResponse(response); lock (_process) { @@ -254,6 +266,7 @@ public override void Next(Response response, dynamic arguments) public override void StepIn(Response response, dynamic arguments) { + LogCommandReceived(); SendResponse(response); lock (_process) { @@ -266,6 +279,7 @@ public override void StepIn(Response response, dynamic arguments) public override void StepOut(Response response, dynamic arguments) { + LogCommandReceived(); SendResponse(response); lock (_process) { @@ -278,13 +292,13 @@ public override void StepOut(Response response, dynamic arguments) public override void Pause(Response response, dynamic arguments) { + LogCommandReceived(); throw new NotImplementedException(); } public override void StackTrace(Response response, dynamic arguments) { - SessionLog.WriteLine("Stacktrace request accepted"); - SessionLog.WriteLine(arguments.ToString()); + LogCommandReceived(); var firstFrameIdx = (int?)arguments.startFrame ?? 0; var limit = (int?) arguments.levels ?? 0; var threadId = (int) arguments.threadId; @@ -304,6 +318,7 @@ public override void StackTrace(Response response, dynamic arguments) public override void Scopes(Response response, dynamic arguments) { + LogCommandReceived(); int frameId = getInt(arguments, "frameId"); var frame = _framesHandles.Get(frameId, null); if (frame == null) @@ -315,13 +330,12 @@ public override void Scopes(Response response, dynamic arguments) var frameVariablesHandle = _variableHandles.Create(frame); var localScope = new Scope("Локальные переменные", frameVariablesHandle); SendResponse(response, new ScopesResponseBody(new Scope[] {localScope})); - SessionLog.WriteLine("Scopes done"); } public override void Variables(Response response, dynamic arguments) { + LogCommandReceived(); int varsHandle = getInt(arguments, "variablesReference"); - SessionLog.WriteLine($"variables request {varsHandle}"); var variables = _variableHandles.Get(varsHandle, null); if (variables == null) { @@ -354,8 +368,8 @@ public override void Variables(Response response, dynamic arguments) public override void Threads(Response response, dynamic arguments) { + LogCommandReceived(); var threads = new List(); - SessionLog.WriteLine("Threads request accepted"); var processThreads = _process.GetThreads(); for (int i = 0; i < processThreads.Length; i++) { @@ -363,11 +377,11 @@ public override void Threads(Response response, dynamic arguments) } SendResponse(response, new ThreadsResponseBody(threads)); - SessionLog.WriteLine("Threads processed"); } public override void Evaluate(Response response, dynamic arguments) { + LogCommandReceived(); // expression, frameId, context int frameId = getInt(arguments, "frameId"); var frame = _framesHandles.Get(frameId, null); @@ -379,6 +393,8 @@ public override void Evaluate(Response response, dynamic arguments) var expression = (string) arguments.expression; var context = (string) arguments.context; + + Log.Debug("Evaluate {Expression} in {Context}", expression, context); int id = -1; OneScript.DebugProtocol.Variable evalResult; @@ -388,7 +404,7 @@ public override void Evaluate(Response response, dynamic arguments) if (evalResult.IsStructured) { - var loc = new EvaluatedVariableLocator(expression, frame.ThreadId, frameId); + var loc = new EvaluatedVariableLocator(expression, frame.ThreadId, frame.Index); id = _variableHandles.Create(loc); } } @@ -432,12 +448,22 @@ private static int getInt(dynamic container, string propertyName, int dflt = 0) return dflt; } - - private void RequestDummy(string message, Response response, dynamic arguments) + protected override void OnRequestError(Exception e) { - SessionLog.WriteLine(message); - SendResponse(response, arguments); + Log.Error(e, "Unhandled request processing error"); } + private void LogCommandReceived(dynamic args = null, [CallerMemberName] string commandName = "") + { + if (args == null) + Log.Debug("Command received {Command}", commandName); + else + Log.Debug("Command received {Command}: {Args}", commandName, JsonConvert.SerializeObject(args)); + } + + private void LogEventOccured([CallerMemberName] string eventName = "") + { + Log.Debug("Event occured {Event}", eventName); + } } } diff --git a/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/RpcProcessor.cs b/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/RpcProcessor.cs index a1e20d51f..ffe0e8333 100644 --- a/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/RpcProcessor.cs +++ b/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/RpcProcessor.cs @@ -11,6 +11,7 @@ This Source Code Form is subject to the terms of the using OneScript.DebugProtocol; using OneScript.DebugProtocol.Abstractions; using OneScript.DebugProtocol.TcpServer; +using Serilog; namespace VSCode.DebugAdapter { @@ -21,6 +22,8 @@ public class RpcProcessor private readonly Queue _responses = new Queue(); private readonly AutoResetEvent _responseAvailable = new AutoResetEvent(false); + private static readonly ILogger Log = Serilog.Log.ForContext(); + private struct ChannelRecord { public IMethodsDispatcher Dispatcher; @@ -46,14 +49,14 @@ public void Stop() private void ServerOnDataReceived(object sender, CommunicationEventArgs e) { - SessionLog.WriteLine("Data received " + e.Data); if (e.Exception == null) { + Log.Debug("Data received {@Data}", (TcpProtocolDtoBase)e.Data); DispatchMessage((TcpProtocolDtoBase)e.Data, e.Channel); } else { - SessionLog.WriteLine("RPC Exception " + e.Exception + " critical: " + e.Exception.StopChannel); + Log.Error(e.Exception, "RPC Exception received. Critical: {Critical}", e.Exception.StopChannel); if (e.Exception.StopChannel) { Stop(); @@ -65,23 +68,24 @@ private void DispatchMessage(TcpProtocolDtoBase data, ICommunicationChannel resp { if (!_dispatchers.TryGetValue(data.ServiceName, out var serviceRecord)) { - SessionLog.WriteLine("No dispatcher for " + data.ServiceName); + Log.Warning("No dispatcher for {ServiceName}", data.ServiceName); return; } if (data is RpcCall rpcCall) { - SessionLog.WriteLine("Processing call to " + rpcCall.Id); + Log.Debug("Processing call to {Id}", rpcCall.Id); var result = serviceRecord.Dispatcher.Dispatch(serviceRecord.ServiceInstance, rpcCall.Id, rpcCall.Parameters); if (result != null) { var callResult = RpcCallResult.Respond(rpcCall, result); + Log.Debug("Sending response {Result}", callResult.ReturnValue); responseChannel.Write(callResult); } } else if(data is RpcCallResult result) { - SessionLog.WriteLine("Saving response to " + result.Id); + Log.Debug("Enque response to {Id}. Value {Value}", result.Id, result.ReturnValue); lock (_responses) { _responses.Enqueue(result); diff --git a/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugConnector.cs b/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugServerClient.cs similarity index 84% rename from src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugConnector.cs rename to src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugServerClient.cs index 4f4c6d9d6..3953079de 100644 --- a/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugConnector.cs +++ b/src/VSCode.DebugAdapter/OscriptProtocols/Tcp/TcpDebugServerClient.cs @@ -12,17 +12,20 @@ This Source Code Form is subject to the terms of the using OneScript.DebugProtocol; using OneScript.DebugProtocol.Abstractions; using OneScript.DebugProtocol.TcpServer; +using Serilog; namespace VSCode.DebugAdapter { - public class TcpDebugConnector : IDebuggerService + public class TcpDebugServerClient : IDebuggerService { private readonly int _port; private readonly IDebugEventListener _eventBackChannel; private BinaryChannel _commandsChannel; private RpcProcessor _processor; + + private static readonly ILogger Log = Serilog.Log.ForContext(); - public TcpDebugConnector(int port, IDebugEventListener eventBackChannel) + public TcpDebugServerClient(int port, IDebugEventListener eventBackChannel) { _port = port; _eventBackChannel = eventBackChannel; @@ -32,13 +35,11 @@ public void Connect() { var debuggerUri = GetDebuggerUri(_port); - SessionLog.WriteLine("Creating commands tcp channel"); - var client = new TcpClient(); TryConnect(client, debuggerUri); _commandsChannel = new BinaryChannel(client); - SessionLog.WriteLine("connected"); + Log.Debug("Connected to {Host}:{Port}", debuggerUri.Host, debuggerUri.Port); RunEventsListener(_commandsChannel); } @@ -69,7 +70,7 @@ private static void TryConnect(TcpClient client, Uri debuggerUri) if (i == limit - 1) throw; - SessionLog.WriteLine("Error. Retry connect"); + Log.Warning("Error. Retry connect {Attempt}", i); Thread.Sleep(1500); } } @@ -95,26 +96,28 @@ private void RunEventsListener(ICommunicationChannel channelToListen) private void WriteCommand(T data, [CallerMemberName] string command = "") { - SessionLog.WriteLine($"Sending {command} to debuggee"); + Log.Verbose("Sending {Command} to debuggee, param {Parameter}", command, data); var dto = RpcCall.Create(nameof(IDebuggerService), command, data); _commandsChannel.Write(dto); + Log.Verbose("Successfully written: {Command}", command); } private void WriteCommand(object[] data, [CallerMemberName] string command = "") { - SessionLog.WriteLine($"Sending {command} to debuggee"); + Log.Verbose("Sending {Command} to debuggee, params {Parameters}", command, data); var dto = RpcCall.Create(nameof(IDebuggerService), command, data); _commandsChannel.Write(dto); + Log.Verbose("Successfully written: {Command}", command); } private T GetResponse() { var rpcResult = _processor.GetResult(); - SessionLog.WriteLine("Response received " + rpcResult.Id + " t = " + rpcResult.ReturnValue); + Log.Verbose("Response received {Result} = {Value}", rpcResult.Id, rpcResult.ReturnValue); if (rpcResult.ReturnValue is RpcExceptionDto excDto) { - SessionLog.WriteLine($"Exception received: {excDto.Description}"); + Log.Verbose("RPC Exception received: {Description}", excDto.Description); throw new RpcOperationException(excDto); } @@ -190,6 +193,11 @@ public void StepOut(int threadId) WriteCommand(threadId); } + public void Disconnect(bool terminate) + { + WriteCommand(terminate); + } + public int[] GetThreads() { WriteCommand(null); diff --git a/src/VSCode.DebugAdapter/Program.cs b/src/VSCode.DebugAdapter/Program.cs index 41fe253c7..c3a621604 100644 --- a/src/VSCode.DebugAdapter/Program.cs +++ b/src/VSCode.DebugAdapter/Program.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Net; using System.Net.Sockets; +using Serilog; namespace VSCode.DebugAdapter { @@ -15,81 +16,30 @@ class Program { static void Main(string[] args) { - bool showTrace = false; - - foreach (var argument in args) - { - switch (argument) - { - case "-trace": - showTrace = true; - break; - } - } - - AppDomain currentDomain = AppDomain.CurrentDomain; - currentDomain.UnhandledException += (s, e) => - { - SessionLog.WriteLine(e.ExceptionObject.ToString()); - }; - - StartSession(showTrace, Console.OpenStandardInput(), Console.OpenStandardOutput()); + StartSession(Console.OpenStandardInput(), Console.OpenStandardOutput()); } - private static void StartSession(bool showTrace, Stream input, Stream output) + private static void StartSession(Stream input, Stream output) { var session = new OscriptDebugSession(); - session.TRACE = showTrace; - session.TRACE_RESPONSE = showTrace; - SessionLog.Open(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "/debug.log"); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.AppSettings() + .Enrich.FromLogContext() + .CreateLogger(); + try { session.Start(input, output); } catch (Exception e) { - SessionLog.WriteLine(e.ToString()); + Log.Fatal(e, "Exception on session start"); } finally { - SessionLog.Close(); + Log.CloseAndFlush(); } } - - -#if DEBUG - private static void RunServer(int port) - { - TcpListener serverSocket = new TcpListener(IPAddress.Parse("127.0.0.1"), port); - serverSocket.Start(); - - new System.Threading.Thread(() => { - while (true) - { - var clientSocket = serverSocket.AcceptSocket(); - if (clientSocket != null) - { - Console.Error.WriteLine(">> accepted connection from client"); - - new System.Threading.Thread(() => { - using (var networkStream = new NetworkStream(clientSocket)) - { - try - { - StartSession(true, networkStream, networkStream); - } - catch (Exception e) - { - Console.Error.WriteLine("Exception: " + e); - } - } - clientSocket.Close(); - Console.Error.WriteLine(">> client connection closed"); - }).Start(); - } - } - }).Start(); - } -#endif } } diff --git a/src/VSCode.DebugAdapter/Protocol.cs b/src/VSCode.DebugAdapter/Protocol.cs index 8c1f0c497..fad6cd03b 100644 --- a/src/VSCode.DebugAdapter/Protocol.cs +++ b/src/VSCode.DebugAdapter/Protocol.cs @@ -13,6 +13,7 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Text.RegularExpressions; using Newtonsoft.Json; +using Serilog; namespace VSCodeDebug { @@ -93,31 +94,22 @@ public Event(string type, dynamic bdy = null) : base("event") { */ public abstract class ProtocolServer { - public bool TRACE; - public bool TRACE_RESPONSE; - protected const int BUFFER_SIZE = 4096; protected const string TWO_CRLF = "\r\n\r\n"; protected static readonly Regex CONTENT_LENGTH_MATCHER = new Regex(@"Content-Length: (\d+)"); protected static readonly Encoding Encoding = System.Text.Encoding.UTF8; - private int _sequenceNumber; + private int _sequenceNumber = 1; private Stream _outputStream; - private ByteBuffer _rawData; - private int _bodyLength; + private ByteBuffer _rawData = new ByteBuffer(); + private int _bodyLength = -1; private bool _stopRequested; - public ProtocolServer() { - _sequenceNumber = 1; - _bodyLength = -1; - _rawData = new ByteBuffer(); - } - public void Start(Stream inputStream, Stream outputStream) { _outputStream = outputStream; @@ -190,9 +182,8 @@ private void Dispatch(string req) { var request = JsonConvert.DeserializeObject(req); if (request != null && request.type == "request") { - if (TRACE) - Console.Error.WriteLine(string.Format("C {0}: {1}", request.command, JsonConvert.SerializeObject(request.arguments))); - + Log.Verbose("Got {Command} with args {Args}", request.command, JsonConvert.SerializeObject(request.arguments)); + var response = new Response(request); DispatchRequest(request.command, request.arguments, response); @@ -205,12 +196,12 @@ protected void SendMessage(ProtocolMessage message) { message.seq = _sequenceNumber++; - if (TRACE_RESPONSE && message.type == "response") { - Console.Error.WriteLine(string.Format(" R: {0}", JsonConvert.SerializeObject(message))); + if (message.type == "response") { + Log.Verbose("Response {Response}", JsonConvert.SerializeObject(message)); } - if (TRACE && message.type == "event") { + if (message.type == "event") { Event e = (Event)message; - Console.Error.WriteLine(string.Format("E {0}: {1}", e.eventType, JsonConvert.SerializeObject(e.body))); + Log.Verbose("Event {EventType} with args {Args}", e.eventType, JsonConvert.SerializeObject(e.body)); } var data = ConvertToBytes(message); diff --git a/src/VSCode.DebugAdapter/README.md b/src/VSCode.DebugAdapter/README.md index 4e2c3743c..0c3805040 100644 --- a/src/VSCode.DebugAdapter/README.md +++ b/src/VSCode.DebugAdapter/README.md @@ -14,4 +14,48 @@ ### Подробное описание каждого параметра выводится при наведении мышки на опцию в файле launch.json. -При возникновении вопросов напишите обращение на https://github.com/EvilBeaver/OneScript/issues. Мы обязательно вам поможем. \ No newline at end of file +При возникновении вопросов напишите обращение на https://github.com/EvilBeaver/OneScript/issues. Мы обязательно вам поможем. + +## Примеры конфигураций запуска + +### Запуск 1Script, файл my-program.os с передачей аргументов командной строки и установкой переменных окружения + +```json +{ + "name": "Отладка 1Script", + "type": "oscript", + "request": "launch", + "cwd": "${workspaceRoot}/src", + "program": "my-program.os", + "args": ["arg1", "arg2"], + "env": { + "OSCRIPT_CONFIG": "lib.system=D:/myOsLibraries", + "JAVA_HOME": "D:/MyJava/JDK_29_Full" + }, + "debugPort": 5051 +} +``` + +### Запуск сервера 1Script.Web, установленного по пути e:/osweb на порту 5051 + +```json +{ + "name": "Отладка 1Script.Web", + "type": "oscript.web", + "request": "launch", + "appDir": "${workspaceRoot}/src", + "runtimeExecutable": "e:/osweb/OneScript.WebHost.exe", + "debugPort": 5051 +} +``` + +### Подключение к работающему процессу 1Script.Web на порту 5051 + +```json +{ + "name": "Отладка 1Script.Web (attach)", + "type": "oscript.web", + "request": "attach", + "debugPort": 5051 +} +``` \ No newline at end of file diff --git a/src/VSCode.DebugAdapter/ServerProcess.cs b/src/VSCode.DebugAdapter/ServerProcess.cs index ad9c8c9be..ffc12fadd 100644 --- a/src/VSCode.DebugAdapter/ServerProcess.cs +++ b/src/VSCode.DebugAdapter/ServerProcess.cs @@ -26,6 +26,8 @@ public ServerProcess(PathHandlingStrategy pathHandling) : base(pathHandling) public IDictionary Environment { get; set; } = new Dictionary(); + public bool WaitOnStart { get; set; } + protected override Process CreateProcess() { var dbgArgs = new List(); @@ -34,7 +36,7 @@ protected override Process CreateProcess() dbgArgs.Add($"--debug.port={DebugPort}"); } dbgArgs.Add("--debug.protocol=tcp"); - dbgArgs.Add("--debug.wait=1"); + dbgArgs.Add($"--debug.wait={(WaitOnStart ? "1" : "0")}"); var debugArguments = string.Join(" ", dbgArgs); var process = new Process(); @@ -104,6 +106,7 @@ protected override void InitInternal(JObject args) DebugPort = options.DebugPort; Environment = options.Env; DebugProtocol = "tcp"; + WaitOnStart = options.WaitOnStart; } } } \ No newline at end of file diff --git a/src/VSCode.DebugAdapter/SessionLog.cs b/src/VSCode.DebugAdapter/SessionLog.cs deleted file mode 100644 index 5ff5e7747..000000000 --- a/src/VSCode.DebugAdapter/SessionLog.cs +++ /dev/null @@ -1,58 +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/. -----------------------------------------------------------*/ -using System; -using System.Diagnostics; -using System.IO; - -namespace VSCode.DebugAdapter -{ - static class SessionLog - { - private static StreamWriter _log; - private static object lockObj = new object(); - - private static string _path; - [Conditional("DEBUG")] - public static void Open(string path) - { - _path = path; - _log = new StreamWriter(path); - _log.AutoFlush = true; - _log.WriteLine("started: " + DateTime.Now); - } - - public static void WriteLine(string text) - { -#if DEBUG - lock (lockObj) - { - if (_log == null) - { - _log = new StreamWriter(_path, true); - _log.AutoFlush = true; - _log.WriteLine("started: " + DateTime.Now); - } - _log.WriteLine(text); - } -#endif - } - - [Conditional("DEBUG")] - public static void Close() - { - lock (lockObj) - { - if(_log == null) - return; - - _log.WriteLine("closed: " + DateTime.Now); - _log.Dispose(); - _log = null; - } - } - } -} diff --git a/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj b/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj index d421361ae..cc5e71fe0 100644 --- a/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj +++ b/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj @@ -20,6 +20,9 @@ false + + + diff --git a/src/VSCode.DebugAdapter/WebLaunchOptions.cs b/src/VSCode.DebugAdapter/WebLaunchOptions.cs index 5c287305c..f53df4c5f 100644 --- a/src/VSCode.DebugAdapter/WebLaunchOptions.cs +++ b/src/VSCode.DebugAdapter/WebLaunchOptions.cs @@ -10,5 +10,7 @@ namespace VSCode.DebugAdapter public class WebLaunchOptions : CommonLaunchOptions { public string AppDir { get; set; } + + public bool WaitOnStart { get; set; } } } \ No newline at end of file diff --git a/src/VSCode.DebugAdapter/package.json b/src/VSCode.DebugAdapter/package.json index 3df58bfa6..fb5098a29 100644 --- a/src/VSCode.DebugAdapter/package.json +++ b/src/VSCode.DebugAdapter/package.json @@ -1,7 +1,7 @@ { "name": "oscript-debug", "displayName": "OneScript Debug (BSL)", - "version": "0.7.2", + "version": "0.8.0", "publisher": "EvilBeaver", "description": "Visual Studio Code debugger extension for OneScript (BSL)", "icon": "images/logo-dbg.png", @@ -131,7 +131,8 @@ "env": {}, "runtimeExecutable": null, "runtimeArgs" : [], - "debugPort": 2801 + "debugPort": 2801, + "waitOnStart": false } ], "configurationAttributes": { @@ -166,6 +167,11 @@ "type": "number", "description": "Порт для запуска отладчика. Одновременные сеансы отладки должны быть разделены по портам", "default": 2801 + }, + "waitOnStart": { + "type": "boolean", + "description": "Ожидать подключения отладчика при старте приложения (не выполнять bsl до его подключения)", + "default": false } } }, diff --git a/src/oscript/CgiBehavior.cs b/src/oscript/CgiBehavior.cs index 193f10f42..4c1532c66 100644 --- a/src/oscript/CgiBehavior.cs +++ b/src/oscript/CgiBehavior.cs @@ -10,8 +10,8 @@ This Source Code Form is subject to the terms of the using System.IO; using System.Linq; using System.Text; -using OneScript.Commons; using OneScript.Contexts; +using OneScript.Exceptions; using OneScript.StandardLibrary; using oscript.Web; diff --git a/src/oscript/DebugBehavior.cs b/src/oscript/DebugBehavior.cs index dfd84dbd9..b76664f0f 100644 --- a/src/oscript/DebugBehavior.cs +++ b/src/oscript/DebugBehavior.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 OneScript.DebugProtocol; using OneScript.DebugServices; namespace oscript @@ -20,6 +21,8 @@ public DebugBehavior(int port, string path, string[] args) : base(path, args) public override int Execute() { + Output.ConsoleOutputEncoding = DebuggerSettings.DebugModeEncoding; + var tcpDebugServer = new BinaryTcpDebugServer(_port); DebugController = tcpDebugServer.CreateDebugController(); diff --git a/src/oscript/ExecuteScriptBehavior.cs b/src/oscript/ExecuteScriptBehavior.cs index 12ee05a04..9e6069be2 100644 --- a/src/oscript/ExecuteScriptBehavior.cs +++ b/src/oscript/ExecuteScriptBehavior.cs @@ -1,105 +1,111 @@ -/*---------------------------------------------------------- -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 OneScript.StandardLibrary; -using ScriptEngine; -using ScriptEngine.HostedScript; -using ScriptEngine.Hosting; -using ScriptEngine.Machine; - -namespace oscript -{ - class ExecuteScriptBehavior : AppBehavior, IHostApplication, ISystemLogWriter - { - protected string[] _scriptArgs; - protected string _path; - - public ExecuteScriptBehavior(string path, string[] args) - { - _scriptArgs = args; - _path = path; - } - - public IDebugController DebugController { get; set; } - - public string CodeStatFile { get; set; } - - public bool CodeStatisticsEnabled => CodeStatFile != null; - - public override int Execute() - { - if (!System.IO.File.Exists(_path)) - { - Echo($"Script file is not found '{_path}'"); - return 2; - } - - SystemLogger.SetWriter(this); - - var builder = ConsoleHostBuilder.Create(_path); - builder.WithDebugger(DebugController); - - var hostedScript = ConsoleHostBuilder.Build(builder); - - if (CodeStatisticsEnabled) - hostedScript.EnableCodeStatistics(); - - var source = hostedScript.Loader.FromFile(_path); - Process process; - try - { - process = hostedScript.CreateProcess(this, source); - } - catch (Exception e) - { - ShowExceptionInfo(e); - return 1; - } - - var result = process.Start(); - hostedScript.Dispose(); - - if (CodeStatisticsEnabled) - { - var codeStat = hostedScript.GetCodeStatData(); - var statsWriter = new CodeStatWriter(CodeStatFile, CodeStatWriterType.JSON); - statsWriter.Write(codeStat); - } - - return result; - } - - #region IHostApplication Members - - public void Echo(string text, MessageStatusEnum status = MessageStatusEnum.Ordinary) - { - ConsoleHostImpl.Echo(text, status); - } - - public void ShowExceptionInfo(Exception exc) - { - ConsoleHostImpl.ShowExceptionInfo(exc); - } - - public bool InputString(out string result, string prompt, int maxLen, bool multiline) - { - return ConsoleHostImpl.InputString(out result, prompt, maxLen, multiline); - } - - public string[] GetCommandLineArguments() - { - return _scriptArgs; - } - - #endregion - - public void Write(string text) - { - Console.Error.WriteLine(text); - } - } -} +/*---------------------------------------------------------- +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 OneScript.StandardLibrary; +using ScriptEngine; +using ScriptEngine.HostedScript; +using ScriptEngine.Hosting; +using ScriptEngine.Machine; + +namespace oscript +{ + class ExecuteScriptBehavior : AppBehavior, IHostApplication, ISystemLogWriter + { + protected string[] _scriptArgs; + protected string _path; + + public ExecuteScriptBehavior(string path, string[] args) + { + _scriptArgs = args; + _path = path; + } + + public IDebugController DebugController { get; set; } + + public string CodeStatFile { get; set; } + + public bool CodeStatisticsEnabled => CodeStatFile != null; + + public override int Execute() + { + if (!System.IO.File.Exists(_path)) + { + Echo($"Script file is not found '{_path}'"); + return 2; + } + + SystemLogger.SetWriter(this); + + var builder = ConsoleHostBuilder.Create(_path); + builder.WithDebugger(DebugController); + CodeStatProcessor codeStatProcessor = null; + if (CodeStatisticsEnabled) + { + codeStatProcessor = new CodeStatProcessor(); + builder.Services.RegisterSingleton(codeStatProcessor); + } + + var hostedScript = ConsoleHostBuilder.Build(builder); + + + + var source = hostedScript.Loader.FromFile(_path); + Process process; + try + { + process = hostedScript.CreateProcess(this, source); + } + catch (Exception e) + { + ShowExceptionInfo(e); + return 1; + } + + var result = process.Start(); + hostedScript.Dispose(); + + if (codeStatProcessor != null) + { + codeStatProcessor.EndCodeStat(); + var codeStat = codeStatProcessor.GetStatData(); + var statsWriter = new CodeStatWriter(CodeStatFile, CodeStatWriterType.JSON); + statsWriter.Write(codeStat); + } + + return result; + } + + #region IHostApplication Members + + public void Echo(string text, MessageStatusEnum status = MessageStatusEnum.Ordinary) + { + ConsoleHostImpl.Echo(text, status); + } + + public void ShowExceptionInfo(Exception exc) + { + ConsoleHostImpl.ShowExceptionInfo(exc); + } + + public bool InputString(out string result, string prompt, int maxLen, bool multiline) + { + return ConsoleHostImpl.InputString(out result, prompt, maxLen, multiline); + } + + public string[] GetCommandLineArguments() + { + return _scriptArgs; + } + + #endregion + + public void Write(string text) + { + Console.Error.WriteLine(text); + } + } +} diff --git a/src/oscript/ShowUsageBehavior.cs b/src/oscript/ShowUsageBehavior.cs index c24e0c830..5b5baba3a 100644 --- a/src/oscript/ShowUsageBehavior.cs +++ b/src/oscript/ShowUsageBehavior.cs @@ -1,39 +1,37 @@ -/*---------------------------------------------------------- -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.Reflection; - -namespace oscript -{ - internal class ShowUsageBehavior : AppBehavior - { - public override int Execute() - { - Output.WriteLine($"1Script Execution Engine. Version {Program.GetVersion()}"); - Output.WriteLine(); - Output.WriteLine("Usage:"); - Output.WriteLine(); - Output.WriteLine("I. Script execution: oscript.exe [script arguments..]"); - Output.WriteLine(); - Output.WriteLine("II. Special mode: oscript.exe [script arguments..]"); - Output.WriteLine("Mode can be one of these:"); - Output.WriteLine($" {"-measure",-12}measures execution time"); - Output.WriteLine($" {"-compile",-12}shows compiled module without execution"); - Output.WriteLine($" {"-check [-env=]",-12}provides syntax check"); - Output.WriteLine($" {"-check -cgi",-12}provides syntax check in CGI-mode"); - Output.WriteLine($" {"-version",-12}output version string"); - Output.WriteLine(); - Output.WriteLine(" -encoding= set output encoding"); - Output.WriteLine(" -codestat= write code statistics"); - Output.WriteLine(); - Output.WriteLine("III. Run as CGI application: oscript.exe -cgi [script arguments..]"); - Output.WriteLine(" Runs as CGI application under HTTP-server (Apache/Nginx/IIS/etc...)"); - - return 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/. +----------------------------------------------------------*/ + +namespace oscript +{ + internal class ShowUsageBehavior : AppBehavior + { + public override int Execute() + { + Output.WriteLine($"1Script Execution Engine. Version {Program.GetVersion()}"); + Output.WriteLine(); + Output.WriteLine("Usage:"); + Output.WriteLine(); + Output.WriteLine("I. Script execution: oscript.exe [script arguments..]"); + Output.WriteLine(); + Output.WriteLine("II. Special mode: oscript.exe [script arguments..]"); + Output.WriteLine("Mode can be one of these:"); + Output.WriteLine($" {"-measure",-12}measures execution time"); + Output.WriteLine($" {"-compile",-12}shows compiled module without execution"); + Output.WriteLine($" {"-check [-env=]",-12}provides syntax check"); + Output.WriteLine($" {"-check -cgi",-12}provides syntax check in CGI-mode"); + Output.WriteLine($" {"-version",-12}output version string"); + Output.WriteLine(); + Output.WriteLine(" -encoding= set output encoding"); + Output.WriteLine(" -codestat= write code statistics"); + Output.WriteLine(); + Output.WriteLine("III. Run as CGI application: oscript.exe -cgi [script arguments..]"); + Output.WriteLine(" Runs as CGI application under HTTP-server (Apache/Nginx/IIS/etc...)"); + + return 0; + } + } } \ No newline at end of file diff --git a/src/oscript/ShowVersionBehavior.cs b/src/oscript/ShowVersionBehavior.cs index 02ef0119f..bdb13a095 100644 --- a/src/oscript/ShowVersionBehavior.cs +++ b/src/oscript/ShowVersionBehavior.cs @@ -1,20 +1,18 @@ -/*---------------------------------------------------------- -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.Reflection; - -namespace oscript -{ - internal class ShowVersionBehavior : AppBehavior - { - public override int Execute() - { - Output.WriteLine(Program.GetVersion()); - return 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/. +----------------------------------------------------------*/ + +namespace oscript +{ + internal class ShowVersionBehavior : AppBehavior + { + public override int Execute() + { + Output.WriteLine(Program.GetVersion()); + return 0; + } + } } \ No newline at end of file diff --git a/tests/engine-behaviors.os b/tests/engine-behaviors.os index e2a2b1f45..01867ddf2 100644 --- a/tests/engine-behaviors.os +++ b/tests/engine-behaviors.os @@ -50,6 +50,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПрерываниеВложенныхПопыток"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПродолжениеВложенныхПопыток"); ВсеТесты.Добавить("ТестДолжен_ПроверитьИнформацияОбОшибкеВнеИсключения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПараметровПоСсылке"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСравнениеНаБольшеМеньше"); Возврат ВсеТесты; @@ -241,7 +243,7 @@ Попытка ПроброситьИсключение(); Исключение - юТест.ПроверитьИстину(ПустаяСтрока(ИнформацияОбОшибке().Описание), "Текст исключения должен быть пустым"); + юТест.ПроверитьРавенство("", ИнформацияОбОшибке().Описание, "Текст исключения должен быть пустым"); КонецПопытки; КонецПроцедуры @@ -466,7 +468,7 @@ юТест.ПроверитьРавенство(П.П1, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П2, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П3, "1", "Пропущенный параметр со значением по-умолчанию"); - + П = ПропущенныеПараметры1(,,); юТест.ПроверитьРавенство(П.П1, Неопределено, "Пропущенный параметр без значения по-умолчанию"); @@ -478,25 +480,25 @@ юТест.ПроверитьРавенство(П.П1, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П2, 2, "Параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П3, "1", "Пропущенный параметр со значением по-умолчанию"); - + П = ПропущенныеПараметры1(3,); юТест.ПроверитьРавенство(П.П1, 3, "Параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П2, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П3, "1", "Пропущенный параметр со значением по-умолчанию"); - + П = ПропущенныеПараметры1(3,,); юТест.ПроверитьРавенство(П.П1, 3, "Параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П2, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П3, "1", "Пропущенный параметр со значением по-умолчанию"); - + П = ПропущенныеПараметры1(,,"4"); юТест.ПроверитьРавенство(П.П1, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П2, Неопределено, "Пропущенный параметр без значения по-умолчанию"); юТест.ПроверитьРавенство(П.П3, "4", "Параметр со значением по-умолчанию"); - + П = ПропущенныеПараметры1(, 2, "6"); юТест.ПроверитьРавенство(П.П1, Неопределено, "Пропущенный параметр без значения по-умолчанию"); @@ -627,4 +629,65 @@ юТест.ПроверитьРавенство("", ИнформацияОбОшибке.ПодробноеОписаниеОшибки()); юТест.ПроверитьРавенство(Неопределено, ИнформацияОбОшибке.Параметры); -КонецПроцедуры \ No newline at end of file +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПередачуПараметровПоСсылке() Экспорт + + Структура = Новый Структура("Поле", 1); + + Т = 0; + Рез = Структура.Свойство("Поле", Т); + юТест.ПроверитьРавенство(1, Т, "Для переменной"); + + Массив = Новый Массив(1); + Рез = Структура.Свойство("Поле", Массив[0]); + юТест.ПроверитьРавенство(1, Массив[0], "Для элемента массива"); + + Структура2 = Новый Структура("Поле", 2); + Рез = Структура.Свойство("Поле", Структура2.Поле); + юТест.ПроверитьРавенство(1, Структура2.Поле, "Для поля структуры"); + + Рез = Структура.Свойство("Поле", 3); // не должно упасть + юТест.ПроверитьРавенство(истина, Рез); + + Рез = Структура.Свойство("Поле", ТекущаяДата()); // не должно упасть + юТест.ПроверитьРавенство(истина, Рез); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСравнениеНаБольшеМеньше() Экспорт + + Ошибка = "Сравнение на больше/меньше для данного типа не поддерживается"; + + юТест.ПроверитьКодСОшибкой( + "Рез = (СтатусСообщения.БезСтатуса <= СтатусСообщения.БезСтатуса);", + Ошибка, "Для одинаковых значений перечислений" ); + + юТест.ПроверитьКодСОшибкой( + "Рез = (ЦветКонсоли.Черный < СтатусСообщения.БезСтатуса);", + Ошибка, "Для значений перечислений разных типов" ); + + юТест.ПроверитьКодСОшибкой( + "Рез = (КодировкаТекста >= КодировкаТекста);", + Ошибка, "Для одинаковых перечислений" ); + юТест.ПроверитьКодСОшибкой( + "Рез = (ХешФункция > СтатусСообщения);", + Ошибка, "Для перечислений разных типов" ); + + юТест.ПроверитьКодСОшибкой( + "Рез = (ТипЗнч(истина) > ТипЗнч(0));", + Ошибка, "Для значений типа 'Тип'" ); + + юТест.ПроверитьКодСОшибкой( + "Массив = Новый Массив(1); + |Структура = Новый Структура; + |Рез = (Массив > Структура);", + Ошибка, "Для объектов разных типов" ); + + юТест.ПроверитьКодСОшибкой( + "Массив = Новый Массив(1); + |Массив2 = Новый Массив(1);; + |Рез = (Массив <= Массив2);", + Ошибка, "Для одинаковых объектов" ); + +КонецПроцедуры diff --git a/tests/native-compiler.os b/tests/eratosthenes.os similarity index 100% rename from tests/native-compiler.os rename to tests/eratosthenes.os diff --git a/tests/eval.os b/tests/eval.os index d6f31fba6..3344fe294 100644 --- a/tests/eval.os +++ b/tests/eval.os @@ -1,4 +1,5 @@ Перем юТест; +Перем Глобал; Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт @@ -15,7 +16,15 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВОператореВыполнитьЗапрещенВозврат"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоЭтотОбъект_issue712"); ВсеТесты.Добавить("ТестДолжен_ПроверитьКешКомпиляцииВРазныхФреймах"); - + ВсеТесты.Добавить("ТестДолжен_ПроверитьРекурсивныйВызовВычислить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСложныеВложенныеВызовыВычислить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьВычислитьВнутриВыполнить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьАлиасыФункцийИПеременныхВВычислить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьОбработкуИсключенияВВыполнить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьРекурсивныйВызовВыполнить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьВложенныеВызовыВыполнить"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовыВыполнитьСПопытками"); + Возврат ВсеТесты; КонецФункции @@ -168,3 +177,147 @@ юТест.ПроверитьРавенство(3, Рез4); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьРекурсивныйВызовВычислить() Экспорт + Рез = "Вычислить(1)"; + Для й=1 По 100 Цикл + Рез = "Вычислить("+Рез+")+1"; + КонецЦикла; + + Рез = Вычислить(Рез); + юТест.ПроверитьРавенство(101, Рез); +КонецПроцедуры + + +Функция Один() + Возврат Вычислить("1"); +КонецФункции + +Функция Два() + Один = Вычислить("Один()"); + Возврат Вычислить("Один+Один()"); +КонецФункции + +Функция Шесть() + Три = 3; + Возврат Вычислить("Два()") * Три; +КонецФункции + +Функция СорокДва(Семь) + Возврат Вычислить("Семь * Шесть()"); +КонецФункции + +Функция Ответ() + Возврат Вычислить("Глобал + СорокДва(7)"); +КонецФункции + +Процедура ТестДолжен_ПроверитьСложныеВложенныеВызовыВычислить() Экспорт + Глобал = 0; + Рез = Вычислить("Ответ()"); + юТест.ПроверитьРавенство(42, Рез); + + Глобал = 66; + Рез = Вычислить("Ответ()"); + юТест.ПроверитьРавенство(108, Рез); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВычислитьВнутриВыполнить() Экспорт + Рез = -1; + Выполнить("Для й=1 По 9 Цикл ц = -й; КонецЦикла; Рез = Вычислить(""ц + й"")"); + юТест.ПроверитьРавенство(1, Рез); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьАлиасыФункцийИПеременныхвВычислить() Экспорт + Рез = Вычислить("Лев(""фыв""+Символы.ПС,1)+Left(""fgh""+Chars.LF,1)"); + юТест.ПроверитьРавенство("фf", Рез); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьОбработкуИсключенияВВыполнить() Экспорт + + Рез = 1; + Выполнить " + |Попытка + | Рез = 1/0; + |Исключение + | Рез = -1; + |КонецПопытки;"; + юТест.ПроверитьРавенство(-1, Рез); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьРекурсивныйВызовВыполнить() Экспорт + + Рез = 1; + Код = "Рез=Рез+1;"; + Для й = 1 По 10 Цикл + Код = СтрЗаменить(Код, """", """"""); + Код = "Выполнить""" + Код + """;"; + КонецЦикла; + Выполнить(Код); + + юТест.ПроверитьРавенство(2, Рез); + +КонецПроцедуры + +Процедура Третья(Пар) + Выполнить "Рез = Рез + Пар;"; +КонецПроцедуры + +Процедура Вторая(Пар) + Выполнить "Лок = Пар + 1; Третья(Лок);"; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВложенныеВызовыВыполнить() Экспорт + + Рез = 1; + Выполнить "Вторая(2);"; + + юТест.ПроверитьРавенство(4, Рез); + +КонецПроцедуры + +Процедура СИсключением() + Выполнить " + |Попытка + | Рез = Рез + 8; + | ВызватьИсключение 0; + |Исключение + | Рез = Рез + 9; + |КонецПопытки; + |Выполнить(""Рез = Рез + (-10)"");"; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВызовыВыполнитьСПопытками() Экспорт + + Рез = "0"; + попытка + Выполнить(" + |Лок=""1""; + |Попытка + | Рез = 1/0; + |Исключение + | Рез = Рез + Лок; + |КонецПопытки;"); + Выполнить(" + |Попытка + | Рез = Рез + 2/0; + |Исключение + | Выполнить(""Рез = Рез + 3""); + |КонецПопытки; + |Рез = Рез + 4;"); + Выполнить(" + |Попытка + | Рез = Рез + 5; + | СИсключением(); + |Исключение + | Рез = Рез + 6; + |КонецПопытки; + |Рез = Рез + 7;"); + исключение + Рез = Рез+ "!" ; + конецпопытки; + Рез = Рез + "+"; + + юТест.ПроверитьРавенство("0134589-107+", Рез); + +КонецПроцедуры diff --git a/tests/global-funcs.os b/tests/global-funcs.os index 9bce86e3c..50d9d4d37 100644 --- a/tests/global-funcs.os +++ b/tests/global-funcs.os @@ -43,6 +43,15 @@ ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаДвоичныеДанные"); ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаСтрокаИзПеременной"); ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеДвоичныеДанные"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаNULL"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаGUID"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаПеречисления"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеNULL"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеGUID"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеПеречисления"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЗаписьВBase64"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтениеИзBase64"); @@ -374,6 +383,122 @@ КонецПроцедуры +Процедура ТестДолжен_Проверить_XMLСтрокаNULL() Экспорт + + юТест.ПроверитьРавенство("", XMLСтрока(NULL)); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеNULL() Экспорт + + Тип = Тип("NULL"); + + Значение = XMLЗначение(Тип, " "); + юТест.ПроверитьТип(Значение, Тип); + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип, "NULL"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении NULL в XMLЗначение"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаGUID() Экспорт + + Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e"; + GUID = Новый УникальныйИдентификатор(Строка); + юТест.ПроверитьРавенство(Строка, XMLСтрока(GUID)); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеGUID() Экспорт + + Тип = Тип("УникальныйИдентификатор"); + Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e"; + + Значение = XMLЗначение(Тип, Строка); + юТест.ПроверитьТип(Значение, Тип); + юТест.ПроверитьРавенство(Строка(Значение), Строка); + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип, "-a-e1d6d78c3d54ef0b0962fb4f8e4717e"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении GUID в XMLЗначение"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаПеречисления() Экспорт + + Перечисление = ДопустимыйЗнак.Неотрицательный; + юТест.ПроверитьРавенство("Неотрицательный", XMLСтрока(Перечисление)); // нужно "Nonnegative" + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеПеречисления() Экспорт + Тип = Тип("ДопустимаяДлина"); + Значение = XMLЗначение(Тип, "Fixed"); + + юТест.ПроверитьТип(Значение, Тип); + юТест.ПроверитьРавенство(Значение, ДопустимаяДлина.Фиксированная); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы() Экспорт + + Массив = Новый Массив(1); + БылоИсключение = Ложь; + Попытка + Стр = XMLСтрока(Массив); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока"); + + Перечисление = НаправлениеСортировки.Возр; + БылоИсключение = Ложь; + Попытка + Стр = XMLСтрока(Перечисление); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом перечислении в XMLСтрока"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы() Экспорт + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип("НаправлениеСортировки"), "Возр"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока"); + + Перечисление = НаправлениеСортировки.Возр; + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип("ДопустимаяДлина"), "Возр"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом значении в XMLСтрока"); + +КонецПроцедуры + + Функция ПрочитатьФайлСкрипта(Знач Файл) Ч = Новый ЧтениеТекста(Файл); diff --git a/tests/managed-com.os b/tests/managed-com.os index e92d6d6bc..8cf6bd4db 100644 --- a/tests/managed-com.os +++ b/tests/managed-com.os @@ -14,6 +14,7 @@ Если (Найти(СИ.ВерсияОС, "Windows") > 0) И Не (ПеременныеСреды().Получить("APPVEYOR") = "True") Тогда ВсеТесты.Добавить("ТестДолжен_ПроверитьУстановкуЧисловыхСвойств"); ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовСОпциональнымиПараметрами"); + ВсеТесты.Добавить("ПроверитьВыходныеПараметрыComОбъекта"); КонецЕсли; ВсеТесты.Добавить("ТестДолжен_ПроверитьСозданиеClrОбъекта"); @@ -24,7 +25,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуGetTypeДляЭлементовСписка"); ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуGetTypeДляCLRКоллекции"); ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуТипаНеИзЯдра"); - + Возврат ВсеТесты; КонецФункции @@ -176,3 +177,16 @@ ПроверитьРаботуGetTypeДляОдногоТипа(Ури, "System", "Uri"); КонецПроцедуры + +Процедура ПроверитьВыходныеПараметрыComОбъекта() Экспорт + // Проверяем, что выходной параметр установился, а также то, что попытки записи во входной параметр не было. + + Рег = Новый ФиксированнаяСтруктура("HKEY_LOCAL_MACHINE", "2147483650"); + ИмяФайлаКласса = ""; + РеестрОС = ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv"); + Рез=РеестрОС.GetStringValue(Рег.HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion","DevicePath", ИмяФайлаКласса); + + юТест.ПроверитьРавенство(0, Рез); + юТест.ПроверитьНеравенство("", ИмяФайлаКласса); + +КонецПроцедуры diff --git a/tests/native-api/build.sh b/tests/native-api/build.sh old mode 100644 new mode 100755 index 4a911d356..a2aaacc80 --- a/tests/native-api/build.sh +++ b/tests/native-api/build.sh @@ -11,5 +11,6 @@ cmake -E make_directory build64 cd build64 cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=OFF --build .. cmake --build . +chmod +x *.so cp *.so .. cd .. diff --git a/tests/native-lib/test-import-native-from-stack.os b/tests/native-lib/test-import-native-from-stack.os new file mode 100644 index 000000000..9722dba00 --- /dev/null +++ b/tests/native-lib/test-import-native-from-stack.os @@ -0,0 +1,36 @@ +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ПроверитьОберткуНадРегуляркой"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ПроверитьОберткуНадРегуляркой() Экспорт + ИсходнаяСтрока = "{20221110000049,N, + |{2444a6a24da10,3d},1,1,1,1803214,81,I,""Первое событие"",599, + |{""U""},""Представление данных"",1,1,9,3,0, + |{0} + |}, + |{20221110000049,U, + |{2444a6a24da10,3d},1,1,1,1803214,81,E,""Второе событие"",599, + |{""U""},""Представление данных2"",1,1,9,3,0, + |{2,1,31,2,31} + |}"; + Регулярка = "\,*\r*\n*\{(\d{14}),(\w),\r*\n\{([0-9a-f]+),([0-9a-f]+)\},(\d+),(\d+),(\d+),(\d+),(\d+),(\w),""([^ꡏ]*?)(?="",\d+,\r*\n)"",(\d+),\r*\n\{([^ꡏ]*?)(?=\},"")\},""([^ꡏ]*?)(?="",\d+)"",(\d+),(\d+),(\d+),(\d+),\d+[,\d+]*,\r*\n\{((\d+)|\d+,(\d+),(\d+),(\d+),(\d+))\}\r*\n\},*\r*\n*"; + + ОберткаНадРегуляркой = Новый ОберткаНадРегуляркой(Регулярка); + + Совпадения = ОберткаНадРегуляркой.НайтиСовпадения(ИсходнаяСтрока); + Совпадение = Совпадения[0]; + + юТест.ПроверитьРавенство(2, Совпадения.Количество()); +КонецПроцедуры + diff --git a/tests/native-lib/test-native-change-array.os b/tests/native-lib/test-native-change-array.os new file mode 100644 index 000000000..9c9845f58 --- /dev/null +++ b/tests/native-lib/test-native-change-array.os @@ -0,0 +1,30 @@ +#native + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ИзменениеМассиваПоСсылке"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ИзменениеМассиваПоСсылке() Экспорт + + МойМассив = Новый Массив; + + ДобавитьВМассив(МойМассив); + + Значение = МойМассив[0]; + + юТест.ПроверитьРавенство(Значение, 1, "Массив изменен корректно"); + +КонецПроцедуры + +Процедура ДобавитьВМассив(Массив) + Массив.Добавить(1); +КонецПроцедуры diff --git a/tests/native-lib/test-native-default-params-in-methods.os b/tests/native-lib/test-native-default-params-in-methods.os new file mode 100644 index 000000000..aafbc6153 --- /dev/null +++ b/tests/native-lib/test-native-default-params-in-methods.os @@ -0,0 +1,74 @@ +#native + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюСтрока"); + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюБулево"); + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюНеопределено"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюСтрока() Экспорт + + Результат = МетодСтроки(,"Текст"); + + юТест.ПроверитьРавенство(Результат, "Т1 Текст", "Текст сформирован корректно"); + +КонецПроцедуры + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюБулево() Экспорт + + Результат1 = МетодБулево(); + Результат2 = МетодБулево(Истина); + Результат3 = МетодБулево(Ложь); + + юТест.ПроверитьРавенство(Результат1, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат2, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат3, 0, "параметр передан корректно"); + +КонецПроцедуры + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюНеопределено() Экспорт + + Результат1 = МетодНеопределено(); + Результат2 = МетодНеопределено(Неопределено); + Результат3 = МетодНеопределено(Ложь); + + юТест.ПроверитьРавенство(Результат1, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат2, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат3, 0, "параметр передан корректно"); + +КонецПроцедуры + +Функция МетодСтроки(Текст1 = "Т1 ", Текст2 = "Т2 ") + Сообщить(Текст1); + Сообщить(Текст2); + Возврат Текст1 + Текст2; +КонецФункции + +Функция МетодБулево(Булево = Истина) + + Если Булево = Истина Или Булево Тогда + Возврат 1; + Иначе + Возврат 0; + КонецЕсли; + +КонецФункции + +Функция МетодНеопределено(Параметр = Неопределено) + + Если Параметр = Неопределено Тогда + Возврат 1; + Иначе + Возврат 0; + КонецЕсли; + +КонецФункции \ No newline at end of file diff --git a/tests/native-lib/test-native-kolichestvo.os b/tests/native-lib/test-native-kolichestvo.os new file mode 100644 index 000000000..2fa09ba8a --- /dev/null +++ b/tests/native-lib/test-native-kolichestvo.os @@ -0,0 +1,91 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ПроверитьКоличество_Массив"); + Тесты.Добавить("ТестДолжен_ПроверитьКоличество_Структура"); + Тесты.Добавить("ТестДолжен_ПроверитьКоличество_СписокЗначений"); + Тесты.Добавить("ТестДолжен_ПроверитьКоличество_Соответствие"); + Тесты.Добавить("ТестДолжен_ПроверитьКоличество_ТаблицаЗначений"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ПроверитьКоличество_Массив() Экспорт + + // Дано + Коллекция = Новый Массив(); + + // Когда + Количество = Коллекция.Количество(); + + // Тогда + + юТест.ПроверитьРавенство(Количество, 0, "Количество получено"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКоличество_Структура() Экспорт + + // Дано + Коллекция = Новый Структура(); + + // Когда + Количество = Коллекция.Количество(); + + // Тогда + + юТест.ПроверитьРавенство(Количество, 0, "Количество получено"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКоличество_СписокЗначений() Экспорт + + // Дано + Коллекция = Новый СписокЗначений(); + + // Когда + Количество = Коллекция.Количество(); + + // Тогда + + юТест.ПроверитьРавенство(Количество, 0, "Количество получено"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКоличество_Соответствие() Экспорт + + // Дано + Коллекция = Новый Соответствие(); + + // Когда + Количество = Коллекция.Количество(); + + // Тогда + + юТест.ПроверитьРавенство(Количество, 0, "Количество получено"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКоличество_ТаблицаЗначений() Экспорт + + // Дано + Коллекция = Новый ТаблицаЗначений(); + + // Когда + Количество = Коллекция.Количество(); + КоличествоКолонок = Коллекция.Колонки.Количество(); + + // Тогда + + юТест.ПроверитьРавенство(Количество, 0, "Количество получено"); + юТест.ПроверитьРавенство(КоличествоКолонок, 0, "Количество получено"); + +КонецПроцедуры diff --git a/tests/native-lib/test-native-search-in-array.os b/tests/native-lib/test-native-search-in-array.os new file mode 100644 index 000000000..d3a2e1f33 --- /dev/null +++ b/tests/native-lib/test-native-search-in-array.os @@ -0,0 +1,40 @@ +#native + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ПроверитьПоискВМассиве"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ПроверитьПоискВМассиве() Экспорт + + Массив = Новый Массив(); + Массив.Добавить("1"); + Массив.Добавить("2"); + Массив.Добавить("3"); + + Если Массив.Найти("1") <> Неопределено Тогда + НашлиЗначение1 = Истина; + Иначе + НашлиЗначение1 = Ложь; + КонецЕсли; + + Если Массив.Найти("9") <> Неопределено Тогда + НашлиЗначение9 = Истина; + Иначе + НашлиЗначение9 = Ложь; + КонецЕсли; + + юТест.ПроверитьРавенство(НашлиЗначение1, Истина, "Нашли 1"); + юТест.ПроверитьРавенство(НашлиЗначение9, Ложь, "Не нашли 9"); + юТест.ПроверитьРавенство(Массив.Найти("2"), 1, "Индекс элемента по значению"); + +КонецПроцедуры + diff --git a/tests/native-lib/test-native-use-default-params-bool.os b/tests/native-lib/test-native-use-default-params-bool.os new file mode 100644 index 000000000..526a080de --- /dev/null +++ b/tests/native-lib/test-native-use-default-params-bool.os @@ -0,0 +1,29 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьБулево"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьБулево() Экспорт + + Сценарий = Новый ПараметрыПоУмолчанию; + + Результат1 = Сценарий.МетодБулево(); + Результат2 = Сценарий.МетодБулево(Истина); + Результат3 = Сценарий.МетодБулево(Ложь); + + юТест.ПроверитьРавенство(Результат1, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат2, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат3, 0, "параметр передан корректно"); + +КонецПроцедуры diff --git a/tests/native-lib/test-native-use-default-params-string.os b/tests/native-lib/test-native-use-default-params-string.os new file mode 100644 index 000000000..ae5102c99 --- /dev/null +++ b/tests/native-lib/test-native-use-default-params-string.os @@ -0,0 +1,25 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьСтрока"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьСтрока() Экспорт + + Сценарий = Новый ПараметрыПоУмолчанию; + + Результат = Сценарий.МетодСтроки(,"Текст"); + + юТест.ПроверитьРавенство(Результат, "Т1 Текст", "Текст сформирован корректно"); + +КонецПроцедуры diff --git a/tests/native-lib/test-native-use-default-params-undefinde.os b/tests/native-lib/test-native-use-default-params-undefinde.os new file mode 100644 index 000000000..d0ce0e2aa --- /dev/null +++ b/tests/native-lib/test-native-use-default-params-undefinde.os @@ -0,0 +1,29 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьНеопределено"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ЗначенияВМетодахПоУмолчаниюИспользоватьНеопределено() Экспорт + + Сценарий = Новый ПараметрыПоУмолчанию; + + Результат1 = Сценарий.МетодНеопределено(); + Результат2 = Сценарий.МетодНеопределено(Неопределено); + Результат3 = Сценарий.МетодНеопределено(Ложь); + + юТест.ПроверитьРавенство(Результат1, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат2, 1, "параметр передан корректно"); + юТест.ПроверитьРавенство(Результат3, 0, "параметр передан корректно"); + +КонецПроцедуры diff --git a/tests/native-lib/test-native-use-params-in-constructor.os b/tests/native-lib/test-native-use-params-in-constructor.os new file mode 100644 index 000000000..dce112f4f --- /dev/null +++ b/tests/native-lib/test-native-use-params-in-constructor.os @@ -0,0 +1,23 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ПроверитьПередачуЗначенияВКонструктор"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ПроверитьПередачуЗначенияВКонструктор() Экспорт + + НужныйОбъект = Новый СценарийСТекстомВКонструкторе("1"); + + юТест.ПроверитьРавенство(НужныйОбъект.Поле1, "1", "параметр передан корректно"); + +КонецПроцедуры diff --git a/tests/native-lib/test-native-use.os b/tests/native-lib/test-native-use.os new file mode 100644 index 000000000..26e561fe4 --- /dev/null +++ b/tests/native-lib/test-native-use.os @@ -0,0 +1,89 @@ +#native +#Использовать "." + +Перем юТест; + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + юТест = Тестирование; + + Тесты = Новый Массив; + Тесты.Добавить("ТестДолжен_ПроверитьСозданиеОбъекта_ИзНативногоКласса"); + Тесты.Добавить("ТестДолжен_ПроверитьПодключениеСценария"); + Тесты.Добавить("ТестДолжен_ПроверитьВызовМетодовСПараметрамиПоУмолчанию"); + Тесты.Добавить("ТестДолжен_ПроверитьВызовМетодовСПропущеннымиПараметрами"); + Тесты.Добавить("ТестДолжен_ПроверитьВызовМетодовСОшибочноПропущеннымиПараметрами"); + Тесты.Добавить("ТестДолжен_ПроверитьВызовМетодовСЛишнимиПараметрами"); + + Возврат Тесты; + +КонецФункции + +Процедура ТестДолжен_ПроверитьСозданиеОбъекта_ИзНативногоКласса() Экспорт + ТестовыйСценарий = Новый ТестовыйСценарий; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПодключениеСценария() Экспорт + ПодключитьСценарий(ОбъединитьПути(ТекущийСценарий().Каталог, "Классы", "ТестовыйСценарий.os"), "ПодключенныйСценарий"); + + ТестовыйСценарий = Новый ПодключенныйСценарий; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВызовМетодовСПараметрамиПоУмолчанию() Экспорт + Сценарий = Новый ПараметрыПоУмолчанию; + + Результат1 = Сценарий.МетодБулево(); + Результат2 = Сценарий.МетодБулево(Истина); + Результат3 = Сценарий.МетодБулево(Ложь); + + Если НЕ Результат1 = 1 Тогда + ВызватьИсключение "Ошибка передачи параметра"; + КонецЕсли; + + Если НЕ Результат2 = 1 Тогда + ВызватьИсключение "Ошибка передачи параметра"; + КонецЕсли; + + Если НЕ Результат3 = 0 Тогда + ВызватьИсключение "Ошибка передачи параметра"; + КонецЕсли; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВызовМетодовСПропущеннымиПараметрами() Экспорт + Сценарий = Новый ПараметрыПоУмолчанию; + + Результат = Сценарий.МетодЧисло(,2); + + юТест.ПроверитьРавенство(Результат, 1, "Ошибка передачи пропущенного параметра"); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВызовМетодовСОшибочноПропущеннымиПараметрами() Экспорт + Сценарий = Новый ПараметрыПоУмолчанию; + + ОК = Ложь; + Ошибка = ""; + Попытка + Результат = Сценарий.МетодЧисло(1,); + Исключение + Ошибка = ИнформацияОбОшибке().Описание; + ОК = СтрНайти(Ошибка,"Пропущен") > 0; + КонецПопытки; + + юТест.ПроверитьИстину(ОК, "Не было исключения о пропущенном параметре."+Ошибка); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВызовМетодовСЛишнимиПараметрами() Экспорт + Сценарий = Новый ПараметрыПоУмолчанию; + + ОК = Ложь; + Ошибка = ""; + Попытка + Результат = Сценарий.МетодЧисло(1,2,3); + Исключение + Ошибка = ИнформацияОбОшибке().Описание; + ОК = СтрНайти(Ошибка,"Слишком много") > 0; + КонецПопытки; + + юТест.ПроверитьИстину(ОК, "Не было исключения о лишнем параметре."+Ошибка); +КонецПроцедуры \ No newline at end of file diff --git "a/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\320\265\321\200\321\202\320\272\320\260\320\235\320\260\320\264\320\240\320\265\320\263\321\203\320\273\321\217\321\200\320\272\320\276\320\271.os" "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\320\265\321\200\321\202\320\272\320\260\320\235\320\260\320\264\320\240\320\265\320\263\321\203\320\273\321\217\321\200\320\272\320\276\320\271.os" new file mode 100644 index 000000000..fb82ecfa0 --- /dev/null +++ "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\320\265\321\200\321\202\320\272\320\260\320\235\320\260\320\264\320\240\320\265\320\263\321\203\320\273\321\217\321\200\320\272\320\276\320\271.os" @@ -0,0 +1,15 @@ +#native + +Перем РегулярноеВыражение; + +Процедура ПриСозданииОбъекта(ТекстРегулярки) + РегулярноеВыражение = Новый РегулярноеВыражение(ТекстРегулярки); +КонецПроцедуры + +Функция НайтиСовпадения(Текст) Экспорт + + КоллекцияСовпадений = РегулярноеВыражение.НайтиСовпадения(Текст); + + Возврат КоллекцияСовпадений; + +КонецФункции \ No newline at end of file diff --git "a/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\320\276\320\243\320\274\320\276\320\273\321\207\320\260\320\275\320\270\321\216.os" "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\320\276\320\243\320\274\320\276\320\273\321\207\320\260\320\275\320\270\321\216.os" new file mode 100644 index 000000000..b943f980f --- /dev/null +++ "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\320\276\320\243\320\274\320\276\320\273\321\207\320\260\320\275\320\270\321\216.os" @@ -0,0 +1,39 @@ +#native + +Процедура ПриСозданииОбъекта() + +КонецПроцедуры + +Функция МетодСтроки(Текст1 = "Т1 ", Текст2 = "Т2 ") Экспорт + Возврат Текст1 + Текст2; +КонецФункции + +Функция МетодБулево(Булево = Истина) Экспорт + + Если Булево = Истина Или Булево Тогда + Возврат 1; + Иначе + Возврат 0; + КонецЕсли; + +КонецФункции + +Функция МетодНеопределено(Параметр = Неопределено) Экспорт + + Если Параметр = Неопределено Тогда + Возврат 1; + Иначе + Возврат 0; + КонецЕсли; + +КонецФункции + +Функция МетодЧисло(Параметр1 = -1, Параметр2 ) Экспорт + + Если Параметр1 = -1 Тогда + Возврат 1; + Иначе + Возврат 0 * Параметр2; + КонецЕсли; + +КонецФункции \ No newline at end of file diff --git "a/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271\320\241\320\242\320\265\320\272\321\201\321\202\320\276\320\274\320\222\320\232\320\276\320\275\321\201\321\202\321\200\321\203\320\272\321\202\320\276\321\200\320\265.os" "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271\320\241\320\242\320\265\320\272\321\201\321\202\320\276\320\274\320\222\320\232\320\276\320\275\321\201\321\202\321\200\321\203\320\272\321\202\320\276\321\200\320\265.os" new file mode 100644 index 000000000..3aaddf5de --- /dev/null +++ "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271\320\241\320\242\320\265\320\272\321\201\321\202\320\276\320\274\320\222\320\232\320\276\320\275\321\201\321\202\321\200\321\203\320\272\321\202\320\276\321\200\320\265.os" @@ -0,0 +1,7 @@ +#native + +Перем Поле1 Экспорт; + +Процедура ПриСозданииОбъекта(Параметр1) + Поле1 = Параметр1; +КонецПроцедуры \ No newline at end of file diff --git "a/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271.os" "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271.os" new file mode 100644 index 000000000..a9f126b28 --- /dev/null +++ "b/tests/native-lib/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\321\206\320\265\320\275\320\260\321\200\320\270\320\271.os" @@ -0,0 +1,18 @@ +#native + +Перем Поле1 Экспорт; + +Перем Поле2; + +Процедура ПриСозданииОбъекта() + Поле1 = 1; +КонецПроцедуры + + +Процедура Метод1() + +КонецПроцедуры + +Процедура Метод2() Экспорт + +КонецПроцедуры \ No newline at end of file diff --git a/tests/tasks.os b/tests/tasks.os index a09b38028..42e1f2c42 100644 --- a/tests/tasks.os +++ b/tests/tasks.os @@ -19,6 +19,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьОжиданиеКонкретногоЗадания"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВЗаданииПроставленаИнформацияОбОшибке"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВозвращаетсяРезультат"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВозвращаетсяРезультатДелегата"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоРаботаетБлокировка"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоКодМожетОпределитьИДЗадания"); @@ -179,6 +180,22 @@ КонецПроцедуры +Процедура ТестДолжен_ПроверитьЧтоВозвращаетсяРезультатДелегата() Экспорт + + Делегат = Новый Действие(ЭтотОбъект, "ПодсчетСуммы"); + + МассивПараметров = Новый Массив(2); + МассивПараметров[0] = 1; + МассивПараметров[1] = 5; + + ФЗ = ФоновыеЗадания.Выполнить(Делегат, "Выполнить", МассивПараметров); + + ФЗ.ОжидатьЗавершения(); + + юТест.ПроверитьРавенство(15, ФЗ.Результат); + +КонецПроцедуры + Процедура ТестДолжен_ПроверитьЧтоРаботаетБлокировка() Экспорт глБлокировка = Новый БлокировкаРесурса; diff --git a/tests/typedescription.os b/tests/typedescription.os index d780c3620..8a58a8228 100644 --- a/tests/typedescription.os +++ b/tests/typedescription.os @@ -31,6 +31,14 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеДат"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеБезПриведения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеЧисел"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеНеопределено"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеОбъектов"); + + ВсеТесты.Добавить("ТестДолжен_Преобразование_ОписаниеБезТипов"); + ВсеТесты.Добавить("ТестДолжен_Преобразование_ОписаниеБезТипов_КвалификаторыИгнорируются"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьОдинаковыйПорядокТипов"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПорядокПриведенияТипов"); Возврат ВсеТесты; @@ -445,3 +453,184 @@ юТест.ПроверитьРавенство(Описание.ПривестиЗначение(12345.555), 999.99, "Забивает девятками"); КонецПроцедуры + +Процедура ТестДолжен_Преобразование_ОписаниеБезТипов() Экспорт + + МассивТиповНеопределено = Новый Массив; + МассивТиповНеопределено.Добавить(Тип("Неопределено")); + + ПроверяемыеОписания = Новый СписокЗначений; + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов, + "Новый ОписаниеТипов" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов("Неопределено"), + "Новый ОписаниеТипов(""Неопределено"")" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов(МассивТиповНеопределено), + "Новый ОписаниеТипов(МассивТиповНеопределено)" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов("Undefined"), + "Новый ОписаниеТипов(""Undefined"")" + ); + + Для Каждого мЭлементПроверки Из ПроверяемыеОписания Цикл + + ОписаниеБезТипов = мЭлементПроверки.Значение; + ОписаниеСлучая = мЭлементПроверки.Представление; + + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(), Неопределено, "Приведение без параметра. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(1), 1, "Приведение числа. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение("1"), "1", "Приведение строки. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(Тип("Строка")), Тип("Строка"), "Приведение Типа. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение('20230817104356'), '20230817104356', "Приведение даты. " + ОписаниеСлучая); + + ДД = ПолучитьДвоичныеДанныеИзСтроки("Строка"); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(ДД), ДД, "Двоичные данные не ломаются. " + ОписаниеСлучая); + + юТест.ПроверитьРавенство(ОписаниеБезТипов.Типы().Количество(), 0, "Типы() пустой. " + ОписаниеСлучая); + // юТест.ПроверитьЛожь(ОписаниеБезТипов.СодержитТип(Тип("Неопределено")), "Нет типа Неопределено. " + ОписаниеСлучая); + + КонецЦикла; + +КонецПроцедуры + +Процедура ТестДолжен_Преобразование_ОписаниеБезТипов_КвалификаторыИгнорируются() Экспорт + + КЧ = Новый КвалификаторыЧисла(1); + КС = Новый КвалификаторыСтроки(1); + КД = Новый КвалификаторыДаты(ЧастиДаты.Время); + + МассивТиповНеопределено = Новый Массив; + МассивТиповНеопределено.Добавить(Тип("Неопределено")); + + ПроверяемыеОписания = Новый СписокЗначений; + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов(, КЧ, КС, КД), + "Новый ОписаниеТипов(, КЧ, КС, КД)" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов("Неопределено", КЧ, КС, КД), + "Новый ОписаниеТипов(""Неопределено"", КЧ, КС, КД)" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов(МассивТиповНеопределено, КЧ, КС, КД), + "Новый ОписаниеТипов(МассивТиповНеопределено, КЧ, КС, КД)" + ); + ПроверяемыеОписания.Добавить( + Новый ОписаниеТипов("Undefined", КЧ, КС, КД), + "Новый ОписаниеТипов(""Undefined"", КЧ, КС, КД)" + ); + + Для Каждого мЭлементПроверки Из ПроверяемыеОписания Цикл + + ОписаниеБезТипов = мЭлементПроверки.Значение; + ОписаниеСлучая = мЭлементПроверки.Представление; + + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(), Неопределено, "Приведение без параметра. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(123), 123, "Число не режется. " + ОписаниеСлучая); // не 1 + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение("123"), "123", "Строка не режется. " + ОписаниеСлучая); // не "1" + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(Тип("Строка")), Тип("Строка"), "Значение типа Тип не ломается. " + ОписаниеСлучая); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение('20230817104356'), '20230817104356', "Дата не режется. " + ОписаниеСлучая); // не `00010101104356` + + ДД = ПолучитьДвоичныеДанныеИзСтроки("Строка"); + юТест.ПроверитьРавенство(ОписаниеБезТипов.ПривестиЗначение(ДД), ДД, "Двоичные данные не ломаются. " + ОписаниеСлучая); + + юТест.ПроверитьРавенство(ОписаниеБезТипов.Типы().Количество(), 0, "Типы() пустой. " + ОписаниеСлучая); + юТест.ПроверитьЛожь(ОписаниеБезТипов.СодержитТип(Тип("Неопределено")), "Нет типа Неопределено. " + ОписаниеСлучая); + + КонецЦикла; + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПорядокПриведенияТипов() Экспорт + + ОписаниеТипов = Новый ОписаниеТипов("Число, Строка", Новый КвалификаторыСтроки(1)); + + юТест.ПроверитьРавенство(ОписаниеТипов.ПривестиЗначение(Истина), "Д"); // TODO: локализация + юТест.ПроверитьРавенство(ОписаниеТипов.ПривестиЗначение("Строка"), "С"); + юТест.ПроверитьРавенство(ОписаниеТипов.ПривестиЗначение(15), 15); + юТест.ПроверитьРавенство(ОписаниеТипов.ПривестиЗначение('20230911'), "1"); // TODO: локализация + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьОдинаковыйПорядокТипов() Экспорт + + ОТ = Новый ОписаниеТипов("Число, Строка"); + ПроверитьПорядокТипов(ОТ.Типы(), "Строка, Число"); + + ОТ = Новый ОписаниеТипов("Строка, Число"); + ПроверитьПорядокТипов(ОТ.Типы(), "Строка, Число"); + + ОТ = Новый ОписаниеТипов("Строка, Число, Строка"); + ПроверитьПорядокТипов(ОТ.Типы(), "Строка, Число"); + + ОТ = Новый ОписаниеТипов("Число, Число, Строка"); + ПроверитьПорядокТипов(ОТ.Типы(), "Строка, Число"); + + ОТ = Новый ОписаниеТипов("Число, Число, Строка, Дата, Булево, Неопределено"); + ПроверитьПорядокТипов(ОТ.Типы(), "Булево, Строка, Дата, Число"); + + ОТ = Новый ОписаниеТипов("Неопределено, Число, Дата, Строка, Дата, Булево"); + ПроверитьПорядокТипов(ОТ.Типы(), "Булево, Строка, Дата, Число"); + + ОТ = Новый ОписаниеТипов("ДвоичныеДанные, Неопределено, Тип, NULL, Число, Дата, Строка, Дата, Булево"); + ПроверитьПорядокТипов(ОТ.Типы(), "Булево, ДвоичныеДанные, Строка, Дата, Null, Число, Тип"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеНеопределено() Экспорт + + ОТ = Новый ОписаниеТипов("Число, Строка"); + юТест.ПроверитьИстину(ОТ.СодержитТип(Тип("Неопределено")), "Неопределено содержится в описании типов"); + юТест.ПроверитьРавенство(ОТ.Типы().Найти(Тип("Неопределено")), Неопределено, "Неопределено не содержится в типах"); + юТест.ПроверитьРавенство(ОТ.ПривестиЗначение(Неопределено), Неопределено, "Неопределено в неопределено"); + + ОТ = Новый ОписаниеТипов; + юТест.ПроверитьРавенство(ОТ.ПривестиЗначение(Неопределено), Неопределено, "Неопределено в неопределено"); + юТест.ПроверитьЛожь(ОТ.СодержитТип(Тип("Неопределено")), "Неопределено не содержится в описании типов (без типов)"); + юТест.ПроверитьРавенство(ОТ.Типы().Найти(Тип("Неопределено")), Неопределено, "Неопределено не содержится в типах"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеОбъектов() Экспорт + + ОТ = Новый ОписаниеТипов("Массив, Структура, Строка"); + + М1 = Новый Массив; + М1.Добавить(1); + М1.Добавить(2); + + М2 = ОТ.ПривестиЗначение(М1); + юТест.ПроверитьРавенство(М2, М1, "Массив тот же самый"); + +КонецПроцедуры + +Процедура ПроверитьПорядокТипов(Знач ТипыОписанияТипов, Знач ОжидаемыйПорядок, Знач Текст = Неопределено) + + Если Текст = Неопределено Тогда + Текст = СтрШаблон("Ожидаемый порядок: %1 + |Полученный порядок: %2", ОжидаемыйПорядок, СтрСоединить(ТипыОписанияТипов, ", ") + ); + КонецЕсли; + + ТипыСтроками = СтрРазделить(ОжидаемыйПорядок, ","); + + юТест.ПроверитьБольшеИлиРавно(ТипыОписанияТипов.Количество(), ТипыСтроками.Количество(), Текст); + + ИндексТипа = 0; + Для Каждого мТипСтрокой Из ТипыСтроками Цикл + + ТипОписания = ТипыОписанияТипов[ИндексТипа]; + ТипОжидаемый = Тип(СокрЛП(мТипСтрокой)); + + юТест.ПроверитьРавенство(ТипОписания, ТипОжидаемый); + + ИндексТипа = ИндексТипа + 1; + + КонецЦикла; + +КонецПроцедуры