From 04fb56f0c6f00ea2b3011571ced7083629bc672f Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Thu, 26 Dec 2024 14:34:32 +0300 Subject: [PATCH] Squash type inference --- .gitignore | 3 + build.gradle.kts | 1 + buildSrc/build.gradle.kts | 3 +- buildSrc/settings.gradle.kts | 1 - buildSrc/src/main/kotlin/Dependencies.kt | 38 +- .../src/main/kotlin/DetektConfiguration.kt | 7 +- .../kotlin/usvmpython/tasks/JNIHeaderTask.kt | 12 +- .../usvmpython/tasks/PythonSamplesTasks.kt | 9 +- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 +- gradlew.bat | 2 + settings.gradle.kts | 21 + usvm-dataflow-ts/.gitignore | 1 + usvm-dataflow-ts/README.md | 167 + usvm-dataflow-ts/build.gradle.kts | 133 + .../org/usvm/dataflow/ts/ifds/UnitResolver.kt | 62 + .../org/usvm/dataflow/ts/infer/AccessPath.kt | 104 + .../org/usvm/dataflow/ts/infer/Accessors.kt | 26 +- .../org/usvm/dataflow/ts/infer/Alias.kt | 345 + .../usvm/dataflow/ts/infer/AnalyzerEvent.kt | 25 + .../dataflow/ts/infer/ApplicationGraph.kt | 78 + .../dataflow/ts/infer/BackwardAnalyzer.kt | 44 + .../ts/infer/BackwardFlowFunctions.kt | 593 + .../dataflow/ts/infer/EntryPointsProcessor.kt | 25 + .../dataflow/ts/infer/EtsMethodTypeFacts.kt | 8 + .../org/usvm/dataflow/ts/infer/EtsTypeFact.kt | 530 + .../usvm/dataflow/ts/infer/ForwardAnalyzer.kt | 44 + .../dataflow/ts/infer/ForwardFlowFunctions.kt | 580 + .../usvm/dataflow/ts/infer/TypeDomainFact.kt | 21 + .../org/usvm/dataflow/ts/infer/TypeGuesser.kt | 271 + .../dataflow/ts/infer/TypeInferenceManager.kt | 705 + .../dataflow/ts/infer/TypeInferenceResult.kt | 57 + .../ts/infer/annotation/ExprTypeAnnotator.kt | 226 + .../ts/infer/annotation/StmtTypeAnnotator.kt | 70 + .../ts/infer/annotation/ValueTypeAnnotator.kt | 113 + .../ts/infer/annotation/withInferredTypes.kt | 91 + .../usvm/dataflow/ts/infer/cli/InferTypes.kt | 149 + .../org/usvm/dataflow/ts/infer/dto/Convert.kt | 195 + .../org/usvm/dataflow/ts/infer/dto/DTO.kt | 96 + .../org/usvm/dataflow/ts/infer/dto/OldDTO.kt | 213 + .../usvm/dataflow/ts/infer/verify/EntityId.kt | 79 + .../ts/infer/verify/VerificationResult.kt | 32 + .../usvm/dataflow/ts/infer/verify/Verify.kt | 28 + .../collectors/ClassSummaryCollector.kt | 39 + .../verify/collectors/ExprSummaryCollector.kt | 93 + .../verify/collectors/StmtSummaryCollector.kt | 80 + .../verify/collectors/SummaryCollector.kt | 76 + .../ts/infer/verify/collectors/Utils.kt | 34 + .../collectors/ValueSummaryCollector.kt | 84 + .../org/usvm/dataflow/ts/util/EtsTraits.kt | 252 + .../ts/util/TypeInferenceStatistics.kt | 694 + .../src/main/resources/logback.xml | 25 + .../org/usvm/dataflow/ts/test/EtsIfdsTest.kt | 437 + .../ts/test/EtsProjectAnalysisTest.kt | 155 + .../org/usvm/dataflow/ts/test/EtsSceneTest.kt | 184 + .../dataflow/ts/test/EtsTaintAnalysisTest.kt | 140 + .../dataflow/ts/test/EtsTypeAnnotationTest.kt | 193 + .../dataflow/ts/test/EtsTypeInferenceTest.kt | 603 + .../ts/test/EtsTypeResolverAbcTest.kt | 83 + .../ts/test/EtsTypeResolverWithAstTest.kt | 358 + .../usvm/dataflow/ts/test/TypeFactDtoTest.kt | 147 + .../ts/test/utils/ExpectedTypesExtractor.kt | 377 + .../dataflow/ts/test/utils/TaintConfig.kt | 108 + .../src/test/resources/ir/call.ts.json | 619 + .../src/test/resources/ir/cast.ts.json | 532 + .../src/test/resources/ir/data.ts.json | 1038 + .../src/test/resources/ir/microphone.ts.json | 1527 + .../test/resources/ir/microphone_ctor.ts.json | 1574 + .../src/test/resources/ir/nested_init.ts.json | 1234 + .../test/resources/ir/resolver_test.ts.json | 2605 ++ .../src/test/resources/ir/taint.ts.json | 1495 + .../src/test/resources/ir/testcases.ts.json | 26440 ++++++++++++++++ .../src/test/resources/ir/types.ts.json | 2691 ++ .../src/test/resources/logback.xml | 25 + .../src/test/resources/ts/call.ts | 13 + .../src/test/resources/ts/cast.ts | 12 + .../src/test/resources/ts/data.ts | 17 + .../src/test/resources/ts/microphone.ts | 25 + .../src/test/resources/ts/microphone_ctor.ts | 33 + .../src/test/resources/ts/nested_init.ts | 23 + .../src/test/resources/ts/resolver_test.ts | 50 + .../src/test/resources/ts/taint.ts | 32 + .../src/test/resources/ts/testcases.ts | 994 + .../src/test/resources/ts/types.ts | 55 + .../kotlin/org/usvm/dataflow/ts/LoadEts.kt | 117 + .../kotlin/org/usvm/dataflow/ts/Resources.kt | 20 + .../org/usvm/dataflow/ts/TestFactoryDsl.kt | 52 + usvm-dataflow/build.gradle.kts | 8 +- .../org/usvm/dataflow/config/Condition.kt | 4 +- .../org/usvm/dataflow/config/Position.kt | 6 +- .../org/usvm/dataflow/config/TaintAction.kt | 10 +- .../kotlin/org/usvm/dataflow/ifds/Maybe.kt | 60 - .../usvm/dataflow/taint/TaintFlowFunctions.kt | 3 +- usvm-jvm-dataflow/build.gradle.kts | 3 - .../usvm/dataflow/jvm/npe/NpeFlowFunctions.kt | 2 +- .../jvm/impl/ConditionEvaluatorTest.kt | 4 +- .../impl/NullabilityAssumptionAnalysisTest.kt | 69 - .../kotlin/org/usvm/TSApplicationGraph.kt | 6 +- .../main/kotlin/org/usvm/TSExprResolver.kt | 27 +- .../src/main/kotlin/org/usvm/TSInterpreter.kt | 2 +- usvm-ts/src/main/kotlin/org/usvm/TSMachine.kt | 4 +- .../src/main/kotlin/org/usvm/TSTypeSystem.kt | 4 +- .../org/usvm/util/TSMethodTestRunner.kt | 7 +- .../src/main/kotlin/org/usvm/util/Logging.kt | 8 +- .../src/main/kotlin/org/usvm/util/Maybe.kt | 62 +- 106 files changed, 50651 insertions(+), 240 deletions(-) create mode 100644 usvm-dataflow-ts/.gitignore create mode 100644 usvm-dataflow-ts/README.md create mode 100644 usvm-dataflow-ts/build.gradle.kts create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/ifds/UnitResolver.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AccessPath.kt rename usvm-jvm-dataflow/src/samples/java/NullAssumptionAnalysisExample.java => usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Accessors.kt (63%) create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Alias.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AnalyzerEvent.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ApplicationGraph.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardAnalyzer.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardFlowFunctions.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EntryPointsProcessor.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsMethodTypeFacts.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsTypeFact.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardAnalyzer.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardFlowFunctions.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeDomainFact.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeGuesser.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceManager.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceResult.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ExprTypeAnnotator.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/StmtTypeAnnotator.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ValueTypeAnnotator.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/withInferredTypes.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/cli/InferTypes.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/Convert.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/DTO.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/OldDTO.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/EntityId.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/VerificationResult.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/Verify.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ClassSummaryCollector.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ExprSummaryCollector.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/StmtSummaryCollector.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/SummaryCollector.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/Utils.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ValueSummaryCollector.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/EtsTraits.kt create mode 100644 usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/TypeInferenceStatistics.kt create mode 100644 usvm-dataflow-ts/src/main/resources/logback.xml create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsIfdsTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsProjectAnalysisTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsSceneTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTaintAnalysisTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeAnnotationTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeInferenceTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverAbcTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverWithAstTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/TypeFactDtoTest.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/ExpectedTypesExtractor.kt create mode 100644 usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/TaintConfig.kt create mode 100644 usvm-dataflow-ts/src/test/resources/ir/call.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/cast.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/data.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/microphone.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/microphone_ctor.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/nested_init.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/resolver_test.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/taint.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/testcases.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/ir/types.ts.json create mode 100644 usvm-dataflow-ts/src/test/resources/logback.xml create mode 100644 usvm-dataflow-ts/src/test/resources/ts/call.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/cast.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/data.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/microphone.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/microphone_ctor.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/nested_init.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/resolver_test.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/taint.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/testcases.ts create mode 100644 usvm-dataflow-ts/src/test/resources/ts/types.ts create mode 100644 usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/LoadEts.kt create mode 100644 usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/Resources.kt create mode 100644 usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/TestFactoryDsl.kt delete mode 100644 usvm-dataflow/src/main/kotlin/org/usvm/dataflow/ifds/Maybe.kt delete mode 100644 usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/NullabilityAssumptionAnalysisTest.kt diff --git a/.gitignore b/.gitignore index 3322abd66b..adbbc452c4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ buildSrc/.gradle # Ignore Python execution cache __pycache__/ run_python_with_gdb.sh + +# Ignore Kotlin build directory +.kotlin/ diff --git a/build.gradle.kts b/build.gradle.kts index d2e8d1144c..af49bd0af8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ plugins { + id(Plugins.Shadow) id("usvm.kotlin-conventions") } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index cbd46db18e..5075d846cd 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,9 +12,8 @@ repositories { maven("https://jitpack.io") } - dependencies { implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$detektVersion") implementation("org.glavo:gjavah:$gjavahVersion") -} \ No newline at end of file +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index c6e4cfd742..27752ba2fd 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1,2 +1 @@ rootProject.name="usvm-conventions" - diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 1f3b2f8c76..a75c9cee9e 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -3,9 +3,10 @@ import org.gradle.plugin.use.PluginDependenciesSpec object Versions { - const val detekt = "1.18.1" + const val clikt = "5.0.0" + const val detekt = "1.23.7" const val ini4j = "0.5.4" - const val jacodb = "6539d5020c" + const val jacodb = "7df406e5e7" const val juliet = "1.3.2" const val junit = "5.9.3" const val kotlin = "2.1.0" @@ -18,7 +19,7 @@ object Versions { const val mockk = "1.13.4" const val rd = "2023.2.0" const val sarif4k = "0.5.0" - const val shadow = "8.1.1" + const val shadow = "8.3.3" const val slf4j = "1.6.1" // versions for jvm samples @@ -121,6 +122,11 @@ object Libs { name = "jacodb-core", version = Versions.jacodb ) + val jacodb_api_common = dep( + group = jacodbPackage, + name = "jacodb-api-common", + version = Versions.jacodb + ) val jacodb_api_jvm = dep( group = jacodbPackage, name = "jacodb-api-jvm", @@ -136,16 +142,6 @@ object Libs { name = "jacodb-storage", version = Versions.jacodb ) - val jacodb_ets = dep( - group = jacodbPackage, - name = "jacodb-ets", - version = Versions.jacodb - ) - val jacodb_api_common = dep( - group = jacodbPackage, - name = "jacodb-api-common", - version = Versions.jacodb - ) val jacodb_approximations = dep( group = jacodbPackage, name = "jacodb-approximations", @@ -156,6 +152,11 @@ object Libs { name = "jacodb-taint-configuration", version = Versions.jacodb ) + val jacodb_ets = dep( + group = jacodbPackage, + name = "jacodb-ets", + version = Versions.jacodb + ) // https://github.com/Kotlin/kotlinx.coroutines val kotlinx_coroutines_core = dep( @@ -240,6 +241,13 @@ object Libs { name = "PythonTypesAPI", version = Versions.pythonTypesAPI ) + + // https://github.com/ajalt/clikt + val clikt = dep( + group = "com.github.ajalt.clikt", + name = "clikt", + version = Versions.clikt + ) } object Plugins { @@ -258,9 +266,9 @@ object Plugins { version = Versions.rd ) - // https://github.com/johnrengelman/shadow + // https://github.com/GradleUp/shadow object Shadow : ProjectPlugin( - id = "com.github.johnrengelman.shadow", + id = "com.gradleup.shadow", version = Versions.shadow ) } diff --git a/buildSrc/src/main/kotlin/DetektConfiguration.kt b/buildSrc/src/main/kotlin/DetektConfiguration.kt index b1fa87b9b9..60726cf8c7 100644 --- a/buildSrc/src/main/kotlin/DetektConfiguration.kt +++ b/buildSrc/src/main/kotlin/DetektConfiguration.kt @@ -1,7 +1,6 @@ -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.detekt -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.detektPlugins import io.gitlab.arturbosch.detekt.Detekt import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask +import io.gitlab.arturbosch.detekt.extensions.DetektExtension import io.gitlab.arturbosch.detekt.report.ReportMergeTask import org.gradle.api.Project import org.gradle.api.tasks.TaskProvider @@ -11,7 +10,7 @@ import org.gradle.kotlin.dsl.withType fun Project.configureDetekt() { dependencies { - detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:${detekt.toolVersion}") + "detektPlugins"("io.gitlab.arturbosch.detekt:detekt-formatting:${Versions.detekt}") } val includes = listOf( @@ -36,7 +35,7 @@ fun Project.configureDetekt() { val configFile = rootDir.resolve("detekt").resolve("config.yml") val reportFile = rootProject.layout.buildDirectory.file("reports/detekt/detekt.sarif") - detekt { + extensions.configure("detekt") { buildUponDefaultConfig = true ignoreFailures = true parallel = true diff --git a/buildSrc/src/main/kotlin/usvmpython/tasks/JNIHeaderTask.kt b/buildSrc/src/main/kotlin/usvmpython/tasks/JNIHeaderTask.kt index cf8559de73..b85c72a068 100644 --- a/buildSrc/src/main/kotlin/usvmpython/tasks/JNIHeaderTask.kt +++ b/buildSrc/src/main/kotlin/usvmpython/tasks/JNIHeaderTask.kt @@ -1,20 +1,20 @@ package usvmpython.tasks -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.main -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.sourceSets import org.glavo.javah.JavahTask import org.gradle.api.Project -import usvmpython.getGeneratedHeadersPath +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.kotlin.dsl.get import usvmpython.CPYTHON_ADAPTER_CLASS - +import usvmpython.getGeneratedHeadersPath fun Project.generateJNIForCPythonAdapterTask() { val task = JavahTask() task.outputDir = getGeneratedHeadersPath().toPath() - val classpath = sourceSets.main.get().runtimeClasspath + val sourceSets = extensions.getByName("sourceSets") as SourceSetContainer + val classpath = sourceSets["main"].runtimeClasspath classpath.files.forEach { task.addClassPath(it.toPath()) } task.addClass(CPYTHON_ADAPTER_CLASS) task.run() -} \ No newline at end of file +} diff --git a/buildSrc/src/main/kotlin/usvmpython/tasks/PythonSamplesTasks.kt b/buildSrc/src/main/kotlin/usvmpython/tasks/PythonSamplesTasks.kt index f405d46cb0..5bd88797be 100644 --- a/buildSrc/src/main/kotlin/usvmpython/tasks/PythonSamplesTasks.kt +++ b/buildSrc/src/main/kotlin/usvmpython/tasks/PythonSamplesTasks.kt @@ -1,12 +1,12 @@ package usvmpython.tasks -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.sourceSets -import gradle.kotlin.dsl.accessors._466a692754d3da37fc853e1c7ad8ae1e.test import org.gradle.api.Project import org.gradle.api.tasks.Exec import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.environment +import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.register import usvmpython.* import java.io.File @@ -45,10 +45,11 @@ fun Project.registerBuildSamplesTask(): TaskProvider { dependsOn(installMypyRunner) inputs.files(fileTree(samplesSourceDir).exclude("**/__pycache__/**")) outputs.dir(samplesBuildDir) - classpath = sourceSets.test.get().runtimeClasspath + val sourceSets = extensions.getByName("sourceSets") as SourceSetContainer + classpath = sourceSets["test"].runtimeClasspath args = listOf(samplesSourceDir.canonicalPath, samplesBuildDir.canonicalPath, pythonBinaryPath) environment("LD_LIBRARY_PATH" to "$cpythonBuildPath/lib:$cpythonAdapterBuildPath") environment("PYTHONHOME" to cpythonBuildPath) mainClass.set(BUILD_SAMPLES_ENTRY_POINT) } -} \ No newline at end of file +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 34463 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 SXRcJ{65?fGI57uQ5&!`B?F@7P delta 34554 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce5c..7cf748e743 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4269..f5feea6d6b 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 25da30dbde..9d21a21834 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/settings.gradle.kts b/settings.gradle.kts index 121c7fcbd5..a22993f813 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,6 +8,7 @@ include("usvm-jvm-instrumentation") include("usvm-sample-language") include("usvm-dataflow") include("usvm-jvm-dataflow") +include("usvm-dataflow-ts") include("usvm-python") include("usvm-python:cpythonadapter") @@ -21,6 +22,11 @@ findProject(":usvm-python:usvm-python-runner")?.name = "usvm-python-runner" include("usvm-python:usvm-python-commons") findProject(":usvm-python:usvm-python-commons")?.name = "usvm-python-commons" +// Actually, `includeBuild("../jacodb")` is enough, but there is a bug in IDEA when path is a symlink. +// As a workaround, we convert it to a real absolute path. +// See IDEA bug: https://youtrack.jetbrains.com/issue/IDEA-329756 +// includeBuild(file("../jacodb").toPath().toRealPath().toAbsolutePath()) + pluginManagement { resolutionStrategy { eachPlugin { @@ -30,3 +36,18 @@ pluginManagement { } } } + +plugins { + id("com.gradle.develocity") version ("3.18.2") +} + +develocity { + buildScan { + // Accept the term of use for the build scan plugin: + termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use") + termsOfUseAgree.set("yes") + + // Publish build scans on-demand, when `--scan` option is provided: + publishing.onlyIf { false } + } +} diff --git a/usvm-dataflow-ts/.gitignore b/usvm-dataflow-ts/.gitignore new file mode 100644 index 0000000000..333c1e910a --- /dev/null +++ b/usvm-dataflow-ts/.gitignore @@ -0,0 +1 @@ +logs/ diff --git a/usvm-dataflow-ts/README.md b/usvm-dataflow-ts/README.md new file mode 100644 index 0000000000..59dd9cae7f --- /dev/null +++ b/usvm-dataflow-ts/README.md @@ -0,0 +1,167 @@ +# USVM Dataflow TS + +## Type Inference + +In order to run type inference on an arbitrary TypeScript project, you need the following: +1. IR dumped into JSON files: either from TS sources or from +binary ABC/HAP files. +2. USVM with type inference CLI: `usvm-dataflow-ts-all.jar` "fat" JAR. + +**NOTE:** the instructions below are given for Linux. If you are using Windows, you need to adjust the paths and commands accordingly, or use WSL. Overall, the process should be similar, and USVM should work on any platform that supports Java. + +### ArkTS IR + +- Below, we use the term "ArkIR" to refer to the representation of ArkTS inside ArkAnalyzer in a form of TypeScript classes and interfaces, such as `ArkMethod`, `ArkAssignStmt`, `ArkInstanceInvokeExpr`. + +- In USVM, we also have a similar model of representing ArkTS, but in the form of Java/Kotlin classes. In order to differentiate between the two models, we use the prefix "Ets" for the classes in USVM, such as `EtsMethod`, `EtsAssignStmt`, `EtsInstanceCallExpr`. + +### Setup ArkAnalyzer + +First of all, you need to clone the ArkAnalyzer repo. Here, we use the fork of the repo and the specific branch (named `neo/`) that is consistent with USVM internals. Note that this branch might change in the future. +```bash +cd ~ +git clone -b neo/2024-10-31 https://gitee.com/Lipenx/arkanalyzer arkanalyzer-usvm +cd arkanalyzer-usvm +``` + +Then, you need to install the dependencies and build the project. +```bash +npm install +npm run build +``` + +**Note:** after building the ArkAnalyzer project, the script for serializing ArkIR will be located at `out/save/serializeArkIR.js` and can be run with Node.js. + +**Note:** you can also use TS script directly using `npx ts-node src/save/serializeArkIR.ts` instead of building the whole project. + +### Serialize ArkIR to JSON + +Now, you can run the `serializeArkIR` script on your TS project in order to construct its ArkIR representation and dump it into JSON files, which can later be used by USVM. +```bash +node ~/arkanalyzer-usvm/out/src/save/serializeArkIR.js --help +``` +```text +Usage: serializeArkIR [options] + +Serialize ArkIR for TypeScript files or projects to JSON + +Arguments: + input Input file or directory + output Output file or directory + +Options: + -p, --project Flag to indicate the input is a project directory (default: false) + -t, --infer-types [times] Infer types in the ArkIR + -v, --verbose Verbose output (default: false) + -h, --help display help for command +``` + +If you have a single TS file `sample.ts`, just run the following command: +```bash +node .../serializeArkIR.js sample.ts sample.json +``` +The resulting `sample.json` file will contain the ArkIR in JSON format. + +If you have a TS project in the `project` directory, use `-p` flag: +```bash +node .../serializeArkIR.js -p project etsir +``` +The resulting `etsir` directory will contain the ArkIR in JSON format. The structure of the resulting directory (hierarchy of subfolders) will be the same as the structure of the input project, but all the files will be `*.ts.json`. + +_Note:_ We call the result "EtsIR" since it is a modified version of the ArkIR model suitable for serialization. When we load IR from JSONs in USVM (Java/Kotlin), the resulting data model (structure of classes) is very similar to ArkIR in ArkAnalyzer (TypeScript), but has some minor differences. The term "EtsIR" is used to distinguish between the two. + +If you have a TS project with multiple modules, run the serialization for each module separately: +```bash +node .../serializeArkIR.js -p project/entry etsir/entry +node .../serializeArkIR.js -p project/common etsir/common +node .../serializeArkIR.js -p project/feature etsir/feature +``` + +### Type Inference with USVM + +In order to run USVM type inference, you need to obtain `usvm-dataflow-ts-all.jar` "fat" JAR (download or build it yourself) and either use it directly or use a wrapper script `src/usvm/inferTypes.ts` in ArkAnalyzer repo. + +#### Build `usvm-type-inference` binary + +In order to build the USVM binary, you need to clone the USVM repo (and also its dependency `jacodb` in the _sibling directory_) and build the project using Gradle. +```bash +cd ~ +git clone -b lipen/usvm-type-inference https://github.com/UnitTestBot/jacodb +git clone -b lipen/type-inference https://github.com/UnitTestBot/usvm +cd usvm +./gradlew :usvm-dataflow-ts:installDist +``` +The last command will build the project and create the binary at `usvm-dataflow-ts/build/install/usvm-dataflow-ts/bin/usvm-type-inference` (on Windows, the corresponding "binary" is with `.bat` extension). + +#### Build "Fat" JAR + +Alternatively, you can build the "fat" JAR (also known as "Uber JAR" or "shadow JAR") that contains all the dependencies. +```bash +./gradlew :usvm-dataflow-ts:shadowJar +``` + +#### Run Type Inference + +You can run the type inference manually using USVM CLI: +```bash +usvm-dataflow-ts/build/install/usvm-dataflow-ts/bin/usvm-type-inference --help +# OR +java -jar usvm-dataflow-ts/build/libs/usvm-dataflow-ts-all.jar --help +``` +```text +Usage: infer-types [] + +Options: +* -i, --input= Input file or directory with IR (required) +* -o, --output= Output file with inferred types in JSON format (required) + -h, --help Show this message and exit +``` + +_Note:_ `-i` option can be supplied multiple times for multi-module projects. All input IR will be merged. + +For example, if you have the `project/entry` and `project/common` directories with the dumped ArkIR, you can run the following command: +```bash +java -jar usvm-dataflow-ts/build/libs/usvm-dataflow-ts-all.jar -i project/entry -i project/common -o inferred.json +``` + +### Type Inference with Wrapper Script + +You can also use the wrapper script `src/usvm/inferTypes.ts` from the ArkAnalyzer repo. This script will run the serialization of ArkIR and type inference with USVM in a single command. + +```bash +node ~/arkanalyzer-usvm/out/src/usvm/inferTypes.js --help +``` +```text +Usage: inferTypes [options] + +Arguments: + input input directory with ETS project + +Options: + -v, --verbose Verbose output (default: false) + -t, --aa-types Run type inference in ArkAnalyzer (default: false) + -s, --substitute Substitute inferred types (default: false) + -h, --help display help for command +``` + +For example: +```bash +node .../inferTypes.js myproject/entry +``` +```text +Building scene... +Serializing Scene to '/tmp/2f8aa8b34548b808167a8f6b30121dcc/etsir'... +... +USVM command: ~/usvm/usvm-dataflow-ts/build/install/usvm-dataflow-ts/bin/usvm-type-inference --input=/tmp/2f8aa8b34548b808167a8f6b30121dcc/etsir --output=/tmp/2f8aa8b34548b808167a8f6b30121dcc/inference-result --no-skip-anonymous +... +=== Inferred Types Statistics === +Total Classes: 10 +Total Methods: 305 +... +Deserialization successful. +... +Substituting inferred types... +... +Substituting type of local '$temp16' in method '@entry/model/Calculator.ts: _DEFAULT_ARK_CLASS.getFloatNum(unknown, unknown, unknown)' from unknown to number +... +``` diff --git a/usvm-dataflow-ts/build.gradle.kts b/usvm-dataflow-ts/build.gradle.kts new file mode 100644 index 0000000000..4330a721b9 --- /dev/null +++ b/usvm-dataflow-ts/build.gradle.kts @@ -0,0 +1,133 @@ + +import java.io.FileNotFoundException +import java.nio.file.Files +import java.nio.file.attribute.FileTime + +plugins { + id("usvm.kotlin-conventions") + kotlin("plugin.serialization") version Versions.kotlin + application + id(Plugins.Shadow.id) + `java-test-fixtures` +} + +dependencies { + api(project(":usvm-dataflow")) + api(project(":usvm-util")) + + api(Libs.jacodb_api_common) + api(Libs.jacodb_ets) + implementation(Libs.jacodb_taint_configuration) + implementation(Libs.kotlinx_collections) + implementation(Libs.kotlinx_serialization_json) + implementation(Libs.clikt) + + testImplementation(Libs.mockk) + testImplementation(Libs.junit_jupiter_params) + testImplementation(Libs.logback) + testImplementation(Libs.kotlinx_serialization_core) + + testFixturesImplementation(Libs.kotlin_logging) + testFixturesImplementation(Libs.junit_jupiter_api) +} + +tasks.withType { + maxHeapSize = "4G" +} + +val generateTestResources by tasks.registering { + group = "build" + description = "Generates JSON resources from TypeScript files using ArkAnalyzer." + doLast { + val envVarName = "ARKANALYZER_DIR" + val defaultArkAnalyzerDir = "../arkanalyzer" + + val arkAnalyzerDir = rootDir.resolve(System.getenv(envVarName) ?: run { + println("Please, set $envVarName environment variable. Using default value: '$defaultArkAnalyzerDir'") + defaultArkAnalyzerDir + }) + if (!arkAnalyzerDir.exists()) { + throw FileNotFoundException("ArkAnalyzer directory does not exist: '$arkAnalyzerDir'. Did you forget to set the '$envVarName' environment variable?") + } + + val scriptSubPath = "src/save/serializeArkIR" + val script = arkAnalyzerDir.resolve("out").resolve("$scriptSubPath.js") + if (!script.exists()) { + throw FileNotFoundException("Script file not found: '$script'. Did you forget to execute 'npm run build' in the arkanalyzer project?") + } + + val resources = projectDir.resolve("src/test/resources") + val inputDir = resources.resolve("ts") + val outputDir = resources.resolve("ir") + println("Generating test resources in '${outputDir.relativeTo(projectDir)}'...") + + inputDir.walkTopDown().filter { it.isFile }.forEach { input -> + val output = outputDir + .resolve(input.relativeTo(inputDir)) + .resolveSibling(input.name + ".json") + val inputFileTime = Files.getLastModifiedTime(input.toPath()) + val outputFileTime = if (output.exists()) { + Files.getLastModifiedTime(output.toPath()) + } else { + FileTime.fromMillis(0) + } + + if (!output.exists() || inputFileTime > outputFileTime) { + println("Regenerating JSON for '${output.relativeTo(outputDir)}'...") + + val cmd: List = listOf( + "node", + script.absolutePath, + input.relativeTo(resources).path, + output.relativeTo(resources).path, + ) + println("Running: '${cmd.joinToString(" ")}'") + val process = ProcessBuilder(cmd).directory(resources).start(); + val ok = process.waitFor(10, TimeUnit.MINUTES) + + val stdout = process.inputStream.bufferedReader().readText().trim() + if (stdout.isNotBlank()) { + println("[STDOUT]:\n--------\n$stdout\n--------") + } + val stderr = process.errorStream.bufferedReader().readText().trim() + if (stderr.isNotBlank()) { + println("[STDERR]:\n--------\n$stderr\n--------") + } + + if (!ok) { + println("Timeout!") + process.destroy() + } else { + println("Done running!") + } + } else { + println("Skipping '${output.relativeTo(outputDir)}'") + } + } + } +} + +// tasks.test { +// dependsOn(generateTestResources) +// } + +application { + mainClass = "org.usvm.dataflow.ts.infer.cli.InferTypesKt" + applicationDefaultJvmArgs = listOf("-Dfile.encoding=UTF-8", "-Dsun.stdout.encoding=UTF-8") +} + +tasks.startScripts { + applicationName = "usvm-type-inference" +} + +tasks.shadowJar { + minimize { + // Note: keep 'mordant' dependency inside shadowJar, or else the following error occurs: + // ``` + // Exception in thread "main" java.util.ServiceConfigurationError: + // com.github.ajalt.mordant.terminal.TerminalInterfaceProvider: + // Provider com.github.ajalt.mordant.terminal.terminalinterface.jna.TerminalInterfaceProviderJna not found + // ``` + exclude(dependency("com.github.ajalt.mordant:.*:.*")) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/ifds/UnitResolver.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/ifds/UnitResolver.kt new file mode 100644 index 0000000000..ba9bba9971 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/ifds/UnitResolver.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.ifds + +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsMethodSignature +import org.usvm.dataflow.ifds.SingletonUnit +import org.usvm.dataflow.ifds.UnitResolver +import org.usvm.dataflow.ifds.UnitType + +data class MethodUnit(val method: EtsMethodSignature) : UnitType { + override fun toString(): String { + return "MethodUnit(${method.name})" + } +} + +data class ClassUnit(val clazz: EtsClassSignature) : UnitType { + override fun toString(): String { + return "ClassUnit(${clazz.name})" + } +} + +// TODO: PackageUnit +// data class PackageUnit(val packageName: String) : UnitType { +// override fun toString(): String { +// return "PackageUnit($packageName)" +// } +// } + +fun interface EtsUnitResolver : UnitResolver + +val MethodUnitResolver = EtsUnitResolver { method -> + MethodUnit(method.signature) +} + +val ClassUnitResolver = EtsUnitResolver { method -> + ClassUnit(method.signature.enclosingClass) +} + +// TODO: PackageUnitResolver +// val PackageUnitResolver = EtsUnitResolver { method -> +// PackageUnit(method.enclosingClass.packageName) +// } + +val SingletonUnitResolver = EtsUnitResolver { + SingletonUnit +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AccessPath.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AccessPath.kt new file mode 100644 index 0000000000..85a3ad6a00 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AccessPath.kt @@ -0,0 +1,104 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.base.EtsArrayAccess +import org.jacodb.ets.base.EtsCastExpr +import org.jacodb.ets.base.EtsConstant +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsInstanceFieldRef +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsStaticFieldRef +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsValue + +data class AccessPath(val base: AccessPathBase, val accesses: List) { + operator fun plus(accessor: Accessor) = AccessPath(base, accesses + accessor) + operator fun plus(accessors: List) = AccessPath(base, accesses + accessors) + + override fun toString(): String { + return base.toString() + accesses.joinToString("") { it.toSuffix() } + } +} + +fun List.startsWith(other: List): Boolean { + return this.take(other.size) == other +} + +fun AccessPath?.startsWith(other: AccessPath?): Boolean { + if (this == null || other == null) { + return false + } + if (this.base != other.base) { + return false + } + return this.accesses.startsWith(other.accesses) +} + +fun List.hasDuplicateFields(limit: Int = 2): Boolean { + val counts = this.groupingBy { it }.eachCount() + return counts.any { it.value >= limit } +} + +sealed interface AccessPathBase { + object This : AccessPathBase { + override fun toString(): String = "" + } + + object Static : AccessPathBase { + override fun toString(): String = "" + } + + data class Arg(val index: Int) : AccessPathBase { + override fun toString(): String = "arg($index)" + } + + data class Local(val name: String) : AccessPathBase { + override fun toString(): String = "local($name)" + } + + data class Const(val constant: EtsConstant) : AccessPathBase { + override fun toString(): String = "const($constant)" + } +} + +fun EtsValue.toBase(): AccessPathBase = when (this) { + is EtsConstant -> AccessPathBase.Const(this) + is EtsLocal -> if (name == "this") AccessPathBase.This else AccessPathBase.Local(name) + is EtsThis -> AccessPathBase.This + is EtsParameterRef -> AccessPathBase.Arg(index) + else -> error("$this is not access path base") +} + +fun EtsEntity.toPathOrNull(): AccessPath? = when (this) { + is EtsConstant -> AccessPath(toBase(), emptyList()) + + is EtsLocal -> AccessPath(toBase(), emptyList()) + + is EtsThis -> AccessPath(toBase(), emptyList()) + + is EtsParameterRef -> AccessPath(toBase(), emptyList()) + + is EtsArrayAccess -> { + array.toPathOrNull()?.let { + it + ElementAccessor + } + } + + is EtsInstanceFieldRef -> { + instance.toPathOrNull()?.let { + it + FieldAccessor(field.name) + } + } + + is EtsStaticFieldRef -> { + AccessPath(AccessPathBase.Static, listOf(FieldAccessor(field.name))) + } + + is EtsCastExpr -> arg.toPathOrNull() + + else -> null +} + +fun EtsEntity.toPath(): AccessPath { + return toPathOrNull() ?: error("Unable to build access path for value $this") +} diff --git a/usvm-jvm-dataflow/src/samples/java/NullAssumptionAnalysisExample.java b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Accessors.kt similarity index 63% rename from usvm-jvm-dataflow/src/samples/java/NullAssumptionAnalysisExample.java rename to usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Accessors.kt index abdcec3540..d077062d57 100644 --- a/usvm-jvm-dataflow/src/samples/java/NullAssumptionAnalysisExample.java +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Accessors.kt @@ -14,16 +14,20 @@ * limitations under the License. */ -public class NullAssumptionAnalysisExample { - public void test1(String a) { - System.out.println("Hello from test1"); - System.out.println(a.length()); - } +package org.usvm.dataflow.ts.infer - public void test2(Object a) { - System.out.println("Hello from test2"); - System.out.println(a.hashCode()); - String x = (String) a; - System.out.println(x.length()); - } +sealed interface Accessor { + fun toSuffix(): String +} + +data class FieldAccessor( + val name: String, +) : Accessor { + override fun toSuffix(): String = ".${name}" + override fun toString(): String = name +} + +object ElementAccessor : Accessor { + override fun toSuffix(): String = "[*]" + override fun toString(): String = "*" } diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Alias.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Alias.kt new file mode 100644 index 0000000000..ed80441082 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/Alias.kt @@ -0,0 +1,345 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer + +import kotlinx.collections.immutable.PersistentMap +import kotlinx.collections.immutable.mutate +import kotlinx.collections.immutable.persistentHashMapOf +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsCallExpr +import org.jacodb.ets.base.EtsCastExpr +import org.jacodb.ets.base.EtsConstant +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsNewArrayExpr +import org.jacodb.ets.base.EtsNewExpr +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsRef +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.model.EtsMethod + +sealed interface Allocation { + class New : Allocation + data class Arg(val index: Int) : Allocation + class CallResult : Allocation + class Imm : Allocation +} + +// class Allocation2(val index: Int?) { +// override fun equals(other: Any?): Boolean { +// if (other === this) return true +// if (other !is Allocation2) return false +// if (index != null) return index == other.index +// return false +// } +// } + +class AliasInfo( + // B: Base -> Object + val B: PersistentMap, + // F: Object x Field -> Object + val F: PersistentMap>, +) { + // A: Base x Field* -> Object + fun find(path: AccessPath): Allocation? { + val b = B[path.base] ?: return null + if (path.accesses.isEmpty()) return b + // TODO: handle multiple accesses + check(path.accesses.size == 1) + return when (val a = path.accesses.single()) { + is FieldAccessor -> { + val f = F[b] ?: return null + f[a.name] + } + + is ElementAccessor -> null + } + } + + fun merge(other: AliasInfo): AliasInfo { + // Intersect B: + val newB = persistentHashMapOf().mutate { newB -> + for ((base, obj) in this.B) { + if (other.B[base] == obj) { + newB[base] = obj + } + } + } + + // Intersect F: + val newF = persistentHashMapOf>().mutate { newF -> + for ((obj, fields) in this.F) { + newF[obj] = persistentHashMapOf().mutate { newFields -> + val otherFields = other.F[obj] + if (otherFields != null) { + for ((field, alloc) in fields) { + if (otherFields[field] == alloc) { + newFields[field] = alloc + } + } + } + } + } + } + + return AliasInfo(newB, newF) + } + + /** + * Returns the set of access paths that must alias with the given path (excluding the path itself). + */ + fun getAliases(path: AccessPath): Set { + val obj = find(path) ?: return emptySet() + return getAliases(obj) - path + } + + private fun getAliases(obj: Allocation): Set { + val paths = mutableSetOf() + + val invF = hashMapOf>>() + for ((obj1, fields) in F) { + for ((field, obj2) in fields) { + invF.computeIfAbsent(obj2) { hashMapOf() } + invF.computeIfAbsent(obj2) { hashMapOf() } + .computeIfAbsent(field) { mutableListOf() } + .add(obj1) + } + } + + val invB = hashMapOf>() + for ((base, alloc) in B) { + invB.computeIfAbsent(alloc) { mutableListOf() } + .add(base) + } + + val queue = ArrayDeque>>(listOf(obj to emptyList())) + while (queue.isNotEmpty()) { + val (cur, path) = queue.removeFirst() + // TODO: eliminate loops as in computeAliases via DFS with PATH/STACK + // TODO: think about loop-edges + if (path.size > 10) continue + if (cur in invB) { + for (base in invB[cur]!!) { + paths.add(AccessPath(base, path.reversed())) + } + } + if (cur in invF) { + for ((field, objs) in invF[cur]!!) { + for (alloc in objs) { + queue.add(alloc to path + FieldAccessor(field)) + } + } + } + } + + return paths + } +} + +fun computeAliases(method: EtsMethod): Map> { + val preAliases = mutableMapOf() + val postAliases = mutableMapOf() + + // val root = method.cfg.stmts[0] + // val queue = ArrayDeque(listOf(root)) + // val preds: MutableMap> = hashMapOf() + // val order: MutableList = mutableListOf() + // val visited: MutableSet = hashSetOf() + // + // while (queue.isNotEmpty()) { + // val cur = queue.first() + // + // if (visited.add(cur)) { + // for (next in method.cfg.successors(cur)) { + // if (next !in visited) { + // queue.addFirst(next) + // } + // } + // } else { + // order.add(cur) + // queue.removeFirst() + // } + // } + + val visited: MutableSet = hashSetOf() + val order: MutableList = mutableListOf() + val preds: MutableMap> = hashMapOf() + + fun postOrderDfs(node: EtsStmt) { + if (visited.add(node)) { + for (next in method.cfg.successors(node)) { + if (next !in visited) { + preds.computeIfAbsent(next) { mutableListOf() } += node + } + postOrderDfs(next) + } + order += node + } + } + + val root = method.cfg.stmts[0] + postOrderDfs(root) + order.reverse() + + fun computePostAliases(stmt: EtsStmt): AliasInfo { + if (stmt in postAliases) return postAliases[stmt]!! + + val pre = preAliases[stmt]!! + var newF = pre.F + val newB = pre.B.mutate { newB -> + newF = newF.mutate { newF -> + if (stmt is EtsAssignStmt) { + val lhv = stmt.lhv + val rhv = stmt.rhv + + if (rhv is EtsLocal || rhv is EtsRef || (rhv is EtsCastExpr && rhv.arg is EtsRef)) { + val lhs = lhv.toPath() + val rhs = rhv.toPath() + + if (rhv is EtsParameterRef) { + check(lhs.accesses.isEmpty()) + newB[lhs.base] = Allocation.Arg(rhv.index) + } else { + if (lhs.accesses.isEmpty() && rhs.accesses.isEmpty()) { + // x := y + newB[lhs.base] = newB.computeIfAbsent(rhs.base) { Allocation.Imm() } + } else if (lhs.accesses.isEmpty()) { + // x := y.f OR x := y[i] + when (val a = rhs.accesses.single()) { + is FieldAccessor -> { + // x := y.f + val b: Allocation = newB.computeIfAbsent(rhs.base) { Allocation.Imm() } + newF[b] = newF.getOrElse(b) { persistentHashMapOf() }.mutate { f -> + newB[lhs.base] = f.computeIfAbsent(a.name) { Allocation.Imm() } + } + } + + is ElementAccessor -> { + // x := y[i] + newB.remove(lhs.base) + } + } + } else if (rhs.accesses.isEmpty()) { + // x.f := y OR x[i] := y + when (val a = lhs.accesses.single()) { + is FieldAccessor -> { + // x.f := y + val b: Allocation = newB.computeIfAbsent(rhs.base) { Allocation.Imm() } + newF[b] = newF.getOrElse(b) { persistentHashMapOf() }.mutate { f -> + f[a.name] = newB.computeIfAbsent(rhs.base) { Allocation.Imm() } + } + } + + is ElementAccessor -> { + // x[i] := y + // do nothing + } + } + } else { + error("Incorrect 3AC: $stmt") + } + } + } + + if (rhv is EtsConstant || (rhv is EtsCastExpr && rhv.arg is EtsConstant)) { + val lhs = lhv.toPath() + if (lhs.accesses.isEmpty()) { + // x := const + newB.remove(lhs.base) + } else { + when (val a = lhs.accesses.single()) { + is FieldAccessor -> { + // x.f := const + val b = newB.computeIfAbsent(lhs.base) { Allocation.Imm() } + newF[b] = newF.getOrElse(b) { persistentHashMapOf() }.mutate { f -> + f.remove(a.name) + } + } + + is ElementAccessor -> { + // x[i] := const + // do nothing + } + } + } + } + + if (rhv is EtsNewExpr || rhv is EtsNewArrayExpr) { + val lhs = lhv.toPath() + if (lhs.accesses.isEmpty()) { + // x := new() + newB.computeIfAbsent(lhs.base) { Allocation.New() } + } else { + when (val a = lhs.accesses.single()) { + is FieldAccessor -> { + // x.f := new() + val b = newB.computeIfAbsent(lhs.base) { Allocation.Imm() } + newF[b] = newF.getOrElse(b) { persistentHashMapOf() }.mutate { f -> + f[a.name] = Allocation.New() + } + } + + is ElementAccessor -> { + // x[i] := new() + // do nothing + } + } + } + } + + if (rhv is EtsCastExpr) { + check(rhv.arg !is EtsCallExpr) + check(rhv.arg is EtsLocal || rhv.arg is EtsRef || rhv.arg is EtsConstant) + } + + if (rhv is EtsCallExpr) { + val lhs = lhv.toPath() + check(lhs.accesses.isEmpty()) + newB[lhs.base] = Allocation.CallResult() + } + } + } + } + + val newInfo = AliasInfo(newB, newF) + postAliases[stmt] = newInfo + return newInfo + } + + fun computePreAliases(stmt: EtsStmt): AliasInfo { + if (stmt in preAliases) return preAliases[stmt]!! + + val merged = preds[stmt] + ?.map { postAliases[it]!! } + ?.reduceOrNull { a, b -> a.merge(b) } + ?: AliasInfo(persistentHashMapOf(), persistentHashMapOf()) + + preAliases[stmt] = merged + return merged + } + + for (stmt in order) { + computePreAliases(stmt) + computePostAliases(stmt) + } + + for (stmt in method.cfg.stmts) { + check(stmt in preAliases) + check(stmt in postAliases) + } + + return method.cfg.stmts.associateWithTo(HashMap()) { stmt -> Pair(preAliases[stmt]!!, postAliases[stmt]!!) } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AnalyzerEvent.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AnalyzerEvent.kt new file mode 100644 index 0000000000..c44ebbb026 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/AnalyzerEvent.kt @@ -0,0 +1,25 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.model.EtsMethod +import org.usvm.dataflow.ifds.Vertex + +sealed interface AnalyzerEvent + +data class ForwardSummaryAnalyzerEvent( + val method: EtsMethod, + val initialVertex: Vertex, + val exitVertex: Vertex, +) : AnalyzerEvent { + val initialFact get() = initialVertex.fact + val exitFact get() = exitVertex.fact +} + +data class BackwardSummaryAnalyzerEvent( + val method: EtsMethod, + val initialVertex: Vertex, + val exitVertex: Vertex, +) : AnalyzerEvent { + val initialFact get() = initialVertex.fact + val exitFact get() = exitVertex.fact +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ApplicationGraph.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ApplicationGraph.kt new file mode 100644 index 0000000000..6f63a9055d --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ApplicationGraph.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.base.EtsInstLocation +import org.jacodb.ets.base.EtsNopStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.graph.EtsApplicationGraphImpl +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene + +fun createApplicationGraph(cp: EtsScene): EtsApplicationGraph { + val base = EtsApplicationGraphImpl(cp) + val explicit = EtsApplicationGraphWithExplicitEntryPoint(base) + return explicit +} + +class EtsApplicationGraphWithExplicitEntryPoint( + private val graph: EtsApplicationGraphImpl, +) : EtsApplicationGraph { + + override val cp: EtsScene + get() = graph.cp + + override fun methodOf(node: EtsStmt): EtsMethod = node.location.method + + override fun exitPoints(method: EtsMethod): Sequence = graph.exitPoints(method) + + private fun methodEntryPoint(method: EtsMethod) = + EtsNopStmt(EtsInstLocation(method, index = -1)) + + override fun entryPoints(method: EtsMethod): Sequence = sequenceOf(methodEntryPoint(method)) + + override fun callers(method: EtsMethod): Sequence = graph.callers(method) + + override fun callees(node: EtsStmt): Sequence = graph.callees(node) + + override fun successors(node: EtsStmt): Sequence { + val method = methodOf(node) + val methodEntry = methodEntryPoint(method) + + if (node == methodEntry) { + return graph.entryPoints(method) + } + + return graph.successors(node) + } + + override fun predecessors(node: EtsStmt): Sequence { + val method = methodOf(node) + val methodEntry = methodEntryPoint(method) + + if (node == methodEntry) { + return emptySequence() + } + + if (node in graph.entryPoints(method)) { + return sequenceOf(methodEntry) + } + + return graph.predecessors(node) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardAnalyzer.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardAnalyzer.kt new file mode 100644 index 0000000000..df2bd2ebb6 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardAnalyzer.kt @@ -0,0 +1,44 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.api.common.analysis.ApplicationGraph +import org.jacodb.impl.cfg.graphs.GraphDominators +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.model.EtsMethod +import org.usvm.dataflow.ifds.Analyzer +import org.usvm.dataflow.ifds.Edge +import org.usvm.dataflow.ifds.Vertex + +class BackwardAnalyzer( + val graph: ApplicationGraph, + savedTypes: MutableMap>, + dominators: (EtsMethod) -> GraphDominators +) : Analyzer { + + override val flowFunctions = BackwardFlowFunctions(graph, dominators, savedTypes) + + override fun handleCrossUnitCall( + caller: Vertex, + callee: Vertex + ): List { + error("No cross unit calls") + } + + override fun handleNewEdge(edge: Edge): List { + val (startVertex, currentVertex) = edge + val (current, currentFact) = currentVertex + + val method = graph.methodOf(current) + val currentIsExit = current in graph.exitPoints(method) + + if (!currentIsExit) return emptyList() + + return listOf( + BackwardSummaryAnalyzerEvent( + method = method, + initialVertex = startVertex, + exitVertex = currentVertex, + ) + ) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardFlowFunctions.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardFlowFunctions.kt new file mode 100644 index 0000000000..733f2cd515 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/BackwardFlowFunctions.kt @@ -0,0 +1,593 @@ +package org.usvm.dataflow.ts.infer + +import mu.KotlinLogging +import org.jacodb.api.common.analysis.ApplicationGraph +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsCastExpr +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsEqExpr +import org.jacodb.ets.base.EtsIfStmt +import org.jacodb.ets.base.EtsInExpr +import org.jacodb.ets.base.EtsInstanceCallExpr +import org.jacodb.ets.base.EtsLValue +import org.jacodb.ets.base.EtsNewExpr +import org.jacodb.ets.base.EtsNumberConstant +import org.jacodb.ets.base.EtsRef +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsStringConstant +import org.jacodb.ets.base.EtsThrowStmt +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.utils.callExpr +import org.jacodb.impl.cfg.graphs.GraphDominators +import org.usvm.dataflow.ifds.FlowFunction +import org.usvm.dataflow.ifds.FlowFunctions +import org.usvm.dataflow.ts.infer.BackwardTypeDomainFact.TypedVariable +import org.usvm.dataflow.ts.infer.BackwardTypeDomainFact.Zero +import org.usvm.util.Maybe + +private val logger = KotlinLogging.logger {} + +class BackwardFlowFunctions( + val graph: ApplicationGraph, + val dominators: (EtsMethod) -> GraphDominators, + val savedTypes: MutableMap>, +) : FlowFunctions { + + // private val aliasesCache: MutableMap>> = hashMapOf() + // + // private fun getAliases(method: EtsMethod): Map> { + // return aliasesCache.computeIfAbsent(method) { computeAliases(method) } + // } + + override fun obtainPossibleStartFacts(method: EtsMethod) = listOf(Zero) + + override fun obtainSequentFlowFunction( + current: EtsStmt, + next: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + if (current is EtsAssignStmt) { + val lhvPath = current.lhv.toPathOrNull() + val rhvPath = current.rhv.toPathOrNull() + if (lhvPath != null && rhvPath != null && lhvPath == rhvPath) { + return@FlowFunction listOf(fact) + } + } + when (fact) { + Zero -> sequentZero(current) + is TypedVariable -> sequent(current, fact).myFilter() + } + } + + private fun Iterable.myFilter(): List = filter { + if (it.type.complexity() >= 5) { + logger.warn { "Dropping too complex fact: $it" } + return@filter false + } + true + } + + /** + * Complexity of a type fact is the maximum depth of nested types. + */ + private fun EtsTypeFact.complexity(): Int = when (this) { + is EtsTypeFact.ObjectEtsTypeFact -> (properties.values.maxOfOrNull { it.complexity() } ?: 0) + 1 + is EtsTypeFact.ArrayEtsTypeFact -> elementType.complexity() + 1 + is EtsTypeFact.UnionEtsTypeFact -> (types.maxOfOrNull { it.complexity() } ?: 0) + 1 + is EtsTypeFact.IntersectionEtsTypeFact -> (types.maxOfOrNull { it.complexity() } ?: 0) + 1 + else -> 0 + } + + private fun TypedVariable.withTypeGuards(current: EtsStmt): TypedVariable { + val dominators = dominators(current.method).dominators(current).asReversed() + + var result = this + + for (stmt in dominators.filterIsInstance()) { + val (guardedVariable, typeGuard) = resolveTypeGuard(stmt) ?: continue + + if (guardedVariable != result.variable) continue + + val branches = graph.predecessors(stmt).toList() // graph is reversed + check(branches.size == 2) { "Unexpected IF branches: $branches" } + + val (falseBranch, trueBranch) = branches + + val isTrueStatement = current.isReachableFrom(trueBranch) + val isFalseStatement = current.isReachableFrom(falseBranch) + + if (isTrueStatement && !isFalseStatement) { + val type = result.type.withGuard(typeGuard, guardNegated = false) + result = TypedVariable(result.variable, type) + } + + if (!isTrueStatement && isFalseStatement) { + val type = result.type.withGuard(typeGuard, guardNegated = true) + result = TypedVariable(result.variable, type) + } + } + + return result + } + + private fun resolveTypeGuard(branch: EtsIfStmt): Pair? { + val condition = branch.condition as? EtsEqExpr ?: return null + + if (condition.right == EtsNumberConstant(0.0)) { + return resolveTypeGuard(condition.left, branch) + } + + return null + } + + private fun resolveTypeGuard(value: EtsEntity, stmt: EtsStmt): Pair? { + val valueAssignment = findAssignment(value, stmt) ?: return null + + return when (val rhv = valueAssignment.rhv) { + is EtsRef, is EtsLValue -> { + resolveTypeGuard(rhv, valueAssignment) + } + + is EtsInExpr -> { + resolveTypeGuardFromIn(rhv.left, rhv.right) + } + + else -> null + } + } + + private fun findAssignment(value: EtsEntity, stmt: EtsStmt): EtsAssignStmt? { + val cache = hashMapOf>() + findAssignment(value, stmt, cache) + val maybeValue = cache.getValue(stmt) + + return if (maybeValue.isNone) null else maybeValue.getOrThrow() + } + + private fun findAssignment( + value: EtsEntity, + stmt: EtsStmt, + cache: MutableMap>, + ) { + if (stmt in cache) return + + if (stmt is EtsAssignStmt && stmt.lhv == value) { + cache[stmt] = Maybe.some(stmt) + return + } + + // val predecessors = graph.successors(stmt) // graph is reversed + // val predecessors = dominators(stmt.method).dominators(stmt) - stmt + val predecessors = dominators(stmt.method).dominators(stmt).toSet().intersect(graph.successors(stmt).toSet()) + predecessors.forEach { findAssignment(value, it, cache) } + + val predecessorValues = predecessors.map { cache.getValue(it) } + if (predecessorValues.any { it.isNone }) { + cache[stmt] = Maybe.none() + return + } + + val values = predecessorValues.map { it.getOrThrow() }.toHashSet() + if (values.size == 1) { + cache[stmt] = Maybe.some(values.single()) + return + } + + cache[stmt] = Maybe.none() + } + + private fun resolveTypeGuardFromIn( + left: EtsEntity, + right: EtsEntity, + ): Pair? { + if (left !is EtsStringConstant) return null + + check(right is EtsValue) + val base = right.toBase() + val type = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(left.value to EtsTypeFact.UnknownEtsTypeFact) + ) + return base to type + } + + private fun EtsStmt.isReachableFrom(stmt: EtsStmt): Boolean { + val visited = hashSetOf() + val queue = mutableListOf(stmt) + + while (queue.isNotEmpty()) { + val s = queue.removeLast() + if (this == s) return true + + if (!visited.add(s)) continue + + val successors = graph.predecessors(s) // graph is reversed + queue.addAll(successors) + } + + return false + } + + private fun sequentZero(current: EtsStmt): List { + val result = mutableListOf(Zero) + + // Case `return x` + // ∅ |= x:unknown + if (current is EtsReturnStmt) { + val variable = current.returnValue?.toBase() + if (variable != null) { + result += TypedVariable(variable, EtsTypeFact.UnknownEtsTypeFact) + } + } + + if (current is EtsAssignStmt) { + val rhv = when (val r = current.rhv) { + is EtsRef -> r.toPath() // This, FieldRef, ArrayAccess + is EtsLValue -> r.toPath() // Local + else -> { + // logger.info { "TODO backward assign zero: $current" } + null + } + } + + // When RHS is not const-like, handle possible new facts for RHV: + if (rhv != null) { + val y = rhv.base + + if (rhv.accesses.isEmpty()) { + // Case `x... := y` + // ∅ |= y:unknown + result += TypedVariable(y, EtsTypeFact.UnknownEtsTypeFact) + } else { + // Case `x := y.f` OR `x := y[i]` + + check(rhv.accesses.size == 1) + when (val accessor = rhv.accesses.single()) { + // Case `x := y.f` + // ∅ |= y:{f:unknown} + is FieldAccessor -> { + val type = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(accessor.name to EtsTypeFact.UnknownEtsTypeFact) + ) + result += TypedVariable(y, type).withTypeGuards(current) + } + + // Case `x := y[i]` + // ∅ |= y:Array + is ElementAccessor -> { + // Note: ElementAccessor guarantees that `y` is an array, + // since `y[i]` for property access (i.e. access property + // with name "i") is represented via FieldAccessor. + val type = EtsTypeFact.ArrayEtsTypeFact( + elementType = EtsTypeFact.UnknownEtsTypeFact + ) + result += TypedVariable(y, type).withTypeGuards(current) + } + } + } + } + + val lhv = when (val r = current.lhv) { + is EtsRef -> r.toPath() // This, FieldRef, ArrayAccess + is EtsLValue -> r.toPath() // Local + else -> { + logger.info { "TODO backward assign zero: $current" } + error("Unexpected LHV in assignment: $current") + } + } + + // Handle new possible facts for LHS: + if (lhv.accesses.isNotEmpty()) { + // Case `x.f := y` OR `x[i] := y` + val x = lhv.base + + when (val a = lhv.accesses.single()) { + // Case `x.f := y` + // ∅ |= x:{f:unknown} + is FieldAccessor -> { + val type = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(a.name to EtsTypeFact.UnknownEtsTypeFact) + ) + result += TypedVariable(x, type).withTypeGuards(current) + } + + // Case `x[i] := y` + // ∅ |= x:Array + is ElementAccessor -> { + // Note: ElementAccessor guarantees that `y` is an array, + // since `y[i]` for property access (i.e. access property + // with name "i") is represented via FieldAccessor. + val type = EtsTypeFact.ArrayEtsTypeFact( + elementType = EtsTypeFact.UnknownEtsTypeFact + ) + result += TypedVariable(x, type) + } + } + } + } + + return result + } + + private fun unrollAccessorsToTypeFact(accesses: List, type: EtsTypeFact): EtsTypeFact { + var t = type + for (a in accesses.reversed()) { + // Note: getAliases can only return access path with FieldAccessor. + check(a is FieldAccessor) { "Unexpected accessor: $a" } + t = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(a.name to t) + ) + } + return t + } + + private fun sequent( + current: EtsStmt, + fact: TypedVariable, + ): List { + // println("sequentFact(current = $current, fact = $fact)") + + if (current !is EtsAssignStmt) { + return listOf(fact) + } + + val lhv = current.lhv.toPath() + + val rhv = when (val r = current.rhv) { + is EtsRef -> r.toPath() // This, FieldRef, ArrayAccess + is EtsLValue -> r.toPath() // Local + is EtsCastExpr -> r.toPath() // Cast + is EtsNewExpr -> { + // TODO: what about `x.f := new T()` ? + // `x := new T()` with fact `x:U` => `saved[T] += U` + if (fact.variable == lhv.base) { + savedTypes.getOrPut(r.type) { mutableListOf() }.add(fact.type) + } + return listOf(fact) + } + + else -> { + // logger.info { "TODO backward assign: $current" } + return listOf(fact) + } + } + + // Pass-through completely unrelated facts: + if (fact.variable != lhv.base) return listOf(fact) + + // val (preAliases, _) = getAliases(current.method)[current]!! + + if (lhv.accesses.isEmpty() && rhv.accesses.isEmpty()) { + // Case `x := y` + + // x:T |= x:T (keep) + y:T + val y = rhv.base + val newFact = TypedVariable(y, fact.type).withTypeGuards(current) + return listOf(fact, newFact) + + } else if (lhv.accesses.isEmpty()) { + // Case `x := y.f` OR `x := y[i]` + + check(rhv.accesses.size == 1) + when (val a = rhv.accesses.single()) { + // Case `x := y.f` + is FieldAccessor -> { + // // Drop facts containing duplicate fields + // if (fact.type is EtsTypeFact.ObjectEtsTypeFact && a.name in fact.type.properties) { + // // can just drop? + // return listOf(fact) + // } + + // x:T |= x:T (keep) + y:{f:T} + aliases + val result = mutableListOf(fact) + val y = rhv.base + val type = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(a.name to fact.type) + ) + result += TypedVariable(y, type).withTypeGuards(current) + // aliases: +|= z:{f:T} + // for (z in preAliases.getAliases(AccessPath(y, emptyList()))) { + // val type2 = unrollAccessorsToTypeFact(z.accesses + a, fact.type) + // result += TypedVariable(z.base, type2).withTypeGuards(current) + // } + return result + } + + // Case `x := y[i]` + is ElementAccessor -> { + // x:T |= x:T (keep) + y:Array + val y = rhv.base + val type = EtsTypeFact.ArrayEtsTypeFact(elementType = fact.type) + val newFact = TypedVariable(y, type).withTypeGuards(current) + return listOf(fact, newFact) + } + } + + } else if (rhv.accesses.isEmpty()) { + // Case `x.f := y` OR `x[i] := y` + + check(lhv.accesses.size == 1) + when (val a = lhv.accesses.single()) { + // Case `x.f := y` + is FieldAccessor -> { + if (fact.type is EtsTypeFact.UnionEtsTypeFact) { + TODO("Support union type for x.f := y in BW-sequent") + } + + if (fact.type is EtsTypeFact.IntersectionEtsTypeFact) { + TODO("Support intersection type for x.f := y in BW-sequent") + } + + // x:primitive |= x:primitive (pass) + if (fact.type !is EtsTypeFact.ObjectEtsTypeFact) { + return listOf(fact) + } + + // x:{no f} |= only keep x:{..} + + // x:{f:T} |= x:{f:T} (keep) + y:T + val (typeWithoutProperty, removedPropertyType) = fact.type.removePropertyType(a.name) + // val updatedFact = TypedVariable(fact.variable, typeWithoutProperty) + val updatedFact = fact + val y = rhv.base + val newType = removedPropertyType?.let { type -> TypedVariable(y, type).withTypeGuards(current) } + return listOfNotNull(updatedFact, newType) + } + + // Case `x[i] := y` + is ElementAccessor -> { + if (fact.type is EtsTypeFact.UnionEtsTypeFact) { + TODO("Support union type for x[i] := y in BW-sequent") + } + + if (fact.type is EtsTypeFact.IntersectionEtsTypeFact) { + TODO("Support intersection type for x[i] := y in BW-sequent") + } + + // x:Array |= x:Array (pass) + if (fact.type !is EtsTypeFact.ArrayEtsTypeFact) { + return listOf(fact) + } + + // x:Array |= x:Array (keep) + y:T + val y = rhv.base + val type = fact.type.elementType + val newFact = TypedVariable(y, type).withTypeGuards(current) + return listOf(fact, newFact) + } + } + } else { + error("Incorrect 3AC: $current") + } + + error("unreachable") + + // Pass-through unrelated facts: + return listOf(fact) + } + + private fun EtsTypeFact.ObjectEtsTypeFact.removePropertyType(propertyName: String): Pair { + val propertyType = properties[propertyName] + val updatedThis = EtsTypeFact.ObjectEtsTypeFact(cls, properties - propertyName) + return updatedThis to propertyType + } + + override fun obtainCallToReturnSiteFlowFunction( + callStatement: EtsStmt, + returnSite: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> callZero(callStatement) + is TypedVariable -> call(callStatement, fact) + } + } + + private fun callZero( + callStatement: EtsStmt, + ): List { + val result = mutableListOf(Zero) + + val callExpr = callStatement.callExpr ?: error("No call") + + if (callExpr is EtsInstanceCallExpr) { + val instance = callExpr.instance + val path = instance.toBase() + val objectWithMethod = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf( + callExpr.method.name to EtsTypeFact.FunctionEtsTypeFact + ) + ) + result += TypedVariable(path, objectWithMethod) + } + + return result + } + + private fun call( + callStatement: EtsStmt, + fact: TypedVariable, + ): List { + val result = mutableListOf() + + val callResult = (callStatement as? EtsAssignStmt)?.lhv?.toBase() + if (callResult != null) { + // If fact was for LHS, drop it as overridden + if (fact.variable == callResult) return result + } + + result += fact + return result + } + + override fun obtainCallToStartFlowFunction( + callStatement: EtsStmt, + calleeStart: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> listOf(fact) + is TypedVariable -> start(callStatement, calleeStart, fact) + } + } + + private fun start( + callStatement: EtsStmt, + calleeStart: EtsStmt, + fact: TypedVariable, + ): List { + val callResult = (callStatement as? EtsAssignStmt)?.lhv?.toBase() ?: return emptyList() + + if (fact.variable != callResult) return emptyList() + + if (calleeStart is EtsThrowStmt) return emptyList() // TODO support throwStmt + + check(calleeStart is EtsReturnStmt) + + val exitValue = calleeStart.returnValue?.toBase() ?: return emptyList() + + return listOf(TypedVariable(exitValue, fact.type)) + } + + override fun obtainExitToReturnSiteFlowFunction( + callStatement: EtsStmt, + returnSite: EtsStmt, + exitStatement: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> listOf(fact) + is TypedVariable -> exit(callStatement, fact) + } + } + + private fun exit( + callStatement: EtsStmt, + fact: TypedVariable, + ): List { + val callExpr = callStatement.callExpr ?: error("No call") + + when (fact.variable) { + is AccessPathBase.This -> { + if (callExpr !is EtsInstanceCallExpr) { + return emptyList() + } + + val instance = callExpr.instance + val instancePath = instance.toBase() + return listOf(TypedVariable(instancePath, fact.type)) + } + + is AccessPathBase.Arg -> { + val arg = callExpr.args.getOrNull(fact.variable.index)?.toBase() ?: return emptyList() + return listOf(TypedVariable(arg, fact.type)) + } + + else -> return emptyList() + } + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EntryPointsProcessor.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EntryPointsProcessor.kt new file mode 100644 index 0000000000..ee89b037ff --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EntryPointsProcessor.kt @@ -0,0 +1,25 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene + +object EntryPointsProcessor { + fun extractEntryPoints( + scene: EtsScene, + ): ArtificialMainWithAllMethods { + val artificialMainMethods = scene.projectClasses + .asSequence() + .flatMap { it.methods } + .filter { it.name == "@dummyMain" } + .toList() + return ArtificialMainWithAllMethods( + mainMethods = artificialMainMethods, + allMethods = scene.projectAndSdkClasses.flatMap { it.methods }, + ) + } +} + +data class ArtificialMainWithAllMethods( + val mainMethods: List, + val allMethods: List, +) diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsMethodTypeFacts.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsMethodTypeFacts.kt new file mode 100644 index 0000000000..058cba690d --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsMethodTypeFacts.kt @@ -0,0 +1,8 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.model.EtsMethod + +data class EtsMethodTypeFacts( + val method: EtsMethod, + val types: Map, +) diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsTypeFact.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsTypeFact.kt new file mode 100644 index 0000000000..fe50e55d59 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/EtsTypeFact.kt @@ -0,0 +1,530 @@ +package org.usvm.dataflow.ts.infer + +import mu.KotlinLogging +import org.jacodb.ets.base.ANONYMOUS_CLASS_PREFIX +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsBooleanType +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsFunctionType +import org.jacodb.ets.base.EtsNullType +import org.jacodb.ets.base.EtsNumberType +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnclearRefType +import org.jacodb.ets.base.EtsUndefinedType +import org.jacodb.ets.base.EtsUnionType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.base.INSTANCE_INIT_METHOD_NAME + +private val logger = KotlinLogging.logger {} + +sealed interface EtsTypeFact { + + fun toPrettyString(): String { + return toString() + } + + sealed interface BasicType : EtsTypeFact + + fun union(other: EtsTypeFact): EtsTypeFact { + if (this == other) return this + + return when { + this is ObjectEtsTypeFact && other is ObjectEtsTypeFact -> union(this, other) + this is ObjectEtsTypeFact && other is StringEtsTypeFact -> union(this, other) + this is UnionEtsTypeFact -> union(this, other) + this is IntersectionEtsTypeFact -> union(this, other) + this is GuardedTypeFact -> union(this, other) + other is UnionEtsTypeFact -> union(other, this) + other is IntersectionEtsTypeFact -> union(other, this) + other is GuardedTypeFact -> union(other, this) + else -> mkUnionType(this, other) + } + } + + fun intersect(other: EtsTypeFact): EtsTypeFact? { + if (this == other) return this + + if (other is UnknownEtsTypeFact) return this + if (other is AnyEtsTypeFact) return other + + return when (this) { + is UnknownEtsTypeFact -> other + + is AnyEtsTypeFact -> this + + is StringEtsTypeFact, + is NumberEtsTypeFact, + is BooleanEtsTypeFact, + is NullEtsTypeFact, + is UndefinedEtsTypeFact, + -> when (other) { + is UnionEtsTypeFact -> intersect(other, this) + is IntersectionEtsTypeFact -> intersect(other, this) + is GuardedTypeFact -> intersect(other, this) + else -> null + } + + is FunctionEtsTypeFact -> when (other) { + is ObjectEtsTypeFact -> mkIntersectionType(this, other) + is UnionEtsTypeFact -> intersect(other, this) + is IntersectionEtsTypeFact -> intersect(other, this) + is GuardedTypeFact -> intersect(other, this) + else -> null + } + + is ArrayEtsTypeFact -> when (other) { + is ArrayEtsTypeFact -> { + val t = elementType.intersect(other.elementType) + if (t == null) { + logger.warn{"Empty intersection of array element types: $elementType & ${other.elementType}"} + null + } else { + ArrayEtsTypeFact(t) + } + } + else -> null + } + + is ObjectEtsTypeFact -> when (other) { + is ObjectEtsTypeFact -> intersect(this, other) + is StringEtsTypeFact -> intersect(this, other) + is FunctionEtsTypeFact -> mkIntersectionType(this, other) + is UnionEtsTypeFact -> intersect(other, this) + is IntersectionEtsTypeFact -> intersect(other, this) + is GuardedTypeFact -> intersect(other, this) + else -> null + } + + is UnionEtsTypeFact -> intersect(this, other) + is IntersectionEtsTypeFact -> intersect(this, other) + is GuardedTypeFact -> intersect(this, other) + } + } + + object UnknownEtsTypeFact : EtsTypeFact, BasicType { + override fun toString(): String = "unknown" + } + + object AnyEtsTypeFact : BasicType { + override fun toString(): String = "any" + } + + object StringEtsTypeFact : BasicType { + override fun toString(): String = "string" + } + + object NumberEtsTypeFact : BasicType { + override fun toString(): String = "number" + } + + object BooleanEtsTypeFact : BasicType { + override fun toString(): String = "boolean" + } + + object NullEtsTypeFact : BasicType { + override fun toString(): String = "null" + } + + object UndefinedEtsTypeFact : BasicType { + override fun toString(): String = "undefined" + } + + // object VoidEtsTypeFact : BasicType { + // override fun toString(): String = "void" + // } + // + // object NeverEtsTypeFact : BasicType { + // override fun toString(): String = "never" + // } + + object FunctionEtsTypeFact : BasicType { + override fun toString(): String = "function" + } + + data class ArrayEtsTypeFact( + val elementType: EtsTypeFact, + ) : BasicType { + override fun toString(): String = "Array<$elementType>" + } + + data class ObjectEtsTypeFact( + val cls: EtsType?, + val properties: Map, + ) : BasicType { + override fun toString(): String { + val clsName = cls?.typeName?.takeUnless { it.startsWith(ANONYMOUS_CLASS_PREFIX) } ?: "Object" + val funProps = properties.entries + .filter { it.value is FunctionEtsTypeFact } + .filterNot { it.key == CONSTRUCTOR_NAME } + .filterNot { it.key == INSTANCE_INIT_METHOD_NAME } + .sortedBy { it.key } + val nonFunProps = properties.entries + .filter { it.value !is FunctionEtsTypeFact } + .sortedBy { it.key } + val props = (funProps + nonFunProps).joinToString(", ") { (name, type) -> "$name: $type" } + return "$clsName { $props }" + } + + // Object { + // ..foo: Object { + // ....bar: string + // ..} + // } + override fun toPrettyString(): String { + val clsName = cls?.typeName ?: "Object" + val funProps = properties.entries + .filter { it.value is FunctionEtsTypeFact } + .sortedBy { it.key } + val nonFunProps = properties.entries + .filter { it.value !is FunctionEtsTypeFact } + .sortedBy { it.key } + return buildString { + appendLine("$clsName {") + for ((name, type) in funProps) { + appendLine(" $name: $type") + } + for ((name, type) in nonFunProps) { + appendLine("$name: ${type.toPrettyString()}".lines().joinToString("\n") { " $it" }) + } + append("}") + } + } + + override fun equals(other: Any?): Boolean { + if (other !is ObjectEtsTypeFact) return false + + if (other.cls != null && other.cls == cls) return true + + return properties == other.properties + } + + override fun hashCode(): Int { + if (cls == null) return properties.hashCode() + + return cls.hashCode() + } + } + + data class UnionEtsTypeFact( + val types: Set, + ) : EtsTypeFact { + init { + require(types.isNotEmpty()) { + "An empty set of types is passed as an union type" + } + } + + override fun toString(): String { + return types.map { + when (it) { + is UnionEtsTypeFact, is IntersectionEtsTypeFact -> "(${it})" + else -> it.toString() + } + }.sorted().joinToString(" | ") + } + + override fun toPrettyString(): String { + return types.map { + when (it) { + is UnionEtsTypeFact, is IntersectionEtsTypeFact -> "($it)" + else -> it.toString() + } + }.sorted().joinToString(" | ") + } + } + + data class IntersectionEtsTypeFact( + val types: Set, + ) : EtsTypeFact { + init { + require(types.isNotEmpty()) { + "An empty set of types is passed as an intersection type" + } + } + + override fun toString(): String { + return types.map { + when (it) { + is UnionEtsTypeFact, is IntersectionEtsTypeFact -> "(${it})" + else -> it.toString() + } + }.sorted().joinToString(" & ") + } + + override fun toPrettyString(): String { + return types.map { + when (it) { + is UnionEtsTypeFact, is IntersectionEtsTypeFact -> "(${it})" + else -> it.toString() + } + }.sorted().joinToString(" & ") + } + } + + data class GuardedTypeFact( + val guard: BasicType, + val guardNegated: Boolean, + val type: EtsTypeFact, + ) : EtsTypeFact + + companion object { + internal val allStringProperties = listOf( + "length", + "constructor", + "anchor", + "at", + "big", + "blink", + "bold", + "charAt", + "charCodeAt", + "codePointAt", + "concat", + "endsWith", + "fontcolor", + "fontsize", + "fixed", + "includes", + "indexOf", + "isWellFormed", + "italics", + "lastIndexOf", + "link", + "localeCompare", + "match", + "matchAll", + "normalize", + "padEnd", + "padStart", + "repeat", + "replace", + "replaceAll", + "search", + "slice", + "small", + "split", + "strike", + "sub", + "substr", + "substring", + "sup", + "startsWith", + "toString", + "toWellFormed", + "trim", + "trimStart", + "trimLeft", + "trimEnd", + "trimRight", + "toLocaleLowerCase", + "toLocaleUpperCase", + "toLowerCase", + "toUpperCase", + "valueOf", + ) + + private fun intersect(unionType: UnionEtsTypeFact, other: EtsTypeFact): EtsTypeFact { + // todo: push intersection + return mkIntersectionType(unionType, other) + } + + private fun intersect(intersectionType: IntersectionEtsTypeFact, other: EtsTypeFact): EtsTypeFact? { + val result = hashSetOf() + for (type in intersectionType.types) { + val intersection = type.intersect(other) ?: return null + if (intersection is IntersectionEtsTypeFact) { + result.addAll(intersection.types) + } else { + result.add(intersection) + } + } + return mkIntersectionType(result) + } + + private fun intersect(guardedType: GuardedTypeFact, other: EtsTypeFact): EtsTypeFact? { + if (other is GuardedTypeFact) { + if (other.guard == guardedType.guard) { + return if (other.guardNegated == guardedType.guardNegated) { + guardedType.type.intersect(other.type)?.withGuard(guardedType.guard, guardedType.guardNegated) + } else { + guardedType.type.union(other.type) + } + } + } + + // todo: evaluate types + return mkIntersectionType(guardedType, other) + } + + private fun intersect(obj1: ObjectEtsTypeFact, obj2: ObjectEtsTypeFact): EtsTypeFact? { + val intersectionProperties = obj1.properties.toMutableMap() + for ((property, type) in obj2.properties) { + val currentType = intersectionProperties[property] + if (currentType == null) { + intersectionProperties[property] = type + continue + } + + intersectionProperties[property] = currentType.intersect(type) ?: return null + } + + val intersectionCls = if (obj1.cls != null && obj2.cls != null) { + obj1.cls.takeIf { it == obj2.cls } + } else { + obj1.cls ?: obj2.cls + } + return ObjectEtsTypeFact(intersectionCls, intersectionProperties) + } + + private fun intersect(obj: ObjectEtsTypeFact, string: StringEtsTypeFact): EtsTypeFact? { + if (obj.cls == EtsStringType) return string + if (obj.cls != null) return null + + val intersectionProperties = obj.properties + .filter { it.key in allStringProperties } + .mapValues { (_, type) -> + // TODO: intersect with the corresponding type of String's property + type + } + + return ObjectEtsTypeFact(obj.cls, intersectionProperties) + } + + private fun union(unionType: UnionEtsTypeFact, other: EtsTypeFact): EtsTypeFact { + val result = hashSetOf() + for (type in unionType.types) { + val union = type.union(other) + if (union is UnionEtsTypeFact) { + result.addAll(union.types) + } else { + result.add(union) + } + } + return mkUnionType(result) + } + + private fun union(guardedType: GuardedTypeFact, other: EtsTypeFact): EtsTypeFact { + // todo: evaluate types + return mkUnionType(guardedType, other) + } + + private fun union(intersectionType: IntersectionEtsTypeFact, other: EtsTypeFact): EtsTypeFact { + // todo: push union + return mkUnionType(intersectionType, other) + } + + private fun union(obj1: ObjectEtsTypeFact, obj2: ObjectEtsTypeFact): EtsTypeFact { + if (obj1.cls != null && obj2.cls != null && obj1.cls != obj2.cls) { + return mkUnionType(obj1, obj2) + } + + val commonProperties = obj1.properties.keys.intersect(obj2.properties.keys).associateWith { property -> + val thisType = obj1.properties.getValue(property) + val otherType = obj2.properties.getValue(property) + thisType.union(otherType) + } + + val o1OnlyProperties = obj1.properties.filter { it.key !in obj2.properties } + val o2OnlyProperties = obj2.properties.filter { it.key !in obj1.properties } + + val o1 = ObjectEtsTypeFact(obj1.cls, o1OnlyProperties) + val o2 = ObjectEtsTypeFact(obj2.cls, o2OnlyProperties) + + if (commonProperties.isEmpty()) { + return mkUnionType(o1, o2) + } + + val commonCls = obj1.cls.takeIf { it == obj2.cls } + val commonObject = ObjectEtsTypeFact(commonCls, commonProperties) + + if (o1OnlyProperties.isEmpty() && o2OnlyProperties.isEmpty()) { + return commonObject + } + + return mkIntersectionType(commonObject, mkUnionType(o1, o2)) + } + + private fun union(obj: ObjectEtsTypeFact, string: StringEtsTypeFact): EtsTypeFact { + if (obj.cls == EtsStringType) return string + if (obj.cls != null) return mkUnionType(obj, string) + + for (p in obj.properties.keys) { + if (p !in allStringProperties) { + return mkUnionType(obj, string) + } + } + + return string + } + + fun mkUnionType(vararg types: EtsTypeFact): EtsTypeFact = mkUnionType(types.toHashSet()) + + fun mkUnionType(types: Set): EtsTypeFact { + if (types.size == 1) return types.single() + return UnionEtsTypeFact(types) + } + + fun mkIntersectionType(vararg types: EtsTypeFact): EtsTypeFact = mkIntersectionType(types.toHashSet()) + + fun mkIntersectionType(types: Set): EtsTypeFact { + if (types.size == 1) return types.single() + return IntersectionEtsTypeFact(types) + } + + fun from(type: EtsType): EtsTypeFact { + return when (type) { + is EtsAnyType -> AnyEtsTypeFact + is EtsUnknownType -> UnknownEtsTypeFact + is EtsUnionType -> UnionEtsTypeFact(type.types.map { from(it) }.toSet()) + is EtsBooleanType -> BooleanEtsTypeFact + is EtsNumberType -> NumberEtsTypeFact + is EtsStringType -> StringEtsTypeFact + is EtsNullType -> NullEtsTypeFact + is EtsUndefinedType -> UndefinedEtsTypeFact + is EtsClassType -> ObjectEtsTypeFact(type, emptyMap()) + is EtsFunctionType -> FunctionEtsTypeFact + // is EtsArrayType -> ObjectEtsTypeFact( + // cls = type, + // properties = mapOf( + // "index" to ObjectEtsTypeFact( + // cls = null, + // properties = mapOf( + // "name" to StringEtsTypeFact, + // "value" to from(type.elementType) + // ) + // ), + // "length" to NumberEtsTypeFact + // ) + // ) + is EtsArrayType -> ArrayEtsTypeFact(elementType = from(type.elementType)) + is EtsUnclearRefType -> ObjectEtsTypeFact(type, emptyMap()) + // is EtsGenericType -> TODO() + else -> { + logger.error { "Unsupported type: $type" } + UnknownEtsTypeFact + } + } + } + } +} + +fun EtsTypeFact.withGuard(guard: EtsTypeFact.BasicType, guardNegated: Boolean): EtsTypeFact { + val duplicateGuard = findDuplicateGuard(this, guard) + + if (duplicateGuard != null) { + if (guardNegated == duplicateGuard.guardNegated) return this + + TODO("Same guard with different sign") + } + + return EtsTypeFact.GuardedTypeFact(guard, guardNegated, this) +} + +private fun findDuplicateGuard(fact: EtsTypeFact, guard: EtsTypeFact.BasicType): EtsTypeFact.GuardedTypeFact? { + if (fact !is EtsTypeFact.GuardedTypeFact) return null + if (fact.guard == guard) return fact + return findDuplicateGuard(fact.type, guard) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardAnalyzer.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardAnalyzer.kt new file mode 100644 index 0000000000..7090b8d8fb --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardAnalyzer.kt @@ -0,0 +1,44 @@ +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.model.EtsMethod +import org.usvm.dataflow.ifds.Analyzer +import org.usvm.dataflow.ifds.Edge +import org.usvm.dataflow.ifds.Vertex + +class ForwardAnalyzer( + val graph: EtsApplicationGraph, + methodInitialTypes: Map, + typeInfo: Map, + doAddKnownTypes: Boolean = true, +) : Analyzer { + + override val flowFunctions = ForwardFlowFunctions(graph, methodInitialTypes, typeInfo, doAddKnownTypes) + + override fun handleCrossUnitCall( + caller: Vertex, + callee: Vertex, + ): List { + error("No cross unit calls") + } + + override fun handleNewEdge(edge: Edge): List { + val (startVertex, currentVertex) = edge + val (current, currentFact) = currentVertex + + val method = graph.methodOf(current) + val currentIsExit = current in graph.exitPoints(method) + + if (!currentIsExit) return emptyList() + + return listOf( + ForwardSummaryAnalyzerEvent( + method = method, + initialVertex = startVertex, + exitVertex = currentVertex, + ) + ) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardFlowFunctions.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardFlowFunctions.kt new file mode 100644 index 0000000000..cf54009faa --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/ForwardFlowFunctions.kt @@ -0,0 +1,580 @@ +package org.usvm.dataflow.ts.infer + +import mu.KotlinLogging +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArithmeticExpr +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsBooleanConstant +import org.jacodb.ets.base.EtsCastExpr +import org.jacodb.ets.base.EtsFieldRef +import org.jacodb.ets.base.EtsInstanceCallExpr +import org.jacodb.ets.base.EtsLValue +import org.jacodb.ets.base.EtsNewArrayExpr +import org.jacodb.ets.base.EtsNewExpr +import org.jacodb.ets.base.EtsNullConstant +import org.jacodb.ets.base.EtsNumberConstant +import org.jacodb.ets.base.EtsRef +import org.jacodb.ets.base.EtsRelationExpr +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsStringConstant +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUndefinedConstant +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.utils.callExpr +import org.usvm.dataflow.ifds.FlowFunction +import org.usvm.dataflow.ifds.FlowFunctions +import org.usvm.dataflow.ts.infer.ForwardTypeDomainFact.TypedVariable +import org.usvm.dataflow.ts.infer.ForwardTypeDomainFact.Zero + +private val logger = KotlinLogging.logger {} + +class ForwardFlowFunctions( + val graph: EtsApplicationGraph, + val methodInitialTypes: Map, + val typeInfo: Map, + val doAddKnownTypes: Boolean = true, +) : FlowFunctions { + + private val aliasesCache: MutableMap>> = hashMapOf() + + private fun getAliases(method: EtsMethod): Map> { + return aliasesCache.computeIfAbsent(method) { computeAliases(method) } + } + + override fun obtainPossibleStartFacts(method: EtsMethod): Collection { + val result = mutableListOf(Zero) + + val initialTypes = methodInitialTypes[method] + if (initialTypes != null) { + for ((base, type) in initialTypes.types) { + val path = AccessPath(base, accesses = emptyList()) + addTypes(path, type, result) + } + } + + if (doAddKnownTypes) { + for (local in method.locals) { + if (local.type != EtsUnknownType && local.type != EtsAnyType) { + val path = AccessPath(AccessPathBase.Local(local.name), accesses = emptyList()) + val type = EtsTypeFact.from(local.type) + if (type != EtsTypeFact.UnknownEtsTypeFact && type != EtsTypeFact.AnyEtsTypeFact) { + logger.debug { "Adding known type for $path: $type" } + addTypes(path, type, result) + } + } + } + } + + return result + } + + private fun addTypes( + path: AccessPath, + type: EtsTypeFact, + facts: MutableList, + ) { + when (type) { + EtsTypeFact.UnknownEtsTypeFact -> { + facts += TypedVariable(path, EtsTypeFact.AnyEtsTypeFact) + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + for ((propertyName, propertyType) in type.properties) { + val propertyPath = path + FieldAccessor(propertyName) + addTypes(propertyPath, propertyType, facts) + } + + facts += TypedVariable(path, type) + } + + is EtsTypeFact.ArrayEtsTypeFact -> { + // check(type.elementType !is EtsTypeFact.ArrayEtsTypeFact) + facts += TypedVariable(path, type) + addTypes(path + ElementAccessor, type.elementType, facts) + } + + is EtsTypeFact.GuardedTypeFact -> { + addTypes(path, type.type, facts) + } + + is EtsTypeFact.IntersectionEtsTypeFact -> { + type.types.forEach { addTypes(path, it, facts) } + } + + is EtsTypeFact.UnionEtsTypeFact -> { + type.types.forEach { addTypes(path, it, facts) } + } + + else -> { + facts += TypedVariable(path, type) + } + } + } + + override fun obtainSequentFlowFunction( + current: EtsStmt, + next: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + if (current is EtsAssignStmt) { + val lhvPath = current.lhv.toPathOrNull() + val rhvPath = current.rhv.toPathOrNull() + if (lhvPath != null && rhvPath != null && lhvPath == rhvPath) { + return@FlowFunction listOf(fact) + } + } + when (fact) { + Zero -> sequentZero(current) + is TypedVariable -> sequentFact(current, fact).filter { + if (it.variable.accesses.size > 5) { + logger.warn { "Dropping too long fact: $it" } + return@filter false + } + if (it.variable.accesses.hasDuplicateFields(3)) { + logger.warn { "Dropping fact with duplicate fields: $it" } + return@filter false + } + true + } + } + } + + private fun sequentZero(current: EtsStmt): List { + if (current !is EtsAssignStmt) return listOf(Zero) + + val lhv = current.lhv.toPath() + val result = mutableListOf(Zero) + val (preAliases, _) = getAliases(current.method)[current]!! + + fun addTypeFactWithAliases(path: AccessPath, type: EtsTypeFact) { + result += TypedVariable(path, type) + if (path.accesses.isNotEmpty()) { + check(path.accesses.size == 1) + val base = AccessPath(path.base, emptyList()) + for (alias in preAliases.getAliases(base)) { + val newPath = alias + path.accesses.single() + result += TypedVariable(newPath, type) + } + } + } + + when (val rhv = current.rhv) { + is EtsNewExpr -> { + // val newType = rhv.type + // if (newType is EtsClassType) { + // val cls = graph.cp.classes + // .firstOrNull { it.name == newType.typeName } + // if (cls != null) { + // for (f in cls.fields) { + // val path = lhv + FieldAccessor(f.name) + // result += TypedVariable(path, EtsTypeFact.from(f.type)) + // } + // } + // } + + val type = typeInfo[rhv.type] + ?: EtsTypeFact.ObjectEtsTypeFact(cls = rhv.type, properties = emptyMap()) + addTypeFactWithAliases(lhv, type) + } + + is EtsNewArrayExpr -> { + // TODO: check + val elementType = EtsTypeFact.from(rhv.elementType) + val type = EtsTypeFact.ArrayEtsTypeFact(elementType = elementType) + result += TypedVariable(lhv, type) + result += TypedVariable(lhv + ElementAccessor, elementType) + } + + is EtsStringConstant -> { + addTypeFactWithAliases(lhv, EtsTypeFact.StringEtsTypeFact) + } + + is EtsNumberConstant -> { + addTypeFactWithAliases(lhv, EtsTypeFact.NumberEtsTypeFact) + } + + is EtsBooleanConstant -> { + addTypeFactWithAliases(lhv, EtsTypeFact.BooleanEtsTypeFact) + } + + is EtsNullConstant -> { + addTypeFactWithAliases(lhv, EtsTypeFact.NullEtsTypeFact) + } + + is EtsUndefinedConstant -> { + addTypeFactWithAliases(lhv, EtsTypeFact.UndefinedEtsTypeFact) + } + + // Note: do not handle cast in forward ff! + // is EtsCastExpr -> { + // result += TypedVariable(lhv, EtsTypeFact.from(rhv.type)) + // } + + is EtsFieldRef -> { + if (doAddKnownTypes && rhv.type != EtsUnknownType && rhv.type != EtsAnyType) { + val type = EtsTypeFact.from(rhv.type) + logger.debug { "Adding known type for $lhv from $rhv: $type" } + addTypeFactWithAliases(lhv, type) + } + } + + is EtsArithmeticExpr -> { + result += TypedVariable(lhv, EtsTypeFact.StringEtsTypeFact) + result += TypedVariable(lhv, EtsTypeFact.NumberEtsTypeFact) + } + + is EtsRelationExpr -> { + result += TypedVariable(lhv, EtsTypeFact.BooleanEtsTypeFact) + } + + else -> { + // logger.info { "TODO: forward assign $current" } + } + } + + return result + } + + private fun sequentFact(current: EtsStmt, fact: TypedVariable): List { + if (current !is EtsAssignStmt) return listOf(fact) + + val lhv = current.lhv.toPath() + + val rhv = when (val r = current.rhv) { + is EtsRef -> r.toPath() // This, FieldRef, ArrayAccess + is EtsLValue -> r.toPath() // Local + is EtsCastExpr -> r.toPath() // Cast + else -> { + // logger.info { "TODO forward assign: $current" } + null + } + } + + val (preAliases, _) = getAliases(current.method)[current]!! + + // Override LHS when RHS is const-like: + if (rhv == null) { + if (lhv.accesses.isEmpty()) { + // x := const + + // TODO: `x := const as T` + + // x.*:T |= drop + if (fact.variable.startsWith(lhv)) { + return emptyList() + } + + } else { + // x.f := const OR x[i] := const + + check(lhv.accesses.size == 1) + when (val a = lhv.accesses.single()) { + // x.f := const + is FieldAccessor -> { + val base = AccessPath(lhv.base, emptyList()) + + // x.f.*:T |= drop + if (fact.variable.startsWith(lhv)) { + return emptyList() + } + // z in G(x), z.f.*:T |= drop + if (preAliases.getAliases(base).any { fact.variable.startsWith(it + a) }) { + return emptyList() + } + } + + // x[i] := const + is ElementAccessor -> { + // do nothing, pass-through + } + } + } + + // Pass-through unrelated facts: + return listOf(fact) + } + + if (lhv.accesses.isEmpty() && rhv.accesses.isEmpty()) { + // x := y + + // TODO: x := x + // Note: handled outside + + // x.*:T |= drop + if (fact.variable.startsWith(lhv)) { + return emptyList() + } + + // y.*:T |= y.*:T (keep) + x.*:T (same tail) + if (fact.variable.startsWith(rhv)) { + // Extra case with cast: `x := y as U`: + // `y.*:T` |= keep + new fact `x.*:W`, where `W = T intersect U` + // TODO: Currently, we just take the type from the CastExpr, without intersecting. + // The problem is that when we have fact `y:any`, the intersection (though probably correctly) + // produces `x:any`, so we just lose type information from the cast. + // Using the cast type directly is just a temporary solution to satisfy simple tests. + if (current.rhv is EtsCastExpr) { + val path = AccessPath(lhv.base, fact.variable.accesses) + // val type = EtsTypeFact.from((current.rhv as EtsCastExpr).type).intersect(fact.type) ?: fact.type + val type = EtsTypeFact.from((current.rhv as EtsCastExpr).type) + return listOf(fact, TypedVariable(path, type)) + } + + val path = AccessPath(lhv.base, fact.variable.accesses) + return listOf(fact, TypedVariable(path, fact.type)) + } + + } else if (lhv.accesses.isEmpty()) { + // x := y.f OR x := y[i] + + // TODO: x := x.f + // ??????? x.f:T |= drop + + // x.*:T |= drop + if (fact.variable.startsWith(lhv)) { + return emptyList() + } + + check(rhv.accesses.size == 1) + when (val a = rhv.accesses.single()) { + // x := y.f + is FieldAccessor -> { + // y.f.*:T |= y.f.*:T (keep) + x.*:T (same tail after .f) + if (fact.variable.startsWith(rhv)) { + val path = lhv + fact.variable.accesses.drop(1) + return listOf(fact, TypedVariable(path, fact.type)) + } + // Note: the following is unnecessary due to `z := y` alias + // // z in G(y), z.f.*:T |= z.f.*:T (keep) + x.*:T (same tail after .f) + // val y = AccessPath(rhv.base, emptyList()) + // for (z in preAliases.getAliases(y)) { + // if (fact.variable.startsWith(z + a)) { + // val path = lhv + fact.variable.accesses.drop(z.accesses.size + 1) + // return listOf(fact, TypedVariable(path, fact.type)) + // } + // } + } + + // x := y[i] + is ElementAccessor -> { + // do nothing, pass-through + // TODO: ??? + + // TODO: do we need to add type fact `x.*:T` here? + // y[i].*:T |= y[i].*:T (keep) + x.*:T (same tail after [i]) + if (fact.variable.startsWith(rhv)) { + val path = lhv + fact.variable.accesses.drop(1) + return listOf(fact, TypedVariable(path, fact.type)) + } + } + } + + } else if (rhv.accesses.isEmpty()) { + // x.f := y OR x[i] := y + + check(lhv.accesses.size == 1) + when (val a = lhv.accesses.single()) { + // x.f := y + is FieldAccessor -> { + // TODO: x.f := x + + // x.f.*:T |= drop + if (fact.variable.startsWith(lhv)) { + return emptyList() + } + // z in G(x), z.f.*:T |= drop + val x = AccessPath(lhv.base, emptyList()) + if (preAliases.getAliases(x).any { z -> fact.variable.startsWith(z + a) }) { + return emptyList() + } + + // x.*:T |= x.*:T (keep) + // Note: .* does NOT start with .f, which is handled above + if (fact.variable.base == lhv.base) { + return listOf(fact) + } + + // y.*:T |= y.*:T (keep) + x.f.*:T (same tail) + aliases + // aliases: z in G(x), z.f.*:T |= x.f.*:T (same tail) + if (fact.variable.startsWith(rhv)) { + val result = mutableListOf(fact) + // skip duplicate fields + // if (fact.variable.accesses.firstOrNull() != a) { + val path1 = lhv + fact.variable.accesses + result += TypedVariable(path1, fact.type) + // } + for (z in preAliases.getAliases(x)) { + // skip duplicate fields + // if (z.accesses.firstOrNull() != a) { + // TODO: what about z.accesses.last == a ? + val path2 = z + a + fact.variable.accesses + result += TypedVariable(path2, fact.type) + // } + } + return result + } + // Note: the following is unnecessary due to `z := y` alias + // // z in G(y), z.*:T |= x.f.*:T (same tail) + // for (z in preAliases.getAliases(rhv)) { + // if (fact.variable.startsWith(z)) { + // val path = lhv + fact.variable.accesses + // return listOf(fact, TypedVariable(path, fact.type)) + // } + // } + } + + // x[i] := y + is ElementAccessor -> { + // do nothing, pass-through + // TODO: ??? + + // TODO: do we really want to add type fact `x[i]:T` here? + // y.*:T |= y.*:T (keep) + x[i].*:T (same tail) + // TODO: what about aliases of x? + if (fact.variable.startsWith(rhv)) { + val path = lhv + fact.variable.accesses + return listOf(fact, TypedVariable(path, fact.type)) + } + } + } + + } else { + error("Incorrect 3AC: $current") + } + + return listOf(fact) + } + + override fun obtainCallToReturnSiteFlowFunction( + callStatement: EtsStmt, + returnSite: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> listOf(Zero) + is TypedVariable -> call(callStatement, fact) + } + } + + private fun call( + callStatement: EtsStmt, + fact: TypedVariable, + ): List { + val callResultValue = (callStatement as? EtsAssignStmt)?.lhv?.toPath() + if (callResultValue != null) { + // Drop fact on LHS as it will be overwritten by the call result + if (fact.variable.base == callResultValue.base) return emptyList() + } + + val callExpr = callStatement.callExpr ?: error("No call") + + // todo: hack, keep fact if call was not resolved + if (graph.callees(callStatement).none()) { + return listOf(fact) + } + + if (callExpr is EtsInstanceCallExpr) { + val instance = callExpr.instance.toPath() + if (fact.variable.base == instance.base) return emptyList() + } + + for (arg in callExpr.args) { + val argPath = arg.toPath() + if (fact.variable.base == argPath.base) return emptyList() + } + + return listOf(fact) + } + + override fun obtainCallToStartFlowFunction( + callStatement: EtsStmt, + calleeStart: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> listOf(Zero) + is TypedVariable -> start(callStatement, fact) + } + } + + private fun start( + callStatement: EtsStmt, + fact: TypedVariable, + ): List { + val result = mutableListOf() + + val callExpr = callStatement.callExpr ?: error("No call") + + if (callExpr is EtsInstanceCallExpr) { + val instance = callExpr.instance.toPath() + if (fact.variable.base == instance.base) { + val path = AccessPath(AccessPathBase.This, fact.variable.accesses) + result += TypedVariable(path, fact.type) + } + } + + for ((index, arg) in callExpr.args.withIndex()) { + val argPath = arg.toPath() + if (fact.variable.base == argPath.base) { + val path = AccessPath(AccessPathBase.Arg(index), fact.variable.accesses) + result += TypedVariable(path, fact.type) + } + } + + return result + } + + override fun obtainExitToReturnSiteFlowFunction( + callStatement: EtsStmt, + returnSite: EtsStmt, + exitStatement: EtsStmt, + ): FlowFunction = FlowFunction { fact -> + when (fact) { + Zero -> listOf(Zero) + is TypedVariable -> exit(callStatement, exitStatement, fact) + } + } + + private fun exit( + callStatement: EtsStmt, + exitStatement: EtsStmt, + fact: TypedVariable, + ): List { + val factVariableBase = fact.variable.base + val callExpr = callStatement.callExpr ?: error("No call") + + when (factVariableBase) { + is AccessPathBase.This -> { + // Drop facts on This if the call was static + if (callExpr !is EtsInstanceCallExpr) { + return emptyList() + } + + val instance = callExpr.instance.toPath() + check(instance.accesses.isEmpty()) + + val path = AccessPath(instance.base, fact.variable.accesses) + return listOf(TypedVariable(path, fact.type)) + } + + is AccessPathBase.Arg -> { + val arg = callExpr.args.getOrNull(factVariableBase.index)?.toPath() ?: return emptyList() + val path = AccessPath(arg.base, fact.variable.accesses) + return listOf(TypedVariable(path, fact.type)) + } + + else -> { + if (exitStatement !is EtsReturnStmt) return emptyList() + val exitValue = exitStatement.returnValue?.toPath() ?: return emptyList() + + if (fact.variable.base != exitValue.base) return emptyList() + + val callResult = (callStatement as? EtsAssignStmt)?.lhv?.toPath() ?: return emptyList() + check(callResult.accesses.isEmpty()) + + val path = AccessPath(callResult.base, fact.variable.accesses) + return listOf(TypedVariable(path, fact.type)) + } + } + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeDomainFact.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeDomainFact.kt new file mode 100644 index 0000000000..196dea887c --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeDomainFact.kt @@ -0,0 +1,21 @@ +package org.usvm.dataflow.ts.infer + +sealed interface BackwardTypeDomainFact { + data object Zero : BackwardTypeDomainFact + + // Requirement + data class TypedVariable( + val variable: AccessPathBase, + val type: EtsTypeFact, + ) : BackwardTypeDomainFact +} + +sealed interface ForwardTypeDomainFact { + data object Zero : ForwardTypeDomainFact + + // Exact type + data class TypedVariable( + val variable: AccessPath, + val type: EtsTypeFact, // primitive or Object + ) : ForwardTypeDomainFact +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeGuesser.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeGuesser.kt new file mode 100644 index 0000000000..abe935a3a3 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeGuesser.kt @@ -0,0 +1,271 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer + +import mu.KotlinLogging +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.model.EtsClass +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene + +private val logger = KotlinLogging.logger {} + +fun guessTypes( + scene: EtsScene, + facts: Map>, + propertyNameToClasses: Map> +): Map> { + return facts.mapValues { (method, types) -> + if (types.isEmpty()) { + logger.warn { "Facts are empty for method ${method.signature}" } + return@mapValues types + } + + val updatedTypes = types.mapValues { (accessPath, fact) -> + // logger.info { + // "Resolving a type for a fact \"$fact\" for access path \"$accessPath\" in the method \"$method\"" + // } + + val resultingType = fact.resolveType(scene, propertyNameToClasses) + // logger.info { "The result is $resultingType" } + + resultingType + } + + updatedTypes + } +} + +fun EtsTypeFact.resolveType( + scene: EtsScene, + propertyNameToClasses: Map> +): EtsTypeFact { + val simplifiedFact = simplify() + + return when (simplifiedFact) { + is EtsTypeFact.ArrayEtsTypeFact -> simplifiedFact.resolveArrayTypeFact(scene, propertyNameToClasses) + is EtsTypeFact.ObjectEtsTypeFact -> simplifiedFact.resolveObjectTypeFact(scene, propertyNameToClasses) + is EtsTypeFact.FunctionEtsTypeFact -> simplifiedFact + is EtsTypeFact.GuardedTypeFact -> TODO("guarded") + is EtsTypeFact.IntersectionEtsTypeFact -> { + val updatedTypes = simplifiedFact.types.mapTo(hashSetOf()) { + it.resolveType(scene, propertyNameToClasses) + } + EtsTypeFact.mkIntersectionType(updatedTypes).simplify() + } + + is EtsTypeFact.UnionEtsTypeFact -> { + val updatedTypes = simplifiedFact.types.mapNotNullTo(mutableSetOf()) { type -> + val resolvedType = type.resolveType(scene, propertyNameToClasses) + resolvedType.takeIf { it !is EtsTypeFact.AnyEtsTypeFact } + } + + if (updatedTypes.isEmpty()) { + EtsTypeFact.AnyEtsTypeFact + } else { + EtsTypeFact.mkUnionType(updatedTypes).simplify() + } + } + + else -> simplify() + } +} + +private fun EtsTypeFact.ObjectEtsTypeFact.resolveObjectTypeFact( + scene: EtsScene, + propertyNameToClasses: Map>, +): EtsTypeFact { + if (cls != null) { + return this + } + + val touchedPropertiesNames = properties.keys + val classesInSystem = collectSuitableClasses(touchedPropertiesNames, propertyNameToClasses) + + if (classesInSystem.isEmpty()) { + return tryToDetermineSpecialObjects(scene, touchedPropertiesNames, propertyNameToClasses) + } + + val suitableTypes = resolveTypesFromClasses(classesInSystem, scene, propertyNameToClasses) + + // TODO process arrays here (and strings) + + return when { + suitableTypes.isEmpty() -> error("Should be processed earlier") + suitableTypes.size == 1 -> suitableTypes.single() + suitableTypes.size in 2..5 -> EtsTypeFact.mkUnionType(suitableTypes).simplify() + else -> this + } +} + +private fun EtsTypeFact.ObjectEtsTypeFact.resolveTypesFromClasses( + classesInSystem: Iterable, + scene: EtsScene, + propertyNameToClasses: Map>, +) = classesInSystem + .mapTo(hashSetOf()) { cls -> + EtsTypeFact.ObjectEtsTypeFact( + cls = EtsClassType(signature = cls.signature), + properties = properties.mapValues { + it.value.resolveType(scene, propertyNameToClasses) + } + ) + } + +private fun collectSuitableClasses( + touchedPropertiesNames: Set, + propertyNameToClasses: Map>, +): Set { + val classesWithProperties = touchedPropertiesNames.map { propertyNameToClasses[it] ?: emptySet() } + + return classesWithProperties.reduceOrNull { a, b -> a intersect b } ?: emptySet() +} + +private fun EtsTypeFact.ObjectEtsTypeFact.tryToDetermineSpecialObjects( + scene: EtsScene, + touchedPropertiesNames: Set, + propertyNameToClasses: Map>, +): EtsTypeFact.BasicType { + val indicesProperties = properties.filter { (k, _) -> k.toIntOrNull() != null } + if (indicesProperties.isNotEmpty()) { + val elementTypeFacts = indicesProperties.mapTo(hashSetOf()) { + it.value.resolveType(scene, propertyNameToClasses) + } + + val typeFact = EtsTypeFact.mkUnionType(elementTypeFacts).simplify() + + return EtsTypeFact.ArrayEtsTypeFact(typeFact) + } + + if ("length" in touchedPropertiesNames && "splice" in touchedPropertiesNames) { + return EtsTypeFact.ArrayEtsTypeFact(EtsTypeFact.AnyEtsTypeFact) + } + + return this +} + +private fun EtsTypeFact.ArrayEtsTypeFact.resolveArrayTypeFact( + scene: EtsScene, + propertyNameToClasses: Map>, +): EtsTypeFact.ArrayEtsTypeFact { + return if (elementType is EtsTypeFact.UnknownEtsTypeFact) { + this + } else { + val updatedElementType = elementType.resolveType(scene, propertyNameToClasses) + + if (updatedElementType === elementType) this else copy(elementType = elementType) + } +} + +fun EtsTypeFact.simplify(): EtsTypeFact { + return when (this) { + is EtsTypeFact.UnionEtsTypeFact -> simplifyUnionTypeFact() + is EtsTypeFact.IntersectionEtsTypeFact -> simplifyIntersectionTypeFact() + is EtsTypeFact.GuardedTypeFact -> TODO("Guarded type facts are unsupported in simplification") + is EtsTypeFact.ArrayEtsTypeFact -> { + val elementType = elementType.simplify() + + if (elementType === this.elementType) this else copy(elementType = elementType) + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + if (cls != null) { + return this + } + + val props = properties.mapValues { it.value.simplify() } + copy(properties = props) + } + + else -> this + } +} + +private fun EtsTypeFact.IntersectionEtsTypeFact.simplifyIntersectionTypeFact(): EtsTypeFact { + val simplifiedArgs = types.map { it.simplify() } + + simplifiedArgs.singleOrNull()?.let { return it } + + val updatedTypeFacts = hashSetOf() + + val (objectClassFacts, otherFacts) = simplifiedArgs.partition { + it is EtsTypeFact.ObjectEtsTypeFact && it.cls == null + } + + updatedTypeFacts.addAll(otherFacts) + + if (objectClassFacts.isNotEmpty()) { + val allProperties = hashMapOf>().withDefault { hashSetOf() } + + objectClassFacts.forEach { fact -> + fact as EtsTypeFact.ObjectEtsTypeFact + + fact.properties.forEach { (name, propertyFact) -> + allProperties.getValue(name).add(propertyFact) + } + } + + val mergedAllProperties = hashMapOf() + allProperties.forEach { (name, propertyFact) -> + mergedAllProperties[name] = EtsTypeFact.mkUnionType(propertyFact) + } + + updatedTypeFacts += EtsTypeFact.ObjectEtsTypeFact(cls = null, properties = mergedAllProperties) + } + + return EtsTypeFact.mkIntersectionType(updatedTypeFacts) +} + +private fun EtsTypeFact.UnionEtsTypeFact.simplifyUnionTypeFact(): EtsTypeFact { + val simplifiedArgs = types.map { it.simplify() } + + simplifiedArgs.singleOrNull()?.let { return it } + + val updatedTypeFacts = hashSetOf() + + var atLeastOneNonEmptyObjectFound = false + var emptyTypeObjectFact: EtsTypeFact? = null + + simplifiedArgs.forEach { + if (it !is EtsTypeFact.ObjectEtsTypeFact) { + updatedTypeFacts += it + return@forEach + } + + if (it.cls != null) { + atLeastOneNonEmptyObjectFound = true + updatedTypeFacts += it + return@forEach + } + + if (it.properties.isEmpty() && emptyTypeObjectFact == null) { + emptyTypeObjectFact = it + } else { + updatedTypeFacts += it + atLeastOneNonEmptyObjectFound = true + } + } + + // take a fact `Object {}` only if there were no other objects in the facts + emptyTypeObjectFact?.let { + if (!atLeastOneNonEmptyObjectFound) { + updatedTypeFacts += it + } + } + + return EtsTypeFact.mkUnionType(updatedTypeFacts) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceManager.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceManager.kt new file mode 100644 index 0000000000..9aed9543a4 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceManager.kt @@ -0,0 +1,705 @@ +package org.usvm.dataflow.ts.infer + +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import org.jacodb.ets.base.ANONYMOUS_CLASS_PREFIX +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.INSTANCE_INIT_METHOD_NAME +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.graph.findDominators +import org.jacodb.ets.model.EtsMethod +import org.jacodb.impl.cfg.graphs.GraphDominators +import org.usvm.dataflow.graph.reversed +import org.usvm.dataflow.ifds.ControlEvent +import org.usvm.dataflow.ifds.Edge +import org.usvm.dataflow.ifds.Manager +import org.usvm.dataflow.ifds.QueueEmptinessChanged +import org.usvm.dataflow.ifds.SingletonUnit +import org.usvm.dataflow.ifds.UniRunner +import org.usvm.dataflow.ts.infer.EtsTypeFact.Companion.allStringProperties +import org.usvm.dataflow.ts.util.EtsTraits +import java.util.concurrent.ConcurrentHashMap +import kotlin.time.Duration.Companion.seconds + +class TypeInferenceManager( + val traits: EtsTraits, + val graph: EtsApplicationGraph, +) : Manager { + private lateinit var runnerFinished: CompletableDeferred + + private val backwardSummaries = ConcurrentHashMap>() + private val forwardSummaries = ConcurrentHashMap>() + + private val methodDominatorsCache = ConcurrentHashMap>() + + private fun methodDominators(method: EtsMethod): GraphDominators = + methodDominatorsCache.computeIfAbsent(method) { + method.flowGraph().findDominators() + } + + private val savedTypes: ConcurrentHashMap> = ConcurrentHashMap() + + fun analyze( + entrypoints: List, + allMethods: List = entrypoints, + doAddKnownTypes: Boolean = true, + doInferAllLocals: Boolean = true, + ): TypeInferenceResult = runBlocking(Dispatchers.Default) { + val methodTypeScheme = collectSummaries( + startMethods = entrypoints, + doAddKnownTypes = doAddKnownTypes, + ) + val remainingMethodsForAnalysis = allMethods.filter { it !in methodTypeScheme.keys } + + val updatedTypeScheme = if (remainingMethodsForAnalysis.isEmpty()) { + methodTypeScheme + } else { + collectSummaries( + startMethods = remainingMethodsForAnalysis, + doAddKnownTypes = doAddKnownTypes, + ) + } + + createResultsFromSummaries(updatedTypeScheme, doInferAllLocals) + } + + private suspend fun collectSummaries( + startMethods: List, + doAddKnownTypes: Boolean = true, + ): Map = coroutineScope { + logger.info { "Preparing backward analysis" } + val backwardGraph = graph.reversed + val backwardAnalyzer = BackwardAnalyzer(backwardGraph, savedTypes, ::methodDominators) + val backwardRunner = UniRunner( + traits = traits, + manager = this@TypeInferenceManager, + graph = backwardGraph, + analyzer = backwardAnalyzer, + unitResolver = { SingletonUnit }, + unit = SingletonUnit, + zeroFact = BackwardTypeDomainFact.Zero, + ) + + val backwardJob = launch(start = CoroutineStart.LAZY) { + backwardRunner.run(startMethods) + } + + logger.info { "Running backward analysis" } + runnerFinished = CompletableDeferred() + backwardJob.start() + runnerFinished.await() + backwardJob.cancelAndJoin() + logger.info { "Backward analysis finished" } + + // logger.info { + // buildString { + // appendLine("Backward summaries: (${backwardSummaries.size})") + // for ((method, summaries) in backwardSummaries) { + // appendLine("=== Backward summaries for ${method.signature.enclosingClass.name}::${method.name}: (${summaries.size})") + // for (summary in summaries) { + // appendLine(" ${summary.initialFact} -> ${summary.exitFact}") + // } + // } + // } + // } + + val methodTypeScheme = methodTypeScheme() + + logger.info { + buildString { + appendLine("Backward types:") + for ((method, typeFacts) in methodTypeScheme) { + appendLine("Backward types for ${method.enclosingClass.name}::${method.name} in ${method.enclosingClass.file}:") + for ((base, fact) in typeFacts.types.entries.sortedBy { + when (val key = it.key) { + is AccessPathBase.This -> 0 + is AccessPathBase.Arg -> key.index + 1 + else -> 1_000_000 + } + }) { + appendLine("$base: ${fact.toPrettyString()}") + } + } + } + } + + val typeInfo: Map = savedTypes.mapValues { (type, facts) -> + val typeFact = EtsTypeFact.ObjectEtsTypeFact(type, properties = emptyMap()) + facts.fold(typeFact as EtsTypeFact) { acc, it -> + acc.intersect(it) ?: run { + logger.error { "Empty intersection type: $acc & $it" } + acc + } + } + } + + logger.info { "Preparing forward analysis" } + val forwardGraph = graph + val forwardAnalyzer = ForwardAnalyzer(forwardGraph, methodTypeScheme, typeInfo, doAddKnownTypes) + val forwardRunner = UniRunner( + traits = traits, + manager = this@TypeInferenceManager, + graph = forwardGraph, + analyzer = forwardAnalyzer, + unitResolver = { SingletonUnit }, + unit = SingletonUnit, + zeroFact = ForwardTypeDomainFact.Zero, + ) + + val forwardJob = launch(start = CoroutineStart.LAZY) { + forwardRunner.run(startMethods) + } + + logger.info { "Running forward analysis" } + runnerFinished = CompletableDeferred() + forwardJob.start() + withTimeout(3600.seconds) { + runnerFinished.await() + } + forwardJob.cancelAndJoin() + logger.info { "Forward analysis finished" } + + // logger.info { + // buildString { + // appendLine("Forward summaries: (${forwardSummaries.size})") + // for ((method, summaries) in forwardSummaries) { + // appendLine("=== Forward summaries for ${method.signature.enclosingClass.name}::${method.name}: (${summaries.size})") + // for (summary in summaries) { + // appendLine(" ${summary.initialFact} -> ${summary.exitFact}") + // } + // } + // } + // } + + methodTypeScheme + } + + private fun createResultsFromSummaries( + methodTypeScheme: Map, + doInferAllLocals: Boolean, + ): TypeInferenceResult { + val refinedTypes = refineMethodTypes(methodTypeScheme).toMutableMap() + logger.info { + buildString { + appendLine("Forward types:") + for ((method, typeFacts) in refinedTypes) { + appendLine("Forward types for ${method.signature.enclosingClass.name}::${method.name} in ${method.signature.enclosingClass.file}:") + for ((base, fact) in typeFacts.types.entries.sortedBy { + when (val key = it.key) { + is AccessPathBase.This -> 0 + is AccessPathBase.Arg -> key.index + 1 + else -> 1_000_000 + } + }) { + appendLine("$base: ${fact.toPrettyString()}") + } + } + } + } + + // Infer types for 'this' in each class + val inferredCombinedThisTypes = run { + val allClasses = methodTypeScheme.keys + .map { it.enclosingClass } + .distinct() + .map { sig -> graph.cp.projectAndSdkClasses.first { cls -> cls.signature == sig } } + .filterNot { it.name.startsWith(ANONYMOUS_CLASS_PREFIX) } + allClasses.mapNotNull { cls -> + val combinedBackwardType = + methodTypeScheme.asSequence().filter { (method, _) -> method in (cls.methods + cls.ctor) } + .mapNotNull { (_, facts) -> facts.types[AccessPathBase.This] }.reduceOrNull { acc, type -> + val intersection = acc.intersect(type) + + if (intersection == null) { + System.err.println("Empty intersection type: $acc & $type") + } + + intersection ?: acc + } + logger.info { + buildString { + appendLine("Combined backward type for This in class '${cls.signature}': ${combinedBackwardType?.toPrettyString()}") + } + } + + if (combinedBackwardType == null) { + return@mapNotNull null + } + + val typeFactsOnThisMethods = forwardSummaries.asSequence() + .filter { (method, _) -> method.enclosingClass == cls.signature } + .filter { (method, _) -> method.name != INSTANCE_INIT_METHOD_NAME } + .flatMap { (_, summaries) -> summaries.asSequence() } + .mapNotNull { it.initialFact as? ForwardTypeDomainFact.TypedVariable } + .filter { it.variable.base is AccessPathBase.This } + .toList() + .distinct() + + val typeFactsOnThisCtor = forwardSummaries.asSequence() + .filter { (method, _) -> method.enclosingClass == cls.signature } + .filter { (method, _) -> method.name == CONSTRUCTOR_NAME || method.name == INSTANCE_INIT_METHOD_NAME } + .flatMap { (_, summaries) -> summaries.asSequence() } + .mapNotNull { it.exitFact as? ForwardTypeDomainFact.TypedVariable } + .filter { it.variable.base is AccessPathBase.This } + .toList() + .distinct() + + val typeFactsOnThis = (typeFactsOnThisMethods + typeFactsOnThisCtor).distinct() + + val propertyRefinements = typeFactsOnThis + .groupBy({ it.variable.accesses }, { it.type }) + .mapValues { (_, types) -> types.reduce { acc, t -> acc.union(t) } } + + logger.info { + buildString { + appendLine("Property refinements for This in class '${cls.signature}':") + for ((property, propertyType) in propertyRefinements.toList() + .sortedBy { it.first.joinToString(".") }) { + appendLine(" this.${property.joinToString(".")}: $propertyType") + } + } + } + + var refined: EtsTypeFact = combinedBackwardType + for ((property, propertyType) in propertyRefinements) { + refined = refined.refineProperty(property, propertyType) ?: this@TypeInferenceManager.run { + System.err.println("Empty intersection type: $combinedBackwardType[$property] & $propertyType") + refined + } + } + + combinedBackwardType.let {} + typeFactsOnThisMethods.let {} + typeFactsOnThisCtor.let {} + typeFactsOnThis.let {} + propertyRefinements.let {} + cls.let {} + + cls.signature to refined + }.toMap() + } + logger.info { + buildString { + appendLine("Combined and refined types for This:") + for ((cls, type) in inferredCombinedThisTypes) { + appendLine("Combined This in class '${cls}': ${type.toPrettyString()}") + } + } + } + + // Infer return types for each method + val inferredReturnTypes = run { + forwardSummaries.asSequence().mapNotNull { (method, summaries) -> + val typeFacts = summaries.asSequence().map { it.exitVertex }.mapNotNull { + val stmt = it.statement as? EtsReturnStmt ?: return@mapNotNull null + val fact = it.fact as? ForwardTypeDomainFact.TypedVariable ?: return@mapNotNull null + val r = stmt.returnValue?.toPath() ?: return@mapNotNull null + check(r.accesses.isEmpty()) + if (fact.variable.base != r.base) return@mapNotNull null + r.base to fact + }.groupBy({ it.first }, { it.second }) + + val returnFact = typeFacts.mapValues { (_, typeRefinements) -> + val propertyRefinements = typeRefinements.groupBy({ it.variable.accesses }, { it.type }) + .mapValues { (_, types) -> types.reduce { acc, t -> acc.union(t) } } + + val rootType = propertyRefinements[emptyList()] ?: run { + if (propertyRefinements.keys.any { it.isNotEmpty() }) { + EtsTypeFact.ObjectEtsTypeFact(null, emptyMap()) + } else { + EtsTypeFact.AnyEtsTypeFact + } + } + + val refined = rootType.refineProperties(emptyList(), propertyRefinements) + + refined + }.values.reduceOrNull { acc, type -> acc.union(type) } + if (returnFact != null) { + method to returnFact + } else { + null + } + }.toMap() + } + logger.info { + buildString { + appendLine("Return types:") + for ((method, type) in inferredReturnTypes) { + appendLine("Return type for ${method.signature.enclosingClass.file}::${method.signature.enclosingClass.name}::${method.name}: ${type.toPrettyString()}") + } + } + } + + val inferredLocalTypes: Map>? = if (doInferAllLocals) { + forwardSummaries.asSequence().map { (method, summaries) -> + val typeFacts = summaries.asSequence() + .mapNotNull { it.exitVertex.fact as? ForwardTypeDomainFact.TypedVariable } + .filter { it.variable.base is AccessPathBase.Local } + .groupBy { it.variable.base } + + val localTypes = typeFacts.mapValues { (_, typeFacts) -> + val propertyRefinements = typeFacts + .groupBy({ it.variable.accesses }, { it.type }) + .mapValues { (_, types) -> types.reduce { acc, t -> acc.union(t) } } + + val rootType = propertyRefinements[emptyList()] ?: run { + if (propertyRefinements.keys.any { it.isNotEmpty() }) { + EtsTypeFact.ObjectEtsTypeFact(null, emptyMap()) + } else { + EtsTypeFact.AnyEtsTypeFact + } + } + + val refined = rootType.refineProperties(emptyList(), propertyRefinements) + + refined + } + + method to localTypes + }.toMap() + } else { + null + } + + if (inferredLocalTypes != null) { + logger.info { + buildString { + appendLine("Local types:") + for ((method, localTypes) in inferredLocalTypes) { + appendLine("Local types for ${method.signature.enclosingClass.name}::${method.name} in ${method.signature.enclosingClass.file}:") + for ((base, fact) in localTypes.entries.sortedBy { (it.key as AccessPathBase.Local).name }) { + appendLine("$base: ${fact.toPrettyString()}") + } + } + } + } + + for ((method, localFacts) in inferredLocalTypes) { + val facts = refinedTypes[method]!! + refinedTypes[method] = facts.copy(types = facts.types + localFacts) + } + } + + val inferredTypes = refinedTypes + // Extract 'types': + .mapValues { (_, facts) -> facts.types } + // Sort by 'base': + .mapValues { (_, types) -> + types.entries.sortedBy { + when (val key = it.key) { + is AccessPathBase.This -> 0 + is AccessPathBase.Arg -> key.index + 1 + else -> 1_000_000 + } + }.associate { it.key to it.value } + }.mapValues { (_, methodFacts) -> + methodFacts.mapValues { (_, fact) -> + fact.simplify() + } + } + + return TypeInferenceResult( + inferredTypes = inferredTypes, + inferredReturnType = inferredReturnTypes, + inferredCombinedThisType = inferredCombinedThisTypes, + ) + } + + private fun methodTypeScheme(): Map = + backwardSummaries.mapValues { (method, summaries) -> + buildMethodTypeScheme(method, summaries) + } + + private fun refineMethodTypes(schema: Map): Map = + schema.mapValues { (method, facts) -> + val summaries = forwardSummaries[method].orEmpty() + refineMethodTypes(facts, summaries) + } + + private fun buildMethodTypeScheme( + method: EtsMethod, + summaries: Iterable, + ): EtsMethodTypeFacts { + val types = summaries + .mapNotNull { it.exitFact as? BackwardTypeDomainFact.TypedVariable } + .groupBy({ it.variable }, { it.type }) + .filter { (base, _) -> base is AccessPathBase.This || base is AccessPathBase.Arg } + .mapValues { (_, typeFacts) -> + typeFacts.reduce { acc, typeFact -> + val intersection = acc.intersect(typeFact) + + if (intersection == null) { + System.err.println("Empty intersection type: $acc & $typeFact") + } + + intersection ?: acc + } + } + + return EtsMethodTypeFacts(method, types) + } + + private fun refineMethodTypes( + facts: EtsMethodTypeFacts, // backward types + summaries: Iterable, + ): EtsMethodTypeFacts { + // Contexts + val typeFacts = summaries.asSequence() + .mapNotNull { it.initialFact as? ForwardTypeDomainFact.TypedVariable } + .filter { it.variable.base is AccessPathBase.This || it.variable.base is AccessPathBase.Arg } + .groupBy { it.variable.base } + + val refinedTypes = facts.types.mapValues { (base, type) -> + val typeRefinements = typeFacts[base] ?: return@mapValues type + + val propertyRefinements = typeRefinements + .groupBy({ it.variable.accesses }, { it.type }) + .mapValues { (_, types) -> types.reduce { acc, t -> acc.union(t) } } + + val rootType = propertyRefinements[emptyList()] ?: run { + if (propertyRefinements.keys.any { it.isNotEmpty() }) { + EtsTypeFact.ObjectEtsTypeFact(null, emptyMap()) + } else { + EtsTypeFact.AnyEtsTypeFact + } + } + + val refined = rootType.refineProperties(emptyList(), propertyRefinements) + + refined + } + + typeFacts.let {} + + return EtsMethodTypeFacts(facts.method, refinedTypes) + } + + private fun EtsTypeFact.refineProperties( + pathFromRootObject: List, + typeRefinements: Map, EtsTypeFact>, + ): EtsTypeFact = when (this) { + is EtsTypeFact.NumberEtsTypeFact -> this + is EtsTypeFact.StringEtsTypeFact -> this + is EtsTypeFact.FunctionEtsTypeFact -> this + is EtsTypeFact.AnyEtsTypeFact -> this + is EtsTypeFact.BooleanEtsTypeFact -> this + is EtsTypeFact.NullEtsTypeFact -> this + is EtsTypeFact.UndefinedEtsTypeFact -> this + is EtsTypeFact.UnknownEtsTypeFact -> { + // logger.warn { "Unknown type after forward analysis" } + EtsTypeFact.AnyEtsTypeFact + } + + is EtsTypeFact.ArrayEtsTypeFact -> { + // TODO: array types + logger.error { "TODO: Array type $this" } + + val elementPath = pathFromRootObject + ElementAccessor + val refinedElemType = + typeRefinements[elementPath]?.intersect(elementType) ?: elementType // todo: mb exception??? + val elemType = refinedElemType.refineProperties(elementPath, typeRefinements) + + EtsTypeFact.ArrayEtsTypeFact(elemType) + } + + is EtsTypeFact.ObjectEtsTypeFact -> refineProperties(pathFromRootObject, typeRefinements) + is EtsTypeFact.UnionEtsTypeFact -> EtsTypeFact.mkUnionType(types.mapTo(hashSetOf()) { + it.refineProperties( + pathFromRootObject, + typeRefinements + ) + }) + + is EtsTypeFact.IntersectionEtsTypeFact -> EtsTypeFact.mkIntersectionType(types.mapTo(hashSetOf()) { + it.refineProperties( + pathFromRootObject, + typeRefinements + ) + }) + + is EtsTypeFact.GuardedTypeFact -> type.refineProperties(pathFromRootObject, typeRefinements) + .withGuard(guard, guardNegated) + } + + private fun EtsTypeFact.ObjectEtsTypeFact.refineProperties( + pathFromRootObject: List, + typeRefinements: Map, EtsTypeFact>, + ): EtsTypeFact { + val refinedProperties = properties.mapValues { (propertyName, type) -> + val propertyAccessor = FieldAccessor(propertyName) + val propertyPath = pathFromRootObject + propertyAccessor + val refinedType = typeRefinements[propertyPath]?.intersect(type) ?: type // todo: mb exception??? + refinedType.refineProperties(propertyPath, typeRefinements) + } + return EtsTypeFact.ObjectEtsTypeFact(cls, refinedProperties) + } + + private fun EtsTypeFact.refineProperty(property: List, type: EtsTypeFact): EtsTypeFact? = when (this) { + is EtsTypeFact.BasicType -> refineProperty(property, type) + + is EtsTypeFact.GuardedTypeFact -> this.type.refineProperty(property, type)?.withGuard(guard, guardNegated) + + is EtsTypeFact.IntersectionEtsTypeFact -> EtsTypeFact.mkIntersectionType(types.mapTo(hashSetOf()) { + it.refineProperty( + property, + type + ) ?: return null + }) + + is EtsTypeFact.UnionEtsTypeFact -> EtsTypeFact.mkUnionType(types.mapNotNullTo(hashSetOf()) { + it.refineProperty( + property, + type + ) + }) + } + + private fun EtsTypeFact.BasicType.refineProperty( + property: List, + type: EtsTypeFact, + ): EtsTypeFact? { + when (this) { + EtsTypeFact.AnyEtsTypeFact, + EtsTypeFact.FunctionEtsTypeFact, + EtsTypeFact.NumberEtsTypeFact, + EtsTypeFact.BooleanEtsTypeFact, + EtsTypeFact.StringEtsTypeFact, + EtsTypeFact.NullEtsTypeFact, + EtsTypeFact.UndefinedEtsTypeFact, + -> return if (property.isNotEmpty()) this else intersect(type) + + is EtsTypeFact.ArrayEtsTypeFact -> { + // TODO: the following check(property.size == 1) fails on multiple projects + // check(property.size == 1) + if (property.size == 1) { + // val p = property.single() + // check(p is ElementAccessor) + val t = elementType.intersect(type) ?: error("Empty intersection") + return EtsTypeFact.ArrayEtsTypeFact(elementType = t) + } else { + return EtsTypeFact.AnyEtsTypeFact + } + } + + is EtsTypeFact.UnknownEtsTypeFact -> { + // .f.g:T -> {f: {g: T}} + // .f[i].g:T -> {f: Array<{g: T}>} + var t = type + for (p in property.reversed()) { + if (p is FieldAccessor) { + t = EtsTypeFact.ObjectEtsTypeFact( + cls = null, + properties = mapOf(p.name to t), + ) + } else { + t = EtsTypeFact.ArrayEtsTypeFact(elementType = t) + } + } + return t + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + val propertyAccessor = property.firstOrNull() as? FieldAccessor + if (propertyAccessor == null) { + // TODO: handle 'type=union' by exploding it into multiple ObjectFacts (later combined with union) with class names from union. + if (type is EtsTypeFact.UnionEtsTypeFact) { + return type.types.map { + refineProperty(property, it) ?: return null + }.reduce { acc: EtsTypeFact, t: EtsTypeFact -> acc.union(t) } + } + + if (type is EtsTypeFact.StringEtsTypeFact) { + // intersect(this:object, type:string) + + if (cls == EtsStringType) return type + if (cls != null) return null + + val intersectionProperties = properties + .filter { it.key in allStringProperties } + .mapValues { (_, type) -> + // TODO: intersect with the corresponding type of String's property + type + } + + return EtsTypeFact.ObjectEtsTypeFact(cls, intersectionProperties) + } + + if (type is EtsTypeFact.NullEtsTypeFact) { + // intersect(this:object, type:null) + // return EtsTypeFact.NullEtsTypeFact + return EtsTypeFact.mkUnionType(this, EtsTypeFact.NullEtsTypeFact) + } + + if (type is EtsTypeFact.UndefinedEtsTypeFact) { + // intersect(this:object, type:undefined) + // return EtsTypeFact.UndefinedEtsTypeFact + return EtsTypeFact.mkUnionType(this, EtsTypeFact.UndefinedEtsTypeFact) + } + + if (type !is EtsTypeFact.ObjectEtsTypeFact || cls != null) { + // todo: hack + if (type is EtsTypeFact.AnyEtsTypeFact) return this + + // TODO("Unexpected: $this & $type") + return this + } + + return EtsTypeFact.ObjectEtsTypeFact(type.cls, properties) + } + + val propertyType = properties[propertyAccessor.name] ?: return this + val refinedProperty = propertyType.refineProperty(property.drop(1), type) ?: return null + val properties = this.properties + (propertyAccessor.name to refinedProperty) + return EtsTypeFact.ObjectEtsTypeFact(cls, properties) + } + } + } + + override fun handleEvent(event: AnalyzerEvent) { + when (event) { + is BackwardSummaryAnalyzerEvent -> { + backwardSummaries.computeIfAbsent(event.method) { + ConcurrentHashMap.newKeySet() + }.add(event) + } + + is ForwardSummaryAnalyzerEvent -> { + forwardSummaries.computeIfAbsent(event.method) { + ConcurrentHashMap.newKeySet() + }.add(event) + } + } + } + + override fun subscribeOnSummaryEdges( + method: EtsMethod, + scope: CoroutineScope, + handler: (Edge) -> Unit, + ) { + error("No cross unit subscriptions") + } + + override fun handleControlEvent(event: ControlEvent) { + if (event is QueueEmptinessChanged) { + if (event.isEmpty) { + runnerFinished.complete(Unit) + } + } + } + + companion object { + val logger = mu.KotlinLogging.logger {} + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceResult.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceResult.kt new file mode 100644 index 0000000000..d4d991bab7 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/TypeInferenceResult.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer + +import org.jacodb.ets.model.EtsClass +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene + +data class TypeInferenceResult( + val inferredTypes: Map>, + val inferredReturnType: Map, + val inferredCombinedThisType: Map, +) { + fun withGuessedTypes(scene: EtsScene): TypeInferenceResult { + val propertyNameToClasses = precalculateCaches(scene) + + return TypeInferenceResult( + inferredTypes = guessTypes(scene, inferredTypes, propertyNameToClasses), + inferredReturnType = inferredReturnType.mapValues { (_, fact) -> + fact.resolveType(scene, propertyNameToClasses) + }, + inferredCombinedThisType = inferredCombinedThisType.mapValues { (_, fact) -> + fact.resolveType(scene, propertyNameToClasses = propertyNameToClasses) + }, + ) + } + + private fun precalculateCaches(scene: EtsScene): Map> { + val result = hashMapOf>() + + scene.projectAndSdkClasses.forEach { clazz -> + clazz.methods.forEach { + result.computeIfAbsent(it.name) { hashSetOf() }.add(clazz) + } + clazz.fields.forEach { + result.computeIfAbsent(it.name) { hashSetOf() }.add(clazz) + } + } + + return result + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ExprTypeAnnotator.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ExprTypeAnnotator.kt new file mode 100644 index 0000000000..d2a58086c7 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ExprTypeAnnotator.kt @@ -0,0 +1,226 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.annotation + +import org.jacodb.ets.base.* +import org.jacodb.ets.model.EtsScene + +class ExprTypeAnnotator( + private val valueAnnotator: ValueTypeAnnotator, + private val scene: EtsScene +) : EtsExpr.Visitor { + private fun inferEntity(entity: EtsEntity) = when (entity) { + is EtsExpr -> entity.accept(this) + is EtsValue -> entity.accept(valueAnnotator) + else -> error("Unsupported entity") + } + private fun inferValue(value: EtsValue) = value.accept(valueAnnotator) + + override fun visit(expr: EtsNewExpr) = expr + + override fun visit(expr: EtsNewArrayExpr) = expr + + override fun visit(expr: EtsLengthExpr) = expr + + override fun visit(expr: EtsCastExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsInstanceOfExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsDeleteExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsAwaitExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsYieldExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsTypeOfExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsVoidExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsNotExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsBitNotExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsNegExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsUnaryPlusExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsPreIncExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsPreDecExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsPostIncExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsPostDecExpr) = expr.copy(arg = inferEntity(expr.arg)) + + override fun visit(expr: EtsEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsNotEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsStrictEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsStrictNotEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsLtExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsLtEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsGtExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsGtEqExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsInExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsAddExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsSubExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsMulExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsDivExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsRemExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsExpExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsBitAndExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsBitOrExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsBitXorExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsLeftShiftExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsRightShiftExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsUnsignedRightShiftExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsAndExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsOrExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsNullishCoalescingExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsInstanceCallExpr): EtsExpr { + val baseInferred = inferValue(expr.instance) as EtsLocal + val argsInferred = expr.args.map(this::inferValue) + val methodInferred = when (val baseType = baseInferred.type) { + is EtsClassType -> { + val etsClass = scene.projectAndSdkClasses.find { it.signature == baseType.signature } + ?: return expr.copy(instance = baseInferred, args = argsInferred) + val callee = etsClass.methods.find { it.signature == expr.method } + ?: return expr.copy(instance = baseInferred, args = argsInferred) + callee.signature + } + else -> expr.method + } + return EtsInstanceCallExpr(baseInferred, methodInferred, argsInferred) + } + + override fun visit(expr: EtsStaticCallExpr): EtsExpr { + val argsInferred = expr.args.map(this::inferValue) + return EtsStaticCallExpr(expr.method, argsInferred) + } + + override fun visit(expr: EtsPtrCallExpr): EtsExpr { + val ptrInferred = inferValue(expr.ptr) as EtsLocal + val argsInferred = expr.args.map(this::inferValue) + return EtsPtrCallExpr(ptrInferred, expr.method, argsInferred) + } + + override fun visit(expr: EtsCommaExpr) = expr.copy( + left = inferEntity(expr.left), + right = inferEntity(expr.right) + ) + + override fun visit(expr: EtsTernaryExpr) = expr.copy( + condition = inferEntity(expr.condition), + thenExpr = inferEntity(expr.thenExpr), + elseExpr = inferEntity(expr.elseExpr) + ) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/StmtTypeAnnotator.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/StmtTypeAnnotator.kt new file mode 100644 index 0000000000..3d9368911d --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/StmtTypeAnnotator.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.annotation + +import org.jacodb.ets.base.* +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.* + +class StmtTypeAnnotator( + types: Map, + thisType: EtsTypeFact?, + scene: EtsScene, +) : EtsStmt.Visitor { + private val valueAnnotator = ValueTypeAnnotator(types, thisType, scene) + private val exprAnnotator = ExprTypeAnnotator(valueAnnotator, scene) + + private fun inferValue(value: EtsValue) = value.accept(valueAnnotator) + + private fun inferExpr(expr: EtsExpr) = expr.accept(exprAnnotator) + + private fun inferEntity(entity: EtsEntity) = when (entity) { + is EtsExpr -> entity.accept(exprAnnotator) + is EtsValue -> entity.accept(valueAnnotator) + else -> error("Unsupported entity") + } + + override fun visit(stmt: EtsNopStmt) = stmt + + override fun visit(stmt: EtsAssignStmt) = stmt.copy( + lhv = inferValue(stmt.lhv), + rhv = inferEntity(stmt.rhv) + ) + + override fun visit(stmt: EtsCallStmt) = stmt.copy( + expr = inferExpr(stmt.expr) as EtsCallExpr + ) + + override fun visit(stmt: EtsReturnStmt) = stmt.copy( + returnValue = stmt.returnValue?.let(this::inferValue) + ) + + override fun visit(stmt: EtsThrowStmt) = stmt.copy( + arg = inferEntity(stmt.arg) + ) + + override fun visit(stmt: EtsGotoStmt) = stmt + + override fun visit(stmt: EtsIfStmt) = stmt.copy( + condition = inferEntity(stmt.condition) + ) + + override fun visit(stmt: EtsSwitchStmt) = stmt.copy( + arg = inferEntity(stmt.arg), + cases = stmt.cases.map(this::inferEntity) + ) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ValueTypeAnnotator.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ValueTypeAnnotator.kt new file mode 100644 index 0000000000..020f9e776e --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/ValueTypeAnnotator.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.annotation + +import org.jacodb.ets.base.EtsArrayAccess +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsInstanceFieldRef +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsStaticFieldRef +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsField +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.dto.toType + +class ValueTypeAnnotator( + private val types: Map, + private val thisType: EtsTypeFact?, + private val scene: EtsScene +) : EtsValue.Visitor.Default { + private inline fun V.infer(base: AccessPathBase, apply: V.(T) -> V): V { + val type = types[base]?.toType() as? T ?: return this + return apply.invoke(this, type) + } + + override fun visit(value: EtsLocal): EtsLocal = + value.infer(AccessPathBase.Local(value.name)) { copy(type = it) } + + override fun visit(value: EtsThis): EtsValue = + (thisType?.toType() as? EtsClassType)?.let { value.copy(type = it) } + ?: value.infer(AccessPathBase.This) { copy(type = it) } + + override fun visit(value: EtsParameterRef) = + value.infer(AccessPathBase.Arg(value.index)) { copy(type = it) } + + override fun visit(value: EtsArrayAccess): EtsArrayAccess { + val arrayInferred = value.array.accept(this) + val arrayType = arrayInferred.type as? EtsArrayType ?: return value + val indexInferred = value.index.accept(this) + return EtsArrayAccess(arrayInferred, indexInferred, arrayType.elementType) + } + + // TODO: discuss (labeled with (Q)) + override fun visit(value: EtsInstanceFieldRef): EtsValue { + val instance = visit(value.instance) + val name = value.field.name + + fun findInClass(signature: EtsClassSignature): EtsField? = + scene.projectClasses + .singleOrNull { it.signature == signature } + ?.fields + ?.singleOrNull { it.name == name } + + // Try to determine field type using the scene + // (Q) Do we really need this step? + with(value.field) { + val etsField = findInClass(enclosingClass) ?: return@with + // Field was found in the scene + + // Check that inferred type is same with the declared one + // (Q) How should we (do we should?) handle the check violation here? + check(instance.type == EtsClassType(enclosingClass)) + + return EtsInstanceFieldRef(instance = instance, field = etsField.signature) + } + + // Field was not found by signature, then try infer instance type + val instanceTypeInfo = types[AccessPathBase.Local(instance.name)] as? EtsTypeFact.ObjectEtsTypeFact + // Instance type was neither specified in signature nor inferred, so no type info can be provided + // (Q) Should we check special properties of primitives (like `string.length`)? + ?: return value.copy(instance = instance) + + // Find field signature in inferred class fields + (instanceTypeInfo.cls as? EtsClassType)?.run { + val etsField = findInClass(signature) ?: return@run + // Field was found in the inferred class + return EtsInstanceFieldRef(instance = instance, field = etsField.signature) + } + + // Find field type in inferred fields - we don't know precisely the base class, but can infer the field type + instanceTypeInfo.properties[name]?.toType()?.let { fieldType -> + val fieldSubSignature = value.field.sub.copy(type = fieldType) + // (Q) General: Should we use our inferred type if there is a non-trivial type in the original scene? + return EtsInstanceFieldRef(instance = instance, field = value.field.copy(sub = fieldSubSignature)) + } + + return value.copy(instance = instance) + } + + override fun visit(value: EtsStaticFieldRef): EtsValue = value + + override fun defaultVisit(value: EtsValue): EtsValue = value +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/withInferredTypes.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/withInferredTypes.kt new file mode 100644 index 0000000000..ee71d2cbe9 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/annotation/withInferredTypes.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("MemberVisibilityCanBePrivate") + +package org.usvm.dataflow.ts.infer.annotation + +import org.jacodb.ets.graph.EtsCfg +import org.jacodb.ets.model.EtsClass +import org.jacodb.ets.model.EtsClassImpl +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsMethodImpl +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceResult + +data class EtsTypeAnnotator( + val scene: EtsScene, + val typeInferenceResult: TypeInferenceResult, +) { + private fun selectTypesFor(method: EtsMethod) = typeInferenceResult.inferredTypes[method] ?: emptyMap() + + private fun combinedThisFor(method: EtsMethod) = typeInferenceResult.inferredCombinedThisType[method.enclosingClass] + + fun annotateWithTypes(scene: EtsScene) = with(scene) { + EtsScene( + projectFiles = projectFiles.map { annotateWithTypes(it) } + ) + } + + fun annotateWithTypes(file: EtsFile) = with(file) { + EtsFile( + signature = signature, + classes = classes.map { annotateWithTypes(it) }, + namespaces = namespaces, + ) + } + + fun annotateWithTypes(clazz: EtsClass) = with(clazz) { + EtsClassImpl( + signature = signature, + fields = fields, + methods = methods.map { annotateWithTypes(it) }, + ctor = annotateWithTypes(ctor), + superClass = superClass, // TODO: replace with inferred superclass + modifiers = modifiers, + decorators = decorators, + typeParameters = typeParameters, + ) + } + + fun annotateWithTypes(method: EtsMethod) = with(method) { + EtsMethodImpl( + signature = signature, + typeParameters = typeParameters, + locals = locals, + modifiers = modifiers, + decorators = decorators, + ).also { + it._cfg = annotateWithTypes(cfg, selectTypesFor(this), combinedThisFor(this)) + } + } + + fun annotateWithTypes( + cfg: EtsCfg, + types: Map, + thisType: EtsTypeFact?, + ) = with(cfg) { + with(StmtTypeAnnotator(types, thisType, scene)) { + EtsCfg( + stmts = stmts.map { it.accept(this) }, + successorMap = stmts.associateWith { successors(it).toList() }, + ) + } + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/cli/InferTypes.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/cli/InferTypes.kt new file mode 100644 index 0000000000..ef39b8b5b3 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/cli/InferTypes.kt @@ -0,0 +1,149 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("MemberVisibilityCanBePrivate") + +package org.usvm.dataflow.ts.infer.cli + +import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.context +import com.github.ajalt.clikt.core.main +import com.github.ajalt.clikt.output.MordantHelpFormatter +import com.github.ajalt.clikt.parameters.options.convert +import com.github.ajalt.clikt.parameters.options.default +import com.github.ajalt.clikt.parameters.options.flag +import com.github.ajalt.clikt.parameters.options.multiple +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.options.required +import com.github.ajalt.clikt.parameters.types.path +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToStream +import mu.KotlinLogging +import org.jacodb.ets.base.ANONYMOUS_CLASS_PREFIX +import org.jacodb.ets.base.ANONYMOUS_METHOD_PREFIX +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.EntryPointsProcessor +import org.usvm.dataflow.ts.infer.TypeInferenceManager +import org.usvm.dataflow.ts.infer.TypeInferenceResult +import org.usvm.dataflow.ts.infer.createApplicationGraph +import org.usvm.dataflow.ts.infer.dto.toDto +import org.usvm.dataflow.ts.util.EtsTraits +import java.nio.file.Path +import kotlin.io.path.outputStream +import kotlin.time.measureTimedValue + +private val logger = KotlinLogging.logger {} + +class InferTypes : CliktCommand() { + init { + context { + helpFormatter = { + MordantHelpFormatter( + it, + requiredOptionMarker = "*", + showDefaultValues = true, + showRequiredTag = true + ) + } + } + } + + val input by option("-i", "--input", help = "Input file or directory with IR").path().multiple(required = true) + val output by option("-o", "--output", help = "Output file with inferred types in JSON format").path().required() + + val sdkPaths by option( + "--sdk", + help = "Path to SDK directory" + ).path().multiple() + + val sdkNames by option( + "--sdk-names", + help = "Comma-separated list of SDK names" + ).convert { it.split(",") }.default(emptyList(), defaultForHelp = "empty") + + val skipAnonymous by option( + "--skip-anonymous", + help = "Skip anonymous classes and method" + ).flag("--no-skip-anonymous", default = false) + + override fun run() { + logger.info { "Running InferTypes" } + val startTime = System.currentTimeMillis() + + logger.info { "Input: $input" } + logger.info { "Output: $output" } + + val project = loadEtsProjectFromMultipleIR(input, sdkPaths) + val graph = createApplicationGraph(project) + + val (dummyMains, allMethods) = EntryPointsProcessor.extractEntryPoints(project) + val publicMethods = allMethods.filter { m -> + m.isPublic && m.signature.enclosingClass.file.projectName !in sdkNames + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + + val (result, timeAnalyze) = measureTimedValue { + manager.analyze(dummyMains, publicMethods).withGuessedTypes(project) + } + logger.info { "Inferred types for ${result.inferredTypes.size} methods in $timeAnalyze" } + + dumpTypeInferenceResult(result, output, skipAnonymous) + + logger.info { "All done in %.1f s".format((System.currentTimeMillis() - startTime) / 1000.0) } + } +} + +private fun loadEtsProjectFromMultipleIR(input: List, sdkPaths: List): EtsScene { + TODO() +} + +fun main(args: Array) { + InferTypes().main(args) +} + +@OptIn(ExperimentalSerializationApi::class) +fun dumpTypeInferenceResult( + result: TypeInferenceResult, + path: Path, + skipAnonymous: Boolean = true, +) { + logger.info { "Dumping inferred types to '$path'" } + val dto = result.toDto() + // Filter out anonymous classes and methods + .let { dto -> + if (skipAnonymous) { + dto.copy( + classes = dto.classes.filterNot { cls -> + cls.signature.name.startsWith(ANONYMOUS_CLASS_PREFIX) + }, + methods = dto.methods.filterNot { method -> + method.signature.declaringClass.name.startsWith(ANONYMOUS_CLASS_PREFIX) || + method.signature.name.startsWith(ANONYMOUS_METHOD_PREFIX) + } + ) + } else { + dto + } + } + path.outputStream().use { stream -> + val json = Json { + prettyPrint = true + } + json.encodeToStream(dto, stream) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/Convert.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/Convert.kt new file mode 100644 index 0000000000..eda5340277 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/Convert.kt @@ -0,0 +1,195 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.dto + +import mu.KotlinLogging +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArrayObjectType +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsBooleanType +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsFunctionType +import org.jacodb.ets.base.EtsGenericType +import org.jacodb.ets.base.EtsLiteralType +import org.jacodb.ets.base.EtsNeverType +import org.jacodb.ets.base.EtsNullType +import org.jacodb.ets.base.EtsNumberType +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsTupleType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnclearRefType +import org.jacodb.ets.base.EtsUndefinedType +import org.jacodb.ets.base.EtsUnionType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.base.EtsVoidType +import org.jacodb.ets.dto.AnyTypeDto +import org.jacodb.ets.dto.ArrayTypeDto +import org.jacodb.ets.dto.BooleanTypeDto +import org.jacodb.ets.dto.ClassSignatureDto +import org.jacodb.ets.dto.ClassTypeDto +import org.jacodb.ets.dto.FileSignatureDto +import org.jacodb.ets.dto.FunctionTypeDto +import org.jacodb.ets.dto.GenericTypeDto +import org.jacodb.ets.dto.LiteralTypeDto +import org.jacodb.ets.dto.MethodParameterDto +import org.jacodb.ets.dto.MethodSignatureDto +import org.jacodb.ets.dto.NamespaceSignatureDto +import org.jacodb.ets.dto.NeverTypeDto +import org.jacodb.ets.dto.NullTypeDto +import org.jacodb.ets.dto.NumberTypeDto +import org.jacodb.ets.dto.PrimitiveLiteralDto +import org.jacodb.ets.dto.StringTypeDto +import org.jacodb.ets.dto.TupleTypeDto +import org.jacodb.ets.dto.TypeDto +import org.jacodb.ets.dto.UnclearReferenceTypeDto +import org.jacodb.ets.dto.UndefinedTypeDto +import org.jacodb.ets.dto.UnionTypeDto +import org.jacodb.ets.dto.UnknownTypeDto +import org.jacodb.ets.dto.VoidTypeDto +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsFileSignature +import org.jacodb.ets.model.EtsMethodParameter +import org.jacodb.ets.model.EtsMethodSignature +import org.jacodb.ets.model.EtsNamespaceSignature +import org.usvm.dataflow.ts.infer.EtsTypeFact + +private val logger = KotlinLogging.logger {} + +fun EtsTypeFact.toType(): EtsType? = when (this) { + is EtsTypeFact.ObjectEtsTypeFact -> if (cls is EtsClassType) cls else null + is EtsTypeFact.ArrayEtsTypeFact -> EtsArrayType( + elementType = elementType.toType() ?: EtsUnknownType, + dimensions = 1, + ) + + EtsTypeFact.AnyEtsTypeFact -> EtsAnyType + EtsTypeFact.BooleanEtsTypeFact -> EtsBooleanType + EtsTypeFact.FunctionEtsTypeFact -> null // TODO: function type + EtsTypeFact.NullEtsTypeFact -> EtsNullType + EtsTypeFact.NumberEtsTypeFact -> EtsNumberType + EtsTypeFact.StringEtsTypeFact -> EtsStringType + EtsTypeFact.UndefinedEtsTypeFact -> EtsUndefinedType + EtsTypeFact.UnknownEtsTypeFact -> EtsUnknownType + + is EtsTypeFact.GuardedTypeFact -> null + is EtsTypeFact.IntersectionEtsTypeFact -> null + is EtsTypeFact.UnionEtsTypeFact -> { + val types = this.types.map { it.toType() } + + if (types.any { it == null }) { + logger.warn { "Cannot convert union type fact to type: $this" } + null + } else { + EtsUnionType(types.map { it!! }) + } + } +} + +fun EtsType.toDto(): TypeDto = when (this) { + is EtsAnyType -> AnyTypeDto + is EtsUnknownType -> UnknownTypeDto + is EtsUnionType -> UnionTypeDto(types = this.types.map { it.toDto() }) + is EtsTupleType -> TupleTypeDto(types = this.types.map { it.toDto() }) + is EtsBooleanType -> BooleanTypeDto + is EtsNumberType -> NumberTypeDto + is EtsStringType -> StringTypeDto + is EtsNullType -> NullTypeDto + is EtsUndefinedType -> UndefinedTypeDto + is EtsVoidType -> VoidTypeDto + is EtsNeverType -> NeverTypeDto + + is EtsLiteralType -> { + val literal = when { + this.literalTypeName.equals("true", ignoreCase = true) -> PrimitiveLiteralDto.BooleanLiteral(true) + this.literalTypeName.equals("false", ignoreCase = true) -> PrimitiveLiteralDto.BooleanLiteral(false) + else -> { + val x = this.literalTypeName.toDoubleOrNull() + if (x != null) { + PrimitiveLiteralDto.NumberLiteral(x) + } else { + PrimitiveLiteralDto.StringLiteral(this.literalTypeName) + } + } + } + LiteralTypeDto(literal = literal) + } + + is EtsClassType -> ClassTypeDto( + signature = this.signature.toDto(), + typeParameters = this.typeParameters.map { it.toDto() } + ) + + is EtsFunctionType -> FunctionTypeDto( + signature = this.method.toDto(), + typeParameters = this.typeParameters.map { it.toDto() } + ) + + is EtsArrayType -> ArrayTypeDto( + elementType = this.elementType.toDto(), + dimensions = this.dimensions + ) + + is EtsArrayObjectType -> TODO("EtsArrayObjectType was removed") + + is EtsUnclearRefType -> UnclearReferenceTypeDto( + name = this.typeName, + typeParameters = this.typeParameters.map { it.toDto() } + ) + + is EtsGenericType -> GenericTypeDto( + name = this.typeName, + defaultType = this.defaultType?.toDto(), + constraint = this.constraint?.toDto(), + ) + + else -> error("Cannot convert ${this::class.java} to DTO: $this") +} + +fun EtsClassSignature.toDto(): ClassSignatureDto = + ClassSignatureDto( + name = this.name, + declaringFile = this.file.toDto(), + declaringNamespace = this.namespace?.toDto(), + ) + +fun EtsFileSignature.toDto(): FileSignatureDto = + FileSignatureDto( + projectName = this.projectName, + fileName = this.fileName, + ) + +fun EtsNamespaceSignature.toDto(): NamespaceSignatureDto = + NamespaceSignatureDto( + name = this.name, + declaringFile = this.file.toDto(), + declaringNamespace = this.namespace?.toDto(), + ) + +fun EtsMethodSignature.toDto(): MethodSignatureDto = + MethodSignatureDto( + declaringClass = this.enclosingClass.toDto(), + name = this.name, + parameters = this.parameters.map { it.toDto() }, + returnType = this.returnType.toDto(), + ) + +fun EtsMethodParameter.toDto(): MethodParameterDto = + MethodParameterDto( + name = this.name, + type = this.type.toDto(), + isOptional = this.isOptional, + ) diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/DTO.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/DTO.kt new file mode 100644 index 0000000000..467443d0ec --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/DTO.kt @@ -0,0 +1,96 @@ +package org.usvm.dataflow.ts.infer.dto + +import kotlinx.serialization.Serializable +import org.jacodb.ets.dto.ClassSignatureDto +import org.jacodb.ets.dto.MethodSignatureDto +import org.jacodb.ets.dto.TypeDto +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceResult + +@Serializable +data class InferredTypesDto( + val classes: List, + val methods: List, +) + +@Serializable +data class ClassTypeResultDto( + val signature: ClassSignatureDto, + val fields: List, + val methods: List, +) + +@Serializable +data class FieldTypeResultDto( + val name: String, + val type: TypeDto, +) + +@Serializable +data class MethodTypeResultDto( + val signature: MethodSignatureDto, + val args: List, + val returnType: TypeDto? = null, + val locals: List, +) + +@Serializable +data class ArgumentTypeResultDto( + val index: Int, + val type: TypeDto, +) + +@Serializable +data class LocalTypeResultDto( + val name: String, + val type: TypeDto, +) + +fun TypeInferenceResult.toDto(): InferredTypesDto { + val classTypeInferenceResult = inferredCombinedThisType.map { (clazz, fact) -> + val properties = (fact as? EtsTypeFact.ObjectEtsTypeFact)?.properties ?: emptyMap() + val methods = properties + .filter { it.value is EtsTypeFact.FunctionEtsTypeFact } + .keys + .sortedBy { it } + val fields = properties + .filterNot { it.value is EtsTypeFact.FunctionEtsTypeFact } + .mapNotNull { (name, fact) -> + fact.toType()?.let { + FieldTypeResultDto(name, it.toDto()) + } + } + .sortedBy { it.name } + ClassTypeResultDto(clazz.toDto(), fields, methods) + }.sortedBy { + it.signature.toString() + } + + val methodTypeInferenceResult = inferredTypes.map { (method, facts) -> + val args = facts.mapNotNull { (base, fact) -> + if (base is AccessPathBase.Arg) { + val type = fact.toType() + if (type != null) { + return@mapNotNull ArgumentTypeResultDto(base.index, type.toDto()) + } + } + null + }.sortedBy { it.index } + val returnType = inferredReturnType[method]?.toType()?.toDto() + val locals = facts.mapNotNull { (base, fact) -> + if (base is AccessPathBase.Local) { + val type = fact.toType() + if (type != null) { + return@mapNotNull LocalTypeResultDto(base.name, type.toDto()) + } + } + null + }.sortedBy { it.name } + MethodTypeResultDto(method.signature.toDto(), args, returnType, locals) + }.sortedBy { + it.signature.toString() + } + + return InferredTypesDto(classTypeInferenceResult, methodTypeInferenceResult) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/OldDTO.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/OldDTO.kt new file mode 100644 index 0000000000..a22e871ee7 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/dto/OldDTO.kt @@ -0,0 +1,213 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalSerializationApi::class) + +package org.usvm.dataflow.ts.infer.dto + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonClassDiscriminator +import org.jacodb.ets.dto.ClassSignatureDto +import org.jacodb.ets.dto.ClassTypeDto +import org.jacodb.ets.dto.FileSignatureDto +import org.jacodb.ets.dto.TypeDto + +@Serializable +data class TypeInferenceResultDto( + val inferredTypes: Map>, + val inferredReturnType: Map, + val inferredCombinedThisType: Map, +) + +@Serializable +data class MethodId( + // TODO: classId? + val className: String, + val methodName: String, +) + +@Serializable +data class ClassId( + val className: String, + val fileName: String, + // TODO: namespace? +) + +@Serializable +@JsonClassDiscriminator("_") +sealed interface AccessPathBaseDto { + @Serializable + @SerialName("This") + object This : AccessPathBaseDto { + override fun toString(): String = "" + } + + @Serializable + @SerialName("Static") + data object Static : AccessPathBaseDto { + override fun toString(): String = "" + } + + @Serializable + @SerialName("Arg") + data class Arg(val index: Int) : AccessPathBaseDto { + override fun toString(): String = "arg($index)" + } + + @Serializable + @SerialName("Local") + data class Local(val name: String) : AccessPathBaseDto { + override fun toString(): String = "local($name)" + } + + @Serializable + @SerialName("Const") + data class Const(val value: String) : AccessPathBaseDto { + override fun toString(): String = "const($value)" + } +} + +@Serializable +@JsonClassDiscriminator("_") +sealed interface TypeFactDto { + sealed interface Basic : TypeFactDto + + @Serializable + @SerialName("AnyType") + object AnyTypeFact : Basic { + override fun toString(): String = "any" + } + + @Serializable + @SerialName("UnknownType") + object UnknownTypeFact : Basic { + override fun toString(): String = "unknown" + } + + @Serializable + @SerialName("NullType") + object NullTypeFact : Basic { + override fun toString(): String = "null" + } + + @Serializable + @SerialName("UndefinedType") + object UndefinedTypeFact : Basic { + override fun toString(): String = "undefined" + } + + @Serializable + @SerialName("BooleanType") + object BooleanTypeFact : Basic { + override fun toString(): String = "boolean" + } + + @Serializable + @SerialName("NumberType") + object NumberTypeFact : Basic { + override fun toString(): String = "number" + } + + @Serializable + @SerialName("StringType") + object StringTypeFact : Basic { + override fun toString(): String = "string" + } + + @Serializable + @SerialName("SymbolType") + object SymbolTypeFact : Basic { + override fun toString(): String = "symbol" + } + + @Serializable + @SerialName("FunctionType") + object FunctionTypeFact : Basic { + override fun toString(): String = "function" + } + + @Serializable + @SerialName("ArrayType") + data class ArrayTypeFact(val elementType: TypeFactDto) : Basic { + override fun toString(): String = "Array<$elementType>" + } + + // TODO: tuple? + + @Serializable + @SerialName("ObjectType") + data class ObjectTypeFact( + val cls: TypeDto? = null, + val properties: Map = emptyMap(), + ) : Basic { + override fun toString(): String = buildString { + // "{}" when cls==null, properties.isEmpty() + // "{ x: number, y: string }" when cls!=null, properties.isNotEmpty() + // "T {}" when cls!=null, properties.isEmpty() + // "T { x: number, y: string }" when cls!=null, properties.isNotEmpty() + if (cls != null) { + append(cls) + append(" ") + } + val inner = properties.entries.joinToString(", ") { (k, v) -> "$k: $v" } + if (inner.isNotEmpty()) { + append("{ ") + append(inner) + append(" }") + } else { + append("{}") + } + } + } + + sealed interface Complex : TypeFactDto + + @Serializable + @SerialName("UnionType") + data class UnionTypeFact(val types: List) : Complex { + override fun toString(): String = types.joinToString(" | ") + } + + @Serializable + @SerialName("IntersectionType") + data class IntersectionTypeFact(val types: List) : Complex { + override fun toString(): String = types.joinToString(" & ") + } +} + +fun main() { + val json = Json { + prettyPrint = true + } + + val o1: TypeFactDto = TypeFactDto.ObjectTypeFact( + // TODO: empty file signature + ClassTypeDto(ClassSignatureDto("T", FileSignatureDto("", ""))), mapOf( + "x" to TypeFactDto.NumberTypeFact, + "y" to TypeFactDto.StringTypeFact, + ) + ) + val s = json.encodeToString(o1) + println(s) + val o2: TypeFactDto = Json.decodeFromString(s) + println(o2) + check(o1 == o2) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/EntityId.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/EntityId.kt new file mode 100644 index 0000000000..33c898f0a6 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/EntityId.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify + +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsFieldSignature +import org.jacodb.ets.model.EtsMethodParameter +import org.jacodb.ets.model.EtsMethodSignature + +sealed interface EntityId + +data class ClassId( + val signature: EtsClassSignature +) : EntityId + +data class MethodId( + val name: String, + val enclosingClass: ClassId +) { + constructor(signature: EtsMethodSignature) + : this(signature.name, ClassId(signature.enclosingClass)) +} + +data class FieldId( + val name: String, + val enclosingClass: ClassId +) : EntityId { + constructor(signature: EtsFieldSignature) + : this(signature.name, ClassId(signature.enclosingClass)) +} + +data class ParameterId( + val index: Int, + val method: MethodId +) : EntityId { + constructor(parameter: EtsMethodParameter, methodSignature: EtsMethodSignature) + : this(parameter.index, MethodId(methodSignature)) + + constructor(etsParameterRef: EtsParameterRef, methodSignature: EtsMethodSignature) + : this(etsParameterRef.index, MethodId(methodSignature)) +} + +data class ReturnId( + val method: MethodId +) : EntityId { + constructor(methodSignature: EtsMethodSignature) + : this(MethodId(methodSignature)) +} + +data class LocalId( + val name: String, + val method: MethodId +) : EntityId { + constructor(local: EtsLocal, methodSignature: EtsMethodSignature) + : this(local.name, MethodId(methodSignature)) +} + +data class ThisId( + val method: MethodId +) : EntityId { + constructor(methodSignature: EtsMethodSignature) + : this(MethodId(methodSignature)) +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/VerificationResult.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/VerificationResult.kt new file mode 100644 index 0000000000..c34657bc6e --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/VerificationResult.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify + +import org.jacodb.ets.base.EtsType + +sealed interface VerificationResult { + data class Success(val mapping: Map) : VerificationResult + + data class Fail(val mapping: Map>) : VerificationResult + + companion object { + fun from(mapping: Map>): VerificationResult = + if (mapping.values.all { it.size == 1 }) + Success(mapping.mapValues { (_, types) -> types.single() }) + else Fail(mapping) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/Verify.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/Verify.kt new file mode 100644 index 0000000000..ede486afe6 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/Verify.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify + +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.verify.collectors.ClassSummaryCollector + +fun collectSummary(scene: EtsScene): Map> = + ClassSummaryCollector(mutableMapOf()).apply { + scene.projectAndSdkClasses.forEach { collect(it) } + }.typeSummary + +fun verify(scene: EtsScene) = VerificationResult.from(collectSummary(scene)) diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ClassSummaryCollector.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ClassSummaryCollector.kt new file mode 100644 index 0000000000..851ab561de --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ClassSummaryCollector.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.model.EtsClass +import org.usvm.dataflow.ts.infer.verify.EntityId + +class ClassSummaryCollector( + override val typeSummary: MutableMap> +) : SummaryCollector { + fun collect(etsClass: EtsClass) { + etsClass.fields.forEach { field -> + yield(field.signature) + } + + etsClass.methods.forEach { method -> + yield(method.signature) + val stmtCollector = StmtSummaryCollector(method.signature, typeSummary) + method.cfg.stmts.forEach { + it.accept(stmtCollector) + } + } + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ExprSummaryCollector.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ExprSummaryCollector.kt new file mode 100644 index 0000000000..d7dfa6bea3 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ExprSummaryCollector.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsBinaryExpr +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsExpr +import org.jacodb.ets.base.EtsInstanceCallExpr +import org.jacodb.ets.base.EtsPtrCallExpr +import org.jacodb.ets.base.EtsStaticCallExpr +import org.jacodb.ets.base.EtsTernaryExpr +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnaryExpr +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.base.EtsInstanceOfExpr +import org.jacodb.ets.base.EtsLengthExpr +import org.jacodb.ets.model.EtsMethodSignature +import org.usvm.dataflow.ts.infer.verify.EntityId + +class ExprSummaryCollector( + override val enclosingMethod: EtsMethodSignature, + override val typeSummary: MutableMap> +) : MethodSummaryCollector, EtsExpr.Visitor.Default { + private val valueSummaryCollector by lazy { + ValueSummaryCollector(enclosingMethod, typeSummary) + } + + private fun collect(entity: EtsEntity) { + when (entity) { + is EtsValue -> entity.accept(valueSummaryCollector) + is EtsExpr -> entity.accept(this) + else -> error("Unsupported entity kind") + } + } + + override fun defaultVisit(expr: EtsExpr) = when (expr) { + is EtsUnaryExpr -> { + collect(expr.arg) + } + + is EtsBinaryExpr -> { + collect(expr.left) + collect(expr.right) + } + + is EtsTernaryExpr -> { + collect(expr.condition) + collect(expr.thenExpr) + collect(expr.elseExpr) + } + + is EtsInstanceCallExpr -> { + yield(expr.method) + collect(expr.instance) + expr.args.forEach { collect(it) } + } + + is EtsStaticCallExpr -> { + yield(expr.method) + expr.args.forEach { collect(it) } + } + + is EtsPtrCallExpr -> { + yield(expr.method) + collect(expr.ptr) + expr.args.forEach { collect(it) } + } + + is EtsLengthExpr -> { + collect(expr.arg) + } + + is EtsInstanceOfExpr -> { + collect(expr.arg) + } + + else -> {} + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/StmtSummaryCollector.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/StmtSummaryCollector.kt new file mode 100644 index 0000000000..3cdb4eb87d --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/StmtSummaryCollector.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsCallStmt +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsExpr +import org.jacodb.ets.base.EtsGotoStmt +import org.jacodb.ets.base.EtsIfStmt +import org.jacodb.ets.base.EtsNopStmt +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsSwitchStmt +import org.jacodb.ets.base.EtsThrowStmt +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.model.EtsMethodSignature +import org.usvm.dataflow.ts.infer.verify.EntityId + +class StmtSummaryCollector( + override val enclosingMethod: EtsMethodSignature, + override val typeSummary: MutableMap> +) : EtsStmt.Visitor, MethodSummaryCollector { + private val exprCollector = ExprSummaryCollector(enclosingMethod, typeSummary) + private val valueCollector = ValueSummaryCollector(enclosingMethod, typeSummary) + + private fun collect(entity: EtsEntity) { + when (entity) { + is EtsValue -> entity.accept(valueCollector) + is EtsExpr -> entity.accept(exprCollector) + else -> error("Unsupported entity kind") + } + } + + override fun visit(stmt: EtsNopStmt) {} + + override fun visit(stmt: EtsAssignStmt) { + collect(stmt.lhv) + collect(stmt.rhv) + } + + override fun visit(stmt: EtsCallStmt) { + collect(stmt.expr) + } + + override fun visit(stmt: EtsReturnStmt) { + stmt.returnValue?.let { collect(it) } + } + + override fun visit(stmt: EtsThrowStmt) { + collect(stmt.arg) + } + + override fun visit(stmt: EtsGotoStmt) {} + + override fun visit(stmt: EtsIfStmt) { + collect(stmt.condition) + } + + override fun visit(stmt: EtsSwitchStmt) { + collect(stmt.arg) + stmt.cases.forEach { collect(it) } + } + +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/SummaryCollector.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/SummaryCollector.kt new file mode 100644 index 0000000000..618f5e3104 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/SummaryCollector.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.model.EtsFieldSignature +import org.jacodb.ets.model.EtsMethodSignature +import org.usvm.dataflow.ts.infer.verify.EntityId +import org.usvm.dataflow.ts.infer.verify.FieldId +import org.usvm.dataflow.ts.infer.verify.LocalId +import org.usvm.dataflow.ts.infer.verify.ParameterId +import org.usvm.dataflow.ts.infer.verify.ReturnId +import org.usvm.dataflow.ts.infer.verify.ThisId + +interface SummaryCollector { + val typeSummary: MutableMap> + + fun yield(field: EtsFieldSignature) { + if (!field.type.isUnresolved) { + typeSummary.getOrPut(FieldId(field), ::mutableSetOf) + .add(field.type) + } + } + + fun yield(method: EtsMethodSignature) { + if (!method.returnType.isUnresolved) { + typeSummary.getOrPut(ReturnId(method), ::mutableSetOf) + .add(method.returnType) + } + method.parameters.forEach { + if (!it.type.isUnresolved) { + typeSummary.getOrPut(ParameterId(it, method), ::mutableSetOf) + .add(it.type) + } + } + } +} + +interface MethodSummaryCollector : SummaryCollector { + val enclosingMethod: EtsMethodSignature + fun yield(parameter: EtsParameterRef) { + if (!parameter.type.isUnresolved) { + typeSummary.getOrPut(ParameterId(parameter, enclosingMethod), ::mutableSetOf) + .add(parameter.type) + } + } + + fun yield(local: EtsLocal) { + if (!local.type.isUnresolved) { + typeSummary.getOrPut(LocalId(local, enclosingMethod), ::mutableSetOf) + .add(local.type) + } + } + + fun yield(etsThis: EtsThis) { + typeSummary.getOrPut(ThisId(enclosingMethod), ::mutableSetOf) + .add(etsThis.type) + } +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/Utils.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/Utils.kt new file mode 100644 index 0000000000..b7a77c8e9d --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/Utils.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsTupleType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnionType +import org.jacodb.ets.base.EtsUnknownType + +val EtsType.isUnresolved: Boolean + get() = when (this) { + is EtsAnyType -> true + is EtsUnknownType -> true + is EtsUnionType -> types.any { it.isUnresolved } + is EtsTupleType -> types.any { it.isUnresolved } + is EtsArrayType -> elementType.isUnresolved + else -> false + } \ No newline at end of file diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ValueSummaryCollector.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ValueSummaryCollector.kt new file mode 100644 index 0000000000..a99ae48356 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/infer/verify/collectors/ValueSummaryCollector.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.infer.verify.collectors + +import org.jacodb.ets.base.EtsArrayAccess +import org.jacodb.ets.base.EtsArrayLiteral +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsExpr +import org.jacodb.ets.base.EtsInstanceFieldRef +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsObjectLiteral +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsStaticFieldRef +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.model.EtsMethodSignature +import org.usvm.dataflow.ts.infer.verify.EntityId + +class ValueSummaryCollector( + override val enclosingMethod: EtsMethodSignature, + override val typeSummary: MutableMap> +) : MethodSummaryCollector, EtsValue.Visitor.Default { + private val exprSummaryCollector by lazy { + ExprSummaryCollector(enclosingMethod, typeSummary) + } + + private fun collect(entity: EtsEntity) { + when (entity) { + is EtsValue -> entity.accept(this) + is EtsExpr -> entity.accept(exprSummaryCollector) + else -> error("Unsupported entity kind") + } + } + + override fun defaultVisit(value: EtsValue) {} + + override fun visit(value: EtsLocal) { + yield(value) + } + override fun visit(value: EtsArrayLiteral) { + value.elements.forEach { collect(it) } + } + + override fun visit(value: EtsObjectLiteral) { + value.properties.forEach { (_, it) -> collect(it) } + } + + override fun visit(value: EtsThis) { + yield(value) + } + + override fun visit(value: EtsParameterRef) { + yield(value) + } + + override fun visit(value: EtsArrayAccess) { + value.array.accept(this) + value.index.accept(this) + } + + override fun visit(value: EtsInstanceFieldRef) { + yield(value.field) + value.instance.accept(this) + } + + override fun visit(value: EtsStaticFieldRef) { + yield(value.field) + } +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/EtsTraits.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/EtsTraits.kt new file mode 100644 index 0000000000..81820a9f0a --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/EtsTraits.kt @@ -0,0 +1,252 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.util + +import org.jacodb.api.common.CommonMethodParameter +import org.jacodb.api.common.cfg.CommonAssignInst +import org.jacodb.api.common.cfg.CommonCallExpr +import org.jacodb.api.common.cfg.CommonExpr +import org.jacodb.api.common.cfg.CommonValue +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsArrayAccess +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsBinaryExpr +import org.jacodb.ets.base.EtsBooleanConstant +import org.jacodb.ets.base.EtsCallExpr +import org.jacodb.ets.base.EtsCastExpr +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsConstant +import org.jacodb.ets.base.EtsEntity +import org.jacodb.ets.base.EtsIfStmt +import org.jacodb.ets.base.EtsImmediate +import org.jacodb.ets.base.EtsInstanceFieldRef +import org.jacodb.ets.base.EtsNewArrayExpr +import org.jacodb.ets.base.EtsNumberConstant +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsStaticFieldRef +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsStringConstant +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsUnaryExpr +import org.jacodb.ets.base.EtsValue +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsMethodImpl +import org.jacodb.ets.model.EtsMethodParameter +import org.jacodb.ets.utils.callExpr +import org.jacodb.ets.utils.getOperands +import org.jacodb.ets.utils.getValues +import org.jacodb.taint.configuration.ConstantBooleanValue +import org.jacodb.taint.configuration.ConstantIntValue +import org.jacodb.taint.configuration.ConstantStringValue +import org.jacodb.taint.configuration.ConstantValue +import org.jacodb.taint.configuration.TypeMatches +import org.usvm.dataflow.ifds.AccessPath +import org.usvm.dataflow.ifds.ElementAccessor +import org.usvm.dataflow.ifds.FieldAccessor +import org.usvm.dataflow.util.Traits + +/** + * ETS-specific extensions for analysis. + */ +class EtsTraits : Traits { + + override fun convertToPathOrNull(expr: CommonExpr): AccessPath? { + check(expr is EtsEntity) + return expr.toPathOrNull() + } + + override fun convertToPathOrNull(value: CommonValue): AccessPath? { + check(value is EtsEntity) + return value.toPathOrNull() + } + + override fun convertToPath(value: CommonValue): AccessPath { + check(value is EtsEntity) + return value.toPath() + } + + override fun getThisInstance(method: EtsMethod): EtsThis { + return EtsThis(EtsClassType(method.signature.enclosingClass)) + } + + override fun getArgument(param: CommonMethodParameter): EtsParameterRef { + check(param is EtsMethodParameter) + return EtsParameterRef(index = param.index, type = param.type) + } + + override fun getArgumentsOf(method: EtsMethod): List { + return method.parameters.map { getArgument(it) } + } + + override fun getCallee(callExpr: CommonCallExpr): EtsMethod { + check(callExpr is EtsCallExpr) + return EtsMethodImpl(callExpr.method) + } + + override fun getCallExpr(statement: EtsStmt): EtsCallExpr? { + return statement.callExpr + } + + override fun getValues(expr: CommonExpr): Set { + check(expr is EtsEntity) + return expr.getValues().toSet() + } + + override fun getOperands(statement: EtsStmt): List { + return statement.getOperands().toList() + } + + override fun getArrayAllocation(statement: EtsStmt): EtsEntity? { + if (statement !is EtsAssignStmt) return null + return statement.rhv as? EtsNewArrayExpr + } + + override fun getArrayAccessIndex(statement: EtsStmt): EtsValue? { + if (statement !is EtsAssignStmt) return null + + val lhv = statement.lhv + if (lhv is EtsArrayAccess) return lhv.index + + val rhv = statement.rhv + if (rhv is EtsArrayAccess) return rhv.index + + return null + } + + override fun getBranchExprCondition(statement: EtsStmt): EtsEntity? { + if (statement !is EtsIfStmt) return null + return statement.condition + } + + override fun isConstant(value: CommonValue): Boolean { + check(value is EtsValue) + return value is EtsConstant + } + + override fun eqConstant(value: CommonValue, constant: ConstantValue): Boolean { + check(value is EtsValue) + return when (constant) { + is ConstantBooleanValue -> { + value is EtsBooleanConstant && value.value == constant.value + } + + is ConstantIntValue -> { + value is EtsNumberConstant && value.value == constant.value.toDouble() + } + + is ConstantStringValue -> { + value is EtsStringConstant && value.value == constant.value + } + } + } + + override fun ltConstant(value: CommonValue, constant: ConstantValue): Boolean { + check(value is EtsValue) + return when (constant) { + is ConstantIntValue -> { + value is EtsNumberConstant && value.value < constant.value.toDouble() + } + + else -> error("Unexpected constant: $constant") + } + } + + override fun gtConstant(value: CommonValue, constant: ConstantValue): Boolean { + check(value is EtsValue) + return when (constant) { + is ConstantIntValue -> { + value is EtsNumberConstant && value.value > constant.value.toDouble() + } + + else -> error("Unexpected constant: $constant") + } + } + + override fun matches(value: CommonValue, pattern: String): Boolean { + check(value is EtsValue) + val s = value.toString() + val re = pattern.toRegex() + return re.matches(s) + } + + override fun typeMatches(value: CommonValue, condition: TypeMatches): Boolean { + check(value is EtsValue) + TODO("Not yet implemented") + } + + override fun isConstructor(method: EtsMethod): Boolean { + return method.name == CONSTRUCTOR_NAME + } + + override fun isLoopHead(statement: EtsStmt): Boolean { + TODO("Not yet implemented") + } + + override fun lineNumber(statement: EtsStmt): Int { + TODO("Not yet implemented") + } + + override fun locationFQN(statement: EtsStmt): String { + TODO("Not yet implemented") + } + + override fun taintFlowRhsValues(statement: CommonAssignInst): List { + check(statement is EtsAssignStmt) + return when (val rhv = statement.rhv) { + is EtsBinaryExpr -> listOf(rhv.left, rhv.right) + is EtsUnaryExpr -> listOf(rhv.arg) + is EtsCastExpr -> listOf(rhv.arg) + else -> listOf(rhv) + } + } + + override fun taintPassThrough(statement: EtsStmt): List>? { + return null + } +} + +fun EtsEntity.toPathOrNull(): AccessPath? = when (this) { + is EtsImmediate -> AccessPath(this, emptyList()) + + is EtsThis -> AccessPath(this, emptyList()) + + is EtsParameterRef -> AccessPath(this, emptyList()) + + is EtsArrayAccess -> { + array.toPathOrNull()?.let { + it + ElementAccessor + } + } + + is EtsInstanceFieldRef -> { + instance.toPathOrNull()?.let { + it + FieldAccessor(field.name) + } + } + + is EtsStaticFieldRef -> { + AccessPath(null, listOf(FieldAccessor(field.name, isStatic = true))) + } + + is EtsCastExpr -> arg.toPathOrNull() + + else -> null +} + +fun EtsEntity.toPath(): AccessPath { + return toPathOrNull() ?: error("Unable to build access path for value $this") +} diff --git a/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/TypeInferenceStatistics.kt b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/TypeInferenceStatistics.kt new file mode 100644 index 0000000000..a6420c57b3 --- /dev/null +++ b/usvm-dataflow-ts/src/main/kotlin/org/usvm/dataflow/ts/util/TypeInferenceStatistics.kt @@ -0,0 +1,694 @@ +package org.usvm.dataflow.ts.util + +import org.jacodb.ets.base.DEFAULT_ARK_CLASS_NAME +import org.jacodb.ets.base.DEFAULT_ARK_METHOD_NAME +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsBooleanType +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsFunctionType +import org.jacodb.ets.base.EtsNullType +import org.jacodb.ets.base.EtsNumberType +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnclearRefType +import org.jacodb.ets.base.EtsUndefinedType +import org.jacodb.ets.base.EtsUnionType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.base.INSTANCE_INIT_METHOD_NAME +import org.jacodb.ets.base.STATIC_INIT_METHOD_NAME +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceResult +import java.io.File + +class TypeInferenceStatistics { + private val noTypesInferred: MutableSet = hashSetOf() + private val allTypesAndFacts: MutableMap> = + hashMapOf() + + private var overallTypes: Long = 0 + + private var exactTypeInferredPreviouslyUnknown = 0L + private var exactTypeInferredCorrectlyPreviouslyKnown = 0L + private var exactTypeInferredPreviouslyWasAny = 0L + private var exactTypeInferredIncorrectlyPreviouslyKnown = 0L + + private var typeInfoInferredPreviouslyUnknown = 0L + private var typeInfoInferredPreviouslyKnownExactly = 0L + private var arrayInfoPreviouslyUnknown = 0L + private var arrayInfoPreviouslyKnown = 0L + + private var noInfoInferredPreviouslyKnown = 0L + private var noInfoInferredPreviouslyUnknown = 0L + + private var unhandled = 0L + + private var undefinedUnknownCombination = 0L + private var unknownAnyCombination = 0L + + fun compareSingleMethodFactsWithTypesInScene( + methodTypeFacts: MethodTypesFacts, + method: EtsMethod, + graph: EtsApplicationGraph, + ) { + overallTypes += 1 // thisType + overallTypes += method.parameters.size + method.locals.size + + methodTypeFacts.apply { + if (combinedThisFact == null + && argumentsFacts.all { it == null } + && returnFact == null + && localFacts.isEmpty() + ) { + noTypesInferred += method + } + } + + val thisType = getEtsClassType(method.enclosingClass, graph.cp) + val argTypes = method.parameters.map { it.type } + val locals = method.locals + + val methodFacts = mutableListOf() + + thisType?.let { + val thisPosition = AccessPathBase.This + val fact = methodTypeFacts.combinedThisFact + + val status = if (fact == null) { + // TODO check how unknown is represented + if (it.signature.name == "Unknown") { + noInfoInferredPreviouslyUnknown++ + InferenceStatus.NO_INFO_PREVIOUSLY_UNKNOWN + } else { + noInfoInferredPreviouslyKnown++ + InferenceStatus.NO_INFO_PREVIOUSLY_KNOWN + } + } else { + when { + fact.matchesWith(it) -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + (fact as? EtsTypeFact.ObjectEtsTypeFact)?.cls != null -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + + else -> { + typeInfoInferredPreviouslyKnownExactly++ + InferenceStatus.TYPE_INFO_FOUND_PREV_KNOWN + } + } + } + + methodFacts += InferenceResult(thisPosition, it, fact, status) + } + + argTypes.forEachIndexed { index, type -> + val fact = methodTypeFacts.argumentsFacts.getOrNull(index) + + val status = if (fact == null) { + if (type is EtsUnknownType) { + noInfoInferredPreviouslyUnknown++ + InferenceStatus.NO_INFO_PREVIOUSLY_UNKNOWN + } else { + noInfoInferredPreviouslyKnown++ + InferenceStatus.NO_INFO_PREVIOUSLY_KNOWN + } + } else { + checkForFact(fact, type) + } + + methodFacts += InferenceResult(AccessPathBase.Arg(index), type, fact, status) + } + + + + locals.forEach { + val type = it.type + val local = AccessPathBase.Local(it.name) + val fact = methodTypeFacts.localFacts[local] + + val status = if (fact == null) { + if (type is EtsUnknownType) { + noInfoInferredPreviouslyUnknown++ + InferenceStatus.NO_INFO_PREVIOUSLY_UNKNOWN + } else { + noInfoInferredPreviouslyKnown++ + InferenceStatus.NO_INFO_PREVIOUSLY_KNOWN + } + } else { + checkForFact(fact, type) + } + + methodFacts += InferenceResult(local, type, fact, status) + } + + allTypesAndFacts[method] = methodFacts + } + + private fun checkForFact(fact: EtsTypeFact, type: EtsType): InferenceStatus { + return when (fact) { + EtsTypeFact.AnyEtsTypeFact -> { + when (type) { + is EtsUnknownType -> { + unknownAnyCombination++ + InferenceStatus.UNKNOWN_ANY_COMBINATION + } + + is EtsAnyType -> { + exactTypeInferredPreviouslyWasAny++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_WAS_ANY + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + + is EtsTypeFact.ArrayEtsTypeFact -> { + when (type) { + is EtsArrayType -> { + arrayInfoPreviouslyKnown++ + InferenceStatus.ARRAY_INFO + } + + is EtsUnclearRefType -> { + arrayInfoPreviouslyKnown++ + InferenceStatus.ARRAY_INFO + } + + is EtsUnknownType -> { + arrayInfoPreviouslyUnknown++ + InferenceStatus.ARRAY_INFO_PREV_UNKNOWN + } + + else -> { + arrayInfoPreviouslyKnown++ + InferenceStatus.ARRAY_INFO + } + } + } + + EtsTypeFact.BooleanEtsTypeFact -> { + when (type) { + is EtsBooleanType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + is EtsUnknownType -> { + exactTypeInferredPreviouslyUnknown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_UNKNOWN + } + + else -> { + when { + (type as? EtsClassType)?.typeName == "Boolean" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + (type as? EtsUnclearRefType)?.typeName == "Boolean" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + } + } + + EtsTypeFact.FunctionEtsTypeFact -> { + when (type) { + is EtsUnknownType -> { + undefinedUnknownCombination++ + InferenceStatus.UNKNOWN_UNDEFINED_COMBINATION + } + + is EtsFunctionType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + + EtsTypeFact.NullEtsTypeFact -> { + when (type) { + is EtsUnknownType -> { + undefinedUnknownCombination++ + InferenceStatus.UNKNOWN_UNDEFINED_COMBINATION + } + + is EtsNullType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + + EtsTypeFact.NumberEtsTypeFact -> { + when (type) { + is EtsNumberType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + is EtsUnknownType -> { + exactTypeInferredPreviouslyUnknown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_UNKNOWN + } + + else -> { + when { + (type as? EtsClassType)?.typeName == "Number" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + (type as? EtsUnclearRefType)?.typeName == "Number" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + } + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + if (type is EtsUnknownType) { + return if (fact.cls != null) { + exactTypeInferredPreviouslyUnknown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_UNKNOWN + } else { + typeInfoInferredPreviouslyUnknown++ + InferenceStatus.TYPE_INFO_FOUND_PREV_UNKNOWN + } + } + + if (type is EtsAnyType) { + return if (fact.cls != null) { + exactTypeInferredPreviouslyWasAny++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_WAS_ANY + } else { + typeInfoInferredPreviouslyKnownExactly++ + InferenceStatus.TYPE_INFO_FOUND_PREV_KNOWN + } + } + + if (fact.cls == null) { + return InferenceStatus.TYPE_INFO_FOUND_PREV_KNOWN + } + + val typeName = fact.cls.typeName + + if ((type is EtsClassType || type is EtsUnclearRefType) && type.typeName == typeName) { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } else { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + + EtsTypeFact.StringEtsTypeFact -> { + when (type) { + is EtsStringType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + is EtsUnknownType -> { + exactTypeInferredPreviouslyUnknown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_UNKNOWN + } + + else -> { + when { + (type as? EtsClassType)?.typeName == "String" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + (type as? EtsUnclearRefType)?.typeName == "String" -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + } + } + + EtsTypeFact.UndefinedEtsTypeFact -> { + when (type) { + is EtsUnknownType -> { + undefinedUnknownCombination++ + InferenceStatus.UNKNOWN_UNDEFINED_COMBINATION + } + is EtsUndefinedType -> { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } + else -> { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + + EtsTypeFact.UnknownEtsTypeFact -> { + if (type is EtsUnknownType) { + exactTypeInferredCorrectlyPreviouslyKnown++ + InferenceStatus.EXACT_MATCH_PREVIOUSLY_KNOWN + } else { + exactTypeInferredIncorrectlyPreviouslyKnown++ + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + + is EtsTypeFact.GuardedTypeFact -> { + unhandled++ + InferenceStatus.UNHANDLED + } + + is EtsTypeFact.IntersectionEtsTypeFact -> { + unhandled++ + InferenceStatus.UNHANDLED + } + + is EtsTypeFact.UnionEtsTypeFact -> { + when (type) { + is EtsUnionType -> { + unhandled++ + InferenceStatus.UNHANDLED + } + + is EtsUnknownType -> { + InferenceStatus.UNION_INSTEAD_OF_UNKNOWN + } + + else -> { + InferenceStatus.DIFFERENT_TYPE_FOUND + } + } + } + } + } + + fun dumpStatistics(outputFilePath: String? = null) { + val data = buildString { + appendLine(this@TypeInferenceStatistics.toString()) + appendLine() + + appendLine("Specifically: ${"=".repeat(42)}") + + val comparator = + Comparator { fst, snd -> + when (fst.position) { + is AccessPathBase.This -> when { + snd.position is AccessPathBase.This -> 0 + else -> -1 + } + + is AccessPathBase.Arg -> when (snd.position) { + is AccessPathBase.This -> 1 + is AccessPathBase.Arg -> { + fst.position.index.compareTo(snd.position.index) + } + + else -> -1 + } + + else -> when (snd.position) { + is AccessPathBase.This, is AccessPathBase.Arg -> 1 + else -> if (fst.position is AccessPathBase.Local && snd.position is AccessPathBase.Local) { + fst.position.name.compareTo(snd.position.name) + } else { + 0 + } + } + } + } + + allTypesAndFacts + .toList() + .sortedBy { it.first.signature.toString() } + .forEach { (method, types) -> + appendLine("${method.signature}:") + + types + .sortedWith(comparator) + .forEach { (path, typeInfo, typeFact, status) -> + appendLine("[${status.message}]: ${path}: $typeInfo -> $typeFact ") + } + appendLine() + } + + appendLine() + appendLine("=".repeat(42)) + appendLine("No types inferred for methods:") + + noTypesInferred + .filterNot { it.name == INSTANCE_INIT_METHOD_NAME || it.name == STATIC_INIT_METHOD_NAME } + .filterNot { it.name == DEFAULT_ARK_METHOD_NAME && it.enclosingClass.name == DEFAULT_ARK_CLASS_NAME } + .sortedBy { it.signature.toString() } + .forEach { + appendLine(it) + } + } + + if (outputFilePath == null) { + println(data) + return + } + + val file = File(outputFilePath) + println("File with statistics is located: ${file.absolutePath}") + file.writeText(data) + } + + private fun calculateImprovement(): Double { + val newExactTypes = exactTypeInferredPreviouslyUnknown + + exactTypeInferredPreviouslyWasAny + + exactTypeInferredIncorrectlyPreviouslyKnown + + arrayInfoPreviouslyUnknown + + val prevTypes = exactTypeInferredCorrectlyPreviouslyKnown + + typeInfoInferredPreviouslyKnownExactly + + arrayInfoPreviouslyKnown + + noInfoInferredPreviouslyKnown + + return newExactTypes.toDouble() / prevTypes * 100 + } + + override fun toString(): String = """ + Total types number: $overallTypes + + Compared to the first state of the Scene: + + Improvement: ${calculateImprovement()}% + + Inferred types that were unknown: $exactTypeInferredPreviouslyUnknown + Inferred types that were already inferred: $exactTypeInferredCorrectlyPreviouslyKnown + Inferred types that were previously inferred as any: $exactTypeInferredPreviouslyWasAny + Inferred types are different from the ones in the Scene: $exactTypeInferredIncorrectlyPreviouslyKnown + + Array types instead of unknown: $arrayInfoPreviouslyUnknown + Array types instead of previously known type: $arrayInfoPreviouslyKnown + + Some facts found about unknown type: $typeInfoInferredPreviouslyUnknown + Some facts found about already inferred type: $typeInfoInferredPreviouslyKnownExactly + + Unhandled type info: $unhandled + + Lost info about type: $noInfoInferredPreviouslyKnown + Nothing inferred, but it was unknown previously as well: $noInfoInferredPreviouslyUnknown + + Was unknown, became undefined: $undefinedUnknownCombination + Was unknown, became any: $unknownAnyCombination + """.trimIndent() + +} + +private fun getEtsClassType(signature: EtsClassSignature, scene: EtsScene): EtsClassType? { + if (signature.name == DEFAULT_ARK_CLASS_NAME || signature.name.isBlank()) { + return null + } + + val clazz = scene.projectAndSdkClasses.firstOrNull { it.signature == signature } + ?: error("No class found in the classpath with signature $signature") + return EtsClassType(clazz.signature) +} + +data class MethodTypesFacts( + val combinedThisFact: EtsTypeFact?, + val argumentsFacts: List, + val localFacts: Map, + val returnFact: EtsTypeFact?, +) { + companion object { + fun from( + result: TypeInferenceResult, + m: EtsMethod, + ): MethodTypesFacts { + val combinedThisFact = result.inferredCombinedThisType.entries.firstOrNull { + it.key.name == m.enclosingClass.name + }?.value + + val factsForMethod = result.inferredTypes.entries.singleOrNull { + compareByMethodNameAndEnclosingClass(it.key, m) + }?.value + + val inferredReturnType = result.inferredReturnType.entries.firstOrNull { + compareByMethodNameAndEnclosingClass(it.key, m) + }?.value + + val arguments = m.parameters.indices.map { + val stmts = m.cfg.stmts + if (stmts.isEmpty()) return@map null + + val realIndex = ((stmts[it] as EtsAssignStmt).rhv as EtsParameterRef).index + factsForMethod?.get(AccessPathBase.Arg(realIndex)) + } + + val locals = factsForMethod?.filterKeys { it is AccessPathBase.Local }.orEmpty() + + return MethodTypesFacts(combinedThisFact, arguments, locals, inferredReturnType) + } + } +} + +// TODO hack because of an issue with signatures +private val compareByMethodNameAndEnclosingClass = { fst: EtsMethod, snd: EtsMethod -> + fst.name === snd.name && fst.enclosingClass.name === snd.enclosingClass.name +} + +private fun EtsTypeFact.matchesWith(type: EtsType): Boolean { + val result = when (this) { + EtsTypeFact.AnyEtsTypeFact -> { + type is EtsAnyType + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + val typeName = this.cls?.typeName + + if (type is EtsUnknownType || type is EtsAnyType) { + this.cls != null + } else { + (type is EtsClassType || type is EtsUnclearRefType) && type.typeName == typeName + } + } + + is EtsTypeFact.ArrayEtsTypeFact -> when (type) { + is EtsArrayType -> this.elementType.matchesWith(type.elementType) + + is EtsUnclearRefType -> { + val elementType = this.elementType as? EtsTypeFact.ObjectEtsTypeFact + elementType?.cls?.typeName == type.typeName + } + + else -> false + } + + EtsTypeFact.BooleanEtsTypeFact -> { + type is EtsBooleanType + || type is EtsUnknownType + || (type as? EtsClassType)?.typeName == "Boolean" + || (type as? EtsUnclearRefType)?.typeName == "Boolean" + } + + EtsTypeFact.FunctionEtsTypeFact -> type is EtsFunctionType || type is EtsUnknownType + EtsTypeFact.NullEtsTypeFact -> type is EtsNullType || type is EtsUnknownType + EtsTypeFact.NumberEtsTypeFact -> { + type is EtsNumberType + || type is EtsUnknownType + || (type as? EtsClassType)?.typeName == "Number" + || (type as? EtsUnclearRefType)?.typeName == "Number" + } + + EtsTypeFact.StringEtsTypeFact -> { + type is EtsStringType + || type is EtsUnknownType + || (type as? EtsClassType)?.typeName == "String" + || (type as? EtsUnclearRefType)?.typeName == "String" + } + + EtsTypeFact.UndefinedEtsTypeFact -> type is EtsUndefinedType + EtsTypeFact.UnknownEtsTypeFact -> type is EtsUnknownType + is EtsTypeFact.GuardedTypeFact -> TODO() + is EtsTypeFact.IntersectionEtsTypeFact -> { + // TODO intersections checks are not supported yet + false + } + + is EtsTypeFact.UnionEtsTypeFact -> types.all { it.matchesWith(type) } + } + + return result +} + +private data class InferenceResult( + val position: AccessPathBase, + val type: EtsType, + val typeFact: EtsTypeFact?, + val status: InferenceStatus, +) + +private enum class InferenceStatus(val message: String) { + EXACT_MATCH_PREVIOUSLY_KNOWN("Exactly matched, previously known"), + EXACT_MATCH_PREVIOUSLY_UNKNOWN("Exactly matched, previously unknown"), + EXACT_MATCH_PREVIOUSLY_WAS_ANY("Exactly matched with any type"), + + TYPE_INFO_FOUND_PREV_KNOWN("Some type facts found, previously known exactly"), + TYPE_INFO_FOUND_PREV_UNKNOWN("Some type facts found, previously unknown"), + DIFFERENT_TYPE_FOUND("Another type is inferred"), + + UNHANDLED("Unhandled type info"), + + UNKNOWN_ANY_COMBINATION("Unknown any combination"), + UNKNOWN_UNDEFINED_COMBINATION("Unknown undefined combination"), + + ARRAY_INFO_PREV_UNKNOWN("Found an array type, previously unknown"), + + ARRAY_INFO("Array information"), + + UNION_INSTEAD_OF_UNKNOWN("Discovered union type, previously unknown"), + + NO_INFO_PREVIOUSLY_UNKNOWN("Not inferred, previously unknown"), + NO_INFO_PREVIOUSLY_KNOWN("Not inferred, previously known") + +} diff --git a/usvm-dataflow-ts/src/main/resources/logback.xml b/usvm-dataflow-ts/src/main/resources/logback.xml new file mode 100644 index 0000000000..978c970783 --- /dev/null +++ b/usvm-dataflow-ts/src/main/resources/logback.xml @@ -0,0 +1,25 @@ + + + + + %highlight([%level]) %replace(%c{0}){'(\$Companion)?\$logger\$1',''} - %msg%n + + + + + logs/app.log + + + logs/app.%d{yyyy-MM-dd_HH}.log + 30 + + + + %highlight([%level]) %replace(%c{0}){'(\$Companion)?\$logger\$1',''} - %msg%n + + + + + + + diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsIfdsTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsIfdsTest.kt new file mode 100644 index 0000000000..e1a3e157d7 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsIfdsTest.kt @@ -0,0 +1,437 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import org.jacodb.ets.graph.EtsApplicationGraphImpl +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.jacodb.taint.configuration.Argument +import org.jacodb.taint.configuration.AssignMark +import org.jacodb.taint.configuration.ConstantTrue +import org.jacodb.taint.configuration.ContainsMark +import org.jacodb.taint.configuration.CopyAllMarks +import org.jacodb.taint.configuration.RemoveMark +import org.jacodb.taint.configuration.Result +import org.jacodb.taint.configuration.TaintConfigurationItem +import org.jacodb.taint.configuration.TaintMark +import org.jacodb.taint.configuration.TaintMethodSink +import org.jacodb.taint.configuration.TaintMethodSource +import org.jacodb.taint.configuration.TaintPassThrough +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledIf +import org.usvm.dataflow.ifds.SingletonUnit +import org.usvm.dataflow.ifds.UnitResolver +import org.usvm.dataflow.taint.TaintAnalysisOptions +import org.usvm.dataflow.taint.TaintManager +import org.usvm.dataflow.ts.loadEtsFileFromResource +import org.usvm.dataflow.ts.util.EtsTraits +import kotlin.io.path.exists +import kotlin.io.path.toPath +import kotlin.time.Duration.Companion.seconds + +private val logger = mu.KotlinLogging.logger {} + +@Disabled("Have several issues with EtsIR") +class EtsIfdsTest { + + companion object { + private const val BASE_PATH = "/etsir/samples" + + private fun loadSample(programName: String): EtsFile { + return loadEtsFileFromResource("$BASE_PATH/${programName}.ts.json") + } + } + + private fun projectAvailable(): Boolean { + val resource = object {}::class.java.getResource("/samples/source/project1")?.toURI() + return resource != null && resource.toPath().exists() + } + + @Test + fun `test taint analysis on MethodCollision`() { + val file = loadSample("MethodCollision") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "isSame" && method.signature.enclosingClass.name == "Foo") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("TAINT"), position = Result), + ), + ) + ) + if (method.name == "log") add( + TaintMethodSink( + method = method, + ruleNote = "CUSTOM SINK", // FIXME + cwe = listOf(), // FIXME + condition = ContainsMark(position = Argument(0), mark = TaintMark("TAINT")) + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val methods = project.projectClasses.flatMap { it.methods }.filter { it.name == "main" } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } + + @Test + fun `test taint analysis on TypeMismatch`() { + val file = loadSample("TypeMismatch") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "add") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("TAINT"), position = Result), + ) + ) + ) + if (method.name == "log") add( + TaintMethodSink( + method = method, + ruleNote = "CUSTOM SINK", // FIXME + cwe = listOf(), // FIXME + condition = ContainsMark(position = Argument(1), mark = TaintMark("TAINT")) + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val methods = project.projectClasses.flatMap { it.methods } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } + + @Disabled("TODO: Sink should be detected in the 'good' method") + @Test + fun `test taint analysis on DataFlowSecurity`() { + val file = loadSample("DataFlowSecurity") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "samples/source") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("TAINT"), position = Result), + ), + ) + ) + if (method.name == "sink") add( + TaintMethodSink( + method = method, + ruleNote = "SINK", // FIXME + cwe = listOf(), // FIXME + condition = ContainsMark(position = Argument(0), mark = TaintMark("TAINT")) + ) + ) + if (method.name == "pass") add( + TaintPassThrough( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + CopyAllMarks(from = Argument(0), to = Result) + ), + ) + ) + if (method.name == "validate") add( + TaintPassThrough( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + RemoveMark(mark = TaintMark("TAINT"), position = Argument(0)) + ), + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val goodMethod = project.projectClasses.flatMap { it.methods }.single { it.name == "good" } + logger.info { "good() method: $goodMethod" } + val goodSinks = manager.analyze(listOf(goodMethod), timeout = 60.seconds) + logger.info { "Sinks in good(): $goodSinks" } + Assertions.assertTrue(goodSinks.isEmpty()) + + val badMethod = project.projectClasses.flatMap { it.methods }.single { it.name == "bad" } + logger.info { "bad() method: $badMethod" } + val badSinks = manager.analyze(listOf(badMethod), timeout = 60.seconds) + logger.info { "Sinks in bad(): $badSinks" } + Assertions.assertTrue(badSinks.isNotEmpty()) + } + + @Test + fun `test taint analysis on case1 - untrusted loop bound scenario`() { + val file = loadSample("cases/case1") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "readInt") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("UNTRUSTED"), position = Result), + ), + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + TaintAnalysisOptions.UNTRUSTED_LOOP_BOUND_SINK = true + + val methods = project.projectClasses.flatMap { it.methods } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } + + @Test + fun `test taint analysis on case2 - untrusted array buffer size scenario`() { + val file = loadSample("cases/case2") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "readInt") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("UNTRUSTED"), position = Result), + ), + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + TaintAnalysisOptions.UNTRUSTED_ARRAY_SIZE_SINK = true + + val methods = project.projectClasses.flatMap { it.methods } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } + + // TODO(): support AnyArgument Position type for more flexible configs + @Test + fun `test taint analysis on case3 - send plain information with sensitive data`() { + val file = loadSample("cases/case3") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "getPassword") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("TAINT"), position = Result), + ), + ) + ) + if (method.name == "publishEvent") add( + TaintMethodSink( + method = method, ruleNote = "SINK", // FIXME + cwe = listOf(), // FIXME + condition = ContainsMark(position = Argument(1), mark = TaintMark("TAINT")) + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val methods = project.projectClasses.flatMap { it.methods } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } + + @EnabledIf("projectAvailable") + @Test + fun `test taint analysis on AccountManager`() { + val file = loadEtsFileFromResource("/etsir/project1/entry/src/main/ets/base/account/AccountManager.ts.json") + val project = EtsScene(listOf(file)) + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + // adhoc taint second argument (cursor: string) + if (method.name == "taintSink") add( + TaintMethodSink( + method = method, + cwe = listOf(), + ruleNote = "SINK", + condition = ContainsMark(position = Argument(0), mark = TaintMark("TAINT")), + ) + ) +// // encodeURI* +// if (method.name.startsWith("encodeURI")) add( +// TaintMethodSource( +// method = method, +// condition = ContainsMark(position = Argument(0), mark = TaintMark("UNSAFE")), +// actionsAfter = listOf( +// RemoveMark(position = Result, mark = TaintMark("UNSAFE")), +// ), +// ) +// ) +// // RequestOption.setUrl +// if (method.name == "setUrl") add( +// TaintMethodSource( +// method = method, +// condition = ConstantTrue, +// actionsAfter = listOf( +// CopyMark( +// mark = TaintMark("UNSAFE"), +// from = Argument(0), +// to = Result +// ), +// ), +// ) +// ) +// // HttpManager.requestSync +// if (method.name == "requestSync") add( +// TaintMethodSink( +// method = method, +// ruleNote = "Unsafe request", // FIXME +// cwe = listOf(), // FIXME +// condition = ContainsMark(position = Argument(0), mark = TaintMark("UNSAFE")) +// ) +// ) + // SyncUtil.requestGet + if (method.name == "requestGet") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf(AssignMark(position = Result, mark = TaintMark("TAINT"))) + ) + ) + } + rules.ifEmpty { null } + } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val methodNames = setOf( + "getDeviceIdListWithCursor", + "requestGet", + "taintRun", + "taintSink" + ) + + val methods = project.projectClasses.flatMap { it.methods }.filter { it.name in methodNames } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + Assertions.assertTrue(sinks.isNotEmpty()) + } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsProjectAnalysisTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsProjectAnalysisTest.kt new file mode 100644 index 0000000000..eb98f41b02 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsProjectAnalysisTest.kt @@ -0,0 +1,155 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import mu.KotlinLogging +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.graph.EtsApplicationGraphImpl +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledIf +import org.usvm.dataflow.ifds.SingletonUnit +import org.usvm.dataflow.ifds.UnitResolver +import org.usvm.dataflow.taint.TaintManager +import org.usvm.dataflow.taint.TaintVulnerability +import org.usvm.dataflow.ts.getResourcePath +import org.usvm.dataflow.ts.getResourceStream +import org.usvm.dataflow.ts.loadEtsFileFromResource +import org.usvm.dataflow.ts.test.utils.getConfigForMethod +import org.usvm.dataflow.ts.test.utils.loadRules +import org.usvm.dataflow.ts.util.EtsTraits +import org.usvm.dataflow.util.getPathEdges +import java.nio.file.Files +import kotlin.io.path.exists +import kotlin.io.path.toPath +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +private val logger = KotlinLogging.logger {} + +class EtsProjectAnalysisTest { + private var tsLinesSuccess = 0L + private var tsLinesFailed = 0L + private var analysisTime: Duration = Duration.ZERO + private var totalPathEdges = 0 + private var totalSinks: MutableList> = mutableListOf() + + companion object { + private const val SOURCE_PROJECT_PATH = + "/projects/applications_app_samples/source/applications_app_samples/code/SuperFeature/DistributedAppDev/ArkTSDistributedCalc" + private const val PROJECT_PATH = "/projects/applications_app_samples/etsir/ast/ArkTSDistributedCalc" + private const val START_PATH = "/entry/src/main/ets" + private const val BASE_PATH = PROJECT_PATH + private const val SOURCE_BASE_PATH = SOURCE_PROJECT_PATH + START_PATH + + private fun loadFromProject(filename: String): EtsFile { + return loadEtsFileFromResource("$BASE_PATH/$filename.json") + } + + private fun countFileLines(path: String): Long { + return getResourceStream(path).bufferedReader().use { reader -> + reader.lines().count() + } + } + + val rules = loadRules("config1.json") + } + + private fun projectAvailable(): Boolean { + val path = object {}::class.java.getResource(PROJECT_PATH)?.toURI()?.toPath() + return path != null && path.exists() + } + + @EnabledIf("projectAvailable") + @Test + fun processAllFiles() { + val baseDir = getResourcePath(BASE_PATH) + Files.walk(baseDir) + .filter { it.toString().endsWith(".json") } + .map { baseDir.relativize(it).toString().replace("\\", "/").substringBeforeLast('.') } + .forEach { filename -> + handleFile(filename) + } + makeReport() + } + + private fun makeReport() { + logger.info { "Analysis Report On $PROJECT_PATH" } + logger.info { "====================" } + logger.info { "Total files processed: ${tsLinesSuccess + tsLinesFailed}" } + logger.info { "Successfully processed lines: $tsLinesSuccess" } + logger.info { "Failed lines: $tsLinesFailed" } + logger.info { "Total analysis time: $analysisTime" } + logger.info { "Total path edges: $totalPathEdges" } + logger.info { "Found sinks: ${totalSinks.size}" } + + if (totalSinks.isNotEmpty()) { + totalSinks.forEachIndexed { idx, sink -> + logger.info { + """Detailed Sink Information: + | + |Sink ID: $idx + |Statement: ${sink.sink.statement} + |Fact: ${sink.sink.fact} + |Condition: ${sink.rule?.condition} + | + """.trimMargin() + } + } + } else { + logger.info { "No sinks found." } + } + logger.info { "====================" } + logger.info { "End of report" } + } + + private fun handleFile(filename: String) { + val fileLines = countFileLines("$SOURCE_BASE_PATH/$filename") + try { + logger.info { "Processing '$filename'" } + val file = loadFromProject(filename) + val project = EtsScene(listOf(file)) + val startTime = System.currentTimeMillis() + runAnalysis(project) + val endTime = System.currentTimeMillis() + analysisTime += (endTime - startTime).milliseconds + tsLinesSuccess += fileLines + } catch (e: Exception) { + logger.warn { "Failed to process '$filename': $e" } + logger.warn { e.stackTraceToString() } + tsLinesFailed += fileLines + } + } + + private fun runAnalysis(project: EtsScene) { + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = { method -> getConfigForMethod(method, rules) }, + ) + val methods = project.projectClasses.flatMap { it.methods } + val sinks = manager.analyze(methods, timeout = 10.seconds) + totalPathEdges += manager.runnerForUnit.values.sumOf { it.getPathEdges().size } + totalSinks += sinks + } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsSceneTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsSceneTest.kt new file mode 100644 index 0000000000..00d9d46fdc --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsSceneTest.kt @@ -0,0 +1,184 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsCallStmt +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsInstLocation +import org.jacodb.ets.base.EtsInstanceCallExpr +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsVoidType +import org.jacodb.ets.graph.EtsApplicationGraphImpl +import org.jacodb.ets.graph.EtsCfg +import org.jacodb.ets.model.EtsClassImpl +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsFieldImpl +import org.jacodb.ets.model.EtsFieldSignature +import org.jacodb.ets.model.EtsFieldSubSignature +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsFileSignature +import org.jacodb.ets.model.EtsMethodImpl +import org.jacodb.ets.model.EtsMethodSignature +import org.jacodb.ets.model.EtsScene +import kotlin.test.Test +import kotlin.test.assertEquals + +class EtsSceneTest { + + @Test + fun `test create EtsScene with multiple files`() { + val fileCatSignature = EtsFileSignature( + projectName = "TestProject", + fileName = "cat.ts", + ) + val classCatSignature = EtsClassSignature( + name = "Cat", + file = fileCatSignature, + namespace = null, + ) + val fieldName = EtsFieldImpl( + signature = EtsFieldSignature( + enclosingClass = classCatSignature, + sub = EtsFieldSubSignature( + name = "name", + type = EtsStringType, + ) + ) + ) + val methodMeow = EtsMethodImpl( + signature = EtsMethodSignature( + enclosingClass = classCatSignature, + name = "meow", + parameters = emptyList(), + returnType = EtsVoidType, + ) + ) + val ctorCat = EtsMethodImpl( + signature = EtsMethodSignature( + enclosingClass = classCatSignature, + name = CONSTRUCTOR_NAME, + parameters = emptyList(), + returnType = EtsVoidType, + ), + ) + val classCat = EtsClassImpl( + signature = classCatSignature, + fields = listOf(fieldName), + methods = listOf(methodMeow), + ctor = ctorCat, + ) + val fileCat = EtsFile( + signature = fileCatSignature, + classes = listOf(classCat), + namespaces = emptyList(), + ) + + val fileBoxSignature = EtsFileSignature( + projectName = "TestProject", + fileName = "box.ts", + ) + val classBoxSignature = EtsClassSignature( + name = "Box", + file = fileBoxSignature, + namespace = null, + ) + val fieldCats = EtsFieldImpl( + signature = EtsFieldSignature( + enclosingClass = classBoxSignature, + sub = EtsFieldSubSignature( + name = "cats", + type = EtsArrayType(EtsClassType(classCatSignature), 1), + ) + ) + ) + val methodTouch = EtsMethodImpl( + signature = EtsMethodSignature( + enclosingClass = classBoxSignature, + name = "touch", + parameters = emptyList(), + returnType = EtsVoidType, + ) + ).also { + var index = 0 + val stmts = listOf( + EtsAssignStmt( + location = EtsInstLocation(it, index++), + lhv = EtsLocal("this", EtsClassType(classBoxSignature)), + rhv = EtsThis(EtsClassType(classBoxSignature)), + ), + EtsCallStmt( + location = EtsInstLocation(it, index++), + expr = EtsInstanceCallExpr( + instance = EtsLocal("this", EtsClassType(classBoxSignature)), + method = methodMeow.signature, + args = emptyList(), + ) + ), + EtsReturnStmt( + location = EtsInstLocation(it, index++), + returnValue = null, + ) + ) + check(index == stmts.size) + val successors = mapOf( + stmts[0] to listOf(stmts[1]), + stmts[1] to listOf(stmts[2]), + ) + it._cfg = EtsCfg( + stmts = stmts, + successorMap = successors, + ) + } + val ctorBox = EtsMethodImpl( + signature = EtsMethodSignature( + enclosingClass = classBoxSignature, + name = CONSTRUCTOR_NAME, + parameters = emptyList(), + returnType = EtsVoidType, + ), + ) + val classBox = EtsClassImpl( + signature = classBoxSignature, + fields = listOf(fieldCats), + methods = listOf(methodTouch), + ctor = ctorBox, + ) + val fileBox = EtsFile( + signature = fileBoxSignature, + classes = listOf(classBox), + namespaces = emptyList(), + ) + + val project = EtsScene(listOf(fileCat, fileBox)) + val graph = EtsApplicationGraphImpl(project) + + val callStmt = project.projectClasses + .asSequence() + .flatMap { it.methods } + .filter { it.name == "touch" } + .flatMap { it.cfg.stmts } + .filterIsInstance() + .first() + assertEquals(methodMeow, graph.callees(callStmt).first()) + } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTaintAnalysisTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTaintAnalysisTest.kt new file mode 100644 index 0000000000..7c7284ac70 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTaintAnalysisTest.kt @@ -0,0 +1,140 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import mu.KotlinLogging +import org.jacodb.ets.graph.EtsApplicationGraphImpl +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.jacodb.taint.configuration.Argument +import org.jacodb.taint.configuration.AssignMark +import org.jacodb.taint.configuration.ConstantTrue +import org.jacodb.taint.configuration.ContainsMark +import org.jacodb.taint.configuration.CopyAllMarks +import org.jacodb.taint.configuration.RemoveMark +import org.jacodb.taint.configuration.Result +import org.jacodb.taint.configuration.TaintConfigurationItem +import org.jacodb.taint.configuration.TaintMark +import org.jacodb.taint.configuration.TaintMethodSink +import org.jacodb.taint.configuration.TaintMethodSource +import org.jacodb.taint.configuration.TaintPassThrough +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.usvm.dataflow.ifds.SingletonUnit +import org.usvm.dataflow.ifds.UnitResolver +import org.usvm.dataflow.taint.TaintManager +import org.usvm.dataflow.ts.loadEtsFileFromResource +import org.usvm.dataflow.ts.util.EtsTraits +import kotlin.test.assertTrue +import kotlin.time.Duration.Companion.seconds + +private val logger = KotlinLogging.logger {} + +class EtsTaintAnalysisTest { + + companion object { + private const val BASE_PATH = "/samples/etsir/ast" + private const val DECOMPILED_PATH = "/decompiled" + + private fun loadFromProject(name: String): EtsFile { + return loadEtsFileFromResource("$BASE_PATH/$name.ts.json") + } + + private fun loadDecompiled(name: String): EtsFile { + return loadEtsFileFromResource("$DECOMPILED_PATH/$name.abc.json") + } + + val getConfigForMethod: (EtsMethod) -> List? = + { method -> + val rules = buildList { + if (method.name == "source") add( + TaintMethodSource( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + AssignMark(mark = TaintMark("TAINT"), position = Result), + ), + ) + ) + if (method.name == "sink") add( + TaintMethodSink( + method = method, + ruleNote = "SINK", // FIXME + cwe = listOf(), // FIXME + condition = ContainsMark(position = Argument(0), mark = TaintMark("TAINT")) + ) + ) + if (method.name == "pass") add( + TaintPassThrough( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + CopyAllMarks(from = Argument(0), to = Result) + ), + ) + ) + if (method.name == "validate") add( + TaintPassThrough( + method = method, + condition = ConstantTrue, + actionsAfter = listOf( + RemoveMark(mark = TaintMark("TAINT"), position = Argument(0)) + ), + ) + ) + } + rules.ifEmpty { null } + } + } + + fun runTaintAnalysis(project: EtsScene) { + val graph = EtsApplicationGraphImpl(project) + val unitResolver = UnitResolver { SingletonUnit } + + val manager = TaintManager( + traits = EtsTraits(), + graph = graph, + unitResolver = unitResolver, + getConfigForMethod = getConfigForMethod, + ) + + val methods = project.projectClasses.flatMap { it.methods }.filter { it.name == "bad" } + logger.info { "Methods: ${methods.size}" } + for (method in methods) { + logger.info { " ${method.name}" } + } + val sinks = manager.analyze(methods, timeout = 60.seconds) + logger.info { "Sinks: $sinks" } + assertTrue(sinks.isNotEmpty()) + } + + @Test + fun `test taint analysis`() { + val file = loadFromProject("TaintAnalysis") + val project = EtsScene(listOf(file)) + runTaintAnalysis(project) + } + + @Disabled("Need to update the EtsIR-ABC json file") + @Test + fun `test taint analysis on decompiled file`() { + val file = loadDecompiled("TaintAnalysis") + val project = EtsScene(listOf(file)) + runTaintAnalysis(project) + } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeAnnotationTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeAnnotationTest.kt new file mode 100644 index 0000000000..cbcc3004c5 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeAnnotationTest.kt @@ -0,0 +1,193 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsAddExpr +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsInstLocation +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsNumberType +import org.jacodb.ets.base.EtsParameterRef +import org.jacodb.ets.base.EtsReturnStmt +import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsThis +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.graph.EtsCfg +import org.jacodb.ets.model.EtsClassImpl +import org.jacodb.ets.model.EtsClassSignature +import org.jacodb.ets.model.EtsDecorator +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsFileSignature +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsMethodParameter +import org.jacodb.ets.model.EtsMethodSignature +import org.jacodb.ets.model.EtsModifiers +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceResult +import org.usvm.dataflow.ts.infer.annotation.EtsTypeAnnotator +import org.usvm.dataflow.ts.infer.verify.LocalId +import org.usvm.dataflow.ts.infer.verify.MethodId +import org.usvm.dataflow.ts.infer.verify.ParameterId +import org.usvm.dataflow.ts.infer.verify.VerificationResult +import org.usvm.dataflow.ts.infer.verify.verify +import kotlin.test.Test + +internal class EtsTypeAnnotationTest { + @Test + fun `test EtsTypeAnnotator`() { + val typeInferenceResult = TypeInferenceResult( + inferredTypes = mapOf( + mainMethod to mapOf( + AccessPathBase.Arg(1) to EtsTypeFact.StringEtsTypeFact, + AccessPathBase.Arg(2) to EtsTypeFact.NumberEtsTypeFact, + AccessPathBase.Local("v1") to EtsTypeFact.StringEtsTypeFact, + AccessPathBase.Local("v2") to EtsTypeFact.NumberEtsTypeFact, + AccessPathBase.Local("v3") to EtsTypeFact.StringEtsTypeFact, + ) + ), + inferredReturnType = mapOf( + mainMethod to EtsTypeFact.StringEtsTypeFact + ), + inferredCombinedThisType = mapOf( + mainClassSignature to EtsTypeFact.ObjectEtsTypeFact( + cls = EtsClassType(mainClassSignature), + properties = mapOf(), + ) + ) + ) + + val annotatedScene = EtsTypeAnnotator(sampleScene, typeInferenceResult) + .annotateWithTypes(sampleScene) + + val verificationResult = verify(annotatedScene) + + assert(verificationResult is VerificationResult.Success) + + with(verificationResult as VerificationResult.Success) { + val main = MethodId(mainMethodSignature) + + assert(mapping[ParameterId(1, main)] == EtsStringType) + assert(mapping[ParameterId(2, main)] == EtsNumberType) + + assert(mapping[LocalId("v1", main)] == EtsStringType) + assert(mapping[LocalId("v2", main)] == EtsNumberType) + assert(mapping[LocalId("v3", main)] == EtsStringType) + } + } + + private val mainTs = EtsFileSignature( + projectName = "sampleProject", + fileName = "main.ts", + ) + + private val mainClassSignature = EtsClassSignature( + name = "MainClass", + file = mainTs, + namespace = null, + ) + + private val mainMethodSignature = EtsMethodSignature( + enclosingClass = mainClassSignature, + name = "mainMethod", + parameters = parameters(2), + returnType = EtsUnknownType, + ) + + private val mainMethod = buildMethod(mainMethodSignature) { + val arg1 = EtsParameterRef(1, EtsUnknownType) + val arg2 = EtsParameterRef(2, EtsUnknownType) + val v1 = EtsLocal("v1", EtsUnknownType) + val v2 = EtsLocal("v2", EtsUnknownType) + val v3 = EtsLocal("v3", EtsUnknownType) + + push(EtsAssignStmt(location, v1, arg1)) + push(EtsAssignStmt(location, v2, arg2)) + push(EtsAssignStmt(location, v3, EtsAddExpr(EtsUnknownType, v1, v2))) + push(EtsReturnStmt(location, v3)) + } + + private val mainClassCtorSignature = EtsMethodSignature( + enclosingClass = mainClassSignature, + name = CONSTRUCTOR_NAME, + parameters = parameters(1), + returnType = EtsUnknownType, + ) + + private val mainClassCtor = buildMethod(mainClassCtorSignature) { + val etsThis = EtsThis(EtsClassType(mainClassSignature)) + push(EtsReturnStmt(location, etsThis)) + } + + private val mainClass = EtsClassImpl( + signature = mainClassSignature, + fields = listOf(), + methods = listOf(mainMethod), + ctor = mainClassCtor, + superClass = null, + ) + + private val mainFile = EtsFile( + signature = mainTs, + classes = listOf(mainClass), + namespaces = listOf(), + ) + + private val sampleScene = EtsScene(listOf(mainFile)) + + private class CfgBuilderContext( + val method: EtsMethod + ) { + private val stmts = mutableListOf() + private val successorsMap = mutableMapOf>() + + fun build(): EtsCfg = EtsCfg(stmts, successorsMap) + + fun push(stmt: EtsStmt) { + stmts.lastOrNull()?.let { link(it, stmt) } + successorsMap[stmt] = mutableListOf() + stmts.add(stmt) + } + + fun link(from: EtsStmt, to: EtsStmt) { + successorsMap.getOrPut(from, ::mutableListOf).add(to) + } + + val location: EtsInstLocation + get() = EtsInstLocation(method, stmts.size) + } + + private fun buildMethod( + signature: EtsMethodSignature, + cfgBuilder: CfgBuilderContext.() -> Unit, + ) = object : EtsMethod { + override val signature = signature + override val typeParameters: List = emptyList() + override val modifiers: EtsModifiers = EtsModifiers.EMPTY + override val decorators: List = emptyList() + override val locals: List = emptyList() + override val cfg = CfgBuilderContext(this).apply(cfgBuilder).build() + } + + private fun parameters(n: Int) = + List(n) { EtsMethodParameter(it, "a$it", EtsUnknownType) } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeInferenceTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeInferenceTest.kt new file mode 100644 index 0000000000..8c7dedf2e7 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeInferenceTest.kt @@ -0,0 +1,603 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test + +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.runInterruptible +import kotlinx.coroutines.withTimeout +import kotlinx.serialization.SerializationException +import mu.KotlinLogging +import org.jacodb.ets.base.CONSTRUCTOR_NAME +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsAssignStmt +import org.jacodb.ets.base.EtsLocal +import org.jacodb.ets.base.EtsStringConstant +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.dto.EtsFileDto +import org.jacodb.ets.dto.convertToEtsFile +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsScene +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.condition.EnabledIf +import org.usvm.dataflow.ts.getResourcePath +import org.usvm.dataflow.ts.getResourcePathOrNull +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceManager +import org.usvm.dataflow.ts.infer.TypeInferenceResult +import org.usvm.dataflow.ts.infer.annotation.EtsTypeAnnotator +import org.usvm.dataflow.ts.infer.createApplicationGraph +import org.usvm.dataflow.ts.infer.dto.toType +import org.usvm.dataflow.ts.loadEtsFileFromResource +import org.usvm.dataflow.ts.loadEtsProjectFromResources +import org.usvm.dataflow.ts.testFactory +import org.usvm.dataflow.ts.util.EtsTraits +import java.io.File +import kotlin.io.path.div +import kotlin.io.path.exists +import kotlin.io.path.toPath +import kotlin.test.assertContains +import kotlin.test.assertEquals +import kotlin.test.assertIs +import kotlin.test.assertNotEquals +import kotlin.test.assertTrue + +private val logger = KotlinLogging.logger {} + +class EtsTypeInferenceTest { + + companion object { + private fun load(path: String): EtsFile { + return loadEtsFileFromResource("/$path") + } + } + + @Test + fun `type inference for microphone`() { + val name = "microphone" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val result = manager.analyze(entrypoints) + val types = result.inferredTypes + + run { + val m = types.keys.first { it.name == "getMicrophoneUuid" } + + // arg0 = 'devices' + val devices = types[m]!![AccessPathBase.Arg(0)]!! + assertIs(devices) + + val devicesCls = devices.cls + assertEquals("VirtualDevices", devicesCls?.typeName) + + assertContains(devices.properties, "microphone") + val microphone = devices.properties["microphone"]!! + assertIs(microphone) + + assertContains(microphone.properties, "uuid") + val uuid = microphone.properties["uuid"]!! + assertIs(uuid) + } + } + + @Test + fun `type inference for types`() { + val name = "types" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + manager.analyze(entrypoints) + } + + @Test + fun `type inference for data`() { + val name = "data" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + manager.analyze(entrypoints) + } + + @Test + fun `type inference for call`() { + val name = "call" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + manager.analyze(entrypoints) + } + + @Test + fun `type inference for nested_init`() { + val name = "nested_init" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + manager.analyze(entrypoints) + } + + @Disabled("EtsIR-ABC is outdated") + @Test + fun `type inference for cast ABC`() { + val name = "cast" + val file = load("abcir/$name.abc.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name.startsWith("entrypoint") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + manager.analyze(entrypoints) + } + + private fun resourceAvailable(dirName: String): Boolean = + object {}::class.java.getResource(dirName) != null + + private fun testHapSet(setPath: String) { + val abcDir = object {}::class.java.getResource(setPath)?.toURI()?.toPath() + ?: error("Resource not found: $setPath") + val haps = abcDir.toFile().listFiles()?.toList() ?: emptyList() + processAllHAPs(haps) + } + + private val TEST_PROJECTS_PATH = "/projects/abcir/" + private fun testProjectsAvailable() = resourceAvailable(TEST_PROJECTS_PATH) + + @Test + @EnabledIf("testProjectsAvailable") + fun `type inference for test projects`() = testHapSet(TEST_PROJECTS_PATH) + + @Test + fun `test single HAP`() { + val abcDirName = "/TestProjects/CertificateManager_240801_843398b" + val projectDir = object {}::class.java.getResource(abcDirName)?.toURI()?.toPath() + ?: error("Resource not found: $abcDirName") + val (scene, result) = testHap(projectDir.toString()) + val scene2 = EtsTypeAnnotator(scene, result).annotateWithTypes(scene) + } + + private fun processAllHAPs(haps: Collection) { + val succeed = mutableListOf() + val timeout = mutableListOf() + val failed = mutableListOf() + + haps.forEach { project -> + try { + runBlocking { + withTimeout(60_000) { + runInterruptible { + testHap(project.path) + } + } + } + succeed += project.name + println("$project - SUCCESS") + } catch (_: TimeoutCancellationException) { + timeout += project.name + println("$project - TIMEOUT") + } catch (e: SerializationException) { + e.printStackTrace() + error("Serialization exception") + } catch (e: Throwable) { + failed += project.name + println("$project - FAILED") + e.printStackTrace() + } + } + + println("Total: ${haps.size} HAPs") + println("Succeed: ${succeed.size}") + println("Timeout: ${timeout.size}") + println("Failed: ${failed.size}") + + println("PASSED") + succeed.forEach { + println(it) + } + println("TIMEOUT") + timeout.forEach { + println(it) + } + println("FAILED") + failed.forEach { + println(it) + } + } + + private fun testHap(projectDir: String): Pair { + val dir = File(projectDir).takeIf { it.isDirectory } ?: error("Not found project dir $projectDir") + println("Found project dir: '$dir'") + + val files = dir + .walk() + .filter { it.extension == "json" } + .toList() + println("Found files: (${files.size})") + for (path in files) { + println(" ${path.relativeTo(dir)}") + } + + println("Processing ${files.size} files...") + val etsFiles = files.map { convertToEtsFile(EtsFileDto.loadFromJson(it.inputStream())) } + val project = EtsScene(etsFiles) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods + it.ctor } + .filter { it.isPublic || it.name == CONSTRUCTOR_NAME } + .filter { !it.enclosingClass.name.startsWith("AnonymousClass") } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val result = manager.analyze(entrypoints) + return Pair(project, result) + } + + @Test + fun `test if guesser does anything`() { + val name = "testcases" + val file = load("ir/$name.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoints = project.projectClasses + .flatMap { it.methods } + .filter { it.name == "entrypoint" } + println("entrypoints: (${entrypoints.size})") + entrypoints.forEach { + println(" ${it.signature.enclosingClass.name}::${it.name}") + } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultWithoutGuessed = manager.analyze(entrypoints) + val resultWithGuessed = resultWithoutGuessed.withGuessedTypes(project) + + assertNotEquals(resultWithoutGuessed.inferredTypes, resultWithGuessed.inferredTypes) + + println("=".repeat(42)) + println("Inferred types WITHOUT guesser: ") + for ((method, types) in resultWithoutGuessed.inferredTypes) { + println(method.enclosingClass.name to types) + } + + println("=".repeat(42)) + println("Inferred types with guesser: ") + for ((method, types) in resultWithGuessed.inferredTypes) { + println(method.enclosingClass.name to types) + } + } + + @TestFactory + fun `type inference on testcases`() = testFactory { + val file = load("ir/testcases.ts.json") + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val allCases = project.projectClasses.filter { it.name.startsWith("Case") } + + for (cls in allCases) { + test(name = cls.name) { + logger.info { "Analyzing testcase: ${cls.name}" } + + val inferMethod = cls.methods.single { it.name == "infer" } + logger.info { "Found infer: ${inferMethod.signature}" } + + val expectedTypeString = mutableMapOf() + var expectedReturnTypeString = "" + for (inst in inferMethod.cfg.stmts) { + if (inst is EtsAssignStmt) { + val lhv = inst.lhv + if (lhv is EtsLocal) { + val rhv = inst.rhv + if (lhv.name.startsWith("EXPECTED_ARG_")) { + check(rhv is EtsStringConstant) + val arg = lhv.name.removePrefix("EXPECTED_ARG_").toInt() + val pos = AccessPathBase.Arg(arg) + expectedTypeString[pos] = rhv.value + logger.info { "Expected type for $pos: ${rhv.value}" } + } else if (lhv.name == "EXPECTED_RETURN") { + check(rhv is EtsStringConstant) + expectedReturnTypeString = rhv.value + logger.info { "Expected return type: ${rhv.value}" } + } else if (lhv.name.startsWith("EXPECTED")) { + logger.error { "Skipping unexpected local: $lhv" } + } + } + } + } + + val entrypoint = cls.methods.single { it.name == "entrypoint" } + logger.info { "Found entrypoint: ${entrypoint.signature}" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val result = manager.analyze(listOf(entrypoint)) + + val inferredTypes = result.inferredTypes[inferMethod] + ?: error("No inferred types for method ${inferMethod.enclosingClass.name}::${inferMethod.name}") + + for (position in expectedTypeString.keys.sortedBy { + when (it) { + is AccessPathBase.This -> -1 + is AccessPathBase.Arg -> it.index + else -> 1_000_000 + } + }) { + val expected = expectedTypeString[position]!! + val inferred = inferredTypes[position] + logger.info { "Inferred type for $position: $inferred" } + val passed = inferred.toString() == expected + assertTrue( + passed, + "Inferred type for $position does not match: inferred = $inferred, expected = $expected" + ) + } + if (expectedReturnTypeString.isNotBlank()) { + val expected = expectedReturnTypeString + val inferred = result.inferredReturnType[inferMethod] + logger.info { "Inferred return type: $inferred" } + val passed = inferred.toString() == expected + assertTrue( + passed, + "Inferred return type does not match: inferred = $inferred, expected = $expected" + ) + } + } + } + } + + @TestFactory + fun `test type inference on projects`() = testFactory { + val p = getResourcePathOrNull("/projects") ?: run { + logger.warn { "No projects directory found in resources" } + return@testFactory + } + val availableProjectNames = p.toFile().listFiles { f -> f.isDirectory }!!.map { it.name }.sorted() + logger.info { + buildString { + appendLine("Found projects: ${availableProjectNames.size}") + for (name in availableProjectNames) { + appendLine(" - $name") + } + } + } + if (availableProjectNames.isEmpty()) { + logger.warn { "No projects found" } + return@testFactory + } + for (projectName in availableProjectNames) { + // if (projectName != "Launcher") continue + // if (projectName != "Demo_Calc") continue + test("infer types in $projectName") { + logger.info { "Loading project: $projectName" } + val projectPath = getResourcePath("/projects/$projectName") + val etsirPath = projectPath / "etsir" + if (!etsirPath.exists()) { + logger.warn { "No etsir directory found for project $projectName" } + return@test + } + val modules = etsirPath.toFile().listFiles { f -> f.isDirectory }!!.map { it.name } + logger.info { "Found ${modules.size} modules: $modules" } + if (modules.isEmpty()) { + logger.warn { "No modules found for project $projectName" } + return@test + } + val project = loadEtsProjectFromResources(modules, "/projects/$projectName/etsir") + logger.info { + buildString { + appendLine("Loaded project with ${project.projectAndSdkClasses.size} classes and ${project.projectClasses.sumOf { it.methods.size }} methods") + for (cls in project.projectAndSdkClasses.sortedBy { it.name }) { + appendLine("= ${cls.signature} with ${cls.methods.size} methods:") + for (method in cls.methods.sortedBy { it.name }) { + appendLine(" - ${method.signature}") + } + } + } + } + val graph = createApplicationGraph(project) + + val entrypoints = project.projectAndSdkClasses + .flatMap { it.methods } + .filter { it.isPublic } + logger.info { "Found ${entrypoints.size} entrypoints" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val result = manager.analyze(entrypoints) + + logger.info { + buildString { + appendLine("Inferred types: ${result.inferredTypes.size}") + for ((method, types) in result.inferredTypes.entries.sortedBy { "${it.key.enclosingClass.name}::${it.key.name}" }) { + appendLine() + appendLine("- $method") + for ((pos, type) in types.entries.sortedBy { + when (val base = it.key) { + is AccessPathBase.This -> -1 + is AccessPathBase.Arg -> base.index + else -> 1_000_000 + } + }) { + appendLine("$pos: $type") + } + } + } + } + logger.info { + buildString { + appendLine("Inferred return types: ${result.inferredReturnType.size}") + for ((method, returnType) in result.inferredReturnType.entries.sortedBy { it.key.toString() }) { + appendLine("${method.enclosingClass.name}::${method.name}: $returnType") + } + } + } + logger.info { + buildString { + appendLine("Inferred combined this types: ${result.inferredCombinedThisType.size}") + for ((clazz, thisType) in result.inferredCombinedThisType.entries.sortedBy { it.key.toString() }) { + appendLine("${clazz.name} in ${clazz.file}: $thisType") + } + } + } + + var totalNumMatchedNormal = 0 + var totalNumMatchedUnknown = 0 + var totalNumMismatchedNormal = 0 + var totalNumLostNormal = 0 + var totalNumBetterThanUnknown = 0 + + for ((method, inferredTypes) in result.inferredTypes) { + var numMatchedNormal = 0 + var numMatchedUnknown = 0 + var numMismatchedNormal = 0 + var numLostNormal = 0 + var numBetterThanUnknown = 0 + + for (local in method.locals) { + val inferredType = inferredTypes[AccessPathBase.Local(local.name)]?.toType() + + logger.info { + "Local ${local.name} in ${method.enclosingClass.name}::${method.name}, known type: ${local.type}, inferred type: $inferredType" + } + + if (inferredType != null) { + if (local.type.isUnknown()) { + if (inferredType.isUnknown()) { + logger.info { "Matched unknown" } + numMatchedUnknown++ + } else { + logger.info { "Better than unknown" } + numBetterThanUnknown++ + } + } else { + if (inferredType == local.type) { + logger.info { "Matched normal" } + numMatchedNormal++ + } else { + logger.info { "Mismatched normal" } + numMismatchedNormal++ + } + } + } else { + if (local.type.isUnknown()) { + logger.info { "Matched (lost) unknown" } + numMatchedUnknown++ + } else { + logger.info { "Lost normal" } + numLostNormal++ + } + } + } + + logger.info { + buildString { + appendLine("Local type matching for ${method.enclosingClass.name}::${method.name}:") + appendLine(" Matched normal: $numMatchedNormal") + appendLine(" Matched unknown: $numMatchedUnknown") + appendLine(" Mismatched normal: $numMismatchedNormal") + appendLine(" Lost normal: $numLostNormal") + appendLine(" Better than unknown: $numBetterThanUnknown") + } + } + totalNumMatchedNormal += numMatchedNormal + totalNumMatchedUnknown += numMatchedUnknown + totalNumMismatchedNormal += numMismatchedNormal + totalNumLostNormal += numLostNormal + totalNumBetterThanUnknown += numBetterThanUnknown + } + + logger.info { + buildString { + appendLine("Total local type matching statistics:") + appendLine(" Matched normal: $totalNumMatchedNormal") + appendLine(" Matched unknown: $totalNumMatchedUnknown") + appendLine(" Mismatched normal: $totalNumMismatchedNormal") + appendLine(" Lost normal: $totalNumLostNormal") + appendLine(" Better than unknown: $totalNumBetterThanUnknown") + } + } + + logger.info { "Done analyzing project: $projectName" } + } + } + } +} + +private fun EtsType.isUnknown(): Boolean = + this == EtsUnknownType || this == EtsAnyType diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverAbcTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverAbcTest.kt new file mode 100644 index 0000000000..48da6bdca2 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverAbcTest.kt @@ -0,0 +1,83 @@ +package org.usvm.dataflow.ts.test + +import org.jacodb.ets.utils.loadEtsProjectFromIR +import org.junit.jupiter.api.Test +import org.usvm.dataflow.ts.infer.EntryPointsProcessor +import org.usvm.dataflow.ts.infer.TypeInferenceManager +import org.usvm.dataflow.ts.infer.createApplicationGraph +import org.usvm.dataflow.ts.util.EtsTraits +import org.usvm.dataflow.ts.util.MethodTypesFacts +import org.usvm.dataflow.ts.util.TypeInferenceStatistics +import kotlin.io.path.Path + +class EtsTypeResolverAbcTest { + private val yourPrefixForTestFolders = "C:/work/TestProjects" + private val testProjectsVersion = "TestProjects_2024_12_5" + + private val pathToSDK: String = TODO("Put your path here") + + private fun runOnAbcProject(projectID: String, abcPath: String) { + val projectAbc = "$yourPrefixForTestFolders/$testProjectsVersion/$abcPath" + val abcScene = loadEtsProjectFromIR(Path(projectAbc), Path(pathToSDK)) + val graphAbc = createApplicationGraph(abcScene) + + val entrypoint = EntryPointsProcessor.extractEntryPoints(abcScene) + val allMethods = entrypoint.allMethods.filter { it.isPublic }.filter { it.cfg.stmts.isNotEmpty() } + + val manager = TypeInferenceManager(EtsTraits(), graphAbc) + val result = manager + .analyze(entrypoint.mainMethods, allMethods) + .withGuessedTypes(abcScene) + + val sceneStatistics = TypeInferenceStatistics() + entrypoint.allMethods + .filter { it.cfg.stmts.isNotEmpty() } + .forEach { + val methodTypeFacts = MethodTypesFacts.from(result, it) + sceneStatistics.compareSingleMethodFactsWithTypesInScene(methodTypeFacts, it, graphAbc) + } + sceneStatistics.dumpStatistics("${projectID}_scene_comparison.txt") + } + + @Test + fun testLoadAbcProject1() = runOnAbcProject( + projectID = "project1", + abcPath = "callui-default-signed", + ) + + @Test + fun testLoadAbcProject2() = runOnAbcProject( + projectID = "project2", + abcPath = "CertificateManager_240801_843398b", + ) + + @Test + fun testLoadAbcProject3() = runOnAbcProject( + projectID = "project3", + abcPath = "mobiledatasettings-callui-default-signed", + ) + + @Test + fun testLoadAbcProject4() = runOnAbcProject( + projectID = "project4", + abcPath = "Music_Demo_240727_98a3500", + ) + + @Test + fun testLoadAbcProject5() = runOnAbcProject( + projectID = "project5", + abcPath = "phone_photos-default-signed_20240905_151755", + ) + + @Test + fun testLoadAbcProject6() = runOnAbcProject( + projectID = "project6", + abcPath = "phone-default-signed_20240409_144519", + ) + + @Test + fun testLoadAbcProject7() = runOnAbcProject( + projectID = "project7", + abcPath = "SecurityPrivacyCenter_240801_843998b", + ) +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverWithAstTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverWithAstTest.kt new file mode 100644 index 0000000000..73eb7d5d5d --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/EtsTypeResolverWithAstTest.kt @@ -0,0 +1,358 @@ +package org.usvm.dataflow.ts.test + +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.jacodb.ets.utils.loadEtsFileAutoConvert +import org.jacodb.ets.utils.loadEtsProjectAutoConvert +import org.jacodb.ets.utils.loadEtsProjectFromIR +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Test +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EntryPointsProcessor +import org.usvm.dataflow.ts.infer.EtsApplicationGraphWithExplicitEntryPoint +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.infer.TypeInferenceManager +import org.usvm.dataflow.ts.infer.TypeInferenceResult +import org.usvm.dataflow.ts.infer.createApplicationGraph +import org.usvm.dataflow.ts.test.utils.ClassMatcherStatistics +import org.usvm.dataflow.ts.test.utils.ExpectedTypesExtractor +import org.usvm.dataflow.ts.util.EtsTraits +import org.usvm.dataflow.ts.util.MethodTypesFacts +import org.usvm.dataflow.ts.util.TypeInferenceStatistics +import java.nio.file.Paths +import kotlin.io.path.Path +import kotlin.test.assertTrue + +class EtsTypeResolverWithAstTest { + companion object { + private fun load(name: String): EtsFile { + return loadEtsFileAutoConvert(Paths.get("/ts/$name.ts")) + } + } + + private val yourPrefixForTestFolders = "C:/work/TestProjects" + private val testProjectsVersion = "TestProjects_2024_11_14" + private val pathToSDK: String? = null // TODO: Put your path here + + @Test + fun testTestHap() { + val projectAbc = "$yourPrefixForTestFolders/$testProjectsVersion/CallUI" + val abcScene = loadEtsProjectFromIR(Path(projectAbc), pathToSDK?.let { Path(it) }) + val graphAbc = createApplicationGraph(abcScene) + + val entrypoint = EntryPointsProcessor.extractEntryPoints(abcScene) // TODO fix error with abc and ast methods + + val manager = TypeInferenceManager(EtsTraits(), graphAbc) + val resultBasic = manager.analyze( + entrypoints = entrypoint.mainMethods, + allMethods = entrypoint.allMethods, + ) + val result = resultBasic.withGuessedTypes(abcScene) + + val classMatcherStatistics = ClassMatcherStatistics() + + // TODO fix error with abc and ast methods + saveTypeInferenceComparison( + entrypoint.allMethods, + entrypoint.allMethods, + graphAbc, + graphAbc, + result, + classMatcherStatistics, + abcScene, + ) + classMatcherStatistics.dumpStatistics("callkit.txt") + } + + fun runOnProjectWithAstComparison(projectID: String, abcPath: String, astPath: String) { + val projectAbc = "$yourPrefixForTestFolders/$testProjectsVersion/$abcPath" + val abcScene = loadEtsProjectFromIR(Path(projectAbc), pathToSDK?.let { Path(it) }) + + val projectAst = "$yourPrefixForTestFolders/AST/$astPath" + val astScene = loadEtsProjectAutoConvert(Paths.get(projectAst)) + + val graphAbc = createApplicationGraph(abcScene) as EtsApplicationGraphWithExplicitEntryPoint + val graphAst = createApplicationGraph(astScene) as EtsApplicationGraphWithExplicitEntryPoint + + val entrypoint = EntryPointsProcessor.extractEntryPoints(abcScene) + val astMethods = extractAllAstMethods(astScene, abcScene) + + println(entrypoint.mainMethods.map { it.signature }) + println(entrypoint.allMethods.map { it.signature }) + + val manager = TypeInferenceManager(EtsTraits(), graphAbc) + val resultBasic = manager.analyze( + entrypoints = entrypoint.mainMethods, + allMethods = entrypoint.allMethods.filter { it.isPublic }, + ) + val result = resultBasic.withGuessedTypes(abcScene) + + val classMatcherStatistics = ClassMatcherStatistics() + saveTypeInferenceComparison( + astMethods, + entrypoint.allMethods, + graphAst, + graphAbc, + result, + classMatcherStatistics, + abcScene + ) + classMatcherStatistics.dumpStatistics("$projectID.txt") + + val sceneStatistics = TypeInferenceStatistics() + abcScene.projectAndSdkClasses + .flatMap { it.methods } + .forEach { + val facts = MethodTypesFacts.from(result, it) + sceneStatistics.compareSingleMethodFactsWithTypesInScene(facts, it, graphAbc) + } + sceneStatistics.dumpStatistics("${projectID}_scene_comparison.txt") + } + + @Test + fun testLoadProject1() = runOnProjectWithAstComparison( + projectID = "project1", + abcPath = "callui-default-signed", + astPath = "16_CallUI/applications_call_230923_4de8" + ) + + @Test + fun testLoadProject2() = runOnProjectWithAstComparison( + projectID = "project2", + abcPath = "CertificateManager_240801_843398b", + astPath = "13_SecurityPrivacyCenter/security_privacy_center" + ) + + @Test + fun testLoadProject3() = runOnProjectWithAstComparison( + projectID = "project3", + abcPath = "mobiledatasettings-callui-default-signed", + astPath = "16_CallUI/applications_call_230923_4de8" + ) + + @Test + fun testLoadProject4() = runOnProjectWithAstComparison( + projectID = "project4", + abcPath = "Music_Demo_240727_98a3500", + astPath = "16_CallUI/applications_call_230923_4de8" + ) + + @Test + fun testLoadProject5() = runOnProjectWithAstComparison( + projectID = "project5", + abcPath = "phone_photos-default-signed_20240905_151755", + astPath = "15_Photos/applications_photos_240905_ea8d1" + ) + + @Test + fun testLoadProject6() = runOnProjectWithAstComparison( + projectID = "project6", + abcPath = "phone-default-signed_20240409_144519", + astPath = "17_Camera/applications_camera_240409_1da805f8" + ) + + @Test + fun testLoadProject7() = runOnProjectWithAstComparison( + projectID = "project7", + abcPath = "SecurityPrivacyCenter_240801_843998b", + astPath = "13_SecurityPrivacyCenter/security_privacy_center" + ) + + @Test + fun `use non unique fields`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useNonUniqueField" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { typeFact: EtsTypeFact.ObjectEtsTypeFact -> + typeFact.cls == null && typeFact.properties.keys.single() == "defaultA" + } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertFalse(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + @Test + fun `use unique fields`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useUniqueFields" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { fact: EtsTypeFact.ObjectEtsTypeFact -> + fact.cls?.typeName == "FieldContainerToInfer" && fact.properties.isEmpty() + } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertTrue(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + @Test + fun `use unique and non unique fields`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useBothA" } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { fact: EtsTypeFact.ObjectEtsTypeFact -> + fact.cls?.typeName == "FieldContainerToInfer" && fact.properties.isEmpty() + } + + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertTrue(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + @Test + fun `use unique methods`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useUniqueMethods" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { typeFact: EtsTypeFact.ObjectEtsTypeFact -> + typeFact.cls?.typeName == "MethodsContainerToInfer" && typeFact.properties.isEmpty() + } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertTrue(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + @Test + fun `use non unique methods`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useNotUniqueMethod" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { typeFact: EtsTypeFact.ObjectEtsTypeFact -> + typeFact.cls == null && typeFact.properties.keys.single() == "notUniqueFunction" + } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertFalse(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + @Test + fun `use function and field`() { + val file = load("resolver_test") + + val project = EtsScene(listOf(file)) + val graph = createApplicationGraph(project) + + val entrypoint = project.projectClasses + .flatMap { it.methods } + .single { it.name == "useFunctionAndField" } + + val manager = TypeInferenceManager(EtsTraits(), graph) + val resultBasic = manager.analyze(listOf(entrypoint)) + val result = resultBasic.withGuessedTypes(project) + + checkAnObjectTypeOfSingleArgument(result.inferredTypes[entrypoint]!!) { typeFact: EtsTypeFact.ObjectEtsTypeFact -> + typeFact.cls?.typeName == "FieldContainerToInfer" && typeFact.properties.isEmpty() + } + + val expectedTypes = ExpectedTypesExtractor(graph).extractTypes(entrypoint) + val actualTypes = MethodTypesFacts.from(result, entrypoint) + + assertTrue(expectedTypes.matchesWithTypeFacts(actualTypes, ignoreReturnType = true, project)) + } + + private fun extractAllAstMethods(astScene: EtsScene, abcScene: EtsScene): List { + val abcMethods = abcScene.projectAndSdkClasses + .flatMapTo(hashSetOf()) { + it.methods.map { method -> method.name } + } + return astScene.projectAndSdkClasses + .flatMap { it.methods } + .filter { it.name in abcMethods } + } + + private fun saveTypeInferenceComparison( + astMethods: List, + abcMethods: List, + graphAst: EtsApplicationGraph, + graphAbc: EtsApplicationGraph, + result: TypeInferenceResult, + classMatcherStatistics: ClassMatcherStatistics, + abcScene: EtsScene, + ) { + astMethods.forEach { m -> + val expectedTypes = ExpectedTypesExtractor(graphAst).extractTypes(m) + val abcMethod = abcMethods.singleOrNull { + it.name == m.name && it.enclosingClass.name == m.enclosingClass.name + } ?: return@forEach + val actualTypes = MethodTypesFacts.from(result, m) + classMatcherStatistics.calculateStats( + actualTypes, + expectedTypes, + abcScene, + m, + abcMethod, + graphAst, + graphAbc + ) + } + } + + private inline fun checkAnObjectTypeOfSingleArgument( + types: Map, + predicate: (T) -> Boolean, + ) { + val type = types.filterKeys { it is AccessPathBase.Arg }.values.single() as T + assertTrue(predicate(type)) + } +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/TypeFactDtoTest.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/TypeFactDtoTest.kt new file mode 100644 index 0000000000..bff01bfe71 --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/TypeFactDtoTest.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("TestFunctionName", "RemoveRedundantBackticks") + +package org.usvm.dataflow.ts.test + +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import org.jacodb.ets.dto.ClassSignatureDto +import org.jacodb.ets.dto.ClassTypeDto +import org.jacodb.ets.dto.FileSignatureDto +import org.usvm.dataflow.ts.infer.dto.TypeFactDto +import kotlin.test.Test +import kotlin.test.assertEquals + +class TypeFactDtoTest { + @Test + fun `NumberTypeFact`() { + val fact = TypeFactDto.NumberTypeFact + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals("{}", serialized) + + val deserialized = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } + + @Test + fun `polymorphic NumberTypeFact`() { + val fact: TypeFactDto = TypeFactDto.NumberTypeFact + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals("""{"_":"NumberType"}""", serialized) + + val deserialized: TypeFactDto = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } + + @Test + fun `polymorphic ObjectTypeFact with null class`() { + val fact: TypeFactDto = TypeFactDto.ObjectTypeFact( + cls = null, + ) + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals("""{"_":"ObjectType"}""", serialized) + + val deserialized: TypeFactDto = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } + + @Test + fun `polymorphic ObjectTypeFact with null class and some properties`() { + val fact: TypeFactDto = TypeFactDto.ObjectTypeFact( + cls = null, + properties = mapOf( + "x" to TypeFactDto.NumberTypeFact, + "bar" to TypeFactDto.ObjectTypeFact( + cls = mkClassType("org.example.Bar"), + ), + ), + ) + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals( + """{"_":"ObjectType","properties":{"x":{"_":"NumberType"},"bar":{"_":"ObjectType","cls":{"_":"ClassType","signature":{"name":"org.example.Bar"}}}}}""", + serialized + ) + + val deserialized: TypeFactDto = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } + + @Test + fun `polymorphic ObjectTypeFact with class`() { + val fact: TypeFactDto = TypeFactDto.ObjectTypeFact( + cls = mkClassType("org.example.Foo"), + ) + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals( + """{"_":"ObjectType","cls":{"_":"ClassType","signature":{"name":"org.example.Foo"}}}""", + serialized + ) + + val deserialized: TypeFactDto = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } + + @Test + fun `polymorphic ObjectTypeFact with class and some properties`() { + val fact: TypeFactDto = TypeFactDto.ObjectTypeFact( + cls = mkClassType("org.example.Foo"), + properties = mapOf( + "x" to TypeFactDto.NumberTypeFact, + "bar" to TypeFactDto.ObjectTypeFact( + cls = mkClassType("org.example.Bar"), + ), + ), + ) + println(fact) + + val serialized = Json.encodeToString(fact) + println(serialized) + assertEquals( + """{"_":"ObjectType","cls":{"_":"ClassType","signature":{"name":"org.example.Foo"}},"properties":{"x":{"_":"NumberType"},"bar":{"_":"ObjectType","cls":{"_":"ClassType","signature":{"name":"org.example.Bar"}}}}}""", + serialized + ) + + val deserialized: TypeFactDto = Json.decodeFromString(serialized) + println(deserialized) + assertEquals(fact, deserialized) + } +} + +// TODO: empty file signature +private fun mkClassType(className: String) = ClassTypeDto(ClassSignatureDto(className, FileSignatureDto("", ""))) diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/ExpectedTypesExtractor.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/ExpectedTypesExtractor.kt new file mode 100644 index 0000000000..b18fcd7e0c --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/ExpectedTypesExtractor.kt @@ -0,0 +1,377 @@ +package org.usvm.dataflow.ts.test.utils + +import org.jacodb.ets.base.DEFAULT_ARK_CLASS_NAME +import org.jacodb.ets.base.EtsAnyType +import org.jacodb.ets.base.EtsArrayType +import org.jacodb.ets.base.EtsBooleanType +import org.jacodb.ets.base.EtsClassType +import org.jacodb.ets.base.EtsFunctionType +import org.jacodb.ets.base.EtsNullType +import org.jacodb.ets.base.EtsNumberType +import org.jacodb.ets.base.EtsStringType +import org.jacodb.ets.base.EtsType +import org.jacodb.ets.base.EtsUnclearRefType +import org.jacodb.ets.base.EtsUndefinedType +import org.jacodb.ets.base.EtsUnknownType +import org.jacodb.ets.graph.EtsApplicationGraph +import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene +import org.usvm.dataflow.ts.infer.AccessPathBase +import org.usvm.dataflow.ts.infer.EtsTypeFact +import org.usvm.dataflow.ts.util.MethodTypesFacts +import java.io.File + +private val logger = mu.KotlinLogging.logger {} + +class ExpectedTypesExtractor(private val graph: EtsApplicationGraph) { + fun extractTypes(method: EtsMethod): MethodTypes { + val returnType = method.returnType + val argumentsTypes = method.parameters.map { it.type } + val thisType = getEtsClassType(method, graph) + + return MethodTypes(thisType, argumentsTypes, returnType) + } + +} + +private fun getEtsClassType(method: EtsMethod, graph: EtsApplicationGraph) = + if (method.enclosingClass.name == DEFAULT_ARK_CLASS_NAME || method.enclosingClass.name.isBlank()) { + null + } else { + val clazz = graph.cp + .projectAndSdkClasses + // .filterNot { it.name.startsWith(ANONYMOUS_CLASS_PREFIX) } + // TODO different representation in abc and ast, replace with signatures + // .singleOrNull { it.name == method.enclosingClass.name } + // ?: error("TODO") + .firstOrNull { it.name == method.enclosingClass.name } + ?: error("") /*return MethodTypes(null, argumentsTypes, returnType)*/ + + EtsClassType(clazz.signature) + } + +class ClassMatcherStatistics { + private val overallTypes: Long + get() = overallThisTypes + overallArgsTypes + overallReturnTypes + private val matched: Long + get() = exactlyMatchedThisTypes + exactlyMatchedArgsTypes + exactlyMatchedReturnTypes + private val someFactsFound: Long + get() = someFactsAboutThisTypes + someFactsAboutArgsTypes + someFactsAboutReturnTypes + returnIsAnyType + argIsAnyType + + private var failedMethods: MutableList = mutableListOf() + + private var overallThisTypes: Long = 0L + private var exactlyMatchedThisTypes: Long = 0L + private var someFactsAboutThisTypes: Long = 0L + + private var overallArgsTypes: Long = 0L + private var exactlyMatchedArgsTypes: Long = 0L + private var someFactsAboutArgsTypes: Long = 0L + private var argIsAnyType: Long = 0L + + private var overallReturnTypes: Long = 0L + private var exactlyMatchedReturnTypes: Long = 0L + private var someFactsAboutReturnTypes: Long = 0L + private var returnIsAnyType: Long = 0L + + private val methodToTypes: MutableMap>> = + hashMapOf() + private val methodToReturnTypes: MutableMap> = hashMapOf() + + private fun EtsMethod.saveComparisonInfo( + position: AccessPathBase, + type: EtsType, + fact: EtsTypeFact?, + ) { + val methodTypes = methodToTypes.getOrPut(this) { hashMapOf() } + check(position !in methodTypes) + methodTypes[position] = type to fact + } + + fun calculateStats( + methodResults: MethodTypesFacts, + types: MethodTypes?, + scene: EtsScene, + astMethod: EtsMethod, + abcMethod: EtsMethod, + astGraph: EtsApplicationGraph, + abcGraph: EtsApplicationGraph, + ) { + methodResults.apply { + if (combinedThisFact == null && argumentsFacts.all { it == null } && returnFact == null && localFacts.isEmpty()) { + saveAbsentResult(astMethod) + return + } + } + + compareTypesWithExpected( + methodResults, + requireNotNull(types), + scene, + astMethod + ) + + } + + private fun compareTypesWithExpected( + facts: MethodTypesFacts, + types: MethodTypes, + scene: EtsScene, + method: EtsMethod, + ) { + // 'this' type + types.thisType?.let { + overallThisTypes++ + + method.saveComparisonInfo(AccessPathBase.This, it, facts.combinedThisFact) + + val thisFact = facts.combinedThisFact ?: return@let + if (thisFact.matchesWith(it, strictMode = false)) { + exactlyMatchedThisTypes++ + } else { + someFactsAboutThisTypes++ + } + } + + // args + types.argumentsTypes.forEachIndexed { index, type -> + overallArgsTypes++ + + val fact = facts.argumentsFacts.getOrNull(index) + + + method.saveComparisonInfo(AccessPathBase.Arg(index), type, fact) + + if (fact is EtsTypeFact.AnyEtsTypeFact) { + argIsAnyType++ + return@forEachIndexed + } + + if (fact == null) return@forEachIndexed + + if (fact.matchesWith(type, strictMode = false)) { + exactlyMatchedArgsTypes++ + } else { + someFactsAboutArgsTypes++ + } + } + + // return type + val inferredReturnType = facts.returnFact ?: EtsTypeFact.AnyEtsTypeFact + + overallReturnTypes++ + methodToReturnTypes[method] = method.returnType to inferredReturnType + + if (inferredReturnType is EtsTypeFact.AnyEtsTypeFact) { + returnIsAnyType++ + return + } + + if (inferredReturnType.matchesWith(types.returnType, strictMode = false)) { + exactlyMatchedReturnTypes++ + } else if (inferredReturnType.partialMatchedBy(types.returnType)) { + someFactsAboutReturnTypes++ + } + } + + fun saveAbsentResult(method: EtsMethod) { + failedMethods += method + } + + override fun toString(): String = """ + Total types number: $overallTypes + Exactly matched: $matched + Partially matched: $someFactsFound + Not found: ${overallTypes - matched - someFactsFound} + + Specifically: + + This types total: $overallThisTypes + Exactly matched this types: $exactlyMatchedThisTypes + Partially matched this types: $someFactsAboutThisTypes + Not found: ${overallThisTypes - exactlyMatchedThisTypes - someFactsAboutThisTypes} + + Args types total: $overallArgsTypes + Exactly matched args types: $exactlyMatchedArgsTypes + Partially matched args types: $someFactsAboutArgsTypes + Any type as arg: $argIsAnyType + Not found: ${overallArgsTypes - exactlyMatchedArgsTypes - someFactsAboutArgsTypes - argIsAnyType} + + Return types total: $overallReturnTypes + Exactly matched return types: $exactlyMatchedReturnTypes + Partially matched return types: $someFactsAboutReturnTypes + Any type is returned: $returnIsAnyType + Not found: ${overallReturnTypes - exactlyMatchedReturnTypes - someFactsAboutReturnTypes - returnIsAnyType} + + Didn't find any types for ${failedMethods.size} methods + """.trimIndent() + + fun dumpStatistics(outputFilePath: String? = null) { + val data = buildString { + appendLine(this@ClassMatcherStatistics.toString()) + appendLine() + + appendLine("Specifically: ${"=".repeat(42)}") + + val comparator = + Comparator>> { fst, snd -> + when (fst.key) { + is AccessPathBase.This -> when { + snd.key is AccessPathBase.This -> 0 + else -> -1 + } + + is AccessPathBase.Arg -> when (snd.key) { + is AccessPathBase.This -> 1 + is AccessPathBase.Arg -> { + (fst.key as AccessPathBase.Arg).index.compareTo((snd.key as AccessPathBase.Arg).index) + } + + else -> -1 + } + + else -> when (snd.key) { + is AccessPathBase.This, is AccessPathBase.Arg -> 1 + else -> 0 + } + } + } + + methodToTypes.forEach { (method, types) -> + appendLine("${method.signature}:") + + types + .entries + .sortedWith(comparator) + .forEach { (path, typeInfo) -> + appendLine("${path}: ${typeInfo.first} -> ${typeInfo.second}") + } + appendLine() + } + + appendLine() + appendLine("=".repeat(42)) + appendLine("Failed methods:") + failedMethods.forEach { + appendLine(it) + } + } + + if (outputFilePath == null) { + println(data) + return + } + + val file = File(outputFilePath) + println("File with statistics is located: ${file.absolutePath}") + file.writeText(data) + } +} + +data class MethodTypes( + val thisType: EtsType?, + val argumentsTypes: List, + val returnType: EtsType, +) { + fun matchesWithTypeFacts(other: MethodTypesFacts, ignoreReturnType: Boolean, scene: EtsScene): Boolean { + if (thisType == null && other.combinedThisFact != null) return false + + if (thisType != null && other.combinedThisFact != null) { + if (!other.combinedThisFact.matchesWith(thisType, strictMode = false)) return false + } + + for ((i, fact) in other.argumentsFacts.withIndex()) { + if (!fact.matchesWith(argumentsTypes[i], strictMode = false)) return false + } + + if (ignoreReturnType) return true + + return other.returnFact.matchesWith(returnType, strictMode = false) + } +} + +private fun EtsTypeFact?.matchesWith(type: EtsType, strictMode: Boolean): Boolean { + val result = when (this) { + null, EtsTypeFact.AnyEtsTypeFact -> { + // TODO any other combination? + type is EtsAnyType || (!strictMode && type is EtsUnknownType) + } + + is EtsTypeFact.ObjectEtsTypeFact -> { + // TODO it should be replaced with signatures + val typeName = this.cls?.typeName + + if ((type is EtsUnknownType || type is EtsAnyType) && !strictMode) { + this.cls != null + } else { + (type is EtsClassType || type is EtsUnclearRefType) && type.typeName == typeName + } + } + + is EtsTypeFact.ArrayEtsTypeFact -> when (type) { + is EtsArrayType -> this.elementType.matchesWith(type.elementType, strictMode) + + is EtsUnclearRefType -> { + val elementType = this.elementType as? EtsTypeFact.ObjectEtsTypeFact + elementType?.cls?.typeName == type.typeName + } + + else -> false + } + + EtsTypeFact.BooleanEtsTypeFact -> { + type is EtsBooleanType + || (type is EtsUnknownType && !strictMode) + || (type as? EtsClassType)?.typeName == "Boolean" + || (type as? EtsUnclearRefType)?.typeName == "Boolean" + } + + EtsTypeFact.FunctionEtsTypeFact -> type is EtsFunctionType || (type is EtsUnknownType && !strictMode) + EtsTypeFact.NullEtsTypeFact -> type is EtsNullType || (type is EtsUnknownType && !strictMode) + EtsTypeFact.NumberEtsTypeFact -> { + type is EtsNumberType + || (type is EtsUnknownType && !strictMode) + || (type as? EtsClassType)?.typeName == "Number" + || (type as? EtsUnclearRefType)?.typeName == "Number" + } + + EtsTypeFact.StringEtsTypeFact -> { + type is EtsStringType + || (type is EtsUnknownType && !strictMode) + || (type as? EtsClassType)?.typeName == "String" + || (type as? EtsUnclearRefType)?.typeName == "String" + } + + EtsTypeFact.UndefinedEtsTypeFact -> type is EtsUndefinedType + EtsTypeFact.UnknownEtsTypeFact -> type is EtsUnknownType + is EtsTypeFact.GuardedTypeFact -> TODO() + is EtsTypeFact.IntersectionEtsTypeFact -> { + // TODO intersections checks are not supported yet + false + } + + is EtsTypeFact.UnionEtsTypeFact -> if (strictMode) { + types.all { it.matchesWith(type, strictMode) } + } else { + types.any { it.matchesWith(type, strictMode) } + } + } + + if (!result) { + logger.warn { + """ + Fact: $this + Type: $type + + """.trimIndent() + } + } + + return result +} + +private fun EtsTypeFact.partialMatchedBy(type: EtsType): Boolean { + if (type is EtsUnknownType) return true + logger.warn { "Not implemented partial match for fact $this and type $type" } + return false +} diff --git a/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/TaintConfig.kt b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/TaintConfig.kt new file mode 100644 index 0000000000..8402634d0f --- /dev/null +++ b/usvm-dataflow-ts/src/test/kotlin/org/usvm/dataflow/ts/test/utils/TaintConfig.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.usvm.dataflow.ts.test.utils + +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import org.jacodb.api.common.CommonMethod +import org.jacodb.taint.configuration.NameExactMatcher +import org.jacodb.taint.configuration.NamePatternMatcher +import org.jacodb.taint.configuration.SerializedTaintCleaner +import org.jacodb.taint.configuration.SerializedTaintConfigurationItem +import org.jacodb.taint.configuration.SerializedTaintEntryPointSource +import org.jacodb.taint.configuration.SerializedTaintMethodSink +import org.jacodb.taint.configuration.SerializedTaintMethodSource +import org.jacodb.taint.configuration.SerializedTaintPassThrough +import org.jacodb.taint.configuration.TaintCleaner +import org.jacodb.taint.configuration.TaintConfigurationItem +import org.jacodb.taint.configuration.TaintEntryPointSource +import org.jacodb.taint.configuration.TaintMethodSink +import org.jacodb.taint.configuration.TaintMethodSource +import org.jacodb.taint.configuration.TaintPassThrough +import org.jacodb.taint.configuration.actionModule +import org.jacodb.taint.configuration.conditionModule +import org.usvm.dataflow.ts.getResourceStream + +private val json = Json { + classDiscriminator = "_" + serializersModule = SerializersModule { + include(conditionModule) + include(actionModule) + } +} + +fun loadRules(configFileName: String): List { + val configJson = getResourceStream("/$configFileName").bufferedReader().readText() + val rules: List = json.decodeFromString(configJson) + // println("Loaded ${rules.size} rules from '$configFileName'") + // for (rule in rules) { + // println(rule) + // } + return rules +} + +fun getConfigForMethod( + method: CommonMethod, + rules: List, +): List? { + val res = buildList { + for (item in rules) { + val matcher = item.methodInfo.functionName + if (matcher is NameExactMatcher) { + if (method.name == matcher.name) add(item.toItem(method)) + } else if (matcher is NamePatternMatcher) { + if (method.name.matches(matcher.pattern.toRegex())) add(item.toItem(method)) + } + } + } + return res.ifEmpty { null } +} + +fun SerializedTaintConfigurationItem.toItem(method: CommonMethod): TaintConfigurationItem { + return when (this) { + is SerializedTaintEntryPointSource -> TaintEntryPointSource( + method = method, + condition = condition, + actionsAfter = actionsAfter + ) + + is SerializedTaintMethodSource -> TaintMethodSource( + method = method, + condition = condition, + actionsAfter = actionsAfter + ) + + is SerializedTaintMethodSink -> TaintMethodSink( + method = method, + ruleNote = ruleNote, + cwe = cwe, + condition = condition + ) + + is SerializedTaintPassThrough -> TaintPassThrough( + method = method, + condition = condition, + actionsAfter = actionsAfter + ) + + is SerializedTaintCleaner -> TaintCleaner( + method = method, + condition = condition, + actionsAfter = actionsAfter + ) + } +} diff --git a/usvm-dataflow-ts/src/test/resources/ir/call.ts.json b/usvm-dataflow-ts/src/test/resources/ir/call.ts.json new file mode 100644 index 0000000000..e9298f1c0a --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/call.ts.json @@ -0,0 +1,619 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "call.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "f", + "type": { + "_": "UnknownType" + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + }, + { + "name": "g", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "7", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "g", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + }, + "name": "g", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "call.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/cast.ts.json b/usvm-dataflow-ts/src/test/resources/ir/cast.ts.json new file mode 100644 index 0000000000..82dfb8a294 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/cast.ts.json @@ -0,0 +1,532 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "getData", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 16384, + "decorators": [] + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "getData", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "AnyType" + } + }, + { + "name": "infer", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "getData", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "CastExpr", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "AnyType" + } + }, + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "arg", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "arg", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "arg", + "type": { + "_": "AnyType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "arg", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "arg", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "cast.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/data.ts.json b/usvm-dataflow-ts/src/test/resources/ir/data.ts.json new file mode 100644 index 0000000000..c30667db18 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/data.ts.json @@ -0,0 +1,1038 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "data.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "process", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [ + { + "name": "a", + "type": { + "_": "NumberType" + }, + "isOptional": false + }, + { + "name": "b", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [ + { + "_": "Constant", + "value": "7", + "type": { + "_": "NumberType" + } + }, + { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "process", + "parameters": [ + { + "name": "data", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "process", + "parameters": [ + { + "name": "data", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "AnyType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + }, + { + "signature": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [ + { + "name": "a", + "type": { + "_": "NumberType" + }, + "isOptional": false + }, + { + "name": "b", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "NumberType" + } + }, + { + "name": "b", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "b", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ParameterRef", + "index": 1, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Local", + "name": "a", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Data", + "declaringFile": { + "projectName": "ts", + "fileName": "data.ts" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Local", + "name": "b", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/microphone.ts.json b/usvm-dataflow-ts/src/test/resources/ir/microphone.ts.json new file mode 100644 index 0000000000..9cb9a18ad2 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/microphone.ts.json @@ -0,0 +1,1527 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "getMicrophoneUuid", + "parameters": [ + { + "name": "device", + "type": { + "_": "UnclearReferenceType", + "name": "Devices", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "device", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "device", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "device", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "uuid", + "type": { + "_": "StringType" + } + }, + { + "name": "getMicrophoneUuid", + "type": { + "_": "UnknownType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "getMicrophoneUuid", + "parameters": [ + { + "name": "device", + "type": { + "_": "UnclearReferenceType", + "name": "Devices", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "StringType" + } + }, + "args": [ + { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "uuid", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [ + "Microphone" + ], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + } + }, + "right": { + "_": "Constant", + "value": "virtual_micro_v3", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [ + "Devices" + ], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/microphone_ctor.ts.json b/usvm-dataflow-ts/src/test/resources/ir/microphone_ctor.ts.json new file mode 100644 index 0000000000..e95ddd68b9 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/microphone_ctor.ts.json @@ -0,0 +1,1574 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "getMicrophoneUuid", + "parameters": [ + { + "name": "devices", + "type": { + "_": "UnclearReferenceType", + "name": "Devices", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "uuid", + "type": { + "_": "StringType" + } + }, + { + "name": "getMicrophoneUuid", + "type": { + "_": "UnknownType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "getMicrophoneUuid", + "parameters": [ + { + "name": "devices", + "type": { + "_": "UnclearReferenceType", + "name": "Devices", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "StringType" + } + }, + "args": [ + { + "_": "Local", + "name": "devices", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "uuid", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [ + "Microphone" + ], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "uuid", + "type": { + "_": "StringType" + } + } + }, + "right": { + "_": "Constant", + "value": "virtual_micro_v3", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Devices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [ + "Devices" + ], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "VirtualDevices", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + }, + "name": "microphone", + "type": { + "_": "ClassType", + "signature": { + "name": "Microphone", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "VirtualMicro", + "declaringFile": { + "projectName": "ts", + "fileName": "microphone_ctor.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/nested_init.ts.json b/usvm-dataflow-ts/src/test/resources/ir/nested_init.ts.json new file mode 100644 index 0000000000..42913535b4 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/nested_init.ts.json @@ -0,0 +1,1234 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "cat", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "infer", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "cat", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "cat", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "foo", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "foo", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Foo", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "Cat", + "declaringFile": { + "projectName": "ts", + "fileName": "nested_init.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/resolver_test.ts.json b/usvm-dataflow-ts/src/test/resources/ir/resolver_test.ts.json new file mode 100644 index 0000000000..f43fdcdec7 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/resolver_test.ts.json @@ -0,0 +1,2605 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useNonUniqueField", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "A", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useUniqueFields", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "FieldContainerToInfer", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueA", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useBothA", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "FieldContainerToInfer", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "NumberType" + } + }, + { + "name": "%1", + "type": { + "_": "NumberType" + } + }, + { + "name": "%2", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueA", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%2", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "BinopExpr", + "op": "+", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Local", + "name": "%1", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%2", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useUniqueMethods", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "MethodsContainerToInfer", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueFunction", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useNotUniqueMethod", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "MethodsContainerToInfer", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "notUniqueFunction", + "parameters": [], + "returnType": { + "_": "NumberType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "useFunctionAndField", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "FieldContainerToInfer", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "notUniqueFunction", + "parameters": [], + "returnType": { + "_": "NumberType" + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + }, + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueA", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "13", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueA", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "12", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "notUniqueFunction", + "parameters": [], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Constant", + "value": "21", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "FieldContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "uniqueFunction", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Constant", + "value": "Hi", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "notUniqueFunction", + "parameters": [], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "MethodsContainerToInfer", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "defaultA", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "23", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "resolver_test.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/taint.ts.json b/usvm-dataflow-ts/src/test/resources/ir/taint.ts.json new file mode 100644 index 0000000000..fa9f95a94f --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/taint.ts.json @@ -0,0 +1,1495 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "source", + "parameters": [], + "returnType": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Constant", + "value": "null", + "type": { + "_": "NullType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "pass", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "validate", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 2 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "==", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "null", + "type": { + "_": "NullType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "ReturnStmt", + "arg": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "sink", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 2 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "==", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "null", + "type": { + "_": "NullType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [], + "predecessors": [ + 0, + 2 + ], + "stmts": [ + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 2, + "successors": [ + 1 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + }, + "args": [ + { + "_": "Constant", + "value": "Error!", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ThrowStmt", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "Error", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + } + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "bad", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + { + "name": "source", + "type": { + "_": "UnknownType" + } + }, + { + "name": "pass", + "type": { + "_": "UnknownType" + } + }, + { + "name": "sink", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "source", + "parameters": [], + "returnType": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "pass", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "sink", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "good", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + { + "name": "source", + "type": { + "_": "UnknownType" + } + }, + { + "name": "validate", + "type": { + "_": "UnknownType" + } + }, + { + "name": "sink", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "source", + "parameters": [], + "returnType": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "validate", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "taint.ts" + }, + "declaringNamespace": null + }, + "name": "sink", + "parameters": [ + { + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "data", + "type": { + "_": "UnionType", + "types": [ + { + "_": "NumberType" + }, + { + "_": "NullType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/testcases.ts.json b/usvm-dataflow-ts/src/test/resources/ir/testcases.ts.json new file mode 100644 index 0000000000..d3fb02eea0 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/testcases.ts.json @@ -0,0 +1,26440 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + }, + { + "name": "y", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "52", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: any }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnknownType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "AnyType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "UnknownType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: any }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToLocal3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: any }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignFieldToSelf", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: any }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignSelfToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "y", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "100", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: number }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalNumberToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: Object { t: number } }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalObjectToField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Constant", + "value": "2", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: Object { f: number } }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseNestedDuplicateFields", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "NumberType" + }, + "size": { + "_": "Constant", + "value": "3", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "2", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "2", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "3", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Array", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayToLocal", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "NumberType" + }, + "size": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "33", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Array", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "NumberType" + }, + "size": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "22", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Array", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "y", + "type": { + "_": "ArrayType", + "elementType": { + "_": "NumberType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "any", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignArgumentArrayElementToLocal2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + { + "name": "y", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "100", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Array", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalToArrayElementNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + }, + { + "signature": { + "declaringClass": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "CastExpr", + "arg": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "type": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "ICustom { }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseCastToInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "AnyType" + } + }, + { + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "right": { + "_": "CastExpr", + "arg": { + "_": "Local", + "name": "y", + "type": { + "_": "AnyType" + } + }, + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "ICustom", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Array", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseCastToArrayInterface", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "93", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "94", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnArgumentNumber", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: number }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_RETURN", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: number }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseReturnArgumentObject", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "15", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "ClassType", + "signature": { + "name": "MyType", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "MyType { f: number }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseNew", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "str", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "kek", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "StringType" + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "str", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "string", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "StringType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "StringType" + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "y", + "type": { + "_": "StringType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "any", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + { + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 3 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "undefined", + "type": { + "_": "UndefinedType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "random", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": ">", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "Constant", + "value": "0.5", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 1, + 3 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 3, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "str", + "type": { + "_": "StringType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number | string", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + { + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 3 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "random", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": ">", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "Constant", + "value": "0.5", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 1, + 3 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 3, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "str", + "type": { + "_": "StringType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number | string", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseArgumentUnion3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + { + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 2 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "str", + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "Math", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "random", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": ">", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "Constant", + "value": "0.5", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [], + "predecessors": [ + 0, + 2 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 2, + "successors": [ + 1 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "StringType" + }, + { + "_": "NumberType" + } + ] + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "number | string", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseUnion4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "y", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "y", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "g", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "AnyType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: Object { g: number } }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAliasChain1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "g", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Constant", + "value": "100", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: Object { g: number } }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "x", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "y", + "type": { + "_": "NumberType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "98", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "g", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Object { f: Object { g: number } }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseAssignLocalNumberToNestedField", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "AnyType" + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "i", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2, + 3 + ], + "predecessors": [ + 0, + 3 + ], + "stmts": [ + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "<", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "10", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 3, + "successors": [ + 1 + ], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "Local", + "name": "x", + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "BinopExpr", + "op": "+", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "any", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "y", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "y", + "type": { + "_": "NumberType" + } + }, + { + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + { + "name": "i", + "type": { + "_": "NumberType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "AnyType" + }, + "size": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2, + 5 + ], + "predecessors": [ + 0, + 5 + ], + "stmts": [ + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "<", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Local", + "name": "y", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 2, + "successors": [ + 3, + 4 + ], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "length", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "==", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 3, + "successors": [], + "predecessors": [ + 2, + 4 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 4, + "successors": [ + 3 + ], + "predecessors": [ + 2 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "push", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + ] + } + } + ] + }, + { + "id": 5, + "successors": [ + 1 + ], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "push", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "BinopExpr", + "op": "+", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseFindAssignmentAfterLoop", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "AnyType" + }, + "size": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "AnyType" + }, + "dimensions": 1 + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "getChildren", + "parameters": [], + "returnType": { + "_": "ArrayType", + "elementType": { + "_": "UnclearReferenceType", + "name": "Tree", + "typeParameters": [] + }, + "dimensions": 1 + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%statInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint", + "parameters": [ + { + "name": "root", + "type": { + "_": "UnclearReferenceType", + "name": "Tree", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "root", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "root", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "right": { + "_": "NewArrayExpr", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "size": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "index": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "Local", + "name": "root", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "traverse", + "parameters": [ + { + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%0", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "root", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "traverse", + "parameters": [ + { + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + { + "name": "i", + "type": { + "_": "NumberType" + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + { + "name": "child", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2, + 3 + ], + "predecessors": [ + 0, + 3 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "length", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "<", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 3, + "successors": [ + 1 + ], + "predecessors": [ + 1 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "child", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ArrayRef", + "array": { + "_": "Local", + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "index": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + }, + "right": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "child", + "type": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "getChildren", + "parameters": [], + "returnType": { + "_": "ArrayType", + "elementType": { + "_": "UnclearReferenceType", + "name": "Tree", + "typeParameters": [] + }, + "dimensions": 1 + } + }, + "args": [] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "traverse", + "parameters": [ + { + "name": "xs", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "children", + "type": { + "_": "ArrayType", + "elementType": { + "_": "ClassType", + "signature": { + "name": "Tree", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + }, + "dimensions": 1 + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "BinopExpr", + "op": "+", + "left": { + "_": "Local", + "name": "i", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "Constant", + "value": "1", + "type": { + "_": "NumberType" + } + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "infer", + "parameters": [ + { + "name": "a", + "type": { + "_": "AnyType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "a", + "type": { + "_": "AnyType" + } + }, + { + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "a", + "type": { + "_": "AnyType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "AnyType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "EXPECTED_ARG_0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "Constant", + "value": "Tree { children: Array }", + "type": { + "_": "StringType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "CaseRecursion", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "42", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToLocal2$entrypoint$0", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "a", + "type": { + "_": "UnknownType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignFieldToSelf$entrypoint$1", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "UnknownType" + } + } + }, + "right": { + "_": "Local", + "name": "a", + "type": { + "_": "UnknownType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignSelfToField$entrypoint$2", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "t", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "t", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "32", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseAssignLocalObjectToField$entrypoint$3", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "95", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseReturnObject$infer$4", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "f", + "type": { + "_": "NumberType" + } + } + }, + "right": { + "_": "Constant", + "value": "96", + "type": { + "_": "NumberType" + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseReturnArgumentObject$entrypoint$5", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$CaseLoop$entrypoint$6", + "declaringFile": { + "projectName": "ts", + "fileName": "testcases.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ir/types.ts.json b/usvm-dataflow-ts/src/test/resources/ir/types.ts.json new file mode 100644 index 0000000000..47adeabab4 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ir/types.ts.json @@ -0,0 +1,2691 @@ +{ + "signature": { + "projectName": "ts", + "fileName": "types.ts" + }, + "namespaces": [], + "classes": [ + { + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "%dflt", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "conditional", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "A", + "typeParameters": [] + }, + "isOptional": false + }, + { + "name": "cond", + "type": { + "_": "BooleanType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "cond", + "type": { + "_": "BooleanType" + } + }, + { + "name": "%0", + "type": { + "_": "StringType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%2", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%3", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 2 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "cond", + "type": { + "_": "BooleanType" + } + }, + "right": { + "_": "ParameterRef", + "index": 1, + "type": { + "_": "BooleanType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "!=", + "left": { + "_": "Local", + "name": "cond", + "type": { + "_": "BooleanType" + } + }, + "right": { + "_": "Constant", + "value": "false", + "type": { + "_": "BooleanType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%2", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "bObj", + "type": { + "_": "ClassType", + "signature": { + "name": "B", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%3", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%2", + "type": { + "_": "UnknownType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "bNum", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%3", + "type": { + "_": "UnknownType" + } + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "field": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "aStr", + "type": { + "_": "StringType" + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "StringType" + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "length", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "ReturnStmt", + "arg": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint1", + "parameters": [ + { + "name": "arg", + "type": { + "_": "UnclearReferenceType", + "name": "A", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "arg", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "conditional", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "NumberType" + } + }, + { + "name": "console", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "arg", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "conditional", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "A", + "typeParameters": [] + }, + "isOptional": false + }, + { + "name": "cond", + "type": { + "_": "BooleanType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "NumberType" + } + }, + "args": [ + { + "_": "Local", + "name": "arg", + "type": { + "_": "ClassType", + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "_": "Constant", + "value": "false", + "type": { + "_": "BooleanType" + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "console", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "log", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%0", + "type": { + "_": "NumberType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "foo", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + { + "name": "strBar", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + { + "name": "numberBar", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [ + 1, + 3 + ], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "IfStmt", + "condition": { + "_": "ConditionExpr", + "op": "!=", + "left": { + "_": "Constant", + "value": "undefined", + "type": { + "_": "UndefinedType" + } + }, + "right": { + "_": "Constant", + "value": "0", + "type": { + "_": "NumberType" + } + }, + "type": { + "_": "BooleanType" + } + } + } + ] + }, + { + "id": 1, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "numberBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + } + ] + } + } + ] + }, + { + "id": 2, + "successors": [], + "predecessors": [ + 1, + 3 + ], + "stmts": [ + { + "_": "ReturnVoidStmt" + } + ] + }, + { + "id": 3, + "successors": [ + 2 + ], + "predecessors": [ + 0 + ], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "strBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "StringType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ] + } + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "baz", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + } + }, + { + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + { + "name": "strBar", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + { + "name": "numberBar", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "strBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "StringType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%0", + "type": { + "_": "UnknownType" + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "InstanceFieldRef", + "instance": { + "_": "Local", + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + } + }, + "field": { + "declaringClass": { + "name": "", + "declaringFile": { + "projectName": "%unk", + "fileName": "%unk" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "UnknownType" + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "numberBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%1", + "type": { + "_": "UnknownType" + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "strBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "StringType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "StringType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "StringType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "StringType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "numberBar", + "parameters": [ + { + "name": "x", + "type": { + "_": "NumberType" + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "x", + "type": { + "_": "NumberType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "x", + "type": { + "_": "NumberType" + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "NumberType" + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "entrypoint2", + "parameters": [ + { + "name": "arg0", + "type": { + "_": "UnclearReferenceType", + "name": "X", + "typeParameters": [] + }, + "isOptional": false + }, + { + "name": "arg1", + "type": { + "_": "UnclearReferenceType", + "name": "Y", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "arg0", + "type": { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "arg1", + "type": { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "foo", + "type": { + "_": "UnknownType" + } + }, + { + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + { + "name": "baz", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "arg0", + "type": { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 0, + "type": { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "arg1", + "type": { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ParameterRef", + "index": 1, + "type": { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "foo", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "arg0", + "type": { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "foo", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnionType", + "types": [ + { + "_": "ClassType", + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + }, + { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + ] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "arg1", + "type": { + "_": "ClassType", + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "NewExpr", + "classType": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "method": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "args": [] + } + }, + { + "_": "CallStmt", + "expr": { + "_": "StaticCallExpr", + "method": { + "declaringClass": { + "name": "%dflt", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "baz", + "parameters": [ + { + "name": "x", + "type": { + "_": "UnclearReferenceType", + "name": "IntersectionType", + "typeParameters": [] + }, + "isOptional": false + } + ], + "returnType": { + "_": "UnknownType" + } + }, + "args": [ + { + "_": "Local", + "name": "%0", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + ] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + }, + { + "signature": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "aStr", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + }, + { + "signature": { + "declaringClass": { + "name": "A", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "bObj", + "type": { + "_": "ClassType", + "signature": { + "name": "B", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "B", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "B", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "bNum", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "X", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "a", + "type": { + "_": "StringType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "Y", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "b", + "type": { + "_": "NumberType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [] + }, + { + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "modifiers": 0, + "decorators": [], + "superClassName": "", + "implementedInterfaceNames": [], + "fields": [ + { + "signature": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "...arg0", + "type": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + }, + { + "signature": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "...arg1", + "type": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "questionToken": false, + "exclamationToken": false + } + ], + "methods": [ + { + "signature": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + }, + { + "signature": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "constructor", + "parameters": [], + "returnType": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + }, + "modifiers": 0, + "decorators": [], + "body": { + "locals": [ + { + "name": "this", + "type": { + "_": "UnknownType" + } + } + ], + "cfg": { + "blocks": [ + { + "id": 0, + "successors": [], + "predecessors": [], + "stmts": [ + { + "_": "AssignStmt", + "left": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "right": { + "_": "ThisRef", + "type": { + "_": "ClassType", + "signature": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + } + } + } + }, + { + "_": "CallStmt", + "expr": { + "_": "InstanceCallExpr", + "instance": { + "_": "Local", + "name": "this", + "type": { + "_": "UnknownType" + } + }, + "method": { + "declaringClass": { + "name": "%AC$%dflt$entrypoint2$0", + "declaringFile": { + "projectName": "ts", + "fileName": "types.ts" + }, + "declaringNamespace": null + }, + "name": "%instInit", + "parameters": [], + "returnType": { + "_": "UnknownType" + } + }, + "args": [] + } + }, + { + "_": "ReturnVoidStmt" + } + ] + } + ] + } + } + } + ] + } + ], + "importInfos": [], + "exportInfos": [] +} \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/logback.xml b/usvm-dataflow-ts/src/test/resources/logback.xml new file mode 100644 index 0000000000..06f188e9dd --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/logback.xml @@ -0,0 +1,25 @@ + + + + %highlight([%level]) %replace(%c{0}){'(\$Companion)?\$logger\$1',''} - %msg%n + + + + + + + ${LOG_DIR}/${LOG_FILE} + + ${LOG_DIR}/${LOG_FILE}_%d{yyyy-MM-dd_HH-mm-ss}.log + 30 + + + [%level] %replace(%c{0}){'(\$Companion)?\$logger\$1',''} - %msg%n + + + + + + + + diff --git a/usvm-dataflow-ts/src/test/resources/ts/call.ts b/usvm-dataflow-ts/src/test/resources/ts/call.ts new file mode 100644 index 0000000000..507c49e9df --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/call.ts @@ -0,0 +1,13 @@ +function entrypoint() { + f(42); + let x= 7 + g(x); +} + +function f(x: any) { + console.log(x); +} + +function g(x: any) { + console.log(x); +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/cast.ts b/usvm-dataflow-ts/src/test/resources/ts/cast.ts new file mode 100644 index 0000000000..53a869a2fd --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/cast.ts @@ -0,0 +1,12 @@ +declare function getData(): any; + +interface Data {} + +function entrypoint() { + let x = getData() as Data; + infer(x); +} + +function infer(arg: any) { + console.log(arg); +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/data.ts b/usvm-dataflow-ts/src/test/resources/ts/data.ts new file mode 100644 index 0000000000..3bbce38da3 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/data.ts @@ -0,0 +1,17 @@ +class Data { + a: number; + b: number; + constructor(a: number, b: number) { + this.a = a; + this.b = b; + } +} + +function entrypoint() { + let data = new Data(7, 42); + process(data); +} + +function process(data: any) { + console.log(data); +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/microphone.ts b/usvm-dataflow-ts/src/test/resources/ts/microphone.ts new file mode 100644 index 0000000000..e436b5f498 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/microphone.ts @@ -0,0 +1,25 @@ +interface Microphone { + uuid: string +} + +class VirtualMicro implements Microphone { + uuid: string = "virtual_micro_v3" +} + +interface Devices { + microphone: Microphone +} + +class VirtualDevices implements Devices { + microphone: Microphone = new VirtualMicro() +} + +function getMicrophoneUuid(device: Devices): string { + return device.microphone.uuid +} + +function entrypoint() { + let devices = new VirtualDevices() + let uuid = getMicrophoneUuid(devices) + console.log(uuid) +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/microphone_ctor.ts b/usvm-dataflow-ts/src/test/resources/ts/microphone_ctor.ts new file mode 100644 index 0000000000..0a5692a4c8 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/microphone_ctor.ts @@ -0,0 +1,33 @@ +interface Microphone { + uuid: string +} + +class VirtualMicro implements Microphone { + uuid: string; + + constructor() { + this.uuid = "virtual_micro_v3" + } +} + +interface Devices { + microphone: Microphone +} + +class VirtualDevices implements Devices { + microphone: Microphone; + + constructor() { + this.microphone = new VirtualMicro(); + } +} + +function getMicrophoneUuid(devices: Devices): string { + return devices.microphone.uuid; +} + +function entrypoint() { + let devices = new VirtualDevices() + let uuid = getMicrophoneUuid(devices) + console.log(uuid) +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/nested_init.ts b/usvm-dataflow-ts/src/test/resources/ts/nested_init.ts new file mode 100644 index 0000000000..beda346630 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/nested_init.ts @@ -0,0 +1,23 @@ +class Foo { +} + +class Cat { + foo: Foo = new Foo(); +} + +// class Cat { +// foo: Foo; +// +// constructor() { +// this.foo = new Foo(); +// } +// } + +function entrypoint() { + let cat = new Cat(); + infer(cat); +} + +function infer(x: any) { + console.log(x); +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/resolver_test.ts b/usvm-dataflow-ts/src/test/resources/ts/resolver_test.ts new file mode 100644 index 0000000000..338e41b26a --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/resolver_test.ts @@ -0,0 +1,50 @@ +class FieldContainerToInfer { + defaultA: number = 13; + uniqueA: number = 12; + + notUniqueFunction(): number { + return 21 + } +} + +class MethodsContainerToInfer { + uniqueFunction() { + console.log("Hi") + } + + notUniqueFunction(): number { + return 42 + } +} + +class A { + defaultA: number = 23 +} + +function useNonUniqueField(x : A) { + return x.defaultA +} + +function useUniqueFields(x : FieldContainerToInfer) { + return x.uniqueA +} + +function useBothA(x : FieldContainerToInfer): number { + return x.uniqueA + x.defaultA +} + +function useUniqueMethods(x : MethodsContainerToInfer) { + x.uniqueFunction() +} + +function useNotUniqueMethod(x : MethodsContainerToInfer) { + x.notUniqueFunction() +} + +function useFunctionAndField(x : FieldContainerToInfer): number { + x.notUniqueFunction() + return x.defaultA +} + + +// TODO examples with another scope of view and anonymous properties \ No newline at end of file diff --git a/usvm-dataflow-ts/src/test/resources/ts/taint.ts b/usvm-dataflow-ts/src/test/resources/ts/taint.ts new file mode 100644 index 0000000000..ea6ee035b7 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/taint.ts @@ -0,0 +1,32 @@ +function source(): number | null { + return null; +} + +function pass(data: number | null): number | null { + return data; +} + +function validate(data: number | null): number { + if (data == null) { + return 0; + } + return data; +} + +function sink(data: number | null) { + if (data == null) { + throw new Error("Error!"); + } +} + +function bad() { + let data = source(); + data = pass(data); + sink(data); +} + +function good() { + let data = source(); + data = validate(data); + sink(data); +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/testcases.ts b/usvm-dataflow-ts/src/test/resources/ts/testcases.ts new file mode 100644 index 0000000000..1731296432 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/testcases.ts @@ -0,0 +1,994 @@ +// Case `x := y` +class CaseAssignLocalToLocal { + entrypoint() { + let x = 52; // x: number + let y = x; // y: number + this.infer(y); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "number"; + } +} + +// ---------------------------------------- + +// Case `x := y.f` +class CaseAssignFieldToLocal1 { + entrypoint(y: any) { + let x = y.f; // y: { f: any } + this.infer(y); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: any }"; + } +} + +// ---------------------------------------- + +// Case `x := y.f` +class CaseAssignFieldToLocal2 { + entrypoint() { + let y = {f: 42}; // y: { f: number } + let x = y.f; // x: number + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "number"; + } +} + +// ---------------------------------------- + +// Case `x := a.f` +class CaseAssignFieldToLocal3 { + entrypoint(y: any) { + this.infer(y); + } + + infer(a: any) { + let x = a.f; // a: { f: any } + const EXPECTED_ARG_0 = "Object { f: any }"; + } +} + +// ---------------------------------------- + +// Case `x := x.f` +class CaseAssignFieldToSelf { + entrypoint(a: any) { + let x = { f: a }; + x = x.f; // x: any + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: any }" + } +} + +// Case `x.f := x` +class CaseAssignSelfToField { + entrypoint(a: any) { + let x = { f: a }; // x: { f: any } + x.f = x; // x: { f: any } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: any }" + } +} + +// ---------------------------------------- + +// Case `x.f := y` +class CaseAssignLocalNumberToField { + entrypoint(x: any) { + let y = 100; // y: number + x.f = y; // x: { f: number } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: number }"; + } +} + +// ---------------------------------------- + +// Case `x.f := y` +class CaseAssignLocalObjectToField { + entrypoint(x: any) { + let y = { t: 32 }; // y: { t: number } + x.f = y; // x: { f: { t: number } } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: Object { t: number } }"; + } +} + +// ---------------------------------------- + +// Case `x.f.f := const` +class CaseNestedDuplicateFields { + entrypoint(x: any) { + x.f.f = 2; // x: { f: { f: number } } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: Object { f: number } }"; + } +} + +// ---------------------------------------- + +// Case `y := [...]` +class CaseAssignArrayToLocal { + entrypoint() { + let y = [1, 2, 3]; // y: Array + this.infer(y); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Array"; + } +} + +// ---------------------------------------- + +// Case `x := y[i]` +class CaseAssignArrayElementToLocal1 { + entrypoint() { + let y = [33]; // y: Array + let x = y[0]; // y: Array + this.infer(y); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Array"; + } +} + +// ---------------------------------------- + +// Case `x := y[i]` +class CaseAssignArrayElementToLocal2 { + entrypoint() { + let y = [22]; // y: Array + let x = y[0]; // x: number + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "number"; + } +} + +// ---------------------------------------- + +// Case `x := y[i]` +class CaseAssignArgumentArrayElementToLocal1 { + entrypoint(y: number[]) { + let x = y[0]; // y: Array + this.infer(y); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Array"; + } +} + +// ---------------------------------------- + +// Case `x := y[i]` +class CaseAssignArgumentArrayElementToLocal2 { + entrypoint(y: number[]) { + let x = y[0]; // x: any + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "any"; + } +} + +// ---------------------------------------- + +// Case `x[i] := y` +class CaseAssignLocalToArrayElementNumber { + entrypoint(x: any[]) { + let y = 100; // y: number + x[0] = y; // x: Array + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Array"; + } +} + +// ---------------------------------------- + +interface ICustom { + a: number; + b: string; +} + +// Case `x := y as T` +class CaseCastToInterface { + entrypoint(y: any) { + let x = y as ICustom; // x: ICustom + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "ICustom { }"; + } +} + +// ---------------------------------------- + +// Case `x := y as T[]` +class CaseCastToArrayInterface { + entrypoint(y: any) { + let x = y as ICustom[]; // x: Array + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Array"; + } +} + +// // ---------------------------------------- +// +// // Case `x := y + z` +// class CaseAddNumbers { +// entrypoint() { +// let y = 5; // y: number +// let z = 10; // z: number +// let x = y + z; // x: number +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := y && z` +// class CaseLogicalAndBooleans { +// entrypoint() { +// let y = true; // y: boolean +// let z = false; // z: boolean +// let x = y && z; // x: boolean +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "boolean"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := y || z` +// class CaseLogicalOrBooleanAndString { +// entrypoint() { +// let y = false; // y: boolean +// let z = "default"; // z: string +// let x = y || z; // x: string +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "boolean | string"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := y + z` +// class CaseAddStrings { +// entrypoint() { +// let y = "Hello, "; // y: string +// let z = "World!"; // z: string +// let x = y + z; // x: string +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "string"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number + string` +// class CaseAddNumberToString { +// entrypoint() { +// let y = 12; // y: number +// let z = " is the answer"; // z: string +// let x = y + z; // x: string +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "string"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := string + number` +// class CaseAddStringToNumber { +// entrypoint() { +// let y = "The answer is "; // y: string +// let z = 13; // z: number +// let x = y + z; // x: string +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "string"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := string - number` +// class CaseSubtractNumberFromString { +// entrypoint() { +// let y = "73"; // y: string +// let z = 10; // z: number +// let x = y - z; // x: number (63) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number - string` +// class CaseSubtractStringFromNumber { +// entrypoint() { +// let y = 96; // y: number +// let z = "51"; // z: string +// let x = y - z; // x: number (45) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := string * number` +// class CaseMultiplyStringByNumber { +// entrypoint() { +// let y = "100"; // y: string +// let z = 30; // z: number +// let x = y * z; // x: number (3000) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number * string` +// class CaseMultiplyNumberByString { +// entrypoint() { +// let y = 40; // y: number +// let z = "500"; // z: string +// let x = y * z; // x: number (20000) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := boolean + number` +// class CaseAddBooleanToNumber { +// entrypoint() { +// let y = true; // y: boolean +// let z = 1; // z: number +// let x = y + z; // x: number (2, as true is coerced to 1) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number + boolean` +// class CaseAddNumberToBoolean { +// entrypoint() { +// let y = 1; // y: number +// let z = false; // z: boolean +// let x = y + z; // x: number (1, as false is coerced to 0) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := null + number` +// class CaseAddNullToNumber { +// entrypoint() { +// let y = null; // y: null +// let z = 105; // z: number +// let x = y + z; // x: number (10, as null is coerced to 0) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number + null` +// class CaseAddNumberToNull { +// entrypoint() { +// let y = 115; // y: number +// let z = null; // z: null +// let x = y + z; // x: number (10, as null is coerced to 0) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := undefined + number` +// class CaseAddUndefinedToNumber { +// entrypoint() { +// let y = undefined; // y: undefined +// let z = 125; // z: number +// let x = y + z; // x: number (NaN) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number + undefined` +// class CaseAddNumberToUndefined { +// entrypoint() { +// let y = 135; // y: number +// let z = undefined; // z: undefined +// let x = y + z; // x: number (NaN) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := string / number` +// class CaseDivideStringByNumber { +// entrypoint() { +// let y = "185"; // y: string +// let z = 5; // z: number +// let x = y / z; // x: number (37) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// // ---------------------------------------- +// +// // Case `x := number / string` +// class CaseDivideNumberByString { +// entrypoint() { +// let y = 195; // y: number +// let z = "5"; // z: string +// let x = y / z; // x: number (39) +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "number"; +// } +// } +// +// ---------------------------------------- + +// Case `return x` +class CaseReturnNumber { + entrypoint() { + this.infer(); + } + + infer(): any { + const EXPECTED_RETURN = "number"; + let x = 93; // x: number + return x; + } +} + +// ---------------------------------------- + + // Case `return arg` + class CaseReturnArgumentNumber { + entrypoint() { + let x = 94; // x: number + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_RETURN = "number"; + return a; + } + } + +// ---------------------------------------- + +// Case `return obj` +class CaseReturnObject { + entrypoint() { + this.infer(); + } + + infer(): any { + const EXPECTED_RETURN = "Object { f: number }"; + let x = { f: 95 }; // x: Object { f: number } + return x; + } +} + +// ---------------------------------------- + +// Case `return obj` +class CaseReturnArgumentObject { + entrypoint() { + let x = { f: 96 }; // x: Object { f: number } + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_RETURN = "Object { f: number }"; + return a; + } +} + +// ---------------------------------------- + +// // Case `x.f[0].g := y` +// class CaseAssignToNestedObjectField { +// entrypoint(x: any) { +// let y = 134; // y: number +// x.f[0].g = y; // x: { f: Array<{ g: number }> } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Array }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f.g.h := y` +// class CaseAssignDeeplyNestedField { +// entrypoint(x: any) { +// let y = "abc"; // y: string +// x.f.g.h = y; // x: { f: { g: { h: string } } } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Object { g: Object { h: string } } }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f[i].g.h := y` +// class CaseAssignToArrayObjectField { +// entrypoint(x: any) { +// let y = false; // y: boolean +// x.f[2].g.h = y; // x: { f: Array<{ g: { h: boolean } }> } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Array }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x[i].f.g := y` +// class CaseAssignArrayFieldToNestedObject { +// entrypoint(x: any) { +// let y = 219; // y: number +// x[0].f.g = y; // x: Array<{ f: { g: number } }> +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Array<{ f: Object { g: number } }>" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f[i][j] := y` +// class CaseAssignToMultiDimensionalArray { +// entrypoint(x: any) { +// let y = "data"; // y: string +// x.f[1][2] = y; // x: { f: Array> } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Array> }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f[0].g[1].h := y` +// class CaseAssignToComplexNestedArrayField { +// entrypoint(x: any) { +// let y = true; // y: boolean +// x.f[0].g[1].h = y; // x: { f: Array<{ g: Array<{ h: boolean }> }> } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Array }> }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f.g.h[i] := y` +// class CaseAssignToArrayInNestedObject { +// entrypoint(x: any) { +// let y = 3.14; // y: number +// x.f.g.h[2] = y; // x: { f: { g: { h: Array } } } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Object { g: Object { h: Array } } }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f[0].g.h[i] := y` +// class CaseAssignToArrayInDeeplyNestedObject { +// entrypoint(x: any) { +// let y = null; // y: null +// x.f[0].g.h[3] = y; // x: { f: Array<{ g: { h: Array } }> } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Array } }> }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f.g[i].h.j := y` +// class CaseAssignToDeeplyNestedObjectArray { +// entrypoint(x: any) { +// let y = "nested"; // y: string +// x.f.g[1].h.j = y; // x: { f: { g: Array<{ h: { j: string } }> } } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Object { g: Array } }" +// } +// } +// +// // ---------------------------------------- +// +// // Case `x.f.g.h[0][i] := y` +// class CaseAssignToMultiDimensionalArrayField { +// entrypoint(x: any) { +// let y = 99; // y: number +// x.f.g.h[0][1] = y; // x: { f: { g: { h: Array> } } } +// this.infer(x); +// } +// +// infer(a: any) { +// const EXPECTED_ARG_0 = "Object { f: Object { g: { h: Array> } } }" +// } +// } + +// ---------------------------------------- + +class MyType { + f: number = 15; +} + +// Case `x := new T()` +class CaseNew { + entrypoint() { + let y = new MyType(); // y: MyType + // hidden: + // y := new MyType() + // -> y.constructor() + // -> this.() + // -> this.f := 15 + // -> this: { f: number } + // -> y: { f.number } + this.infer(y); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "MyType { f: number }" + } +} + +// ---------------------------------------- + +// Case `x := number | string` +class CaseUnion { + entrypoint() { + let x: string | number = "str"; // x: string + x = 42; // x: number + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "number"; + } +} + +// Case `x := number | string` +class CaseArgumentUnion { + entrypoint(x: string | number) { + x = "kek"; + x = 42; + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "number"; + } +} + +// Case `x := y` +class CaseUnion2 { + entrypoint() { + let y = "str"; + let x: string | number = y; + x = 42; + this.infer(y); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "string"; + } +} + +// Case `x := y` +class CaseArgumentUnion2 { + entrypoint(y: string) { + let x: string | number = y; + x = 42; + this.infer(y); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "any"; + } +} + +// Case `x := "string" | number` +class CaseUnion3 { + entrypoint() { + let x: string | number; + if (Math.random() > 0.5) { + x = "str"; + } else { + x = 42; + } + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "number | string"; + } +} + +// Case `x := "string" | number` +class CaseArgumentUnion3 { + entrypoint(x: string | number) { + if (Math.random() > 0.5) { + x = "str"; + } else { + x = 42; + } + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "number | string"; + } +} + +// Case `x := "string", x := number` +class CaseUnion4 { + entrypoint() { + let x: string | number = "str"; + if (Math.random() > 0.5) { + x = 42; + } + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "number | string"; + } +} + +// Case `x := "string", x := number` +// class CaseUnion5 { +// entrypoint() { +// let x: string | number; +// if (Math.random() > 0.5) { +// x = 42; +// } +// this.infer(x); +// } +// +// infer(a: any): any { +// // Currently, `number | undefined` is inferred due to the lack of DeclareStmt +// const EXPECTED_ARG_0 = "number | string"; +// } +// } + +// ---------------------------------------- + +// Case `y := x.f.g` +class CaseAliasChain1 { + entrypoint(x: any) { + let y = x.f; // x: { f: any } + y.g = 42; // x: { f: { g: number } } + this.infer(x); + } + + infer(a: any): any { + const EXPECTED_ARG_0 = "Object { f: Object { g: number } }" + } +} + +// Case `x.f.g := number` +class CaseAssignNumberToNestedField { + entrypoint(x: any) { + x.f.g = 100; // x: { f: { g: number } } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: Object { g: number } }"; + } +} + +// Case `x.f := (y: number)` +class CaseAssignLocalNumberToNestedField { + entrypoint(x: any) { + let y = 98; // y: number + x.f.g = y; // x: { f: { g: number } } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Object { f: Object { g: number } }"; + } +} + +// ---------------------------------------- + +class CaseLoop { + entrypoint() { + let x: any = {}; + let a: any = 42; + for (let i = 0; i < 10; i++) { + x.f = a; + a = x; + } + this.infer(x); + } + + infer(a: any) { + const EXPECTED_ARG_0 = "any"; + } +} + +class CaseFindAssignmentAfterLoop { + entrypoint(y: number) { + let x = []; + for (let i = 0; i < y; i++) { + x.push(i); + } + if (x.length == 0) { + x.push(42); + } + + this.infer(x) + } + + infer(a: any) { + // + } +} + +// ---------------------------------------- + +class Tree { + children: Tree[] = []; + + getChildren(): Tree[] { + return this.children; + } +} + +class CaseRecursion { + entrypoint(root: Tree) { + this.traverse([root]); + this.infer(root); + } + + traverse(xs: Tree[]) { + for (let i = 0; i < xs.length; i++) { + let child: Tree = xs[i]; + let children: Tree[] = child.getChildren(); + this.traverse(children); + } + } + + infer(a: any) { + const EXPECTED_ARG_0 = "Tree { children: Array }"; + } +} diff --git a/usvm-dataflow-ts/src/test/resources/ts/types.ts b/usvm-dataflow-ts/src/test/resources/ts/types.ts new file mode 100644 index 0000000000..4e8d90ccb3 --- /dev/null +++ b/usvm-dataflow-ts/src/test/resources/ts/types.ts @@ -0,0 +1,55 @@ +interface A { + aStr: string + bObj: B +} + +interface B { + bNum: number +} + +function conditional(x: A, cond: boolean): number { + if (cond) { + return x.aStr.length + } else { + return x.bObj.bNum + } +} + +function entrypoint1(arg: A) { + console.log(conditional(arg, false)) +} + +interface X { + a: string +} + +interface Y { + b: number +} + +function foo(x: X | Y) { + if ("a" in x) { + strBar(x.a) + } else { + numberBar(x.b) + } +} + +function baz(x: X & Y) { + strBar(x.a) + numberBar(x.b) +} + +function strBar(x: string) { + +} + +function numberBar(x: number) { + +} + +function entrypoint2(arg0: X, arg1: Y) { + foo(arg0) + foo(arg1) + baz({...arg0, ...arg1}) +} diff --git a/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/LoadEts.kt b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/LoadEts.kt new file mode 100644 index 0000000000..d6195a60b1 --- /dev/null +++ b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/LoadEts.kt @@ -0,0 +1,117 @@ +package org.usvm.dataflow.ts + +import mu.KotlinLogging +import org.jacodb.ets.dto.EtsFileDto +import org.jacodb.ets.dto.convertToEtsFile +import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsScene +import java.nio.file.Path +import kotlin.io.path.extension +import kotlin.io.path.inputStream +import kotlin.io.path.relativeTo +import kotlin.io.path.walk + +private val logger = KotlinLogging.logger {} + +/** + * Load an [EtsFileDto] from a resource file. + * + * For example, `resources/ets/sample.json` can be loaded with: + * ``` + * val dto: EtsFileDto = loadEtsFileDtoFromResource("/ets/sample.json") + * ``` + */ +fun loadEtsFileDtoFromResource(jsonPath: String): EtsFileDto { + logger.debug { "Loading EtsIR from resource: '$jsonPath'" } + require(jsonPath.endsWith(".json")) { "File must have a '.json' extension: '$jsonPath'" } + getResourceStream(jsonPath).use { stream -> + return EtsFileDto.loadFromJson(stream) + } +} + +/** + * Load an [EtsFile] from a resource file. + * + * For example, `resources/ets/sample.json` can be loaded with: + * ``` + * val file: EtsFile = loadEtsFileFromResource("/ets/sample.json") + * ``` + */ +fun loadEtsFileFromResource(jsonPath: String): EtsFile { + val etsFileDto = loadEtsFileDtoFromResource(jsonPath) + return convertToEtsFile(etsFileDto) +} + +/** + * Load multiple [EtsFile]s from a resource directory. + * + * For example, all files in `resources/project/` can be loaded with: + * ``` + * val files: Sequence = loadMultipleEtsFilesFromResourceDirectory("/project") + * ``` + */ +fun loadMultipleEtsFilesFromResourceDirectory(dirPath: String): Sequence { + val rootPath = getResourcePath(dirPath) + return rootPath.walk().filter { it.extension == "json" }.map { path -> + loadEtsFileFromResource("$dirPath/${path.relativeTo(rootPath)}") + } +} + +fun loadMultipleEtsFilesFromMultipleResourceDirectories( + dirPaths: List, +): Sequence { + return dirPaths.asSequence().flatMap { loadMultipleEtsFilesFromResourceDirectory(it) } +} + +fun loadEtsProjectFromResources( + modules: List, + prefix: String, +): EtsScene { + logger.info { "Loading Ets project with modules $modules from '$prefix/'" } + val dirPaths = modules.map { "$prefix/$it" } + val files = loadMultipleEtsFilesFromMultipleResourceDirectories(dirPaths).toList() + logger.info { "Loaded ${files.size} files" } + return EtsScene(files, sdkFiles = emptyList()) +} + +//----------------------------------------------------------------------------- + +/** + * Load an [EtsFileDto] from a file. + * + * For example, `data/sample.json` can be loaded with: + * ``` + * val dto: EtsFileDto = loadEtsFileDto(Path("data/sample.json")) + * ``` + */ +fun loadEtsFileDto(path: Path): EtsFileDto { + require(path.extension == "json") { "File must have a '.json' extension: $path" } + path.inputStream().use { stream -> + return EtsFileDto.loadFromJson(stream) + } +} + +/** + * Load an [EtsFile] from a file. + * + * For example, `data/sample.json` can be loaded with: + * ``` + * val file: EtsFile = loadEtsFile(Path("data/sample.json")) + * ``` + */ +fun loadEtsFile(path: Path): EtsFile { + val etsFileDto = loadEtsFileDto(path) + return convertToEtsFile(etsFileDto) +} + +/** + * Load multiple [EtsFile]s from a directory. + * + * For example, all files in `data` can be loaded with: + * ``` + * val files: Sequence = loadMultipleEtsFilesFromDirectory(Path("data")) + * ``` + */ +fun loadMultipleEtsFilesFromDirectory(dirPath: Path): Sequence { + return dirPath.walk().filter { it.extension == "json" }.map { loadEtsFile(it) } +} diff --git a/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/Resources.kt b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/Resources.kt new file mode 100644 index 0000000000..6b00cd961a --- /dev/null +++ b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/Resources.kt @@ -0,0 +1,20 @@ +package org.usvm.dataflow.ts + +import java.io.InputStream +import java.nio.file.Path +import kotlin.io.path.toPath + +fun getResourcePathOrNull(res: String): Path? { + require(res.startsWith("/")) { "Resource path must start with '/': '$res'" } + return object {}::class.java.getResource(res)?.toURI()?.toPath() +} + +fun getResourcePath(res: String): Path { + return getResourcePathOrNull(res) ?: error("Resource not found: '$res'") +} + +fun getResourceStream(res: String): InputStream { + require(res.startsWith("/")) { "Resource path must start with '/': '$res'" } + return object {}::class.java.getResourceAsStream(res) + ?: error("Resource not found: '$res'") +} diff --git a/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/TestFactoryDsl.kt b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/TestFactoryDsl.kt new file mode 100644 index 0000000000..a710f1c896 --- /dev/null +++ b/usvm-dataflow-ts/src/testFixtures/kotlin/org/usvm/dataflow/ts/TestFactoryDsl.kt @@ -0,0 +1,52 @@ +package org.usvm.dataflow.ts + +import org.junit.jupiter.api.DynamicContainer +import org.junit.jupiter.api.DynamicNode +import org.junit.jupiter.api.DynamicTest +import org.junit.jupiter.api.function.Executable +import java.util.stream.Stream + +private interface TestProvider { + fun test(name: String, test: () -> Unit) +} + +private interface ContainerProvider { + fun container(name: String, init: TestContainerBuilder.() -> Unit) +} + +class TestContainerBuilder(var name: String) : TestProvider, ContainerProvider { + private val nodes: MutableList = mutableListOf() + + override fun test(name: String, test: () -> Unit) { + nodes += dynamicTest(name, test) + } + + override fun container(name: String, init: TestContainerBuilder.() -> Unit) { + nodes += containerBuilder(name, init) + } + + fun build(): DynamicContainer = DynamicContainer.dynamicContainer(name, nodes) +} + +private fun containerBuilder(name: String, init: TestContainerBuilder.() -> Unit): DynamicContainer = + TestContainerBuilder(name).apply(init).build() + +class TestFactoryBuilder : TestProvider, ContainerProvider { + private val nodes: MutableList = mutableListOf() + + override fun test(name: String, test: () -> Unit) { + nodes += dynamicTest(name, test) + } + + override fun container(name: String, init: TestContainerBuilder.() -> Unit) { + nodes += containerBuilder(name, init) + } + + fun build(): Stream = nodes.stream() +} + +fun testFactory(init: TestFactoryBuilder.() -> Unit): Stream = + TestFactoryBuilder().apply(init).build() + +private fun dynamicTest(name: String, test: () -> Unit): DynamicTest = + DynamicTest.dynamicTest(name, Executable(test)) diff --git a/usvm-dataflow/build.gradle.kts b/usvm-dataflow/build.gradle.kts index a4724708fc..bac9f002b4 100644 --- a/usvm-dataflow/build.gradle.kts +++ b/usvm-dataflow/build.gradle.kts @@ -3,11 +3,11 @@ plugins { } dependencies { - implementation(Libs.jacodb_api_common) - implementation(Libs.jacodb_taint_configuration) - implementation(Libs.sarif4k) + api(project(":usvm-util")) + api(Libs.jacodb_api_common) + api(Libs.jacodb_taint_configuration) + api(Libs.sarif4k) } - publishing { publications { create("maven") { diff --git a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Condition.kt b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Condition.kt index ee9c915b16..95968d320b 100644 --- a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Condition.kt +++ b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Condition.kt @@ -35,11 +35,11 @@ import org.jacodb.taint.configuration.Or import org.jacodb.taint.configuration.PositionResolver import org.jacodb.taint.configuration.SourceFunctionMatches import org.jacodb.taint.configuration.TypeMatches -import org.usvm.dataflow.ifds.Maybe -import org.usvm.dataflow.ifds.onSome import org.usvm.dataflow.taint.Tainted import org.usvm.dataflow.util.Traits import org.usvm.dataflow.util.removeTrailingElementAccessors +import org.usvm.util.Maybe +import org.usvm.util.onSome open class BasicConditionEvaluator( val traits: Traits, diff --git a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Position.kt b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Position.kt index e51204caba..f8b95b9cde 100644 --- a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Position.kt +++ b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/Position.kt @@ -30,10 +30,10 @@ import org.jacodb.taint.configuration.ResultAnyElement import org.jacodb.taint.configuration.This import org.usvm.dataflow.ifds.AccessPath import org.usvm.dataflow.ifds.ElementAccessor -import org.usvm.dataflow.ifds.Maybe -import org.usvm.dataflow.ifds.fmap -import org.usvm.dataflow.ifds.toMaybe import org.usvm.dataflow.util.Traits +import org.usvm.util.Maybe +import org.usvm.util.fmap +import org.usvm.util.toMaybe class CallPositionToAccessPathResolver( private val traits: Traits, diff --git a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/TaintAction.kt b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/TaintAction.kt index 622dc56767..5ef603b45a 100644 --- a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/TaintAction.kt +++ b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/config/TaintAction.kt @@ -16,17 +16,17 @@ package org.usvm.dataflow.config -import org.usvm.dataflow.ifds.AccessPath -import org.usvm.dataflow.ifds.Maybe -import org.usvm.dataflow.ifds.fmap -import org.usvm.dataflow.ifds.map -import org.usvm.dataflow.taint.Tainted import org.jacodb.taint.configuration.AssignMark import org.jacodb.taint.configuration.CopyAllMarks import org.jacodb.taint.configuration.CopyMark import org.jacodb.taint.configuration.PositionResolver import org.jacodb.taint.configuration.RemoveAllMarks import org.jacodb.taint.configuration.RemoveMark +import org.usvm.dataflow.ifds.AccessPath +import org.usvm.dataflow.taint.Tainted +import org.usvm.util.Maybe +import org.usvm.util.fmap +import org.usvm.util.map class TaintActionEvaluator( private val positionResolver: PositionResolver>, diff --git a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/ifds/Maybe.kt b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/ifds/Maybe.kt deleted file mode 100644 index e804812aa5..0000000000 --- a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/ifds/Maybe.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2022 UnitTestBot contributors (utbot.org) - *

    - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

    - * http://www.apache.org/licenses/LICENSE-2.0 - *

    - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.usvm.dataflow.ifds - -@JvmInline -value class Maybe private constructor( - private val rawValue: Any?, -) { - val isSome: Boolean get() = rawValue !== NONE_VALUE - val isNone: Boolean get() = rawValue === NONE_VALUE - - fun getOrThrow(): T { - check(isSome) { "Maybe is None" } - @Suppress("UNCHECKED_CAST") - return rawValue as T - } - - companion object { - private val NONE_VALUE = Any() - private val NONE = Maybe(NONE_VALUE) - - fun none(): Maybe = NONE - - fun some(value: T): Maybe = Maybe(value) - - fun from(value: T?): Maybe = if (value == null) none() else some(value) - } -} - -inline fun Maybe.map(body: (T) -> Maybe): Maybe = - if (isNone) Maybe.none() else body(getOrThrow()) - -inline fun Maybe.fmap(body: (T) -> R): Maybe = - if (isNone) Maybe.none() else Maybe.some(body(getOrThrow())) - -inline fun Maybe.onSome(body: (T) -> Unit): Maybe { - if (isSome) body(getOrThrow()) - return this -} - -inline fun Maybe.onNone(body: () -> Unit): Maybe { - if (isNone) body() - return this -} - -fun T?.toMaybe(): Maybe = Maybe.from(this) diff --git a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/taint/TaintFlowFunctions.kt b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/taint/TaintFlowFunctions.kt index 775cad9440..b4375200d0 100644 --- a/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/taint/TaintFlowFunctions.kt +++ b/usvm-dataflow/src/main/kotlin/org/usvm/dataflow/taint/TaintFlowFunctions.kt @@ -48,9 +48,9 @@ import org.usvm.dataflow.ifds.FlowFunctions import org.usvm.dataflow.ifds.isOnHeap import org.usvm.dataflow.ifds.isStatic import org.usvm.dataflow.ifds.minus -import org.usvm.dataflow.ifds.onSome import org.usvm.dataflow.util.Traits import org.usvm.dataflow.util.startsWith +import org.usvm.util.onSome private val logger = mu.KotlinLogging.logger {} @@ -462,7 +462,6 @@ class ForwardTaintFlowFunctions( } } } - class BackwardTaintFlowFunctions( private val traits: Traits, private val graph: ApplicationGraph, diff --git a/usvm-jvm-dataflow/build.gradle.kts b/usvm-jvm-dataflow/build.gradle.kts index e22790a6d9..46b813683b 100644 --- a/usvm-jvm-dataflow/build.gradle.kts +++ b/usvm-jvm-dataflow/build.gradle.kts @@ -11,15 +11,12 @@ val samples by sourceSets.creating { dependencies { api(project(":usvm-dataflow")) - implementation(Libs.jacodb_api_common) implementation(Libs.jacodb_api_jvm) implementation(Libs.jacodb_core) implementation(Libs.jacodb_api_storage) implementation(Libs.jacodb_storage) implementation(Libs.jacodb_taint_configuration) - implementation(Libs.sarif4k) - testImplementation(Libs.mockk) testImplementation(Libs.junit_jupiter_params) diff --git a/usvm-jvm-dataflow/src/main/kotlin/org/usvm/dataflow/jvm/npe/NpeFlowFunctions.kt b/usvm-jvm-dataflow/src/main/kotlin/org/usvm/dataflow/jvm/npe/NpeFlowFunctions.kt index dc61e8e4ad..78b9ba2e7b 100644 --- a/usvm-jvm-dataflow/src/main/kotlin/org/usvm/dataflow/jvm/npe/NpeFlowFunctions.kt +++ b/usvm-jvm-dataflow/src/main/kotlin/org/usvm/dataflow/jvm/npe/NpeFlowFunctions.kt @@ -64,12 +64,12 @@ import org.usvm.dataflow.ifds.FlowFunctions import org.usvm.dataflow.ifds.isOnHeap import org.usvm.dataflow.ifds.isStatic import org.usvm.dataflow.ifds.minus -import org.usvm.dataflow.ifds.onSome import org.usvm.dataflow.jvm.util.JcTraits import org.usvm.dataflow.taint.TaintDomainFact import org.usvm.dataflow.taint.TaintZeroFact import org.usvm.dataflow.taint.Tainted import org.usvm.dataflow.util.startsWith +import org.usvm.util.onSome private val logger = mu.KotlinLogging.logger {} diff --git a/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/ConditionEvaluatorTest.kt b/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/ConditionEvaluatorTest.kt index 2141b9b026..e3545a3c28 100644 --- a/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/ConditionEvaluatorTest.kt +++ b/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/ConditionEvaluatorTest.kt @@ -53,10 +53,10 @@ import org.jacodb.taint.configuration.TypeMatches import org.junit.jupiter.api.Test import org.usvm.dataflow.config.BasicConditionEvaluator import org.usvm.dataflow.config.FactAwareConditionEvaluator -import org.usvm.dataflow.ifds.Maybe -import org.usvm.dataflow.ifds.toMaybe import org.usvm.dataflow.jvm.util.JcTraits import org.usvm.dataflow.taint.Tainted +import org.usvm.util.Maybe +import org.usvm.util.toMaybe import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertTrue diff --git a/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/NullabilityAssumptionAnalysisTest.kt b/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/NullabilityAssumptionAnalysisTest.kt deleted file mode 100644 index 3d4bad0591..0000000000 --- a/usvm-jvm-dataflow/src/test/kotlin/org/usvm/dataflow/jvm/impl/NullabilityAssumptionAnalysisTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022 UnitTestBot contributors (utbot.org) - *

    - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

    - * http://www.apache.org/licenses/LICENSE-2.0 - *

    - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.usvm.dataflow.jvm.impl - -import NullAssumptionAnalysisExample -import org.jacodb.api.jvm.JcClassOrInterface -import org.jacodb.api.jvm.JcMethod -import org.jacodb.api.jvm.cfg.JcAssignInst -import org.jacodb.api.jvm.cfg.JcInstanceCallExpr -import org.jacodb.api.jvm.cfg.JcLocal -import org.jacodb.api.jvm.ext.findClass -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance -import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS -import org.usvm.dataflow.jvm.flow.NullAssumptionAnalysis - -@TestInstance(PER_CLASS) -class NullabilityAssumptionAnalysisTest : BaseAnalysisTest() { - - @Test - fun `null-assumption analysis should work`() { - val clazz = cp.findClass() - with(clazz.findMethod("test1").flowGraph()) { - val analysis = NullAssumptionAnalysis(this).also { - it.run() - } - val sout = (instructions[0] as JcAssignInst).lhv as JcLocal - val a = ((instructions[3] as JcAssignInst).rhv as JcInstanceCallExpr).instance - - assertTrue(analysis.isAssumedNonNullBefore(instructions[2], a)) - assertTrue(analysis.isAssumedNonNullBefore(instructions[0], sout)) - } - } - - @Test - fun `null-assumption analysis should work 2`() { - val clazz = cp.findClass() - with(clazz.findMethod("test2").flowGraph()) { - val analysis = NullAssumptionAnalysis(this).also { - it.run() - } - val sout = (instructions[0] as JcAssignInst).lhv as JcLocal - val a = ((instructions[3] as JcAssignInst).rhv as JcInstanceCallExpr).instance - val x = (instructions[5] as JcAssignInst).lhv as JcLocal - - assertTrue(analysis.isAssumedNonNullBefore(instructions[2], a)) - assertTrue(analysis.isAssumedNonNullBefore(instructions[0], sout)) - analysis.isAssumedNonNullBefore(instructions[5], x) - } - } - - private fun JcClassOrInterface.findMethod(name: String): JcMethod = declaredMethods.first { it.name == name } - -} diff --git a/usvm-ts/src/main/kotlin/org/usvm/TSApplicationGraph.kt b/usvm-ts/src/main/kotlin/org/usvm/TSApplicationGraph.kt index 98c113b938..697cdc3fe3 100644 --- a/usvm-ts/src/main/kotlin/org/usvm/TSApplicationGraph.kt +++ b/usvm-ts/src/main/kotlin/org/usvm/TSApplicationGraph.kt @@ -1,14 +1,14 @@ package org.usvm import org.jacodb.ets.base.EtsStmt +import org.jacodb.ets.graph.EtsApplicationGraph import org.jacodb.ets.graph.EtsApplicationGraphImpl -import org.jacodb.ets.model.EtsFile import org.jacodb.ets.model.EtsMethod import org.jacodb.ets.model.EtsScene import org.usvm.statistics.ApplicationGraph -class TSApplicationGraph(project: EtsFile) : ApplicationGraph { - private val applicationGraph = EtsApplicationGraphImpl(EtsScene(listOf(project))) +class TSApplicationGraph(scene: EtsScene) : ApplicationGraph { + private val applicationGraph: EtsApplicationGraph = EtsApplicationGraphImpl(scene) override fun predecessors(node: EtsStmt): Sequence = applicationGraph.predecessors(node) diff --git a/usvm-ts/src/main/kotlin/org/usvm/TSExprResolver.kt b/usvm-ts/src/main/kotlin/org/usvm/TSExprResolver.kt index e28276aa16..cd26df8888 100644 --- a/usvm-ts/src/main/kotlin/org/usvm/TSExprResolver.kt +++ b/usvm-ts/src/main/kotlin/org/usvm/TSExprResolver.kt @@ -45,6 +45,7 @@ import org.jacodb.ets.base.EtsPostDecExpr import org.jacodb.ets.base.EtsPostIncExpr import org.jacodb.ets.base.EtsPreDecExpr import org.jacodb.ets.base.EtsPreIncExpr +import org.jacodb.ets.base.EtsPtrCallExpr import org.jacodb.ets.base.EtsRemExpr import org.jacodb.ets.base.EtsRightShiftExpr import org.jacodb.ets.base.EtsStaticCallExpr @@ -86,8 +87,8 @@ class TSExprResolver( fun resolveLValue(value: EtsValue): ULValue<*, *>? = when (value) { - is EtsParameterRef, - is EtsLocal -> simpleValueResolver.resolveLocal(value) + is EtsParameterRef, is EtsLocal -> simpleValueResolver.resolveLocal(value) + else -> error("Unexpected value: $value") } @@ -114,8 +115,6 @@ class TSExprResolver( return block(result0, result1) } - - override fun visit(value: EtsLocal): UExpr { return simpleValueResolver.visit(value) } @@ -156,6 +155,10 @@ class TSExprResolver( TODO("Not yet implemented") } + override fun visit(expr: EtsAwaitExpr): UExpr? { + TODO("Not yet implemented") + } + override fun visit(expr: EtsBitAndExpr): UExpr { TODO("Not yet implemented") } @@ -184,14 +187,6 @@ class TSExprResolver( TODO("Not yet implemented") } - override fun visit(expr: EtsAwaitExpr): UExpr? { - TODO("Not yet implemented") - } - - override fun visit(expr: EtsYieldExpr): UExpr? { - TODO("Not yet implemented") - } - override fun visit(expr: EtsDivExpr): UExpr { TODO("Not yet implemented") } @@ -300,6 +295,10 @@ class TSExprResolver( TODO("Not yet implemented") } + override fun visit(expr: EtsPtrCallExpr): UExpr? { + TODO("Not yet implemented") + } + override fun visit(expr: EtsStrictEqExpr): UExpr { TODO("Not yet implemented") } @@ -332,6 +331,10 @@ class TSExprResolver( TODO("Not yet implemented") } + override fun visit(expr: EtsYieldExpr): UExpr? { + TODO("Not yet implemented") + } + override fun visit(value: EtsArrayAccess): UExpr { TODO("Not yet implemented") } diff --git a/usvm-ts/src/main/kotlin/org/usvm/TSInterpreter.kt b/usvm-ts/src/main/kotlin/org/usvm/TSInterpreter.kt index 82d56090c5..3e77717b62 100644 --- a/usvm-ts/src/main/kotlin/org/usvm/TSInterpreter.kt +++ b/usvm-ts/src/main/kotlin/org/usvm/TSInterpreter.kt @@ -182,7 +182,7 @@ class TSInterpreter( state.models = listOf(model) state.callStack.push(method, returnSite = null) - state.memory.stack.push(method.parameters.size, method.localsCount) + state.memory.stack.push(method.parameters.size, method.locals.size) state.pathNode += method.cfg.instructions.first() return state diff --git a/usvm-ts/src/main/kotlin/org/usvm/TSMachine.kt b/usvm-ts/src/main/kotlin/org/usvm/TSMachine.kt index 4e56356488..4d9ac76b79 100644 --- a/usvm-ts/src/main/kotlin/org/usvm/TSMachine.kt +++ b/usvm-ts/src/main/kotlin/org/usvm/TSMachine.kt @@ -1,8 +1,8 @@ package org.usvm import org.jacodb.ets.base.EtsStmt -import org.jacodb.ets.model.EtsFile import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene import org.usvm.ps.createPathSelector import org.usvm.state.TSMethodResult import org.usvm.state.TSState @@ -20,7 +20,7 @@ import org.usvm.stopstrategies.createStopStrategy import kotlin.time.Duration.Companion.seconds class TSMachine( - private val project: EtsFile, + private val project: EtsScene, private val options: UMachineOptions, ) : UMachine() { private val typeSystem = TSTypeSystem(typeOperationsTimeout = 1.seconds, project) diff --git a/usvm-ts/src/main/kotlin/org/usvm/TSTypeSystem.kt b/usvm-ts/src/main/kotlin/org/usvm/TSTypeSystem.kt index 9402a88501..d6f821ada2 100644 --- a/usvm-ts/src/main/kotlin/org/usvm/TSTypeSystem.kt +++ b/usvm-ts/src/main/kotlin/org/usvm/TSTypeSystem.kt @@ -1,14 +1,14 @@ package org.usvm import org.jacodb.ets.base.EtsType -import org.jacodb.ets.model.EtsFile +import org.jacodb.ets.model.EtsScene import org.usvm.types.UTypeStream import org.usvm.types.UTypeSystem import kotlin.time.Duration class TSTypeSystem( override val typeOperationsTimeout: Duration, - val project: EtsFile, + val project: EtsScene, ) : UTypeSystem { override fun isSupertype(supertype: EtsType, type: EtsType): Boolean { diff --git a/usvm-ts/src/test/kotlin/org/usvm/util/TSMethodTestRunner.kt b/usvm-ts/src/test/kotlin/org/usvm/util/TSMethodTestRunner.kt index fa82d2177d..970861388c 100644 --- a/usvm-ts/src/test/kotlin/org/usvm/util/TSMethodTestRunner.kt +++ b/usvm-ts/src/test/kotlin/org/usvm/util/TSMethodTestRunner.kt @@ -1,5 +1,6 @@ package org.usvm.util +import org.jacodb.ets.base.DEFAULT_ARK_CLASS_NAME import org.jacodb.ets.base.EtsAnyType import org.jacodb.ets.base.EtsBooleanType import org.jacodb.ets.base.EtsNumberType @@ -10,6 +11,7 @@ import org.jacodb.ets.dto.EtsFileDto import org.jacodb.ets.dto.convertToEtsFile import org.jacodb.ets.model.EtsFile import org.jacodb.ets.model.EtsMethod +import org.jacodb.ets.model.EtsScene import org.jacodb.ets.utils.loadEtsFileAutoConvert import org.usvm.NoCoverage import org.usvm.PathSelectionStrategy @@ -29,7 +31,7 @@ typealias CoverageChecker = (TSMethodCoverage) -> Boolean open class TSMethodTestRunner : TestRunner() { - protected val globalClassName = "_DEFAULT_ARK_CLASS" + protected val globalClassName = DEFAULT_ARK_CLASS_NAME protected val doNotCheckCoverage: CoverageChecker = { _ -> true } @@ -205,10 +207,11 @@ open class TSMethodTestRunner : TestRunner + TSMachine(project, options).use { machine -> val states = machine.analyze(listOf(method)) states.map { state -> val resolver = TSTestResolver() diff --git a/usvm-util/src/main/kotlin/org/usvm/util/Logging.kt b/usvm-util/src/main/kotlin/org/usvm/util/Logging.kt index cd74322328..0235318c39 100644 --- a/usvm-util/src/main/kotlin/org/usvm/util/Logging.kt +++ b/usvm-util/src/main/kotlin/org/usvm/util/Logging.kt @@ -40,10 +40,10 @@ inline fun LoggerWithLogMethod.bracket( val startNano = System.nanoTime() var alreadyLogged = false - var res : Maybe = Maybe.empty() + var res : Maybe = Maybe.none() try { // Note: don't replace this one with runCatching, otherwise return from lambda breaks "finished" logging. - res = Maybe(block()) + res = Maybe.some(block()) return res.getOrThrow() } catch (t: Throwable) { logMethod { "Finished (in ${elapsedSecFrom(startNano)}): $msg :: EXCEPTION :: ${closingComment(Result.failure(t))}" } @@ -51,7 +51,7 @@ inline fun LoggerWithLogMethod.bracket( throw t } finally { if (!alreadyLogged) { - if (res.hasValue) + if (res.isSome) logMethod { "Finished (in ${elapsedSecFrom(startNano)}): $msg ${closingComment(Result.success(res.getOrThrow()))}" } else logMethod { "Finished (in ${elapsedSecFrom(startNano)}): $msg " } @@ -75,4 +75,4 @@ inline fun KLogger.logException(block: () -> T): T { this.error("Exception occurred", e) throw e } -} \ No newline at end of file +} diff --git a/usvm-util/src/main/kotlin/org/usvm/util/Maybe.kt b/usvm-util/src/main/kotlin/org/usvm/util/Maybe.kt index c630f4d4d1..3ee025572e 100644 --- a/usvm-util/src/main/kotlin/org/usvm/util/Maybe.kt +++ b/usvm-util/src/main/kotlin/org/usvm/util/Maybe.kt @@ -1,23 +1,51 @@ package org.usvm.util -/** - * Analogue of java's [java.util.Optional] - */ -class Maybe private constructor(val hasValue: Boolean, val value:T? ) { - constructor(v: T) : this(true, v) - companion object { - fun empty() = Maybe(false, null) +@JvmInline +value class Maybe private constructor( + private val rawValue: Any?, +) { + val isSome: Boolean get() = rawValue !== NONE_VALUE + val isNone: Boolean get() = rawValue === NONE_VALUE + + fun getOrThrow(): T { + check(isSome) { "Maybe is None" } + @Suppress("UNCHECKED_CAST") + return rawValue as T + } + + override fun toString(): String { + return if (isSome) "Some($rawValue)" else "None" } - /** - * Returns [value] if [hasValue]. Otherwise, throws exception - */ - @Suppress("UNCHECKED_CAST") - fun getOrThrow() : T = if (!hasValue) { - error("Maybe hasn't value") - } else { - value as T + companion object { + private val NONE_VALUE = object { + // Note: toString() for debugger + override fun toString(): String = "None" + } + private val NONE = Maybe(NONE_VALUE) + + fun none(): Maybe = NONE + + fun some(value: T): Maybe = Maybe(value) + + fun from(value: T?): Maybe = if (value == null) none() else some(value) } +} + +inline fun Maybe.map(body: (T) -> Maybe): Maybe = + if (isNone) Maybe.none() else body(getOrThrow()) + +inline fun Maybe.fmap(body: (T) -> R): Maybe = + if (isNone) Maybe.none() else Maybe.some(body(getOrThrow())) + +inline fun Maybe.onSome(body: (T) -> Unit): Maybe { + if (isSome) body(getOrThrow()) + return this +} + +inline fun Maybe.onNone(body: () -> Unit): Maybe { + if (isNone) body() + return this +} - override fun toString(): String = if (hasValue) "Maybe($value)" else "" -} \ No newline at end of file +fun T?.toMaybe(): Maybe = Maybe.from(this)