Commit d8ec59e3 authored by zhen.jiang's avatar zhen.jiang

初次提交

parents

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

*.iml
.kotlin
.gradle
**/build/
xcuserdata
!src/**/build/
local.properties
.idea
.DS_Store
captures
.externalNativeBuild
.cxx
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcodeproj/project.xcworkspace/
!*.xcworkspace/contents.xcworkspacedata
**/xcshareddata/WorkspaceSettings.xcsettings
node_modules/
## Code of Conduct
This project and the corresponding community are governed by the [JetBrains Open Source and Community Code of Conduct](https://github.com/jetbrains#code-of-conduct).
Please make sure you read it.
This diff is collapsed.
# 鸿蒙适配
本分支拓展2.2版本kotlin native以支持鸿蒙真机,**当前尚未经过生产环境测试**,实现仅供参考。
## 版本构建
### 构建 llvm
2.2版本Kotlin/Native使用[llvm 19.1.4](https://github.com/Kotlin/llvm-project/blob/kotlin/llvm-19-apple/cmake/Modules/LLVMVersion.cmake)生成二进制产物。本分支使用[llvm 19.1.7](https://gitee.com/openharmony/third_party_llvm-project/blob/llvm-19.1.7/cmake/Modules/LLVMVersion.cmake)打包鸿蒙二进制,LLVM代码来自 [https://gitee.com/openharmony/third_party_llvm-project/tree/llvm-19.1.7](https://gitee.com/openharmony/third_party_llvm-project/tree/llvm-19.1.7)。当前Windows/Mac/Linux三端均有可用LLVM产物,项目使用本版本Kotlin,构建过程中会自动下载。Mac/Linux产物构建过程已开源,Windows产物构建过程将于近期开源。
为避免环境问题影响构建我们提供了用于打包LLVM的[GitHub Action脚本](/.github/workflows/build-llvm.yaml)。大部分的LLVM构建工作在Linux Docker中执行,只有最终在Mac上运行的二进制需要在Mac上构建。Github Action提供的runner单次构建最多运行6h不够在Linux上完成LLVM构建,因此您需要按照[Github 文档](https://docs.github.com/en/actions/how-tos/manage-runners/self-hosted-runners/add-runners)在项目中添加一个Linux的自托管执行机(self hosted runner)。Linux执行机上只需要安装并启动docker,启动Github Action Runner,Action脚本执行过程中会配置构建LLVM所需的环境
### 构建 Kotlin
构建Kotlin过程中本项目对环境的要求[和上游社区一致](/kotlin-native/README.md#building-from-source),主要需要注意的是java和xcode版本
- Kotlin构建的gradle任务执行过程中会使用[Gradle toolchains](https://docs.gradle.org/current/userguide/toolchains.html)功能下载 Temurin 版本 JDK,不过此外仍需手动安装[Zulu 8](https://www.azul.com/downloads/?version=java-8-lts&architecture=x86-64-bit&package=jdk#zulu)[Temurin 21](https://adoptium.net/temurin/releases?version=21&os=any&arch=any)两个JDK。Mac上可以用 `brew install zulu@8 temurin@21` 命令安装,Windows/Linux上的安装方式请参考官网指导
- 如果您在项目构建过程中遇到 ` Could not find artifact com.sun:tools:iar:1.8.0 at specified path /path/to/java/lib/tools.jar ` 原因应为构建工具没有找到JDK 8,需要您在运行脚本前手动设置 `export JDK_18=/path/to/zulu-8/java_home`
- Mac上需使用 Xcode 26 版本。您可以从 [https://xcodereleases.com](https://xcodereleases.com) 搜索下载最新的发布版本 Xcode(需要苹果账号),并通过 `sudo xcode-select -s /path/to/Xcode.app` 命令指定构建过程中使用的Xcode
- Windows上构建Kotlin需安装Microsoft Build Tools和Windows SDK,Kotlin文档中推荐的2019版本已被微软下线没有官方的下载方式,如找不到2019版本安装包可以使用[Visual Studio 2022 Community 版本](https://visualstudio.microsoft.com/downloads/),在安装过程中需要勾选使用C++的桌面开发下MSVC最新编译器和库和Windows 10 SDK两个组件
构建命令
```shell
# export JDK_18=/path/to/zulu-8.jdk/Contents/Home # 如果maven构建过程中报找不到 com.sun:tools:iar:1.8.0,需要手动指定JDK 8地址
bash scripts/build-ohos.sh
```
发布产物在 [build/repo](./build/repo) 目录下
技巧:
- 修改 [EnabledTargets.kt](/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/EnabledTargets.kt) 可以出只支持鸿蒙的Kotlin版本加快构建。使用这种Kotlin版本的项目中只能声明打包鸿蒙产物,否则构建会失败。
```kotlin
fun enabledTargets(platformManager: PlatformManager) = listOf(KonanTarget.OHOS_ARM64) // 单出鸿蒙
```
- 调试[Kotlin runtime部分](/kotlin-native/runtime/)时可以使用 [scripts/build-ohos-runtime.sh](/scripts/build-ohos-runtime.sh) 脚本快速单独打包runtime部分,提升效率。注意要让修改生效,需要修改下游样例项目根目录的gradle.properties,添加一行 `kotlin.native.home=/path/to/kotiln-native/dist` 配置的值为本项目中 [kotlin-native/dist](/kotlin-native/dist) 文件夹的绝对路径
- Kotlin/Native打包过程中需要设置 kotlin.native.enabled=true,因此拉取项目后在IDEA中直接sync的范围不包含Kotlin/Native相关代码,表现为项目中kotlin-native文件夹下的代码不支持点击跳转定义等功能。您可以在使用 `bash scripts/build-ohos.sh` 命令完成本地出包后,在本项目根目录 [gradle.properties](/gradle.properties)中添加下述配置,存在重复定义的设置将项目中原来的设置注释掉,之后进行sync,让IDEA支持在kotlin-native部分代码中进行跳转定义等操作
```
bootstrap.kotlin.default.version=2.2.255-SNAPSHOT
deployVersion=2.2.255-SNAPSHOT
versions.kotlin-native=2.2.255-SNAPSHOT
konanVersion=2.2.255-SNAPSHOT
bootstrap.kotlin.version=2.2.255-SNAPSHOT
kotlin.native.enabled=true
bootstrap.local=true
bootstrap.local.version=2.2.255-SNAPSHOT
```
## 在线发布
通过在线方式使用本项目需要发布两部分产物:`build/repo` 目录下的maven仓库和llvm。最简单的发布方式需要一个域名和一台运行nginx的服务器。
服务器搭建以debian为例,为了让Konan下载依赖时可以按照nginx配置进行重定向需要提供https网址,因此需要一个域名指向当前服务器
```shell
sudo apt update
sudo apt upgrade -y
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
sudo ufw allow 'Nginx Full'
sudo mkdir -p /var/www/artifact # llvm相关产物
sudo mkdir -p /var/www/maven # maven仓库
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx --register-unsafely-without-email # 按照命令行提示配置https
```
参考nginx配置,主要功能为
1. 在 http://yourdomainnamne.com/maven/ 托管 /var/www/maven 下的 maven 仓库
2. 在 http://yourdomainnamne.com/download/ 托管 /var/www/artifact 下的 llvm 产物,本项目只需提供少量几个产物,其他产物重定向到上游JB cdk进行下载
https相关配置由letsencrypt Certbot自动生成和管理
```
server {
access_log /var/log/nginx/access.log;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name kotlinnativeohos.online www.kotlinnativeohos.online;
location / {
try_files $uri $uri/ =404;
}
location /download/ {
alias /var/www/artifact/; # path to llvm artifacts
try_files $uri $uri/ @cdn_redirect; # if the artifact is not found on our sever, redirect to upstream jetbrains cdn
}
location @cdn_redirect {
rewrite ^/download/(.*)$ https://download-cdn.jetbrains.com/kotlin/native/$1 permanent;
}
location /maven/ {
alias /var/www/maven/; # path to maven repository
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/kotlinnativeohos.online/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/kotlinnativeohos.online/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = kotlinnativeohos.online) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name kotlinnativeohos.online www.kotlinnativeohos.online;
return 404; # managed by Certbot
}
```
配置完成后检查配置格式并重启
```shell
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart nginx
```
上传 maven 产物
```shell
rsync -avz --delete ./build/repo/ root@kotlinnativeohos.online:/var/www/maven
```
上传llvm相关产物,包含llvm 19和ohos sysroot。konan的依赖会被直接解压到 `$KONAN_DATA_DIR/dependencies` 下(不会给解压出来的文件产物创建一个文件夹放进去),因此需要压缩一个和压缩包同名的目录。sysroot当前需要使用 5.0.11.110 command line tools中(或对应DevecoStudio中)的版本,路径在 `command-line-tools-5.0.11.110/sdk/default/openharmony/native/sysroot`
```shell
tar -czf llvm-19.1.7-aarch64-macos-ohos-2.tar.gz llvm-19.1.7-aarch64-macos-ohos-2
tar -czf sysroot-ohos-aarch64-5.0.11.110.tar.gz sysroot-ohos-aarch64-5.0.11.110
scp llvm-19.1.7-aarch64-macos-ohos-2.tar.gz root@kotlinnativeohos.online:/var/www/artifact/
scp sysroot-ohos-aarch64-5.0.11.110.tar.gz root@kotlinnativeohos.online:/var/www/artifact/
```
## 使用 2.2.21-ohos 版本
### 在线版本
1. 在原来项目中指定maven仓的地方添加
```shell
maven("https://kotlinnativeohos.online/maven")
```
> *注意这个maven仓库仅用于临时传递产物,随时有可能下线。这个仓库中的产物只经过极其有限的测试不能用于生产*
1. 切换kotlin版本到本项目版本
### 本地版本
1. 与在线版本一样需要添加maven仓库,仓库地址为本项目 [build/repo](/build/repo/) 文件夹
2. 切换kotlin版本,打包脚本默认版本为 [2.2.255-SNAPSHOT](/scripts/build-ohos.sh#L20)
3. Kotlin Native 编译器 Konan 的依赖不受gradle管理,修改runtime,platformdef等组件的内容后**默认konan不会更新依赖**导致修改在下游项目中不生效,调试这一部分需要在下游项目根目录的 gradle.properties 中设置 `kotlin.native.home=` 本项目中 [kotlin-native/dist/](/kotlin-native/dist/) 文件夹地址
```
kotlin.native.home=/path/to/kotlin-native/dist/
```
## 鸿蒙化修改梳理
总体思路:
- 鸿蒙平台和其他平台共LLVM前端,使用支持打鸿蒙二进制的LLVM后端
- 大多数列出了所有平台的地方需要补充一个OHOS
- 鸿蒙编译相关的配置与Linux较为接近
- 提供封装鸿蒙系统API的platform def文件
修改点:
- 构建脚本:[本地构建](./scripts/build-ohos.sh)[Action流水线](./.github/workflows/)
- 修改Kotlin Native LLVM相关依赖下载地址:[konan.properties](kotlin-native/konan/konan.properties#L18)[build.gradle.kts](kotlin-native/dependencies/build.gradle.kts#L15),这个端点的详细介绍见[在线发布](#在线发布)章节
- 配置编译鸿蒙二进制使用的llvm后端和编译选项:[konan.properties](kotlin-native/konan/konan.properties#L920)
- 鸿蒙系统接口 platform cinterop klib 库定义:[kotlin-native/platformLibs/src/platform/ohos](kotlin-native/platformLibs/src/platform/ohos),针对 5.0.11.110 版本,sdk 15
- 鸿蒙平台相关配置项定义:[Configurables.kt](native/utils/src/org/jetbrains/kotlin/konan/target/Configurables.kt)[ConfigurablesImpl.kt](native/utils/src/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt)
- Kotlin侧支持hilog和hitrace:[Porting.cpp](kotlin-native/runtime/src/main/cpp/Porting.cpp#L87)
- KMP插件增加鸿蒙目标定义:[KotlinTargetContainerWithPresetFunctions.kt](libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetContainerWithPresetFunctions.kt#L30)
- [额外的header搜索路径](native/utils/src/org/jetbrains/kotlin/konan/target/ClangArgs.kt#L180)[鸿蒙链接参数配置](native/utils/src/org/jetbrains/kotlin/konan/target/Linker.kt#L180)[鸿蒙平台使用单独的llvm后端](kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt#L110)
- 其余的修改主要为零散的参照其他平台添加鸿蒙平台配置
[![official project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![TeamCity (simple build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/Kotlin_KotlinPublic_Compiler.svg)](https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_Compiler?branch=%3Cdefault%3E&buildTypeTab=overview&mode=builds)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlin/kotlin-maven-plugin.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.jetbrains.com/scans?search.rootProjectNames=Kotlin)
# Kotlin Programming Language
Welcome to [Kotlin](https://kotlinlang.org/)!
Kotlin is a concise multiplatform language developed by [JetBrains](https://www.jetbrains.com/) and [contributors](https://kotlinlang.org/docs/contribute.html).
Some handy links:
* [Kotlin Site](https://kotlinlang.org/)
* [Getting Started Guide](https://kotlinlang.org/docs/tutorials/getting-started.html)
* [Try Kotlin](https://play.kotlinlang.org/)
* [Kotlin Standard Library](https://kotlinlang.org/api/latest/jvm/stdlib/index.html)
* [Issue Tracker](https://youtrack.jetbrains.com/issues/KT)
* [Kotlin YouTube Channel](https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw)
* [Forum](https://discuss.kotlinlang.org/)
* [Kotlin Blog](https://blog.jetbrains.com/kotlin/)
* [Subscribe to Kotlin YouTube channel](https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw)
* [Follow Kotlin on Twitter](https://twitter.com/kotlin)
* [Public Slack channel](https://slack.kotlinlang.org/)
* [TeamCity CI build](https://teamcity.jetbrains.com/project.html?tab=projectOverview&projectId=Kotlin)
* [Kotlin Foundation](https://kotlinfoundation.org/)
## Kotlin Multiplatform capabilities
Support for multiplatform programming is one of Kotlin’s key benefits. It reduces time spent writing and maintaining the same code for [different platforms](https://kotlinlang.org/docs/reference/mpp-supported-platforms.html) while retaining the flexibility and benefits of native programming.
* [Kotlin Multiplatform Mobile](https://kotlinlang.org/lp/mobile/) for sharing code between Android and iOS
* [Getting Started with Kotlin Multiplatform Mobile Guide](https://kotlinlang.org/docs/mobile/create-first-app.html)
* [Kotlin Multiplatform Benefits](https://kotlinlang.org/docs/reference/multiplatform.html)
* [Share code on all platforms](https://kotlinlang.org/docs/reference/mpp-share-on-platforms.html#share-code-on-all-platforms)
* [Share code on similar platforms](https://kotlinlang.org/docs/reference/mpp-share-on-platforms.html#share-code-on-similar-platforms)
## Editing Kotlin
* [Kotlin IntelliJ IDEA Plugin](https://kotlinlang.org/docs/tutorials/getting-started.html) ([source code](https://github.com/JetBrains/intellij-community/tree/master/plugins/kotlin))
* [Kotlin Eclipse Plugin](https://kotlinlang.org/docs/tutorials/getting-started-eclipse.html)
* [Kotlin Sublime Text Package](https://github.com/vkostyukov/kotlin-sublime-package)
## Build environment requirements
This repository is using [Gradle toolchains](https://docs.gradle.org/current/userguide/toolchains.html) feature
to select and auto-provision required JDKs from [AdoptOpenJdk](https://adoptopenjdk.net) project.
Alternatively, it is still possible to only provide required JDKs via environment variables
(see [gradle.properties](./gradle.properties#L5) for supported variable names). To ensure Gradle uses only JDKs
from environmental variables - disable Gradle toolchain auto-detection by passing `-Porg.gradle.java.installations.auto-detect=false` option
(or put it into `$GRADLE_USER_HOME/gradle.properties`).
On Windows you might need to add long paths setting to the repo:
git config core.longpaths true
## Building
The project is built with Gradle. Run Gradle to build the project and to run the tests
using the following command on Unix/macOS:
./gradlew <tasks-and-options>
or the following command on Windows:
gradlew <tasks-and-options>
On the first project configuration gradle will download and setup the dependencies on
* `intellij-core` is a part of command line compiler and contains only necessary APIs.
* `idea-full` is a full blown IntelliJ IDEA Community Edition to be used in the plugin module.
These dependencies are quite large, so depending on the quality of your internet connection
you might face timeouts getting them. In this case, you can increase timeout by specifying the following
command line parameters on the first run:
./gradlew -Dhttp.socketTimeout=60000 -Dhttp.connectionTimeout=60000
## Important gradle tasks
- `clean` - clean build results
- `dist` - assembles the compiler distribution into `dist/kotlinc/` folder
- `install` - build and install all public artifacts into local maven repository
- `coreLibsTest` - build and run stdlib, reflect and kotlin-test tests
- `gradlePluginTest` - build and run gradle plugin tests
- `compilerTest` - build and run all compiler tests
To reproduce TeamCity build use `-Pteamcity=true` flag. Local builds don't run proguard and have jar compression disabled by default.
**OPTIONAL:** Some artifacts, mainly Maven plugin ones, are built separately with Maven.
Refer to [libraries/ReadMe.md](libraries/ReadMe.md) for details.
To build Kotlin/Native, see
[kotlin-native/README.md](kotlin-native/README.md#building-from-source).
## <a name="working-in-idea"></a> Working with the project in IntelliJ IDEA
It is recommended to use the latest released version of Intellij IDEA (Community or Ultimate Edition). You can download IntelliJ IDEA [here](https://www.jetbrains.com/idea/download).
After cloning the project, import the project in IntelliJ by choosing the project directory in the Open project dialog.
For handy work with compiler tests it's recommended to use [
Kotlin Compiler Test Helper](https://github.com/demiurg906/test-data-helper-plugin)
### Dependency verification
We have a [dependencies verification](https://docs.gradle.org/current/userguide/dependency_verification.html) feature enabled in the
repository for all Gradle builds. Gradle will check hashes (md5 and sha256) of used dependencies and will fail builds with
`Dependency verification failed` errors when local artifacts are absent or have different hashes listed in the
[verification-metadata.xml](https://github.com/JetBrains/kotlin/blob/master/gradle/verification-metadata.xml) file.
It's expected that `verification-metadata.xml` should only be updated with the commits that modify the build. There are some tips how
to perform such updates:
- Delete `components` section of `verification-metadata.xml` to avoid stockpiling of old unused dependencies. You may use the following command:
```bash
#macOS
sed -i '' -e '/<components>/,/<\/components>/d' gradle/verification-metadata.xml
#Linux & Git for Windows
sed -i -e '/<components>/,/<\/components>/d' gradle/verification-metadata.xml
```
- Re-generate dependencies with Gradle's `--write-verification-metadata` command (verify update relates to your changes)
```bash
./gradlew --write-verification-metadata sha256,md5 -Pkotlin.native.enabled=true resolveDependencies
```
*`resolveDependencies` task resolves dependencies for all platforms including dependencies downloaded by plugins.*
You can also use `./scripts/update-verification-metadata.sh` script which includes both of these steps
Keep in mind:
- If you’re adding a dependency with OS mentioned in an artifact name (`darwin`, `mac`, `osx`, `linux`, `windows`), remember to add them to
`implicitDependencies` configuration or update `resolveDependencies` task if needed. `resolveDependencies` should resolve all dependencies
including dependencies for different platforms.
- If you have a `local.properties` file in your Kotlin project folder, make sure that it doesn't contain `kotlin.native.enabled=false`.
Otherwise, native-only dependencies may not be added to the verification metadata. This is because `local.properties` has higher
precedence than the `-Pkotlin.native.enabled=true` specified in the Gradle command.
## Using -dev versions
We publish `-dev` versions frequently.
For `-dev` versions you can use the [list of available versions](https://redirector.kotlinlang.org/maven/bootstrap/org/jetbrains/kotlin/kotlin-compiler/maven-metadata.xml) and include this maven repository:
```kotlin
maven("https://redirector.kotlinlang.org/maven/bootstrap")
```
# License
Kotlin is distributed under the terms of the Apache License (Version 2.0). See [license folder](license/README.md) for details.
# Contributing
Please be sure to review Kotlin's [contributing guidelines](docs/contributing.md) to learn how to help the project.
# Kotlin Foundation
The Kotlin Foundation is a non-profit organization whose mission is to promote and advance the Kotlin ecosystem. You can learn more about the structure and goals of the Kotlin Foundation on its [official website](https://kotlinfoundation.org/).
## Supported Versions
Security updates are applied to the latest feature release (1.x) of the compiler, standard library, and build plugins.
A fix will be shipped with the next incremental (1.x.y) or bug fix release (1.x.yz).
All fixes are also applied to the master branch to be included in all upcoming releases.
## Reporting a Vulnerability
Instructions for reporting a vulnerability can be found on the [Security page](https://kotlinlang.org/docs/security.html).
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
implementation(project(":core:descriptors.jvm"))
implementation(project(":compiler:frontend"))
implementation(project(":compiler:frontend.java"))
implementation(project(":analysis:analysis-api-impl-base"))
implementation(project(":analysis:analysis-internal-utils"))
implementation(project(":analysis:kt-references"))
implementation(project(":compiler:light-classes"))
implementation(project(":compiler:backend"))
implementation(project(":compiler:backend-common"))
implementation(project(":compiler:backend.common.jvm"))
implementation(project(":compiler:backend.jvm"))
implementation(project(":compiler:backend.jvm.entrypoint"))
testApi(platform(libs.junit.bom))
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)
testImplementation(project(":analysis:analysis-api-platform-interface"))
testImplementation(project(":analysis:analysis-api-standalone:analysis-api-standalone-base"))
testImplementation(projectTests(":compiler:tests-common"))
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:test-infrastructure"))
testImplementation(projectTests(":compiler:tests-common-new"))
testImplementation(projectTests(":analysis:analysis-api-impl-base"))
testImplementation(projectTests(":analysis:analysis-test-framework"))
}
sourceSets {
"main" { projectDefault() }
"test" {
projectDefault()
generatedTestDir()
}
}
tasks.withType<KotlinJvmCompile>().configureEach {
compilerOptions {
optIn.addAll(
listOf(
"kotlin.RequiresOptIn",
"org.jetbrains.kotlin.analysis.api.KaImplementationDetail",
"org.jetbrains.kotlin.analysis.api.KaExperimentalApi",
"org.jetbrains.kotlin.analysis.api.KaNonPublicApi",
"org.jetbrains.kotlin.analysis.api.KaIdeApi",
"org.jetbrains.kotlin.analysis.api.KaPlatformInterface",
"org.jetbrains.kotlin.analysis.api.permissions.KaAllowProhibitedAnalyzeFromWriteAction",
)
)
}
}
optInToK1Deprecation()
projectTest(jUnitMode = JUnitMode.JUnit5) {
dependsOn(":dist")
workingDir = rootDir
useJUnitPlatform()
}
testsJar()
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="/META-INF/analysis-api/analysis-api-impl-base.xml"/>
<extensionPoints>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.declarationAttributeAltererExtension"
interface="org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension"
area="IDEA_PROJECT"
/>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.syntheticScopeProviderExtension"
interface="org.jetbrains.kotlin.synthetic.SyntheticScopeProviderExtension"
area="IDEA_PROJECT"
/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<projectService
serviceInterface="org.jetbrains.kotlin.analysis.api.session.KaSessionProvider"
serviceImplementation="org.jetbrains.kotlin.analysis.api.descriptors.KaFe10SessionProvider"
/>
<projectService
serviceInterface="org.jetbrains.kotlin.analysis.api.platform.modification.KaSourceModificationService"
serviceImplementation="org.jetbrains.kotlin.analysis.api.descriptors.modification.KaFe10SourceModificationService"
/>
<projectService
serviceInterface="org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor"
serviceImplementation="org.jetbrains.kotlin.references.fe10.base.KtFe10KotlinReferenceProviderContributor"
/>
<projectService
serviceInterface="org.jetbrains.kotlin.idea.references.ReadWriteAccessChecker"
serviceImplementation="org.jetbrains.kotlin.analysis.api.descriptors.references.ReadWriteAccessCheckerDescriptorsImpl"
/>
</extensions>
</idea-plugin>
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors
import com.intellij.openapi.extensions.AreaInstance
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolOrigin
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.analysis.api.projectStructure.KaSourceModule
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.results.PlatformOverloadsSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.createOverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.tower.KotlinToResolvedCallTransformer
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.util.CancellationChecker
internal class CliFe10AnalysisFacade : Fe10AnalysisFacade {
override fun getAnalysisContext(element: KtElement, token: KaLifetimeToken): Fe10AnalysisContext {
val handler = getHandler(element)
return getAnalysisContext(handler, token)
}
override fun getAnalysisContext(ktModule: KaModule, token: KaLifetimeToken): Fe10AnalysisContext {
val handler = KaFe10AnalysisHandlerExtension.getInstance(ktModule.project, ktModule)
return getAnalysisContext(handler, token)
}
private fun getAnalysisContext(handler: KaFe10AnalysisHandlerExtension, token: KaLifetimeToken): Fe10AnalysisContext {
return Fe10AnalysisContext(
facade = this,
handler.resolveSession.orThrowResolutionNotPerformedError(),
handler.deprecationResolver.orThrowResolutionNotPerformedError(),
handler.callResolver.orThrowResolutionNotPerformedError(),
handler.kotlinToResolvedCallTransformer.orThrowResolutionNotPerformedError(),
handler.overloadingConflictResolver.orThrowResolutionNotPerformedError(),
handler.kotlinTypeRefiner.orThrowResolutionNotPerformedError(),
token,
)
}
override fun analyze(elements: List<KtElement>, mode: Fe10AnalysisFacade.AnalysisMode): BindingContext {
val element = elements.firstOrNull() ?: return BindingContext.EMPTY
return getHandler(element).resolveSession.orThrowResolutionNotPerformedError().bindingContext
}
override fun getOrigin(file: VirtualFile): KaSymbolOrigin {
return KaSymbolOrigin.SOURCE
}
private fun getHandler(useSiteElement: KtElement): KaFe10AnalysisHandlerExtension {
val project = useSiteElement.project
val ktModule = KotlinProjectStructureProvider.getModule(project, useSiteElement, useSiteModule = null)
return KaFe10AnalysisHandlerExtension.getInstance(project, ktModule)
}
private fun <T : Any> T?.orThrowResolutionNotPerformedError(): T =
this ?: error("Resolution is not performed")
}
internal class KaFe10AnalysisHandlerExtension(
private val useSiteModule: KaSourceModule? = null
) : AnalysisHandlerExtension {
internal companion object {
fun getInstance(area: AreaInstance, module: KaModule): KaFe10AnalysisHandlerExtension {
val extensions = AnalysisHandlerExtension.extensionPointName.getExtensions(area)
.filterIsInstance<KaFe10AnalysisHandlerExtension>()
return extensions.firstOrNull { it.useSiteModule == module }
?: extensions.singleOrNull { it.useSiteModule == null }
?: error(KaFe10AnalysisHandlerExtension::class.java.name + " should be registered")
}
}
var resolveSession: ResolveSession? = null
private set
var deprecationResolver: DeprecationResolver? = null
private set
var callResolver: CallResolver? = null
private set
var kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer? = null
private set
var overloadingConflictResolver: OverloadingConflictResolver<ResolvedCall<*>>? = null
private set
var kotlinTypeRefiner: KotlinTypeRefiner? = null
private set
override fun doAnalysis(
project: Project,
module: ModuleDescriptor,
projectContext: ProjectContext,
files: Collection<KtFile>,
bindingTrace: BindingTrace,
componentProvider: ComponentProvider
): AnalysisResult? {
// Single-module [KtFe10AnalysisHandlerExtension] can be registered without specific use-site module.
// Simple null-check below will skip the bail-out.
if (useSiteModule != null &&
module.name.asString().removeSurrounding("<", ">") != useSiteModule.name
) {
// there is no way to properly map KaModule to ModuleDescriptor,
// Multi-module [KtFe10AnalysisHandlerExtension]s are used only for tests,
// so just by name comparison should work as all module names are different
return null
}
resolveSession = componentProvider.get()
deprecationResolver = componentProvider.get()
callResolver = componentProvider.get()
kotlinToResolvedCallTransformer = componentProvider.get()
kotlinTypeRefiner = componentProvider.get()
val builtIns = resolveSession!!.moduleDescriptor.builtIns
val typeSpecificityComparator = componentProvider.get<TypeSpecificityComparator>()
val platformOverloadsSpecificityComparator = componentProvider.get<PlatformOverloadsSpecificityComparator>()
val cancellationChecker = componentProvider.get<CancellationChecker>()
overloadingConflictResolver = createOverloadingConflictResolver(
builtIns,
module,
typeSpecificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
kotlinTypeRefiner!!
)
return super.doAnalysis(project, module, projectContext, files, bindingTrace, componentProvider)
}
}
\ No newline at end of file
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.analysis.api.KaPlatformInterface
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolOrigin
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.tower.KotlinToResolvedCallTransformer
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
@KaPlatformInterface
interface Fe10AnalysisFacade {
companion object {
fun getInstance(project: Project): Fe10AnalysisFacade {
return project.getService(Fe10AnalysisFacade::class.java)
}
}
fun getAnalysisContext(element: KtElement, token: KaLifetimeToken): Fe10AnalysisContext
fun getAnalysisContext(ktModule: KaModule, token: KaLifetimeToken): Fe10AnalysisContext
fun analyze(elements: List<KtElement>, mode: AnalysisMode = AnalysisMode.FULL): BindingContext
fun analyze(element: KtElement, mode: AnalysisMode = AnalysisMode.FULL): BindingContext {
return analyze(listOf(element), mode)
}
fun getOrigin(file: VirtualFile): KaSymbolOrigin
enum class AnalysisMode {
ALL_COMPILER_CHECKS,
FULL,
PARTIAL_WITH_DIAGNOSTICS,
PARTIAL
}
}
@KaPlatformInterface
class Fe10AnalysisContext(
facade: Fe10AnalysisFacade,
val resolveSession: ResolveSession,
val deprecationResolver: DeprecationResolver,
val callResolver: CallResolver,
val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
val overloadingConflictResolver: OverloadingConflictResolver<ResolvedCall<*>>,
val kotlinTypeRefiner: KotlinTypeRefiner,
val token: KaLifetimeToken,
) : Fe10AnalysisFacade by facade {
val builtIns: KotlinBuiltIns
get() = resolveSession.moduleDescriptor.builtIns
val languageVersionSettings: LanguageVersionSettings
get() = resolveSession.languageVersionSettings
}
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors
import org.jetbrains.kotlin.analysis.api.descriptors.components.*
import org.jetbrains.kotlin.analysis.api.impl.base.KaBaseSession
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseAnalysisScopeProviderImpl
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaRendererImpl
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KaResolutionScope
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
internal class KaFe10Session(
val analysisContext: Fe10AnalysisContext,
override val useSiteModule: KaModule,
token: KaLifetimeToken,
analysisSessionProvider: () -> KaFe10Session,
resolutionScope: KaResolutionScope
) : KaBaseSession(
token,
resolver = KaFe10Resolver(analysisSessionProvider),
symbolRelationProvider = KaFe10SymbolRelationProvider(analysisSessionProvider),
diagnosticProvider = KaFe10DiagnosticProvider(analysisSessionProvider),
scopeProvider = KaFe10ScopeProvider(analysisSessionProvider),
completionCandidateChecker = KaFe10CompletionCandidateChecker(analysisSessionProvider),
expressionTypeProvider = KaFe10ExpressionTypeProvider(analysisSessionProvider),
typeProvider = KaFe10TypeProvider(analysisSessionProvider),
typeInformationProvider = KaFe10TypeInformationProvider(analysisSessionProvider),
symbolProvider = KaFe10SymbolProvider(analysisSessionProvider),
javaInteroperabilityComponent = KaFe10JavaInteroperabilityComponent(analysisSessionProvider),
symbolInformationProvider = KaFe10SymbolInformationProvider(analysisSessionProvider),
typeRelationChecker = KaFe10TypeRelationChecker(analysisSessionProvider),
expressionInformationProvider = KaFe10ExpressionInformationProvider(analysisSessionProvider),
evaluator = KaFe10Evaluator(analysisSessionProvider),
referenceShortener = KaFe10ReferenceShortener(analysisSessionProvider),
importOptimizer = KaFe10ImportOptimizer(analysisSessionProvider),
renderer = KaRendererImpl(analysisSessionProvider),
visibilityChecker = KaFe10VisibilityChecker(analysisSessionProvider),
originalPsiProvider = KaFe10OriginalPsiProvider(analysisSessionProvider),
typeCreator = KaFe10TypeCreator(analysisSessionProvider),
analysisScopeProvider = KaBaseAnalysisScopeProviderImpl(analysisSessionProvider, resolutionScope),
signatureSubstitutor = KaFe10SignatureSubstitutor(analysisSessionProvider),
resolveExtensionInfoProvider = KaFe10ResolveExtensionInfoProvider(analysisSessionProvider),
compilerPluginGeneratedDeclarationsProvider = KaFe10CompilerPluginGeneratedDeclarationsProvider(analysisSessionProvider),
compilerFacility = KaFe10CompilerFacility(analysisSessionProvider),
substitutorProvider = KaFe10SubstitutorProvider(analysisSessionProvider),
dataFlowProvider = KaFe10DataFlowProvider(analysisSessionProvider),
sourceProvider = KaFe10SourceProvider(analysisSessionProvider)
)
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.impl.base.sessions.KaBaseSessionProvider
import org.jetbrains.kotlin.analysis.api.impl.base.util.createSession
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KaResolutionScope
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.analysis.api.platform.modification.createProjectWideSourceModificationTracker
import org.jetbrains.kotlin.psi.KtElement
internal class KaFe10SessionProvider(project: Project) : KaBaseSessionProvider(project) {
override fun getAnalysisSession(useSiteElement: KtElement): KaSession {
val useSiteModule = KotlinProjectStructureProvider.getModule(project, useSiteElement, useSiteModule = null)
checkUseSiteModule(useSiteModule)
val facade = Fe10AnalysisFacade.getInstance(project)
val token = tokenFactory.create(project, project.createProjectWideSourceModificationTracker())
val context = facade.getAnalysisContext(useSiteElement, token)
return createSession(context, useSiteModule, token)
}
override fun getAnalysisSession(useSiteModule: KaModule): KaSession {
checkUseSiteModule(useSiteModule)
val facade = Fe10AnalysisFacade.getInstance(project)
val token = tokenFactory.create(project, project.createProjectWideSourceModificationTracker())
val context = facade.getAnalysisContext(useSiteModule, token)
return createSession(context, useSiteModule, token)
}
private fun createSession(context: Fe10AnalysisContext, useSiteModule: KaModule, token: KaLifetimeToken): KaFe10Session {
return createSession {
val resolutionScope = KaResolutionScope.forModule(useSiteModule)
KaFe10Session(context, useSiteModule, token, analysisSessionProvider, resolutionScope)
}
}
override fun clearCaches() {}
}
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinCompilerPluginsProvider
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinCompilerPluginsProvider.CompilerPluginType
import org.jetbrains.kotlin.analysis.api.platform.projectStructure.areCompilerPluginsSupported
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints
import org.jetbrains.kotlin.resolve.extensions.AssignResolutionAltererExtension
@Suppress("unused")
internal class KotlinFe10CompilerPluginsProvider : KotlinCompilerPluginsProvider {
override fun <T : Any> getRegisteredExtensions(module: KaModule, extensionType: ProjectExtensionDescriptor<T>): List<T> {
if (!module.areCompilerPluginsSupported()) {
return emptyList()
}
return extensionType.getInstances(module.project)
}
@OptIn(InternalNonStableExtensionPoints::class)
override fun isPluginOfTypeRegistered(module: KaModule, pluginType: CompilerPluginType): Boolean {
val extension = when (pluginType) {
CompilerPluginType.ASSIGNMENT -> AssignResolutionAltererExtension
}
return getRegisteredExtensions(module, extension).isNotEmpty()
}
}
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.annotations
import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotation
import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotationList
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classIdForAnnotation
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKaAnnotation
import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KaBaseEmptyAnnotationList
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId
internal class KaFe10AnnotationList private constructor(
private val fe10Annotations: Annotations,
private val analysisContext: Fe10AnalysisContext,
private val ignoredAnnotations: Set<ClassId> = emptySet()
) : AbstractList<KaAnnotation>(), KaAnnotationList {
private val backingAnnotations: List<KaAnnotation> by lazy {
buildList {
for (annotationDescriptor in fe10Annotations) {
if (annotationDescriptor.classIdForAnnotation !in ignoredAnnotations) {
add(annotationDescriptor.toKaAnnotation(analysisContext))
}
}
}
}
override val token: KaLifetimeToken
get() = analysisContext.token
override fun isEmpty(): Boolean = withValidityAssertion {
return if (ignoredAnnotations.isEmpty()) {
fe10Annotations.isEmpty()
} else {
backingAnnotations.isEmpty()
}
}
override val size: Int
get() = withValidityAssertion { backingAnnotations.size }
override fun iterator(): Iterator<KaAnnotation> = withValidityAssertion {
return backingAnnotations.iterator()
}
override fun get(index: Int): KaAnnotation = withValidityAssertion {
return backingAnnotations[index]
}
override val classIds: Set<ClassId>
get() = withValidityAssertion {
buildSet {
for (annotation in fe10Annotations) {
val classId = annotation.classIdForAnnotation ?: continue
if (classId in ignoredAnnotations) continue
add(classId)
}
}
}
override fun contains(classId: ClassId): Boolean = withValidityAssertion {
fe10Annotations.hasAnnotation(classId.asSingleFqName())
}
override fun get(classId: ClassId): List<KaAnnotation> = withValidityAssertion {
if (classId in ignoredAnnotations) return@withValidityAssertion emptyList()
fe10Annotations.mapIndexedNotNull { index, annotation ->
if (annotation.classIdForAnnotation != classId) {
return@mapIndexedNotNull null
}
annotation.toKaAnnotation(analysisContext)
}
}
companion object {
fun create(
fe10Annotations: Annotations,
analysisContext: Fe10AnalysisContext,
ignoredAnnotations: Set<ClassId> = emptySet(),
): KaAnnotationList {
return if (!fe10Annotations.isEmpty()) {
KaFe10AnnotationList(fe10Annotations, analysisContext, ignoredAnnotations)
} else {
KaBaseEmptyAnnotationList(analysisContext.token)
}
}
}
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.KaNonPublicApi
import org.jetbrains.kotlin.analysis.api.components.KaCodeCompilationException
import org.jetbrains.kotlin.analysis.api.components.KaCompilationResult
import org.jetbrains.kotlin.analysis.api.components.KaCompilerFacility
import org.jetbrains.kotlin.analysis.api.components.KaCompilerTarget
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.utils.InlineFunctionAnalyzer
import org.jetbrains.kotlin.analysis.api.descriptors.utils.collectReachableInlineDelegatedPropertyAccessors
import org.jetbrains.kotlin.analysis.api.diagnostics.KaDiagnostic
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaClassBuilderFactory
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.impl.base.util.KaBaseCompiledFileForOutputFile
import org.jetbrains.kotlin.backend.jvm.FacadeClassSourceShimForFragmentCompilation
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.load.kotlin.toSourceElement
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.exceptions.rethrowIntellijPlatformExceptionIfNeeded
/**
* Whether unbound IR symbols should be stubbed instead of linked.
* This should be enabled if the compiled file could refer to symbols defined in another file of the same module.
* Such symbols are not compiled (only the file is passed to the backend) and so they cannot be linked from a dependency.
*/
@KaNonPublicApi
val STUB_UNBOUND_IR_SYMBOLS: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey<Boolean>("stub unbound IR symbols")
internal class KaFe10CompilerFacility(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaCompilerFacility, KaFe10SessionComponent {
override fun compile(
file: KtFile,
configuration: CompilerConfiguration,
target: KaCompilerTarget,
allowedErrorFilter: (KaDiagnostic) -> Boolean
): KaCompilationResult = withPsiValidityAssertion(file) {
try {
compileUnsafe(file, configuration, target as KaCompilerTarget.Jvm, allowedErrorFilter)
} catch (e: Throwable) {
rethrowIntellijPlatformExceptionIfNeeded(e)
throw KaCodeCompilationException(e)
}
}
private fun compileUnsafe(
file: KtFile,
configuration: CompilerConfiguration,
target: KaCompilerTarget.Jvm,
allowedErrorFilter: (KaDiagnostic) -> Boolean
): KaCompilationResult {
if (file is KtCodeFragment) {
throw UnsupportedOperationException("Code fragments are not supported in K1 implementation")
}
val effectiveConfiguration = configuration
.copy()
.apply {
put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, true)
}
val disableInline = effectiveConfiguration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE)
// The binding context needs to be built from all files with reachable inline functions, as such files may contain classes whose
// descriptors must be available in the binding context for the IR backend. Note that the full bytecode is only generated for
// `file` because of filtering in `generateClassFilter`, while only select declarations from other files are generated if needed
// by the backend.
val inlineAnalyzer = InlineFunctionAnalyzer(analysisContext, analyzeOnlyReifiedInlineFunctions = disableInline)
inlineAnalyzer.analyze(file)
val filesToCompile = inlineAnalyzer.allFiles().collectReachableInlineDelegatedPropertyAccessors()
val bindingContext = analysisContext.analyze(filesToCompile, AnalysisMode.ALL_COMPILER_CHECKS)
val frontendErrors = computeErrors(bindingContext.diagnostics, allowedErrorFilter)
if (frontendErrors.isNotEmpty()) {
return KaCompilationResult.Failure(frontendErrors)
}
// The IR backend will try to regenerate object literals defined in inline functions from generated class files during inlining.
// Hence, we need to be aware of which object declarations are defined in the relevant inline functions.
val inlineObjectDeclarations = inlineAnalyzer.inlineObjectDeclarations()
val inlineObjectDeclarationFiles = inlineObjectDeclarations.mapTo(mutableSetOf()) { it.containingKtFile }
class GenerateClassFilter : GenerationState.GenerateClassFilter() {
override fun shouldGeneratePackagePart(ktFile: KtFile): Boolean {
return file === ktFile || inlineObjectDeclarationFiles.contains(ktFile)
}
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean {
return processingClassOrObject.containingKtFile === file ||
processingClassOrObject is KtObjectDeclaration && inlineObjectDeclarations.contains(processingClassOrObject)
}
}
val generateClassFilter = GenerateClassFilter()
val codegenFactory = createJvmIrCodegenFactory(effectiveConfiguration)
val classBuilderFactory = KaClassBuilderFactory.create(
delegateFactory = if (target.isTestMode) ClassBuilderFactories.TEST else ClassBuilderFactories.BINARIES,
compiledClassHandler = target.compiledClassHandler
)
val state = GenerationState(
file.project,
analysisContext.resolveSession.moduleDescriptor,
effectiveConfiguration,
classBuilderFactory,
generateDeclaredClassFilter = generateClassFilter,
)
codegenFactory.convertAndGenerate(filesToCompile, state, bindingContext)
val outputFiles = state.factory.asList().map(::KaBaseCompiledFileForOutputFile)
return KaCompilationResult.Success(outputFiles, capturedValues = emptyList(), canBeCached = true)
}
private fun computeErrors(diagnostics: Diagnostics, allowedErrorFilter: (KaDiagnostic) -> Boolean): List<KaDiagnostic> {
return buildList {
for (diagnostic in diagnostics.all()) {
if (diagnostic.severity == Severity.ERROR) {
val ktDiagnostic = KaFe10Diagnostic(diagnostic, token)
if (!allowedErrorFilter(ktDiagnostic)) {
add(ktDiagnostic)
}
}
}
}
}
private fun createJvmIrCodegenFactory(configuration: CompilerConfiguration): JvmIrCodegenFactory {
val stubUnboundIrSymbols = configuration[STUB_UNBOUND_IR_SYMBOLS] == true
val jvmGeneratorExtensions = if (stubUnboundIrSymbols) {
object : JvmGeneratorExtensionsImpl(configuration) {
override fun getContainerSource(descriptor: DeclarationDescriptor): DeserializedContainerSource? {
// Stubbed top-level function IR symbols (from other source files in the module) require a parent facade class to be
// generated, which requires a container source to be provided. Without a facade class, function IR symbols will have
// an `IrExternalPackageFragment` parent, which trips up code generation during IR lowering.
val psiSourceFile =
descriptor.toSourceElement.containingFile as? PsiSourceFile ?: return super.getContainerSource(descriptor)
return FacadeClassSourceShimForFragmentCompilation(psiSourceFile)
}
}
} else {
JvmGeneratorExtensionsImpl(configuration)
}
val ideCodegenSettings = JvmIrCodegenFactory.IdeCodegenSettings(
shouldStubAndNotLinkUnboundSymbols = stubUnboundIrSymbols,
shouldDeduplicateBuiltInSymbols = stubUnboundIrSymbols,
// Because the file to compile may be contained in a "common" multiplatform module, an `expect` declaration doesn't necessarily
// have an obvious associated `actual` symbol. `shouldStubOrphanedExpectSymbols` generates stubs for such `expect` declarations.
shouldStubOrphanedExpectSymbols = true,
// Likewise, the file to compile may be contained in a "platform" multiplatform module, where the `actual` declaration is
// referenced in the symbol table automatically, but not its `expect` counterpart, because it isn't contained in the files to
// compile. `shouldReferenceUndiscoveredExpectSymbols` references such `expect` symbols in the symbol table so that they can
// subsequently be stubbed.
shouldReferenceUndiscoveredExpectSymbols = true,
)
return JvmIrCodegenFactory(
configuration,
jvmGeneratorExtensions = jvmGeneratorExtensions,
ideCodegenSettings = ideCodegenSettings,
)
}
}
\ No newline at end of file
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.components.KaCompilerPluginGeneratedDeclarations
import org.jetbrains.kotlin.analysis.api.components.KaCompilerPluginGeneratedDeclarationsProvider
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseCompilerPluginGeneratedDeclarations
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KaBaseEmptyScope
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
internal class KaFe10CompilerPluginGeneratedDeclarationsProvider(
override val analysisSessionProvider: () -> KaFe10Session,
) : KaBaseSessionComponent<KaFe10Session>(), KaCompilerPluginGeneratedDeclarationsProvider {
override val KaModule.compilerPluginGeneratedDeclarations: KaCompilerPluginGeneratedDeclarations
get() = withValidityAssertion { KaBaseCompilerPluginGeneratedDeclarations(KaBaseEmptyScope(token)) }
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.components.KaCompletionCandidateChecker
import org.jetbrains.kotlin.analysis.api.components.KaCompletionExtensionCandidateChecker
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
internal class KaFe10CompletionCandidateChecker(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaCompletionCandidateChecker, KaFe10SessionComponent {
override fun createExtensionCandidateChecker(
originalFile: KtFile,
nameExpression: KtSimpleNameExpression,
explicitReceiver: KtExpression?
): KaCompletionExtensionCandidateChecker = withPsiValidityAssertion(originalFile, nameExpression, explicitReceiver) {
throw NotImplementedError("Method is not implemented for FE 1.0")
}
}
\ No newline at end of file
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.components.*
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseImplicitReceiverSmartCast
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSmartCastInfo
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.ExplicitSmartCasts
import org.jetbrains.kotlin.resolve.calls.smartcasts.MultipleSmartCasts
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
internal class KaFe10DataFlowProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaDataFlowProvider, KaFe10SessionComponent {
override val KtExpression.smartCastInfo: KaSmartCastInfo?
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val stableSmartCasts = bindingContext[BindingContext.SMARTCAST, this]
val unstableSmartCasts = bindingContext[BindingContext.UNSTABLE_SMARTCAST, this]
when {
stableSmartCasts != null -> {
val type = stableSmartCasts.asSingleType() ?: return null
KaBaseSmartCastInfo(type, true)
}
unstableSmartCasts != null -> {
val type = unstableSmartCasts.asSingleType() ?: return null
KaBaseSmartCastInfo(type, false)
}
else -> null
}
}
private fun ExplicitSmartCasts.asSingleType(): KaType? {
if (this is MultipleSmartCasts) {
return intersectWrappedTypes(map.values).toKtType(analysisContext)
}
return defaultType?.toKtType(analysisContext)
}
override val KtExpression.implicitReceiverSmartCasts: Collection<KaImplicitReceiverSmartCast>
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val smartCasts = bindingContext[BindingContext.IMPLICIT_RECEIVER_SMARTCAST, this] ?: return emptyList()
val call = bindingContext[BindingContext.CALL, this] ?: return emptyList()
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] ?: return emptyList()
listOfNotNull(
createImplicitReceiverSmartCast(
smartCasts.receiverTypes[resolvedCall.dispatchReceiver],
KaImplicitReceiverSmartCastKind.DISPATCH
),
createImplicitReceiverSmartCast(
smartCasts.receiverTypes[resolvedCall.extensionReceiver],
KaImplicitReceiverSmartCastKind.EXTENSION
)
)
}
private fun createImplicitReceiverSmartCast(type: KotlinType?, kind: KaImplicitReceiverSmartCastKind): KaImplicitReceiverSmartCast? {
if (type == null) return null
return KaBaseImplicitReceiverSmartCast(type.toKtType(analysisContext), kind)
}
override fun computeExitPointSnapshot(
statements: List<KtExpression>,
): KaDataFlowExitPointSnapshot = withPsiValidityAssertion(statements) {
throw NotImplementedError("Method is not implemented for FE 1.0")
}
}
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.components.KaDiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.api.components.KaDiagnosticProvider
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.diagnostics.KaDiagnosticWithPsi
import org.jetbrains.kotlin.analysis.api.diagnostics.KaSeverity
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.impl.base.util.toAnalysisApiSeverity
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import kotlin.reflect.KClass
internal class KaFe10DiagnosticProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaDiagnosticProvider, KaFe10SessionComponent {
override fun KtElement.diagnostics(filter: KaDiagnosticCheckerFilter): Collection<KaDiagnosticWithPsi<*>> = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this, AnalysisMode.PARTIAL_WITH_DIAGNOSTICS)
val diagnostics = bindingContext.diagnostics.forElement(this)
return diagnostics.map { KaFe10Diagnostic(it, token) }
}
override fun KtFile.collectDiagnostics(
filter: KaDiagnosticCheckerFilter,
): Collection<KaDiagnosticWithPsi<*>> = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val result = mutableListOf<KaDiagnosticWithPsi<*>>()
for (diagnostic in bindingContext.diagnostics) {
if (this == diagnostic.psiFile) {
result += KaFe10Diagnostic(diagnostic, token)
}
}
return result
}
}
internal class KaFe10Diagnostic(private val diagnostic: Diagnostic, override val token: KaLifetimeToken) : KaDiagnosticWithPsi<PsiElement> {
override val severity: KaSeverity
get() = withValidityAssertion { diagnostic.severity.toAnalysisApiSeverity() }
override val factoryName: String
get() = withValidityAssertion { diagnostic.factory.name }
override val defaultMessage: String
get() = withValidityAssertion {
@Suppress("UNCHECKED_CAST")
val factory = diagnostic.factory as DiagnosticFactory<UnboundDiagnostic>?
return factory?.defaultRenderer?.render(diagnostic)
?: DefaultErrorMessages.getRendererForDiagnostic(diagnostic)?.render(diagnostic)
?: ""
}
override val psi: PsiElement
get() = withValidityAssertion { diagnostic.psiElement }
override val textRanges: Collection<TextRange>
get() = withValidityAssertion { diagnostic.textRanges }
override val diagnosticClass: KClass<out KaDiagnosticWithPsi<PsiElement>>
get() = withValidityAssertion { KaFe10Diagnostic::class }
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KaConstantValue
import org.jetbrains.kotlin.analysis.api.components.KaEvaluator
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKaAnnotationValue
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtConstantValueOrNull
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.types.TypeUtils
internal class KaFe10Evaluator(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaEvaluator, KaFe10SessionComponent {
override fun KtExpression.evaluate(): KaConstantValue? = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val constant = ConstantExpressionEvaluator.getPossiblyErrorConstant(this, bindingContext)
// TODO: how to _not_ evaluate expressions with a compilation error, e.g., uninitialized property access
if (constant?.usesNonConstValAsConstant == true) return null
return constant?.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)?.toKtConstantValueOrNull()
}
override fun KtExpression.evaluateAsAnnotationValue(): KaAnnotationValue? = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val constant = ConstantExpressionEvaluator.getPossiblyErrorConstant(this, bindingContext)
return constant?.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)?.toKaAnnotationValue(analysisContext)
}
}
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.components.KaExpressionInformationProvider
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.cfg.WhenChecker
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
internal class KaFe10ExpressionInformationProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaExpressionInformationProvider, KaFe10SessionComponent {
override val KtReturnExpression.targetSymbol: KaCallableSymbol?
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this, AnalysisMode.PARTIAL)
val targetLabel = getTargetLabel() ?: return parentOfType<KtNamedFunction>()?.let { with(analysisSession) { it.symbol } }
val labelTarget = bindingContext[BindingContext.LABEL_TARGET, targetLabel] as? KtDeclaration ?: return null
return with(analysisSession) { labelTarget.symbol as? KaCallableSymbol }
}
override fun KtWhenExpression.computeMissingCases(): List<WhenMissingCase> = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
return WhenChecker.getMissingCases(this, bindingContext)
}
override val KtExpression.isUsedAsExpression: Boolean
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
return isUsedAsExpression(bindingContext)
}
override val KtExpression.isUsedAsResultOfLambda: Boolean
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
return isUsedAsResultOfLambda(bindingContext)
}
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.components.KaExpressionTypeProvider
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.types.KaErrorType
import org.jetbrains.kotlin.analysis.api.types.KaFunctionType
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
import org.jetbrains.kotlin.resolve.calls.smartcasts.MultipleSmartCasts
import org.jetbrains.kotlin.resolve.calls.smartcasts.SingleSmartCast
import org.jetbrains.kotlin.resolve.calls.util.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.getType
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForAbstractMethod
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
import org.jetbrains.kotlin.types.error.ErrorTypeKind
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.typeUtil.makeNullable
internal class KaFe10ExpressionTypeProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaExpressionTypeProvider, KaFe10SessionComponent {
private companion object {
val NON_EXPRESSION_CONTAINERS = arrayOf(
KtImportDirective::class.java,
KtTypeReference::class.java,
KtPackageDirective::class.java,
KtLabelReferenceExpression::class.java
)
}
override val KtExpression.expressionType: KaType?
get() = withPsiValidityAssertion {
// Not sure if it's safe enough. In theory, some annotations on expressions might change its type
val unwrapped = unwrapParenthesesLabelsAndAnnotations() as? KtExpression ?: return null
if (unwrapped.getParentOfTypes(false, *NON_EXPRESSION_CONTAINERS) != null) {
return null
}
val bindingContext = analysisContext.analyze(unwrapped, AnalysisMode.PARTIAL)
val smartCastType = when (val smartCastType = bindingContext[BindingContext.SMARTCAST, this]) {
is SingleSmartCast -> smartCastType.type
is MultipleSmartCasts -> intersectWrappedTypes(smartCastType.map.values)
else -> null
}
val kotlinType = smartCastType ?: getType(bindingContext) ?: analysisContext.builtIns.unitType
return kotlinType.toKtType(analysisContext)
}
override val KtDeclaration.returnType: KaType
get() = withPsiValidityAssertion { getReturnTypeForKtDeclaration(this) }
private fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KaType {
// Handle callable declarations with explicit return type first
if (declaration is KtCallableDeclaration) {
val typeReference = declaration.typeReference
if (typeReference != null) {
val bindingContext = analysisContext.analyze(typeReference, AnalysisMode.PARTIAL)
val kotlinType =
if (declaration is KtParameter && declaration.isVarArg) {
// we want full Array<out T> type for parity with FIR implementation
bindingContext[BindingContext.VALUE_PARAMETER, declaration]?.returnType
} else {
bindingContext[BindingContext.TYPE, typeReference]
} ?: ErrorUtils.createErrorType(ErrorTypeKind.RETURN_TYPE, typeReference.text)
return kotlinType.toKtType(analysisContext)
}
}
if (declaration is KtFunction && declaration !is KtConstructor<*> && declaration.equalsToken != null) {
val bindingContext = analysisContext.analyze(declaration)
val kotlinType = bindingContext[BindingContext.FUNCTION, declaration]?.returnType
?: ErrorUtils.createErrorType(ErrorTypeKind.IMPLICIT_RETURN_TYPE_FOR_FUNCTION, declaration.name ?: "<unknown>")
return kotlinType.toKtType(analysisContext)
}
if (declaration is KtProperty) {
val bindingContext = analysisContext.analyze(declaration)
val kotlinType = bindingContext[BindingContext.VARIABLE, declaration]?.returnType
?: ErrorUtils.createErrorType(ErrorTypeKind.IMPLICIT_RETURN_TYPE_FOR_PROPERTY, declaration.name ?: "<unknown>")
return kotlinType.toKtType(analysisContext)
}
if (declaration is KtPropertyAccessor) {
val bindingContext = analysisContext.analyze(declaration)
val kotlinType = bindingContext[BindingContext.PROPERTY_ACCESSOR, declaration]?.returnType
?: ErrorUtils.createErrorType(
ErrorTypeKind.IMPLICIT_RETURN_TYPE_FOR_PROPERTY_ACCESSOR, declaration.property.name ?: "<unknown>"
)
return kotlinType.toKtType(analysisContext)
}
// Manually handle custom setter parameter
if (declaration is KtParameter) {
val parameterList = declaration.parent as? KtParameterList
if (parameterList?.parameters?.singleOrNull() == declaration) {
val propertyAccessor = parameterList.parent as? KtPropertyAccessor
val property = propertyAccessor?.parent as? KtProperty
if (property != null && property.setter == propertyAccessor) {
val bindingContext = analysisContext.analyze(property)
val kotlinType = bindingContext[BindingContext.VARIABLE, property]?.returnType
?: ErrorUtils.createErrorType(ErrorTypeKind.RETURN_TYPE_FOR_PROPERTY, declaration.name ?: "<unknown>")
return kotlinType.toKtType(analysisContext)
}
}
}
if (declaration is KtConstructor<*>) {
val bindingContext = analysisContext.analyze(declaration)
val kotlinType = bindingContext[BindingContext.CONSTRUCTOR, declaration]?.returnType
?: ErrorUtils.createErrorType(
ErrorTypeKind.RETURN_TYPE_FOR_CONSTRUCTOR, declaration.containingClass()?.name ?: "<unknown>"
)
return kotlinType.toKtType(analysisContext)
}
return analysisContext.builtIns.unitType.toKtType(analysisContext)
}
override val KtFunction.functionType: KaType
get() = withPsiValidityAssertion {
val analysisMode = if (hasDeclaredReturnType()) AnalysisMode.PARTIAL else AnalysisMode.FULL
val bindingContext = analysisContext.analyze(this, analysisMode)
val functionDescriptor = bindingContext[BindingContext.FUNCTION, this]
if (functionDescriptor != null) {
return getFunctionTypeForAbstractMethod(functionDescriptor, false).toKtType(analysisContext)
}
val parameterCount = valueParameters.size + (if (isExtensionDeclaration()) 1 else 0)
val function = when {
hasModifier(KtTokens.SUSPEND_KEYWORD) -> analysisContext.builtIns.getSuspendFunction(parameterCount)
else -> analysisContext.builtIns.getFunction(parameterCount)
}
val errorMessage = "Descriptor not found for function \"${name}\""
return ErrorUtils.createErrorType(ErrorTypeKind.NOT_FOUND_DESCRIPTOR_FOR_FUNCTION, function.typeConstructor, errorMessage)
.toKtType(analysisContext)
}
override val PsiElement.expectedType: KaType?
get() = withPsiValidityAssertion { computeExpectedType(this) }
private fun computeExpectedType(expression: PsiElement): KaType? {
val ktExpression = expression.getParentOfType<KtExpression>(false) ?: return null
val parentExpression = if (ktExpression.parent is KtLabeledExpression) {
// lambda -> labeled expression -> lambda argument (value argument)
ktExpression.parent.parent
} else {
ktExpression.parent
}
// Unwrap specific expressions
when (ktExpression) {
is KtNameReferenceExpression -> {
if (parentExpression is KtDotQualifiedExpression && parentExpression.selectorExpression == ktExpression) {
return computeExpectedType(parentExpression)
}
}
is KtFunctionLiteral -> {
return computeExpectedType(ktExpression.parent)
}
}
when (parentExpression) {
is KtCallableDeclaration -> {
if (expression is KtBlockExpression) {
return null
}
if (parentExpression.typeReference == null) return null
val bindingContext = analysisContext.analyze(parentExpression)
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, parentExpression]
if (descriptor is CallableDescriptor) {
return descriptor.returnType?.toKtNonErrorType(analysisContext)
}
}
is KtBinaryExpressionWithTypeRHS -> {
val typeReference = parentExpression.right
if (KtPsiUtil.isCast(parentExpression) && typeReference != null) {
val bindingContext = analysisContext.analyze(typeReference)
var kotlinType = bindingContext[BindingContext.TYPE, typeReference]
if (kotlinType != null && KtPsiUtil.isSafeCast(parentExpression)) {
kotlinType = kotlinType.makeNullable()
}
return kotlinType?.toKtNonErrorType(analysisContext)
}
}
is KtValueArgument -> {
val callExpression = getContainingCallExpression(parentExpression)
if (callExpression != null) {
val bindingContext = analysisContext.analyze(callExpression)
val resolvedCall = callExpression.getResolvedCall(bindingContext)
if (resolvedCall != null) {
val parameterDescriptor = resolvedCall.getParameterForArgument(parentExpression)?.original
if (parameterDescriptor != null) {
val kotlinType = when (val originalCallableDescriptor = parameterDescriptor.containingDeclaration) {
is SamConstructorDescriptor -> originalCallableDescriptor.returnTypeOrNothing
else -> {
if (parameterDescriptor.isVararg && !parentExpression.isSpread && !parentExpression.isNamed())
parameterDescriptor.varargElementType
else
parameterDescriptor.type
}
}
return kotlinType?.toKtNonErrorType(analysisContext)
}
}
}
}
is KtWhenConditionWithExpression -> {
val whenExpression = (parentExpression.parent as? KtWhenEntry)?.parent as? KtWhenExpression
if (whenExpression != null) {
val subject = whenExpression.subjectExpression ?: return with(analysisSession) { builtinTypes.boolean }
val kotlinType = analysisContext.analyze(subject).getType(subject)
return kotlinType?.toKtNonErrorType(analysisContext)
}
}
is KtBlockExpression -> {
if (expression == parentExpression.statements.lastOrNull()) {
val functionLiteral = parentExpression.parent as? KtFunctionLiteral
if (functionLiteral != null) {
val functionType = computeExpectedType(functionLiteral) as? KaFunctionType
functionType?.returnType?.let { return it }
}
}
}
is KtWhenEntry -> {
if (expression == parentExpression.expression) {
val whenExpression = parentExpression.parent as? KtWhenExpression
if (whenExpression != null) {
computeExpectedType(whenExpression)?.let { return it }
val entries = whenExpression.entries
val entryExpressions = entries.mapNotNull { entry -> entry.expression?.takeUnless { expression == it } }
val kotlinTypes = entryExpressions.mapNotNull { analysisContext.analyze(it).getType(it) }
return intersectWrappedTypes(kotlinTypes).toKtNonErrorType(analysisContext)
}
}
}
}
val bindingContext = analysisContext.analyze(ktExpression)
val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, ktExpression]
return kotlinType?.toKtNonErrorType(analysisContext)
}
private fun getContainingCallExpression(argument: KtValueArgument): KtCallExpression? {
return when (val parent = argument.parent) {
is KtCallExpression -> parent
is KtValueArgumentList -> parent.parent as? KtCallExpression
else -> null
}
}
override val KtExpression.isDefinitelyNull: Boolean
get() = withPsiValidityAssertion {
val unwrapped = unwrapParenthesesLabelsAndAnnotations() as? KtElement ?: return false
val bindingContext = analysisContext.analyze(this, AnalysisMode.PARTIAL)
if (bindingContext[BindingContext.SMARTCAST_NULL, this] == true) {
return true
}
for (diagnostic in bindingContext.diagnostics.forElement(unwrapped)) {
if (diagnostic.factory == Errors.ALWAYS_NULL) {
return true
}
}
return false
}
override val KtExpression.isDefinitelyNotNull: Boolean
get() = withPsiValidityAssertion {
val bindingContext = analysisContext.analyze(this)
val smartCasts = bindingContext[BindingContext.SMARTCAST, this]
if (smartCasts is MultipleSmartCasts) {
if (smartCasts.map.values.all { !it.isMarkedNullable }) {
return true
}
}
val smartCastType = smartCasts?.defaultType
if (smartCastType != null && !smartCastType.isMarkedNullable) {
return true
}
val expressionType = getType(bindingContext) ?: return false
return !TypeUtils.isNullableType(expressionType)
}
private fun KotlinType.toKtNonErrorType(analysisContext: Fe10AnalysisContext): KaType? =
this.toKtType(analysisContext).takeUnless { it is KaErrorType }
}
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.components.KaImportOptimizer
import org.jetbrains.kotlin.analysis.api.components.KaImportOptimizerResult
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KaFe10Symbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getSymbolDescriptor
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
internal class KaFe10ImportOptimizer(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaImportOptimizer, KaFe10SessionComponent {
override fun analyzeImportsToOptimize(file: KtFile): KaImportOptimizerResult = withPsiValidityAssertion(file) {
error("FE10 implementation of KtImportOptimizer should not be called from anywhere")
}
override val KaSymbol.importableFqName: FqName?
get() = withValidityAssertion {
require(this is KaFe10Symbol)
val descriptor = getSymbolDescriptor(this)
if (descriptor?.canBeReferencedViaImport() != true) return null
return descriptor.getImportableDescriptor().fqNameSafe
}
/**
* Copy of `org.jetbrains.kotlin.idea.imports.ImportsUtils.canBeReferencedViaImport`.
*/
private fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
if (this is PackageViewDescriptor ||
DescriptorUtils.isTopLevelDeclaration(this) ||
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)
) {
return !name.isSpecial
}
//Both TypeAliasDescriptor and ClassDescriptor
val parentClassifier = containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: return false
if (!parentClassifier.canBeReferencedViaImport()) return false
return when (this) {
is ConstructorDescriptor -> !parentClassifier.isInner // inner class constructors can't be referenced via import
is ClassDescriptor, is TypeAliasDescriptor -> true
else -> parentClassifier is ClassDescriptor && parentClassifier.kind == ClassKind.OBJECT
}
}
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.compiled.SignatureParsing
import com.intellij.psi.impl.compiled.StubBuildingVisitor
import org.jetbrains.kotlin.analysis.api.components.KaJavaInteroperabilityComponent
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getDescriptor
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getSymbolDescriptor
import org.jetbrains.kotlin.analysis.api.descriptors.types.base.KaFe10Type
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KaFe10JvmTypeMapperContext
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.analysis.api.types.KaTypeMappingMode
import org.jetbrains.kotlin.asJava.classes.annotateByKotlinType
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.platform.has
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.org.objectweb.asm.Type
internal class KaFe10JavaInteroperabilityComponent(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaJavaInteroperabilityComponent, KaFe10SessionComponent {
private val typeMapper by lazy { KaFe10JvmTypeMapperContext(analysisContext.resolveSession) }
override fun KaType.asPsiType(
useSitePosition: PsiElement,
allowErrorTypes: Boolean,
mode: KaTypeMappingMode,
isAnnotationMethod: Boolean,
suppressWildcards: Boolean?,
preserveAnnotations: Boolean,
allowNonJvmPlatforms: Boolean,
): PsiType? = withPsiValidityAssertion(useSitePosition) {
val kotlinType = (this as KaFe10Type).fe10Type
with(typeMapper.typeContext) {
if (kotlinType.contains { it.isError() }) {
return null
}
}
if (!analysisSession.useSiteModule.targetPlatform.has<JvmPlatform>()) return null
if (mode == KaTypeMappingMode.FUNCTION_RETURN_TYPE && !isAnnotationMethod && kotlinType.isUnit()) {
return PsiTypes.voidType()
}
val typeElement = asPsiTypeElement(
simplifyType(kotlinType),
useSitePosition,
mode.toTypeMappingMode(this, isAnnotationMethod, suppressWildcards),
)
val psiType = typeElement?.type ?: return null
if (!preserveAnnotations) return psiType
return annotateByKotlinType(psiType, kotlinType, typeElement, inferNullability = true)
}
private fun KaTypeMappingMode.toTypeMappingMode(
type: KaType,
isAnnotationMethod: Boolean,
suppressWildcards: Boolean?,
): TypeMappingMode {
require(type is KaFe10Type)
return when (this) {
KaTypeMappingMode.DEFAULT -> TypeMappingMode.DEFAULT
KaTypeMappingMode.DEFAULT_UAST -> TypeMappingMode.DEFAULT_UAST
KaTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT
KaTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE_AS_IS
KaTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS
KaTypeMappingMode.RETURN_TYPE_BOXED -> TypeMappingMode.RETURN_TYPE_BOXED
KaTypeMappingMode.RETURN_TYPE, KaTypeMappingMode.FUNCTION_RETURN_TYPE ->
typeMapper.typeContext.getOptimalModeForReturnType(type.fe10Type, isAnnotationMethod)
KaTypeMappingMode.VALUE_PARAMETER, KaTypeMappingMode.VALUE_PARAMETER_BOXED -> {
val mappingMode = typeMapper.typeContext.getOptimalModeForValueParameter(type.fe10Type)
if (this == KaTypeMappingMode.VALUE_PARAMETER_BOXED) {
mappingMode.wrapInlineClassesMode()
} else {
mappingMode
}
}
}.let { typeMappingMode ->
// Otherwise, i.e., if we won't skip type with no type arguments, flag overriding might bother a case like:
// @JvmSuppressWildcards(false) Long -> java.lang.Long, not long, even though it should be no-op!
if (type.fe10Type.arguments.isEmpty())
typeMappingMode
else
typeMappingMode.updateArgumentModeFromAnnotations(
type.fe10Type,
typeMapper.typeContext,
suppressWildcards,
)
}
}
private fun simplifyType(type: UnwrappedType): KotlinType {
var result = type
do {
val oldResult = result
result = when (type) {
is FlexibleType -> type.upperBound
is DefinitelyNotNullType -> type.original
else -> type
}
} while (result !== oldResult)
return result
}
private fun asPsiTypeElement(type: KotlinType, useSitePosition: PsiElement, mode: TypeMappingMode): PsiTypeElement? {
if (type !is SimpleTypeMarker) return null
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
typeMapper.mapType(type, mode, signatureWriter)
val canonicalSignature = signatureWriter.toString()
require(!canonicalSignature.contains(SpecialNames.ANONYMOUS_STRING))
if (canonicalSignature.contains("L<error>")) return null
if (canonicalSignature.contains(SpecialNames.NO_NAME_PROVIDED.asString())) return null
val signature = SignatureParsing.CharIterator(canonicalSignature)
val typeInfo = SignatureParsing.parseTypeStringToTypeInfo(signature, StubBuildingVisitor.GUESSING_PROVIDER)
val typeText = typeInfo.text() ?: return null
return SyntheticTypeElement(useSitePosition, typeText)
}
override fun PsiType.asKaType(useSitePosition: PsiElement): KaType? = withPsiValidityAssertion(useSitePosition) {
throw UnsupportedOperationException("Conversion to KtType is not supported in K1 implementation")
}
override fun KaType.mapToJvmType(mode: TypeMappingMode): Type = withValidityAssertion {
val kotlinType = (this as KaFe10Type).fe10Type
return typeMapper.mapType(kotlinType, mode)
}
override val KaType.isPrimitiveBacked: Boolean
get() = withValidityAssertion {
val kotlinType = (this as KaFe10Type).fe10Type
return typeMapper.isPrimitiveBacked(kotlinType)
}
override val PsiClass.namedClassSymbol: KaNamedClassSymbol?
get() = withPsiValidityAssertion {
return null /*TODO*/
}
override val PsiMember.callableSymbol: KaCallableSymbol?
get() = withPsiValidityAssertion {
return null /*TODO*/
}
override val KaCallableSymbol.containingJvmClassName: String?
get() = withValidityAssertion {
with(analysisSession) {
val platform = containingModule.targetPlatform
if (!platform.has<JvmPlatform>()) return null
val containingSymbolOrSelf = computeContainingSymbolOrSelf(this@containingJvmClassName, useSiteSession)
return when (val descriptor = containingSymbolOrSelf.getDescriptor()) {
is DescriptorWithContainerSource -> {
when (val containerSource = descriptor.containerSource) {
is FacadeClassSource -> containerSource.facadeClassName ?: containerSource.className
is KotlinJvmBinarySourceElement -> JvmClassName.byClassId(containerSource.binaryClass.classId)
else -> null
}?.fqNameForClassNameWithoutDollars?.asString()
}
else -> {
return if (containingSymbolOrSelf.isTopLevel) {
descriptor?.let(DescriptorToSourceUtils::getContainingFile)
?.takeUnless { it.isScript() }
?.javaFileFacadeFqName?.asString()
} else {
val classId = (containingSymbolOrSelf as? KaConstructorSymbol)?.containingClassId
?: (containingSymbolOrSelf as? KaCallableSymbol)?.callableId?.classId
classId?.takeUnless { it.shortClassName.isSpecial }
?.asFqNameString()
}
}
}
}
}
override val KaPropertySymbol.javaGetterName: Name
get() = withValidityAssertion {
val descriptor = getSymbolDescriptor(this) as? PropertyDescriptor
if (descriptor is SyntheticJavaPropertyDescriptor) {
return descriptor.getMethod.name
}
if (descriptor != null) {
if (descriptor.hasJvmFieldAnnotation()) return descriptor.name
val getter = descriptor.getter ?: return SpecialNames.NO_NAME_PROVIDED
return Name.identifier(DescriptorUtils.getJvmName(getter) ?: JvmAbi.getterName(descriptor.name.asString()))
}
val ktPropertyName = (psi as? KtProperty)?.name ?: return SpecialNames.NO_NAME_PROVIDED
return Name.identifier(JvmAbi.getterName(ktPropertyName))
}
override val KaPropertySymbol.javaSetterName: Name?
get() = withValidityAssertion {
val descriptor = getSymbolDescriptor(this) as? PropertyDescriptor
if (descriptor is SyntheticJavaPropertyDescriptor) {
return descriptor.setMethod?.name
}
if (descriptor != null) {
if (!descriptor.isVar) {
return null
}
if (descriptor.hasJvmFieldAnnotation()) return descriptor.name
val setter = descriptor.setter ?: return SpecialNames.NO_NAME_PROVIDED
return Name.identifier(DescriptorUtils.getJvmName(setter) ?: JvmAbi.setterName(descriptor.name.asString()))
}
val ktPropertyName = (psi as? KtProperty)?.takeIf { it.isVar }?.name ?: return SpecialNames.NO_NAME_PROVIDED
return Name.identifier(JvmAbi.setterName(ktPropertyName))
}
}
private class SyntheticTypeElement(
parent: PsiElement,
typeText: String,
) : ClsTypeElementImpl(parent, typeText, '\u0000'), SyntheticElement
\ No newline at end of file
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DEPRECATION")
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.components.KaOriginalPsiProvider
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
@Suppress("OVERRIDE_DEPRECATION")
internal class KaFe10OriginalPsiProvider(
override val analysisSessionProvider: () -> KaSession
) : KaBaseSessionComponent<KaSession>(), KaOriginalPsiProvider {
override fun KtFile.recordOriginalKtFile(file: KtFile) = withValidityAssertion {
// Do nothing
}
override fun KtDeclaration.recordOriginalDeclaration(declaration: KtDeclaration) = withValidityAssertion {
// Do nothing
}
override fun KtFile.getOriginalKtFile(): KtFile? = withValidityAssertion {
return null
}
override fun KtDeclaration.getOriginalDeclaration(): KtDeclaration? = withValidityAssertion {
return null
}
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.openapi.util.TextRange
import com.intellij.psi.SmartPointerManager
import com.intellij.psi.SmartPsiElementPointer
import org.jetbrains.kotlin.analysis.api.components.*
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaClassLikeSymbol
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
internal class KaFe10ReferenceShortener(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaReferenceShortener, KaFe10SessionComponent {
override fun collectPossibleReferenceShorteningsInElement(
element: KtElement,
shortenOptions: ShortenOptions,
classShortenStrategy: (KaClassLikeSymbol) -> ShortenStrategy,
callableShortenStrategy: (KaCallableSymbol) -> ShortenStrategy
): ShortenCommand = withPsiValidityAssertion(element) {
collectPossibleReferenceShortenings(
element.containingKtFile,
element.textRange,
shortenOptions,
classShortenStrategy,
callableShortenStrategy
)
}
override fun collectPossibleReferenceShortenings(
file: KtFile,
selection: TextRange,
shortenOptions: ShortenOptions,
classShortenStrategy: (KaClassLikeSymbol) -> ShortenStrategy,
callableShortenStrategy: (KaCallableSymbol) -> ShortenStrategy
): ShortenCommand = withPsiValidityAssertion(file) {
// Compiler implementation does nothing.
// Descriptor-based shortening is implemented on the IDE plugin side.
val ktFilePointer = SmartPointerManager.createPointer(file)
return object : ShortenCommand {
override val targetFile: SmartPsiElementPointer<KtFile> get() = ktFilePointer
override val importsToAdd: Set<FqName> get() = emptySet()
override val starImportsToAdd: Set<FqName> get() = emptySet()
override val listOfTypeToShortenInfo: List<TypeToShortenInfo> get() = emptyList()
override val listOfQualifierToShortenInfo: List<QualifierToShortenInfo> get() = emptyList()
override val thisLabelsToShorten: List<ThisLabelToShortenInfo> = emptyList()
override val kDocQualifiersToShorten: List<SmartPsiElementPointer<KDocName>> get() = emptyList()
override val isEmpty: Boolean get() = true
}
}
}
\ No newline at end of file
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.components.KaResolveExtensionInfoProvider
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KaBaseEmptyScope
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.scopes.KaScope
import org.jetbrains.kotlin.psi.KtElement
// Resolve extensions are not supported on FE1.0, so return empty results.
internal class KaFe10ResolveExtensionInfoProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaResolveExtensionInfoProvider, KaFe10SessionComponent {
override val resolveExtensionScopeWithTopLevelDeclarations: KaScope
get() = withValidityAssertion { KaBaseEmptyScope(token) }
override val VirtualFile.isResolveExtensionFile: Boolean
get() = withValidityAssertion { false }
override val KtElement.isFromResolveExtension: Boolean
get() = withValidityAssertion { containingKtFile.virtualFile?.isResolveExtensionFile == true }
override val KtElement.resolveExtensionNavigationElements: Collection<PsiElement>
get() = withValidityAssertion { emptyList() }
}
\ No newline at end of file
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.analysis.api.components.*
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.scopes.*
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.KaFe10FileSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.KaFe10PackageSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KaFe10Symbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.KaFe10DescSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.KaFe10PsiSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.getResolutionScope
import org.jetbrains.kotlin.analysis.api.descriptors.types.base.KaFe10Type
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseScopeContext
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseScopeImplicitReceiverValue
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.impl.base.components.withPsiValidityAssertion
import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KaBaseCompositeScope
import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KaBaseEmptyScope
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.scopes.KaScope
import org.jetbrains.kotlin.analysis.api.scopes.KaTypeScope
import org.jetbrains.kotlin.analysis.api.symbols.KaFileSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaPackageSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KaDeclarationContainerSymbol
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.util.containingNonLocalDeclaration
import org.jetbrains.kotlin.utils.Printer
internal class KaFe10ScopeProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSessionComponent<KaFe10Session>(), KaScopeProvider, KaFe10SessionComponent {
private companion object {
val LOG = Logger.getInstance(KaFe10ScopeProvider::class.java)
}
override val KaDeclarationContainerSymbol.memberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this)
?: return createEmptyScope()
return KaFe10ScopeMember(descriptor.unsubstitutedMemberScope, descriptor.constructors, analysisContext)
}
override val KaDeclarationContainerSymbol.staticMemberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this) ?: return createEmptyScope()
return KaFe10ScopeMember(descriptor.staticScope, emptyList(), analysisContext)
}
override val KaDeclarationContainerSymbol.declaredMemberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this)
?: return createEmptyScope()
return KaFe10ScopeNonStaticMember(DeclaredMemberScope(descriptor), descriptor.constructors, analysisContext)
}
override val KaDeclarationContainerSymbol.staticDeclaredMemberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this)
?: return createEmptyScope()
return KaFe10ScopeMember(
DeclaredMemberScope(descriptor.staticScope, descriptor, forDelegatedMembersOnly = false),
emptyList(),
analysisContext,
)
}
override val KaDeclarationContainerSymbol.combinedDeclaredMemberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this)
?: return createEmptyScope()
return KaFe10ScopeMember(DeclaredMemberScope(descriptor), descriptor.constructors, analysisContext)
}
override val KaDeclarationContainerSymbol.delegatedMemberScope: KaScope
get() = withValidityAssertion {
val descriptor = getDescriptor<ClassDescriptor>(this)
?: return createEmptyScope()
return KaFe10ScopeMember(DeclaredMemberScope(descriptor, forDelegatedMembersOnly = true), emptyList(), analysisContext)
}
private fun createEmptyScope(): KaScope {
return KaBaseEmptyScope(token)
}
private class DeclaredMemberScope(
val allMemberScope: MemberScope,
val owner: ClassDescriptor,
val forDelegatedMembersOnly: Boolean
) : MemberScope {
constructor(owner: ClassDescriptor, forDelegatedMembersOnly: Boolean = false) :
this(owner.unsubstitutedMemberScope, owner, forDelegatedMembersOnly)
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
return allMemberScope.getContributedVariables(name, location).filter {
it.isDeclaredInOwner() && it.isDelegatedIfRequired()
}.mapToDelegatedIfRequired()
}
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
return allMemberScope.getContributedFunctions(name, location).filter {
it.isDeclaredInOwner() && it.isDelegatedIfRequired()
}.mapToDelegatedIfRequired()
}
override fun getFunctionNames(): Set<Name> {
return allMemberScope.getFunctionNames().filterTo(mutableSetOf()) { name ->
getContributedFunctions(name, NoLookupLocation.FROM_IDE).isNotEmpty()
}
}
override fun getVariableNames(): Set<Name> {
return allMemberScope.getVariableNames().filterTo(mutableSetOf()) { name ->
getContributedVariables(name, NoLookupLocation.FROM_IDE).isNotEmpty()
}
}
override fun getClassifierNames(): Set<Name>? {
if (forDelegatedMembersOnly) return null
return allMemberScope.getClassifierNames()?.filterTo(mutableSetOf()) { name ->
getContributedClassifier(name, NoLookupLocation.FROM_IDE) != null
}
}
override fun printScopeStructure(p: Printer) {
allMemberScope.printScopeStructure(p)
}
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
if (forDelegatedMembersOnly) return null
return allMemberScope.getContributedClassifier(name, location)?.takeIf { it.isDeclaredInOwner() }
}
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
return allMemberScope.getContributedDescriptors(kindFilter, nameFilter).filter {
it.isDeclaredInOwner() && it.isDelegatedIfRequired()
}.mapToDelegatedIfRequired()
}
private fun DeclarationDescriptor.isDelegatedIfRequired(): Boolean =
!forDelegatedMembersOnly || this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.DELEGATION
private inline fun <reified D : DeclarationDescriptor> Collection<D>.mapToDelegatedIfRequired(): Collection<D> {
if (!forDelegatedMembersOnly) return this
return map {
val overridden = (it as CallableMemberDescriptor).overriddenDescriptors.firstOrNull()
overridden?.newCopyBuilder()
?.setModality(Modality.OPEN)
?.setKind(CallableMemberDescriptor.Kind.DELEGATION)
?.setDispatchReceiverParameter(it.dispatchReceiverParameter)
?.setPreserveSourceElement()
?.build() as? D ?: it
}
}
private fun DeclarationDescriptor.isDeclaredInOwner() = when (this) {
is CallableDescriptor -> dispatchReceiverParameter?.containingDeclaration == owner
else -> containingDeclaration == owner
}
}
override val KaFileSymbol.fileScope: KaScope
get() = withValidityAssertion {
require(this is KaFe10FileSymbol)
return KaFe10FileScope(psi, analysisContext, token)
}
override val KaPackageSymbol.packageScope: KaScope
get() = withValidityAssertion {
require(this is KaFe10PackageSymbol)
val packageFragments = analysisContext.resolveSession.packageFragmentProvider.packageFragments(fqName)
val scopeDescription = "Compound scope for package \"${fqName}\""
val chainedScope = ChainedMemberScope.create(scopeDescription, packageFragments.map { it.getMemberScope() })
return KaFe10PackageScope(chainedScope, this, analysisContext)
}
override fun List<KaScope>.asCompositeScope(): KaScope = withValidityAssertion {
return KaBaseCompositeScope.create(this, token)
}
override val KaType.scope: KaTypeScope?
get() = withValidityAssertion {
require(this is KaFe10Type)
TODO()
}
override val KaTypeScope.declarationScope: KaScope
get() = withValidityAssertion {
TODO()
}
override val KaType.syntheticJavaPropertiesScope: KaTypeScope?
get() = withValidityAssertion {
require(this is KaFe10Type)
TODO()
}
override fun KtFile.scopeContext(position: KtElement): KaScopeContext = withPsiValidityAssertion(this, position) {
val elementToAnalyze = position.containingNonLocalDeclaration() ?: this
val bindingContext = analysisContext.analyze(elementToAnalyze)
val scopeKind = KaScopeKinds.LocalScope(0) // TODO
val lexicalScope = position.getResolutionScope(bindingContext)
if (lexicalScope != null) {
val compositeScope = KaBaseCompositeScope.create(listOf(KaFe10ScopeLexical(lexicalScope, analysisContext)), token)
return KaBaseScopeContext(
listOf(KaScopeWithKindImpl(compositeScope, scopeKind)),
collectImplicitReceivers(lexicalScope),
token,
)
}
val fileScope = analysisContext.resolveSession.fileScopeProvider.getFileResolutionScope(this)
val compositeScope = KaBaseCompositeScope.create(listOf(KaFe10ScopeLexical(fileScope, analysisContext)), token)
return KaBaseScopeContext(
listOf(KaScopeWithKindImpl(compositeScope, scopeKind)),
collectImplicitReceivers(fileScope),
token,
)
}
override val KtFile.importingScopeContext: KaScopeContext
get() = withPsiValidityAssertion {
val importingScopes = scopeContext(position = this)
.scopes
.filter { it.kind is KaScopeKind.ImportingScope }
return KaBaseScopeContext(importingScopes, implicitValues = emptyList(), token)
}
private inline fun <reified T : DeclarationDescriptor> getDescriptor(symbol: KaSymbol): T? {
return when (symbol) {
is KaFe10DescSymbol<*> -> symbol.descriptor as? T
is KaFe10PsiSymbol<*, *> -> symbol.descriptor as? T
else -> {
require(symbol is KaFe10Symbol) { "Unrecognized symbol implementation found" }
null
}
}
}
private fun collectImplicitReceivers(scope: LexicalScope): MutableList<KaImplicitReceiver> {
val result = mutableListOf<KaImplicitReceiver>()
for ((index, implicitReceiver) in scope.getImplicitReceiversHierarchy().withIndex()) {
val type = implicitReceiver.type.toKtType(analysisContext)
val ownerDescriptor = implicitReceiver.containingDeclaration
val owner = ownerDescriptor.toKtSymbol(analysisContext)
if (owner == null) {
LOG.error("Unexpected implicit receiver owner: $ownerDescriptor (${ownerDescriptor.javaClass})")
continue
}
result += KaBaseScopeImplicitReceiverValue(type, owner, index)
}
return result
}
}
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KaFe10FunctionSignature
import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KaFe10VariableSignature
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSignatureSubstitutor
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.signatures.KaFunctionSignature
import org.jetbrains.kotlin.analysis.api.signatures.KaVariableSignature
import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaVariableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.contextParameters
import org.jetbrains.kotlin.analysis.api.symbols.receiverType
internal class KaFe10SignatureSubstitutor(
override val analysisSessionProvider: () -> KaFe10Session,
) : KaBaseSignatureSubstitutor<KaFe10Session>(), KaFe10SessionComponent {
override fun <S : KaFunctionSymbol> S.asSignature(): KaFunctionSignature<S> = withValidityAssertion {
KaFe10FunctionSignature(
backingSymbol = this,
backingReturnType = returnType,
backingReceiverType = receiverType,
backingValueParameters = valueParameters.map { it.asSignature() },
backingContextParameters = contextParameters.map { it.asSignature() },
)
}
override fun <S : KaVariableSymbol> S.asSignature(): KaVariableSignature<S> = withValidityAssertion {
KaFe10VariableSignature(
backingSymbol = this,
backingReturnType = returnType,
backingReceiverType = receiverType,
backingContextParameters = contextParameters.map { it.asSignature() },
)
}
}
\ No newline at end of file
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.components.KaSourceProvider
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KaDeclarationSymbol
internal class KaFe10SourceProvider(
override val analysisSessionProvider: () -> KaSession
) : KaBaseSessionComponent<KaSession>(), KaSourceProvider {
override val KaDeclarationSymbol.klibSourceFileName: String?
get() = withValidityAssertion {
throw NotImplementedError("Method is not implemented for FE 1.0")
}
}
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.components.KaSubstitutorProvider
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSessionComponent
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaTypeParameterSymbol
import org.jetbrains.kotlin.analysis.api.types.KaSubstitutor
import org.jetbrains.kotlin.analysis.api.types.KaType
internal class KaFe10SubstitutorProvider(
override val analysisSessionProvider: () -> KaSession
) : KaBaseSessionComponent<KaSession>(), KaSubstitutorProvider {
override fun createInheritanceTypeSubstitutor(subClass: KaClassSymbol, superClass: KaClassSymbol): KaSubstitutor? {
withValidityAssertion {
throw UnsupportedOperationException("This operation is not supported in the K1 version of the Analysis API.")
}
}
override fun createSubstitutor(mappings: Map<KaTypeParameterSymbol, KaType>): KaSubstitutor = withValidityAssertion {
if (mappings.isEmpty()) return KaSubstitutor.Empty(token)
throw UnsupportedOperationException("This operation is not supported in the K1 version of the Analysis API.")
}
}
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getSymbolDescriptor
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSymbolDeclarationOverridesProvider
import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaValueParameterSymbol
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
internal class KaFe10SymbolDeclarationOverridesProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSymbolDeclarationOverridesProvider<KaFe10Session>(), KaFe10SessionComponent {
fun <T : KaSymbol> getAllOverriddenSymbols(callableSymbol: T): Sequence<KaCallableSymbol> {
if (callableSymbol is KaValueParameterSymbol) {
return getAllOverriddenSymbolsForParameter(callableSymbol)
}
val descriptor = getSymbolDescriptor(callableSymbol) as? CallableMemberDescriptor ?: return emptySequence()
return getOverriddenDescriptors(descriptor, true)
.mapNotNull { it.toKtCallableSymbol(analysisContext) }
.distinct()
.asSequence()
}
fun <T : KaSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): Sequence<KaCallableSymbol> {
if (callableSymbol is KaValueParameterSymbol) {
return getDirectlyOverriddenSymbolsForParameter(callableSymbol)
}
val descriptor = getSymbolDescriptor(callableSymbol) as? CallableMemberDescriptor ?: return emptySequence()
return getOverriddenDescriptors(descriptor, false)
.mapNotNull { it.toKtCallableSymbol(analysisContext) }
.distinct()
.asSequence()
}
private fun getOverriddenDescriptors(
descriptor: CallableMemberDescriptor,
collectAllOverrides: Boolean
): Collection<CallableMemberDescriptor> {
val overriddenDescriptors = LinkedHashSet<CallableMemberDescriptor>()
val queue = ArrayDeque<CallableMemberDescriptor>().apply { addAll(descriptor.overriddenDescriptors) }
while (queue.isNotEmpty()) {
val current = queue.removeFirst()
if (current.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
overriddenDescriptors.add(current)
if (!collectAllOverrides) {
continue
}
}
val overriddenDescriptorsForCurrent = current.overriddenDescriptors
for (overriddenDescriptor in overriddenDescriptorsForCurrent) {
if (overriddenDescriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
overriddenDescriptors.add(overriddenDescriptor)
}
}
queue.addAll(overriddenDescriptorsForCurrent)
}
return overriddenDescriptors
}
fun isSubClassOf(subClass: KaClassSymbol, superClass: KaClassSymbol): Boolean {
if (subClass == superClass) return false
val subClassDescriptor = getSymbolDescriptor(subClass) as? ClassDescriptor ?: return false
val superClassDescriptor = getSymbolDescriptor(superClass) as? ClassDescriptor ?: return false
return subClassDescriptor.isSubclassOf(superClassDescriptor)
}
fun isDirectSubClassOf(subClass: KaClassSymbol, superClass: KaClassSymbol): Boolean {
val subClassDescriptor = getSymbolDescriptor(subClass) as? ClassDescriptor ?: return false
val superClassDescriptor = getSymbolDescriptor(superClass) as? ClassDescriptor ?: return false
return subClassDescriptor.getSuperClassOrAny() == superClassDescriptor
}
}
\ No newline at end of file
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.KaFe10SessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getDescriptor
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getSymbolDescriptor
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSymbolInformationProvider
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.resolve.AnnotationChecker
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.deprecation.SimpleDeprecationInfo
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.util.OperatorChecks
internal class KaFe10SymbolInformationProvider(
override val analysisSessionProvider: () -> KaFe10Session
) : KaBaseSymbolInformationProvider<KaFe10Session>(), KaFe10SessionComponent {
override val KaSymbol.deprecationStatus: DeprecationInfo?
get() = withValidityAssertion {
val descriptor = getSymbolDescriptor(this) ?: return null
ForceResolveUtil.forceResolveAllContents(descriptor)
return getDeprecation(descriptor)
}
override val KaNamedFunctionSymbol.canBeOperator: Boolean
get() = withValidityAssertion {
val functionDescriptor = this.getDescriptor() as? FunctionDescriptor ?: return false
OperatorChecks.check(functionDescriptor).isSuccess
}
override fun KaSymbol.deprecationStatus(annotationUseSiteTarget: AnnotationUseSiteTarget?): DeprecationInfo? = withValidityAssertion {
when (annotationUseSiteTarget) {
AnnotationUseSiteTarget.PROPERTY_GETTER -> {
if (this is KaPropertySymbol) {
return (getter ?: this).deprecationStatus
}
}
AnnotationUseSiteTarget.PROPERTY_SETTER -> {
if (this is KaPropertySymbol) {
return (setter ?: this).deprecationStatus
}
}
AnnotationUseSiteTarget.SETTER_PARAMETER -> {
if (this is KaPropertySymbol) {
return (setter?.parameter ?: this).deprecationStatus
}
}
else -> {}
}
return deprecationStatus // TODO
}
private fun getDeprecation(descriptor: DeclarationDescriptor): DeprecationInfo? {
if (descriptor is PropertyDescriptor) {
val fieldDescriptor = descriptor.backingField
if (fieldDescriptor != null && fieldDescriptor.annotations.hasAnnotation(DeprecationResolver.JAVA_DEPRECATED)) {
return SimpleDeprecationInfo(DeprecationLevelValue.WARNING, propagatesToOverrides = false, message = null)
}
}
return analysisContext.deprecationResolver.getDeprecations(descriptor).firstOrNull()
}
private fun getAccessorDeprecation(
property: KaPropertySymbol,
accessor: KaPropertyAccessorSymbol?,
accessorDescriptorProvider: (PropertyDescriptor) -> PropertyAccessorDescriptor?
): DeprecationInfo? {
val propertyDescriptor = getSymbolDescriptor(property) as? PropertyDescriptor ?: return null
ForceResolveUtil.forceResolveAllContents(propertyDescriptor)
if (accessor != null) {
val accessorDescriptor = getSymbolDescriptor(accessor) as? PropertyAccessorDescriptor
if (accessorDescriptor != null) {
ForceResolveUtil.forceResolveAllContents(accessorDescriptor.correspondingProperty)
val deprecation = analysisContext.deprecationResolver.getDeprecations(accessorDescriptor).firstOrNull()
if (deprecation != null) {
return deprecation
}
}
}
val accessorDescriptor = accessorDescriptorProvider(propertyDescriptor)
if (accessorDescriptor != null) {
val deprecation = analysisContext.deprecationResolver.getDeprecations(accessorDescriptor).firstOrNull()
if (deprecation != null) {
return deprecation
}
}
return getDeprecation(propertyDescriptor)
}
override val KaPropertySymbol.getterDeprecationStatus: DeprecationInfo?
get() = withValidityAssertion { getAccessorDeprecation(this, getter) { it.getter } }
override val KaPropertySymbol.setterDeprecationStatus: DeprecationInfo?
get() = withValidityAssertion { getAccessorDeprecation(this, setter) { it.setter } }
override val KaClassSymbol.annotationApplicableTargets: Set<KotlinTarget>?
get() = withValidityAssertion {
val descriptor = getSymbolDescriptor(this) as? ClassDescriptor ?: return null
if (descriptor.kind != ClassKind.ANNOTATION_CLASS) return null
return AnnotationChecker.applicableTargetSet(descriptor)
}
}
\ No newline at end of file
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.descriptors.components.base
import org.jetbrains.kotlin.analysis.api.components.KaSessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10Session
internal interface KaFe10SessionComponent : KaSessionComponent {
val analysisSession: KaFe10Session
val analysisContext: Fe10AnalysisContext
get() = analysisSession.analysisContext
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment