[Analysis API] Explicitly specify the context module in a directive

This commit is contained in:
Yan Zhulanow
2024-01-29 16:47:43 +09:00
committed by Space Team
parent 892212bdf6
commit e001fa4e72
84 changed files with 117 additions and 12 deletions
@@ -22,6 +22,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -21,6 +21,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -21,6 +21,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -15,6 +15,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -13,6 +13,7 @@ val Int.ext: String
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -13,6 +13,7 @@ val Int.ext: String
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -13,6 +13,7 @@ val Int.ext: String
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -18,6 +18,7 @@ fun main() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -10,6 +10,7 @@ class Foo(a: Int, b: String) {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -9,6 +9,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -21,6 +21,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -14,6 +14,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -16,6 +16,7 @@ fun consume(obj: Foo) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -20,6 +20,7 @@ fun consume(text: String) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -20,6 +20,7 @@ fun consume(text: String) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -16,6 +16,7 @@ fun consume(n: Int) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -14,6 +14,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -21,6 +21,7 @@ fun consume(obj: Any) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -14,6 +14,7 @@ fun consume(n: Int) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -9,6 +9,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -9,6 +9,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -22,6 +22,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -19,6 +19,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -17,6 +17,7 @@ fun foo() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -24,6 +24,7 @@ fun callString(string: String): Int {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ object Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun test(a: A) {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun test(a: A) {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -19,6 +19,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -18,6 +18,7 @@ class Test {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -24,6 +24,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -14,6 +14,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -17,6 +17,7 @@ expect class Foo {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: common
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun consume(text: String) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ inline fun call(block: (Int) -> Int) {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -8,6 +8,7 @@ fun foo() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -1 +1 @@
(134,135) SYNTAX Syntax error: Unexpected symbol.
(161,162) SYNTAX Syntax error: Unexpected symbol.
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -10,6 +10,7 @@ fun foo() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: main.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -13,6 +13,7 @@ val b: Int = 5
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -11,6 +11,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -13,6 +13,7 @@ fun bar() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -20,6 +21,7 @@ fun bar() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -20,6 +21,7 @@ class Local {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -24,6 +25,7 @@ class Local {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -20,6 +21,7 @@ fun bar() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -12,6 +12,7 @@ val foo = "foo"
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -13,6 +13,7 @@ fun bar() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -13,6 +13,7 @@ val b: Int = 5
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -11,6 +11,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -13,6 +13,7 @@ fun bar() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -20,6 +21,7 @@ fun bar() {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun foo() {}
// MODULE: contextFragment
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: contextFragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -23,6 +24,7 @@ object {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: contextFragment
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ val foo = "foo"
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION
@@ -12,6 +12,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -13,6 +13,7 @@ object Foo
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -12,6 +12,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -0,0 +1,2 @@
Resolved to:
0: (in <local>: test) class Local
@@ -10,6 +10,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -13,6 +13,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: TYPE
@@ -34,4 +34,9 @@ object AnalysisApiTestDirectives : SimpleDirectivesContainer() {
description = "Mark the module as main",
applicability = DirectiveApplicability.Module,
)
val CONTEXT_MODULE by stringDirective(
description = "Specifies the module name which should be treated as a context module for the current one",
applicability = DirectiveApplicability.Module
)
}
@@ -31,7 +31,7 @@ object KtCodeFragmentModuleFactory : KtModuleFactory {
testServices: TestServices,
project: Project,
): KtModuleWithFiles {
requireNotNull(contextModule) { "Context module should precede the code fragment module" }
requireNotNull(contextModule) { "Code fragment requires a context module" }
val testFile = testModule.files.singleOrNull() ?: error("A single file is expected for a code fragment module")
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestDirectives
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
import org.jetbrains.kotlin.test.model.DependencyRelation
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
@@ -46,9 +48,7 @@ object TestModuleStructureFactory {
testServices: TestServices,
project: Project
): KtModuleProjectStructure {
val modules = moduleStructure.modules.mapWithPrevious<TestModule, KtModuleWithFiles> { contextModule, testModule ->
testServices.getKtModuleFactoryForTestModule(testModule).createModule(testModule, contextModule, testServices, project)
}
val modules = createModules(moduleStructure, testServices, project)
val modulesByName = modules.associateByName()
@@ -64,14 +64,27 @@ object TestModuleStructureFactory {
return KtModuleProjectStructure(modules, libraryCache.values)
}
private fun <T : Any, R> List<T>.mapWithPrevious(transform: (R?, T) -> R): List<R> {
val result = ArrayList<R>(this.size)
var previousResult: R? = null
for (item in this) {
val newResult = transform(previousResult, item)
result.add(newResult)
previousResult = newResult
private fun createModules(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
val moduleCount = moduleStructure.modules.size
val existingModules = HashMap<String, KtModuleWithFiles>(moduleCount)
val result = ArrayList<KtModuleWithFiles>(moduleCount)
for (testModule in moduleStructure.modules) {
val contextModuleName = testModule.directives.singleOrZeroValue(AnalysisApiTestDirectives.CONTEXT_MODULE)
val contextModule = contextModuleName?.let(existingModules::getValue)
val moduleWithFiles = testServices
.getKtModuleFactoryForTestModule(testModule)
.createModule(testModule, contextModule, testServices, project)
existingModules[testModule.name] = moduleWithFiles
result.add(moduleWithFiles)
}
return result
}
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -8,6 +8,7 @@ fun test() {
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: BLOCK
@@ -15,6 +15,7 @@ fun consume(foo: Foo) {}
// MODULE: main
// MODULE_KIND: CodeFragment
// CONTEXT_MODULE: context
// FILE: fragment.kt
// CODE_FRAGMENT_KIND: EXPRESSION