├── .github └── workflows │ └── build-docs.yml ├── .idea ├── .gitignore ├── analysis-api-docs.iml ├── modules.xml └── vcs.xml ├── LICENSE ├── README.md └── Writerside ├── c.list ├── hi.tree ├── images ├── statistics-metrics-plotter-analyze-invocations.png └── statistics-metrics-plotter-open-file.png ├── redirection-rules.xml ├── topics ├── Annotations.md ├── Case-Studies.md ├── Declaring-K2-Compatibility.md ├── Diagnostics.md ├── File-Compilation.md ├── Fundamentals.md ├── In-memory-file-analysis.md ├── Index.md ├── Java-Kotlin-Bridging.md ├── KaAnnotation.md ├── KaAnnotationCall.md ├── KaAnnotationValue.md ├── KaAnonymousFunctionSymbol.md ├── KaAnonymousObjectSymbol.md ├── KaBackingFieldSymbol.md ├── KaCall.md ├── KaCallableMemberCall.md ├── KaCallableSymbol.md ├── KaCapturedType.md ├── KaClassErrorType.md ├── KaClassLikeSymbol.md ├── KaClassSymbol.md ├── KaClassType.md ├── KaClassifierSymbol.md ├── KaCompoundArrayAccessCall.md ├── KaCompoundVariableAccessCall.md ├── KaConstructorSymbol.md ├── KaDeclarationSymbol.md ├── KaDefinitelyNotNullType.md ├── KaDelegatedConstructorCall.md ├── KaDiagnostic.md ├── KaDiagnosticWithPsi.md ├── KaDynamicType.md ├── KaEnumEntrySymbol.md ├── KaErrorType.md ├── KaFlexibleType.md ├── KaFunctionCall.md ├── KaFunctionSymbol.md ├── KaFunctionType.md ├── KaIntersectionType.md ├── KaLocalVariableSymbol.md ├── KaNamedClassSymbol.md ├── KaNamedFunctionSymbol.md ├── KaPropertyAccessorSymbol.md ├── KaPropertySymbol.md ├── KaSimpleFunctionCall.md ├── KaSymbol.md ├── KaType.md ├── KaTypeAliasSymbol.md ├── KaTypeParameterSymbol.md ├── KaTypeParameterType.md ├── KaTypeProjection.md ├── KaUsualClassType.md ├── KaValueParameterSymbol.md ├── KaVariableAccessCall.md ├── KaVariableSymbol.md ├── Migrating-from-K1.md ├── Other.md ├── Receivers.md ├── References-And-Calls.md ├── Scopes.md ├── Statistics.md ├── Symbols.md ├── Testing-in-K2-Locally.md └── Types.md ├── v.list └── writerside.cfg /.github/workflows/build-docs.yml: -------------------------------------------------------------------------------- 1 | name: Build documentation 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | id-token: write 10 | pages: write 11 | 12 | env: 13 | INSTANCE: 'Writerside/hi' 14 | ARTIFACT: 'webHelpHI2-all.zip' 15 | DOCKER_VERSION: '241.18775' 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Build docs using Writerside Docker builder 27 | uses: JetBrains/writerside-github-action@v4 28 | with: 29 | instance: ${{ env.INSTANCE }} 30 | artifact: ${{ env.ARTIFACT }} 31 | docker-version: ${{ env.DOCKER_VERSION }} 32 | 33 | - name: Save artifact with build results 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: docs 37 | path: | 38 | artifacts/${{ env.ARTIFACT }} 39 | artifacts/report.json 40 | retention-days: 7 41 | test: 42 | needs: build 43 | runs-on: ubuntu-latest 44 | steps: 45 | - name: Download artifacts 46 | uses: actions/download-artifact@v4 47 | with: 48 | name: docs 49 | path: artifacts 50 | 51 | - name: Test documentation 52 | uses: JetBrains/writerside-checker-action@v1 53 | with: 54 | instance: ${{ env.INSTANCE }} 55 | deploy: 56 | environment: 57 | name: github-pages 58 | url: ${{ steps.deployment.outputs.page_url }} 59 | needs: [build, test] 60 | runs-on: ubuntu-latest 61 | steps: 62 | - name: Download artifacts 63 | uses: actions/download-artifact@v4 64 | with: 65 | name: docs 66 | 67 | - name: Unzip artifact 68 | run: unzip -O UTF-8 -qq '${{ env.ARTIFACT }}' -d dir 69 | 70 | - name: Setup Pages 71 | uses: actions/configure-pages@v4 72 | 73 | - name: Package and upload Pages artifact 74 | uses: actions/upload-pages-artifact@v3 75 | with: 76 | path: dir 77 | 78 | - name: Deploy to GitHub Pages 79 | id: deployment 80 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml -------------------------------------------------------------------------------- /.idea/analysis-api-docs.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 JetBrains s.r.o. and respective authors and developers. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kotlin Analysis API Guide 2 | 3 | [![official project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) 4 | [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 5 | 6 | This repository contains documentation sources for the Kotlin Analysis API library. You might want to check the 7 | [Analysis API guide](https://kotl.in/analysis-api) which is generated from this repository. 8 | 9 | The sources of the Analysis API itself live inside the [Kotlin language repository](https://github.com/JetBrains/kotlin/tree/master/analysis). 10 | 11 | --- 12 | 13 | The Analysis API is a powerful library for analyzing code in Kotlin. Built on top of the Kotlin PSI syntax tree, it 14 | provides access to various semantic information, including reference targets, expression types, declaration scopes, 15 | diagnostics, and more. 16 | -------------------------------------------------------------------------------- /Writerside/c.list: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Writerside/hi.tree: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Writerside/images/statistics-metrics-plotter-analyze-invocations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/analysis-api/ad260699894a64ac42a1a2c5f65555a2869f42e5/Writerside/images/statistics-metrics-plotter-analyze-invocations.png -------------------------------------------------------------------------------- /Writerside/images/statistics-metrics-plotter-open-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/analysis-api/ad260699894a64ac42a1a2c5f65555a2869f42e5/Writerside/images/statistics-metrics-plotter-open-file.png -------------------------------------------------------------------------------- /Writerside/redirection-rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /Writerside/topics/Annotations.md: -------------------------------------------------------------------------------- 1 | # Annotations 2 | 3 | Annotations play a crucial role in Kotlin, providing metadata and influencing code behavior. 4 | The Analysis API allows you to access and analyze annotations applied to both declarations and types. 5 | 6 | ## KaAnnotated 7 | 8 | `KaAnnotated` is an interface exposing a list of annotations. All [types](Types.md) and almost all 9 | [symbols](Symbols.md) implement it. 10 | 11 | 12 | graph TD 13 | KaAnnotated 14 | KaAnnotated --> KaType 15 | KaAnnotated --> KaAnnotatedSymbol 16 | KaAnnotatedSymbol --> KaFileSymbol 17 | KaAnnotatedSymbol --> KaScriptSymbol 18 | KaAnnotatedSymbol --> KaDeclarationSymbol 19 | 20 | 21 | The only property `KaAnnotated` declares is `annotations` of the `KaAnnotationList` type. `KaAnnotationList` itself 22 | is implements a `List`, so you can directly iterate over annotations: 23 | 24 | ```Kotlin 25 | fun KaSession.processAnnotations(symbol: KaDeclarationSymbol) { 26 | for (anno in symbol.annotations) { 27 | // Process the 'annotation' 28 | } 29 | } 30 | ``` 31 | 32 | `KaAnnotationsList` is not just a list. It can also efficiently check whether an annotation with some `ClassId` 33 | is there: 34 | 35 | ```Kotlin 36 | fun KaSession.hasDeprecatedAnnotation(symbol: KaDeclarationSymbol) { 37 | val classId = ClassId.fromString("kotlin/Deprecated") 38 | return classId in symbol.annotations 39 | } 40 | ``` 41 | 42 | You can also get a list of annotations with a specific `ClassId`. Kotlin allows repeatable annotations, so a list 43 | of them is returned: 44 | 45 | ```Kotlin 46 | fun KaSession.findDeprecatedAnnotation(symbol: KaDeclarationSymbol): KaAnnotation? { 47 | val classId = ClassId.fromString("kotlin/Deprecated") 48 | return symbol.annotations[classId].firstOrNull() 49 | } 50 | ``` 51 | 52 | Finally, `KaAnnotationList` exposes a collection of all annotation `ClassId`s: 53 | 54 | ```Kotlin 55 | fun KaSession.collectAnnotations(types: List): Set { 56 | return types.flatMapTo(HashSet()) { it.annotations.classIds } 57 | } 58 | ``` 59 | 60 | ## Use-Site Targets 61 | 62 | Annotations on declarations can have use-site targets, specifying where the annotation applies (e.g., property, field, 63 | or parameter). You can use the `useSiteTarget` property of `KtAnnotation` to access this information. -------------------------------------------------------------------------------- /Writerside/topics/Case-Studies.md: -------------------------------------------------------------------------------- 1 | # Case Study: Main function should return 'Unit' 2 | 3 | ## Introduction 4 | 5 | The `MainFunctionReturnUnitInspection` from the Kotlin IntelliJ IDEA plugin checks whether the `main()`-like function 6 | has the `Unit` return type. If the return type is implicit, it's easy to return something different by mistake. 7 | The inspection helps to avoid the issue. 8 | 9 | In the following function, the author most likely intended to create a `main()` function. But in fact, it returns a 10 | `PrintStream`. 11 | 12 | ```Kotlin 13 | fun main(args: Array) = System.err.apply { 14 | args.forEach(::println) 15 | } 16 | ``` 17 | 18 | Both the K1 and K2 inspection implementations use a named function visitor. 19 | The difference lies in the `processFunction()` implementation. 20 | 21 | ```Kotlin 22 | internal class MainFunctionReturnUnitInspection : LocalInspectionTool() { 23 | override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { 24 | return namedFunctionVisitor { processFunction(it, holder) } 25 | } 26 | } 27 | ``` 28 | 29 | ## K1 Implementation 30 | 31 | Here is the [old](https://github.com/JetBrains/intellij-community/blob/57c570fa9816127f425671605cc390b094e520a0/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/MainFunctionReturnUnitInspection.kt#L27), 32 | K1-based implementation of `processFunction()`. 33 | 34 | ```Kotlin 35 | if (function.name != "main") return 36 | val descriptor = function.descriptor as? FunctionDescriptor ?: return 37 | val mainFunctionDetector = MainFunctionDetector(function.languageVersionSettings) { it.resolveToDescriptorIfAny() } 38 | if (!mainFunctionDetector.isMain(descriptor, checkReturnType = false)) return 39 | if (descriptor.returnType?.let { KotlinBuiltIns.isUnit(it) } == true) return 40 | holder.registerProblem(...) 41 | ``` 42 | 43 | Let's look at the implementation step by step. 44 | 45 | ```Kotlin 46 | if (function.name != "main") return 47 | ``` 48 | 49 | Here we check whether the function is named `main` to avoid running further checking logic that depends on semantic code 50 | analysis. It is crucial, as PSI-based checks are much faster than semantic ones. 51 | 52 | ```Kotlin 53 | val descriptor = function.descriptor as? FunctionDescriptor ?: return 54 | ``` 55 | 56 | Then, by using `function.descriptor` we get a `DeclarationDescriptor`, a container for semantic 57 | declaration information. In the case of a `KtNamedFunction`, it should be a `FunctionDescriptor`, holding the 58 | function's return type. 59 | 60 | The `function.descriptor` [helper](https://github.com/JetBrains/intellij-community/blob/76680787081992373bd0029cc54176963adcd858/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt#L50) 61 | calls `resolveToDescriptorIfAny()`, which itself delegates to `analyze()` to get the 62 | `BindingContext`. The obtained `BindingContext` provides bindings between elements in the code and their semantic 63 | representation (such as, `KtDeclaration` to `DeclarationDescriptor`). 64 | 65 | ```Kotlin 66 | val mainFunctionDetector = MainFunctionDetector(function.languageVersionSettings) { it.resolveToDescriptorIfAny() } 67 | if (!mainFunctionDetector.isMain(descriptor, checkReturnType = false)) return 68 | ``` 69 | 70 | Additionally, we use the `MainFunctionDetector` [compiler utility](https://github.com/JetBrains/kotlin/blob/master/compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt#L36) 71 | to check whether a descriptor indeed looks like a `main()` function. Specifically for the IDE use-cases, 72 | `MainFunctionDetector` provides an overload that allows us to skip the return type check. The `MainFunctionDetector` 73 | expects a descriptor, so we pass the one we've obtained from the `KtNamedFunction`. 74 | 75 | ```Kotlin 76 | if (descriptor.returnType?.let { KotlinBuiltIns.isUnit(it) } == true) return 77 | ``` 78 | 79 | Finally, we check whether the function's return type is `Unit`. We use the `KotlinBuiltIns` class from the compiler 80 | which has a number of static methods which check whether a type is a specific Kotlin built-in type. 81 | 82 | If the return type is not `Unit`, the function is not a proper `main()` one, so we register a problem. 83 | 84 | ## K2 Implementation 85 | 86 | Then, let's compare the old implementation with the [K2-based one](https://github.com/JetBrains/intellij-community/blob/9c7e738f1449985836f74ab2d58ee05ddd1a28e2/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/declarations/MainFunctionReturnUnitInspection.kt#L20). 87 | 88 | ```Kotlin 89 | val detectorConfiguration = KotlinMainFunctionDetector.Configuration(checkResultType = false) 90 | 91 | if (!PsiOnlyKotlinMainFunctionDetector.isMain(function, detectorConfiguration)) return 92 | if (!function.hasDeclaredReturnType() && function.hasBlockBody()) return 93 | if (!KotlinMainFunctionDetector.getInstance().isMain(function, detectorConfiguration)) return 94 | 95 | analyze(function) { 96 | if (!function.symbol.returnType.isUnitType) { 97 | holder.registerProblem(...) 98 | } 99 | } 100 | ``` 101 | 102 | Starting from the beginning, one can notice that the K2 implementation is more efficient. 103 | 104 | ```Kotlin 105 | if (!PsiOnlyKotlinMainFunctionDetector.isMain(function, detectorConfiguration)) return 106 | ``` 107 | 108 | Here we not only check the function name, but we use the [`PsiOnlyKotlinMainFunctionDetector`](https://github.com/JetBrains/intellij-community/blob/db1bf18449fab6d4a3de8576b01ef1e35a4f0ad1/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/PsiOnlyKotlinMainFunctionDetector.kt#L13) 109 | to check whether the function looks like a `main()` one using only PSI-based checks. In particular, the detector checks 110 | also the presence of type/value parameters and the function location in the file. 111 | 112 | ```Kotlin 113 | if (!function.hasDeclaredReturnType() && function.hasBlockBody()) return 114 | ``` 115 | 116 | Next, we check whether the function has a declared return type. If it doesn't, and if the function has a block body, we 117 | assume that the return type is `Unit`, so we skip further checks. 118 | 119 | ```Kotlin 120 | if (!KotlinMainFunctionDetector.getInstance().isMain(function, detectorConfiguration)) return 121 | ``` 122 | 123 | Then, we use another implementation of the `KotlinMainFunctionDetector` – this one performs semantic checks. For the 124 | K2 mode, it will be [`SymbolBasedKotlinMainFunctionDetector`](https://github.com/JetBrains/intellij-community/blob/f0132d1fa64f21db0bd8dd19207a94a90c6ef301/plugins/kotlin/base/fir/code-insight/src/org/jetbrains/kotlin/idea/base/fir/codeInsight/SymbolBasedKotlinMainFunctionDetector.kt#L24). 125 | 126 | We use the same `detectorConfiguration` as before to skip the return type check, as we want to catch `main()`-like 127 | functions with a wrong return type. 128 | 129 | ```Kotlin 130 | analyze(function) { 131 | if (!function.symbol.returnType.isUnitType) { 132 | holder.registerProblem(...) 133 | } 134 | } 135 | ``` 136 | 137 | Finally, we perform the return type check by ourselves using the Analysis API. 138 | 139 | The Analysis API requires all work with resolved declarations to be performed inside the `analyze {}` block. 140 | Inside the lambda, we get access to various helpers providing semantic information about declarations visible 141 | from the use-site module. In our case, it would be the module containing the `function` (as we passed it to `analyze()`). 142 | 143 | We need to check whether the function has a `Unit` return type. One can get it from a `KaFunctionSymbol`, 144 | a semantic representation of a function, similar to `FunctionDescriptor` in the old compiler. 145 | 146 | The `symbol` property available inside the analysis block maps a `KtDeclaration` to a `KaSymbol`. Unlike K1, 147 | the Analysis API guarantees there will be a symbol for every declaration, so we do not need an extra `?: return`. 148 | Also, `symbol` is overloaded for different kinds of declarations, so we can avoid explicit casting to a `KaFunctionSymbol`. 149 | 150 | Just like in the old implementation, we check whether the return type is `Unit`, and if it's not, we register a problem. -------------------------------------------------------------------------------- /Writerside/topics/Declaring-K2-Compatibility.md: -------------------------------------------------------------------------------- 1 | # Declaring compatibility with K2 2 | 3 | The Kotlin IntelliJ plugin assumes that a dependent third-party plugin *does not* support K2 Kotlin out of the box. Such 4 | incompatible plugins will not be loaded if the K2 mode is currently enabled. 5 | 6 | Once a plugin has been migrated to the Analysis API, a setting should be added to its `plugin.xml` to declare its 7 | compatibility with the K2 mode. Even if the plugin does not use any of the old K1 analysis functions and no migration to 8 | the Analysis API is needed, compatibility with the K2 Kotlin plugin should be declared explicitly nonetheless. 9 | 10 | Starting from IntelliJ 2024.2.1 (Preview), the following setting in the `plugin.xml` can be used to declare 11 | compatibility with the K2 mode: 12 | 13 | ```xml 14 | 15 | 16 | 17 | ``` 18 | 19 | It is also possible to declare compatibility with *only* the K2 mode: 20 | 21 | ```xml 22 | 23 | 24 | 25 | ``` 26 | 27 | Currently, the default setting for `supportsK1` is `true` and for `supportsK2` is `false`. 28 | 29 | To test it locally when using the [IntelliJ Platform Gradle Plugin](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin.html), add a [dependency](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html) on the IntelliJ IDEA Community 2024.2.1 (`intellijIdeaCommunity("2024.2.1")`) or higher. 30 | 31 | A number of third-party plugins may already be enabled in the K2 mode without a `supportsK2` declaration. The IntelliJ 32 | Kotlin plugin keeps an [internal list](https://github.com/JetBrains/intellij-community/blob/master/platform/core-impl/resources/pluginsCompatibleWithK2Mode.txt) 33 | of plugins which are known to be compatible with the K2 mode as they do not use Kotlin analysis. The authors of these 34 | plugins should not be surprised if their plugin already works in the K2 mode. However, it's still advised to check and 35 | declare K2 support explicitly as this list is not future-proof and could potentially contain unsafe plugins due to some 36 | circumstances. -------------------------------------------------------------------------------- /Writerside/topics/Diagnostics.md: -------------------------------------------------------------------------------- 1 | # Diagnostics 2 | 3 | The Analysis API allows you to access and analyze compiler diagnostics (errors and warnings) associated with entire 4 | files or specific elements. 5 | 6 | ## Diagnostics in a `KtFile` 7 | 8 | To collect diagnostics for an entire file, use `collectDiagnostics()`: 9 | 10 | ```kotlin 11 | analyze(ktFile) { 12 | val diagnostics = ktFile 13 | .collectDiagnostics(KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS) 14 | .filterIsInstance() 15 | } 16 | ``` 17 | 18 | The `KaDiagnosticCheckerFilter` enum allows you to control which kinds of diagnostics are included: 19 | 20 | * `ONLY_COMMON_CHECKERS`: Includes diagnostics only from the compiler checkers. 21 | * `ONLY_EXTENDED_CHECKERS`: Includes diagnostics from extended checkers (that typically run only in the IDE). 22 | * `EXTENDED_AND_COMMON_CHECKERS`: Includes diagnostics from both common and extended checkers. 23 | 24 | ## Diagnostics on an element 25 | 26 | Experimental API. Subject to changes. 27 | 28 | To get diagnostics for a specific element, use `diagnostics`: 29 | 30 | ```kotlin 31 | analyze(ktElement) { 32 | val diagnostics = ktElement 33 | .diagnostics(KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS) 34 | } 35 | ``` 36 | 37 | Note that the returned list of diagnostics does not include diagnostics for nested `KtElement`s. 38 | 39 | ## `KtDiagnosticWithPsi` 40 | 41 | `collectDiagnostics` and `diagnostics` return a collection of `KtDiagnosticWithPsi` instances. 42 | This interface provides access to information about the diagnostic. 43 | 44 | | Member | Description | 45 | |------------------|-------------------------------------------------------------------------------| 46 | | `severity` | The severity of the diagnostic (e.g., `ERROR`, `WARNING`). | 47 | | `factoryName` | The name of the diagnostic factory that produced the diagnostic. | 48 | | `defaultMessage` | The default message associated with the diagnostic. | 49 | | `psi` | The `PsiElement` to which the diagnostic is attached. | 50 | | `textRanges` | The text ranges within the `psi` element that are relevant to the diagnostic. | -------------------------------------------------------------------------------- /Writerside/topics/File-Compilation.md: -------------------------------------------------------------------------------- 1 | # File Compilation 2 | 3 | Experimental API. Subject to changes. 4 | 5 | The Analysis API enables in-memory compilation of Kotlin files. This allows your tools and plugins to generate and 6 | compile Kotlin code without writing files to disk or invoking the command-line compiler. 7 | 8 | ## Usage 9 | 10 | To compile Kotlin code, you need to provide: 11 | 12 | * `KtFile`: The Kotlin file to compile (might be a `KtCodeFragment`); 13 | * `CompilerConfiguration`: A configuration instance containing compiler settings, such as a module name, and a target 14 | language version; 15 | * `KaCompilerTarget`: The target platform for compilation (currently, only JVM is supported 16 | with `KaCompilerTarget.Jvm`); 17 | * `allowedErrorFilter`: A function that filters allowed diagnostics. Compilation fails if there are errors 18 | that this function rejects. 19 | 20 | Here's an example of compiling a `KtFile`: 21 | 22 | ```kotlin 23 | @RequiresReadLock 24 | @OptIn(KaExperimentalApi::class) 25 | fun performCompilation(file: KtFile): List { 26 | val configuration = CompilerConfiguration() // configure compiler settings 27 | val target = KaCompilerTarget.Jvm(ClassBuilderFactories.BINARIES) 28 | 29 | analyze(file) { 30 | val result = useSiteSession.compile(file, configuration, target) { 31 | // Filter allowed diagnostics (optional) 32 | it.severity != KaSeverity.ERROR 33 | } 34 | 35 | when (result) { 36 | is KaCompilationResult.Success -> { 37 | // Process compiled output 38 | return result.output.map { it.content } 39 | } 40 | is KaCompilationResult.Failure -> { 41 | // Handle compilation errors 42 | throw RuntimeException("Compilation failed: ${result.errors}") 43 | } 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | The `compile` function throws a `KaCodeCompilationException` if any unexpected errors occur during compilation. 50 | Handle this exception appropriately in your code. 51 | 52 | ## KaCompilationResult 53 | 54 | The `compile` function returns a `KaCompilationResult`, which can be either: 55 | 56 | * `KaCompilationResult.Success`: Compilation was successful. You can access the generated output files through 57 | the `output` property. 58 | * `KaCompilationResult.Failure`: Compilation failed due to errors. The `errors` property contains a list of the 59 | encountered diagnostics. 60 | 61 | ## Output Files 62 | 63 | The `output` property of `KaCompilationResult.Success` provides a list of `KaCompiledFile` instances, each containing: 64 | 65 | `val path: String` 66 | : The relative path of the compiled file. 67 | 68 | `val sourceFiles: List` 69 | : The source files that contributed to the compiled file. 70 | 71 | `val content: ByteArray` 72 | : The content of the compiled file as a byte array. -------------------------------------------------------------------------------- /Writerside/topics/Fundamentals.md: -------------------------------------------------------------------------------- 1 | # Fundamentals 2 | 3 | This page covers a few fundamental concepts and rules of the Analysis API. Please read it thoroughly. 4 | 5 | ## Kotlin PSI 6 | 7 | The Kotlin compiler exposes a Kotlin abstract syntax tree, built on top of 8 | the [PSI](https://plugins.jetbrains.com/docs/intellij/psi.html) API, a part of IntelliJ IDEA. For some languages, such 9 | as Java, the PSI acts both as a syntax tree and as a source of semantic information. In Kotlin, though, these concepts 10 | are clearly separated. 11 | 12 | Below is a simplified tree of the Kotlin PSI hierarchy. 13 | 14 | 15 | graph TD 16 | KtElement 17 | KtElement --> KtFile 18 | KtElement --> KtTypeElement 19 | KtElement --> KtExpression 20 | KtExpression --> KtDeclaration 21 | KtDeclaration --> KtClassOrObject 22 | KtDeclaration --> KtFunction 23 | KtDeclaration --> KtVariableDeclaration 24 | KtExpression --> KtOperationExpression 25 | KtOperationExpression --> KtUnaryExpression 26 | KtOperationExpression --> KtBinaryExpression 27 | KtExpression --> KtCallExpression 28 | KtExpression --> KtBlockExpression 29 | 30 | 31 | `KtElement` is the root type of the hierarchy. `KtDeclaration` and `KtExpression` are two notable subtypes of 32 | it. `KtDeclaration` itself is an expression, which makes it possible to have local classes and functions. 33 | 34 | The Kotlin PSI does not have a strict separation between statements and expressions. There is, however, 35 | a `KtStatementExpression` marker interface that annotates statement-like constructs. 36 | 37 | The Analysis API is implemented on top of the Kotlin PSI, mostly as a set of extension functions and properties, 38 | providing access to semantic information. For example, to get an expression type, there is 39 | a `ktExpression.expressionType` extension property. Or, to get resolved call information, one should 40 | use `ktCallExpression.resolveToCall()`. 41 | 42 | ## KaSession 43 | 44 | `KaSession` is the entry point for interacting with the Analysis API. It provides access to various components and 45 | utilities needed for analyzing code in Kotlin. 46 | 47 | Each `KaSession` is associated with a specific module and provides analysis results from the perspective of that module. 48 | In other words, a `KaSession` only sees declarations from the owning (use-site) module and from all its dependencies, 49 | both direct and transitive. 50 | 51 | To get a `KaSession`, use the `analyze {}` function, passing a `KtModule` or some `KtElement` from that module: 52 | 53 | ```Kotlin 54 | @RequiresReadLock 55 | fun perform(element: KtElement) { 56 | analyze(element) { 57 | // Use the 'KaSession' within this block 58 | } 59 | } 60 | ``` 61 | 62 | The `KaSession` is available as an extension receiver within the lambda block. The session is valid only within this 63 | block, and it **should not** be stored or accessed outside of it. 64 | 65 | The `analyze {}` call is only available 66 | inside [read actions](https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#read-access). You can use 67 | the `@RequiresReadLock` annotation to specify that the method must be called from a read action. In later parts of the 68 | documentation, the annotation is not added for clarity. 69 | 70 | ## KaLifetimeOwner 71 | 72 | `KaSession` and most entities retrieved from it (symbols, types, etc.) are valid only within the same read action and 73 | the `analyze` block in which they were created. All such entities have the `KaLifetimeOwner` supertype. 74 | 75 | It is crucial to avoid caching `KaLifetimeOwner`s for an arbitrary time, including storing them in properties of 76 | long-living classes or in a static context. Doing so will likely lead to severe memory leaks as these entities hold the 77 | whole underlying resolution session. Always retrieve and use them within the `analyze` block or pass them as parameters 78 | to functions that require them. 79 | 80 | If you need to extract parts of the resolution logic to a separate function, prefer passing the `KaSession` as an 81 | extension or ordinary parameter, instead of keeping it in some shared context class. 82 | 83 | ```Kotlin 84 | fun perform(element: KtElement) { 85 | analyze(element) { 86 | if (check(element)) { 87 | modify(element) 88 | } 89 | } 90 | } 91 | 92 | // Here we pass the session as a receiver parameter 93 | fun KaSession.check(element: KtElement) { ... } 94 | 95 | fun modify(element: KtElement) { ... } 96 | ``` 97 | 98 | Inside the `analyze {}` block, `KaSession` is also available as a `useSiteSession` property: 99 | 100 | ```Kotlin 101 | fun perform(element: KtElement) { 102 | analyze(element) { 103 | check(useSiteSession, element) 104 | } 105 | } 106 | 107 | // Here we pass the session as an ordinary parameter 108 | fun check(useSiteSession: KaSession, element: KtElement) { ... } 109 | ``` 110 | 111 | If you need to pass a `KaSymbol` to a different analysis session, use `KaSymbolPointer`s. Unlike symbols, pointers do 112 | not capture the analysis session, so they can be freely passed around or cached: 113 | 114 | ```Kotlin 115 | fun perform(ktCall: KtCallExpression) { 116 | val pointer = resolveCall(ktCall) ?: return 117 | processCallTarget(ktCall, pointer) 118 | } 119 | 120 | fun resolveCall(ktCall: KtCallExpression): KaSymbolPointer? { 121 | analyze(ktCall) { 122 | val symbol = ktCall.mainReference.resolveToSymbol() as? KaCallableSymbol 123 | return symbol?.createPointer() // Create the pointer 124 | } 125 | } 126 | 127 | fun processCallTarget(ktContext: KtElement, pointer: KaSymbolPointer) { 128 | analyze(ktContext) { 129 | val symbol = pointer.restoreSymbol() ?: return 130 | symbol.callableId // Use the restored symbol 131 | } 132 | } 133 | ``` 134 | 135 | 136 | In IntelliJ IDEA 2024.3, pointers will become available also for KaTypes. 137 | -------------------------------------------------------------------------------- /Writerside/topics/In-memory-file-analysis.md: -------------------------------------------------------------------------------- 1 | # In-memory file analysis 2 | 3 | Experimental API. Subject to changes. 4 | 5 | Parsing a Kotlin file does not require any knowledge about the project it belongs to. On the other hand, for *semantic 6 | code analysis*, understanding dependencies and compilation options of a file is crucial. 7 | 8 | In most cases, source files — whether written by a user or auto-generated — are stored on disk and belong to a specific module. 9 | The build system understands the project layout and instructs the compiler or the IDE to use appropriate dependencies for 10 | all files in that module. For script files, such as `build.gradle.kts`, the situation is more complex since 11 | scripts technically do not belong to any module. However, in such cases, the build system also provides the necessary 12 | context. For example, Gradle build scripts include the Gradle API and all libraries Gradle depends on in their classpath. 13 | 14 | In certain cases, it might be useful to analyze a file without storing it in the file system. For example, an IDE 15 | inspection may use in-memory files to verify whether code will remain valid after applying a proposed change. 16 | Specifically, the inspection might create a copy of the `KtFile`, apply the change to the copy, and check for new 17 | compilation errors. In such scenarios, the inspection needs to supply the correct analysis context for the in-memory 18 | `KtFile`. 19 | 20 | The Analysis API provides multiple approaches for analyzing in-memory files and attaching context to them. 21 | Below, we explore these options and their differences. 22 | 23 | ## Stand-alone file analysis 24 | 25 | Let's begin with the most generic case: creating an in-memory file with arbitrary content and analyzing it. 26 | 27 | To create a file, we use the `KtPsiFactory` class: 28 | 29 | ```kotlin 30 | val text = 31 | """ 32 | package test 33 | 34 | fun foo() { 35 | println("Hello, world!") 36 | } 37 | """.trimIndent() 38 | 39 | val factory = KtPsiFactory(project) 40 | val file = factory.createFile(text) 41 | ``` 42 | 43 | `KtPsiFactory` offers many utilities for creating chunks of Kotlin code. In our case, we are primarily interested in 44 | creating entire Kotlin files. 45 | 46 | If we analyze the file we created using `analyze {}`, we notice that the `println` reference is reported as unresolved: 47 | 48 | ```kotlin 49 | analyze(file) { 50 | val diagnostics = file.collectDiagnostics(KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS) 51 | // ["Unresolved reference 'println'."] 52 | val messages = diagnostics.map { it.defaultMessage } 53 | } 54 | ``` 55 | 56 | This happens because the `KtFile` we created lacks any attached context, making the Kotlin Standard Library unavailable. 57 | However, code in the file still *can* access a few basic Kotlin types, such as `Int` or `String`, and can resolve 58 | references to declarations from the same file. 59 | 60 | Now, let's assume we have a `contextFile` that belongs to a module and want to analyze our in-memory file as it was 61 | in that module. First, we retrieve the containing module of the `contextFile`. 62 | 63 | ```kotlin 64 | val contextModule = KaModuleProvider.getModule(project, contextFile, useSiteModule = null) 65 | ``` 66 | 67 | Now that we have the module, we attach it to our file: 68 | 69 | ```kotlin 70 | @OptIn(KaExperimentalApi::class) 71 | file.contextModule = contextModule 72 | ``` 73 | 74 | If the context module includes a dependency to the Kotlin Standard library, the analysis will no longer produce errors. 75 | 76 | The created file can reference declarations from the context module, including `internal` ones. 77 | However, no matter the content of our newly created file, it will not affect resolution of our context file. 78 | Such as, if we declare a function in the `file`, it will not be visible from the `contextFile`. 79 | 80 | Here is the complete code of our example: 81 | 82 | ```kotlin 83 | val text = 84 | """ 85 | package test 86 | 87 | fun foo() { 88 | println("Hello, world!") 89 | } 90 | """.trimIndent() 91 | 92 | val factory = KtPsiFactory(project) 93 | val file = factory.createFile(text) 94 | 95 | val contextModule = KaModuleProvider.getModule(project, contextFile, useSiteModule = null) 96 | 97 | @OptIn(KaExperimentalApi::class) 98 | file.contextModule = contextModule 99 | 100 | analyze(file) { 101 | val diagnostics = file.collectDiagnostics(KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS) 102 | // An empty list 103 | val messages = diagnostics.map { it.defaultMessage } 104 | } 105 | ``` 106 | 107 | 108 | ## Context modules 109 | 110 | In the previous example, we used the `KaModuleProvider.getModule()` function to retrieve the module containing the 111 | `contextFile`. The returned value is of type `KaModule` which is an Analysis API abstraction over `Module`, `Library`, 112 | and `Sdk` concepts from IntelliJ IDEA. Specifically, a `KaSourceModule` represents a source module, and libraries and 113 | SDKs are represented by `KaLibraryModule`s. Every `KaSymbol` in the Analysis API is associated with some `KaModule`. 114 | 115 | If you already have a reference to a `Module`, you can convert it to a `KaModule` using one of the Kotlin plugin helper 116 | functions: 117 | 118 | ```kotlin 119 | fun Module.toKaSourceModule(kind: KaSourceModuleKind): KaSourceModule? 120 | fun Module.toKaSourceModuleForProduction(): KaSourceModule? 121 | fun Module.toKaSourceModuleForTest(): KaSourceModule? 122 | ``` 123 | 124 | For more related APIs, refer to the Kotlin plugin's 125 | [source code](https://github.com/JetBrains/intellij-community/blob/master/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/api.kt). 126 | There are also overloads that accept `ModuleId` and `ModuleEntity` from the newer project model API. 127 | 128 | In the `KaModuleProvider.getModule` function call, we passed `useSiteModule = null`. For advanced scenarios, 129 | you might want to analyze files from other modules in the context of a synthetic module. In such cases, that synthetic 130 | module can be passed as a `useSiteModule`. For typical use cases, it is safe to pass `null`. 131 | 132 | 133 | ## Physical and non-physical files 134 | 135 | In the previous example, we used the `KtPsiFactory` to create a non-physical file. From IntelliJ IDEA's perspective, 136 | "non-physical" differs from whether the file is stored on disk. We can create both physical and non-physical `KtFile`s 137 | that are not written to the disk. 138 | 139 | So what is the difference? Non-physical files are typically created for one-shot analysis. Creating them has a lower 140 | cost, but IntelliJ IDEA does not track changes in them. A physical file, on the other hand, is handled by the PSI 141 | modification machinery, allowing the Analysis API to track changes and update analysis results accordingly. 142 | 143 | If you need a long-lived file that will be modified and analyzed multiple times, you should create a physical file by 144 | using a `KtPsiFactory` with `eventSystemEnabled = true`: 145 | 146 | ```kotlin 147 | val factory = KtPsiFactory(project, eventSystemEnabled = true) 148 | val file = factory.createFile(text) 149 | ``` 150 | 151 | 152 | ## File copies 153 | 154 | In some cases, you might want to create a complete copy of an existing file, modify it in some way, and analyze 155 | the result. 156 | 157 | To create a copy of a file, you can use the `copy` function: 158 | 159 | ```kotlin 160 | val fileCopy = file.copy() as KtFile 161 | ``` 162 | 163 | The `copy()` function sets a reference to the original file in the produced copy. As a result, the `getOriginalFile()` 164 | of the newly created file points back to the original file. This allows the Analysis API to automatically use the 165 | context of the original file. In other words, there is no need to manually set the `contextModule` for a copied file. 166 | 167 | The `copy()` function creates non-physical files. For this setup (a non-physical file with a `getOriginalFile()` set), 168 | the Analysis API uses a different analysis strategy by default. 169 | 170 | This behavior is optimized for efficiency. Since the original file might be large, analyzing it from scratch could be 171 | unnecessarily resource-intensive. In most cases, file copies primarily differ in declaration bodies, so the Analysis API 172 | leverages existing analysis results from the original file. 173 | 174 | If you make changes to the declaration signatures in the copied file, you should analyze it independently of the 175 | original file. To do so, use the `PREFER_SELF` resolution mode with the `analyzeCopy()` function: 176 | 177 | ```kotlin 178 | analyzeCopy(fileCopy, KaDanglingFileResolutionMode.PREFER_SELF) { 179 | // Analysis code, just as in `analyze()` 180 | } 181 | ``` 182 | 183 | On the other side, if you manually create a physical file copy, you can still request more efficient analysis by passing 184 | the `KaDanglingFileResolutionMode.IGNORE_SELF` option: 185 | 186 | ```kotlin 187 | val factory = KtPsiFactory(file.project, eventSystemEnabled = true) 188 | val fileCopy = factory.createFile("text.kt", originalFile.text) 189 | fileCopy.originalFile = file 190 | 191 | analyzeCopy(fileCopy, KaDanglingFileResolutionMode.IGNORE_SELF) { 192 | // Analysis code, just as in `analyze()` 193 | } 194 | ``` 195 | 196 | The `analyzeCopy()` function works exclusively for file copies. Unless you need to configure the resolution mode 197 | explicitly, use the usual `analyze()` instead. 198 | 199 | In the future, the Analysis API may be able to track changes in file copies and decide on an appropriate 200 | resolution mode automatically. 201 | 202 | 203 | ## Code fragments 204 | 205 | If you only need to analyze a single expression or reference within the context of surrounding code, creating a full 206 | file copy is often unnecessary. For these use cases, the Analysis API provides the concept of *code fragments*. 207 | 208 | A code fragment is a small piece of code that can be analyzed within the context of some other code. 209 | There are three types of code fragments: 210 | 211 | - `KtExpressionCodeFragment` for analyzing a single expression; 212 | - `KtBlockCodeFragment` for analyzing a block of statements; 213 | - `KtTypeCodeFragment` for analyzing a single type reference. 214 | 215 | All three types of code fragments extend the `KtCodeFragment` class, which itself extends `KtFile`. 216 | 217 | Code fragments differ from typical `KtFile`s in several important ways: 218 | 219 | - **No package directive**: A code fragment cannot have a `package` directive; its package is inherently the same as 220 | the package of the context file. 221 | - **Import handling**: Imports are submitted externally, and no import aliases are permitted. 222 | - **Local-only content**: All content within a code fragment is considered local. 223 | 224 | To create a code fragment, you need two inputs: the source text of the fragment and a context element from the 225 | surrounding code. For example, consider the following code snippet where `print(name)` is a context element: 226 | 227 | ```kotlin 228 | fun test() { 229 | val name = "poem.txt" 230 | print(name) 231 | } 232 | ``` 233 | 234 | Now, let's create a code fragment that references `name` to read from a file: 235 | 236 | ```kotlin 237 | val fragment = KtExpressionCodeFragment( 238 | project, 239 | name = "fragment.kt", 240 | text = "File(name).readText()", 241 | context = contextElement, 242 | imports = listOf("java.io.File") 243 | ) 244 | ``` 245 | 246 | A code fragment can reference any declaration visible from its context element, including local declarations. 247 | For the above example, the code fragment accesses the local variable `name`. 248 | 249 | If we pass the `val name = "poem.txt"` declaration as a context element, the code fragment analysis will result in an 250 | error, as variables are not yet available on the line of their declaration. 251 | 252 | Since code fragments extend `KtFile`, you can analyze them in the same way as you analyze files: 253 | 254 | ```kotlin 255 | analyze(fragment) { 256 | // Analysis code 257 | } 258 | ``` 259 | 260 | Code fragments can have a context element from another code fragment, or from an in-memory file. -------------------------------------------------------------------------------- /Writerside/topics/Index.md: -------------------------------------------------------------------------------- 1 | # Analysis API 2 | 3 | The Analysis API is a powerful library for analyzing code in Kotlin. Built on top of the Kotlin PSI syntax tree, 4 | it provides access to various semantic information, including reference targets, expression types, declaration scopes, 5 | diagnostics, and more. 6 | 7 | While the Analysis API uses the Kotlin compiler internally, the API layer itself does not expose any compiler internals. 8 | The library offers both source and binary backward compatibility for its stable parts. 9 | 10 | The Analysis API encapsulates all challenging parts needed for efficient Kotlin code analysis, including lazy resolution 11 | and cache invalidation, so you can focus on the actual code handling logic. 12 | 13 | ## Quick example 14 | 15 | The `hasStringType()` function below checks if the given expression has a non-null `kotlin.String` type. 16 | 17 | ```Kotlin 18 | @RequiresReadLock 19 | fun KtExpression.hasStringType(): Boolean { 20 | analyze(this) { 21 | return expressionType == builtinTypes.string 22 | } 23 | } 24 | ``` 25 | 26 | Most of the Analysis API surface can be accessed from inside `analyze {}` blocks. Such is the `expressionType` extension 27 | property – for the given `KtExpression`, it returns the resolved type. 28 | 29 | `builtinTypes` is also a part of the Analysis API available inside the analysis block. It provides access to basic 30 | Kotlin types, including number types, `Any`, `Nothing`, and `String`. 31 | 32 | The type of `builtinTypes.string` is a `KaType`. `Ka` is a common prefix for all Analysis API components and 33 | abstractions; it means "Kotlin Analysis API". Instances of classes with the `Ka` prefix often require special handling. 34 | Check the [KaLifetimeOwner](Fundamentals.md#kalifetimeowner) section for more information. 35 | 36 | ## Using in IntelliJ IDEA 37 | 38 | The Analysis API is not just some external API. It serves as the foundation for many features within the Kotlin plugin 39 | for IntelliJ IDEA, including code completion, navigation across declarations, refactorings, inspections, the debugger, 40 | and many more. By using the Analysis API, you get the same tools as the developers of the Kotlin plugin itself. 41 | 42 | 43 | 44 | The Analysis API has been available since IntelliJ IDEA 2024.2. 45 | 46 | 47 | The API mainly targets the K2 Kotlin compiler, but there is also limited support for the legacy 1.0 compiler. 48 | The same piece of logic implemented on top of the Analysis API, works both in the K1 and K2 Kotlin modes. 49 | 50 | 51 | ## Using in command-line tools 52 | 53 | The Analysis API can also be used in command-line tools that perform Kotlin code analysis, including linters, 54 | documentation generators, and code-generating utilities. 55 | 56 | 57 | Currently, the only officially supported use-case is IntelliJ IDEA plugin development. 58 | While the Analysis API provides the Standalone mode for command-line tool developers, it is currently in development 59 | and subject to incompatible changes. 60 | -------------------------------------------------------------------------------- /Writerside/topics/Java-Kotlin-Bridging.md: -------------------------------------------------------------------------------- 1 | # Java/Kotlin Bridging 2 | 3 | Experimental API. Subject to changes. 4 | 5 | While the Analysis API exposes declarations and types from the Kotlin standpoint, it works also with Java source and 6 | library declarations. The API provides a set of utilities for converting between Kotlin and Java views of declarations. 7 | 8 | ## Types 9 | 10 | In IntelliJ IDEA, `PsiType` is a representation for Java types. Conceptually, it is similar to [`KaType`](KaType.md). 11 | The Analysis API provides mapping between the two representations. 12 | 13 | `fun PsiType.asKaType(useSitePosition: PsiElement): KaType?` 14 | : Convert the given Java type to a `KaType`. 15 | `useSitePosition` is the context element used to gather additional information related to the Java type usage. 16 | : **Experimental API**. 17 | 18 | `fun KaType.asPsiType(useSitePosition: PsiElement, allowErrorTypes: Boolean, mode: KaTypeMappingMode = KaTypeMappingMode.DEFAULT, isAnnotationMethod: Boolean = false, suppressWildcards: Boolean? = null, preserveAnnotations: Boolean = true): PsiType?` 19 | : Convert the given Kotlin type to a `PsiType.` 20 | : `useSitePosition` is used to determine if the local type needs to be approximated. 21 | : **Experimental API**. 22 | 23 | `fun KaType.mapToJvmType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): Type` 24 | : Convert the given Kotlin type to a JVM [ASM](https://asm.ow2.io/) type. 25 | : **Experimental API**. 26 | 27 | `val KaType.isPrimitiveBacked: Boolean` 28 | : `true` if the type is backed by a primitive JVM type. 29 | : **Experimental API**. 30 | 31 | ## Symbols 32 | 33 | The Analysis API can create symbols for Java declarations. 34 | 35 | `val PsiClass.namedClassSymbol: KaNamedClassSymbol?` 36 | : Map a Java class to a class symbol. Always `null` for anonymous classes and type parameters (that are also 37 | `PsiClass`es). 38 | : **Experimental API**. 39 | 40 | `val PsiMember.callableSymbol: KaCallableSymbol?` 41 | : Map a Java method or a field to a callable symbol. Always `null` for local Java declarations. 42 | : **Experimental API**. 43 | 44 | ## Other utilities 45 | 46 | `val KaCallableSymbol.containingJvmClassName: String?` 47 | : The fully qualified class name containing the callable (in the `foo.bar.Class.Companion` format). 48 | : **Experimental API**. 49 | 50 | `val KaPropertySymbol.javaGetterName: Name` 51 | : The JVM getter method name for the given property symbol. 52 | 53 | `val KaPropertySymbol.javaSetterName: Name?` 54 | : The JVM setter method name for the given property symbol. -------------------------------------------------------------------------------- /Writerside/topics/KaAnnotation.md: -------------------------------------------------------------------------------- 1 | # KaAnnotation 2 | 3 | Represents an [annotation](https://kotlinlang.org/docs/annotations.html) call, such as `@JvmName("foo")`. 4 | 5 | ## Members 6 | 7 | `val classId: ClassId?` 8 | : The qualified annotation class name, or `null` if the annotation call is unresolved. 9 | 10 | `val constructorSymbol: KaConstructorSymbol?` 11 | : The called annotation constructor, or `null` if the annotation call is unresolved. 12 | 13 | `val hasArguments: Boolean` 14 | : `true` if the annotation call has one or more arguments. 15 | 16 | `val arguments: List` 17 | : A list of arguments passed to the annotation constructor. 18 | 19 | `val psi: KtCallElement?` 20 | : The annotation call `PsiElement`. Only defined for annotations in source files, for libraries it always returns `null`. 21 | 22 | `val useSiteTarget: AnnotationUseSiteTarget?` 23 | : The [use-site target](https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets), if specified. -------------------------------------------------------------------------------- /Writerside/topics/KaAnnotationCall.md: -------------------------------------------------------------------------------- 1 | # KaAnnotationCall 2 | 3 | Represents an annotation constructor call. 4 | 5 | `KaAnnotationCall` does not have unique members and is used mostly for instance check purposes. 6 | 7 | ## Hierarchy 8 | 9 | Inherits [KaFunctionCall](KaFunctionCall.md). -------------------------------------------------------------------------------- /Writerside/topics/KaAnnotationValue.md: -------------------------------------------------------------------------------- 1 | # KaAnnotationValue 2 | 3 | `KaAnnotationValue` represents the value of an annotation argument. Annotation values must be compile-time constants 4 | and can be of the following types: 5 | 6 | * **Primitive Types:** Includes `Int`, `Long`, `Short`, `Byte`, `Char`, `Boolean`, `Float`, `Double`, and their unsigned 7 | counterparts. 8 | * **String:** A string literal. 9 | * **Enum Entry:** A reference to an enum entry. 10 | * **Class Reference:** A reference to a class using the `::class` syntax. 11 | * **Annotation:** A nested annotation call. 12 | * **Array:** An array of any of the above types. 13 | 14 | ## Members 15 | 16 | `val sourcePsi: KtElement?` 17 | : The annotation value `PsiElement`. Only defined for annotations in source files, for libraries it always returns `null`. 18 | 19 | ## Subclasses 20 | 21 | ### `KaAnnotationValue.ConstantValue` 22 | 23 | Represents a constant value, e.g., `"foo"` in `@JvmName("foo")`. 24 | 25 | `val value: KaConstantValue` 26 | : A constant value (a number, `Boolean`, `Char`, or a `String`, wrapped into a `KaConstantValue` abstraction). 27 | 28 | ### `KaAnnotationValue.EnumEntryValue` 29 | 30 | Represents a enum entry value, e.g., `Color.RED`. 31 | 32 | `val callableId: CallableId?` 33 | : The enum entry name. 34 | 35 | ### `KaAnnotationValue.ClassLiteralValue` 36 | 37 | Represents a class literal value, e.g., `String::class` or `Array::class`. 38 | 39 | `public val type: KaType` 40 | : The class reference type. 41 | 42 | ### `KaAnnotationValue.NestedAnnotationValue` 43 | 44 | Represents a nested annotation, e.g., `ReplaceWith("bar()")` in `@Deprecated("Use 'bar()' instead", ReplaceWith("bar()"))`. 45 | 46 | `val annotation: KaAnnotation` 47 | : The nested annotation. 48 | 49 | ### `KaAnnotationValue.ArrayValue` 50 | 51 | Represents an array of other annotation values, passed either as `arrayOf(...)` or as a collection literal `[...]`. 52 | 53 | `val values: Collection` 54 | : A list of annotation values inside the array. 55 | 56 | ### `KaAnnotationValue.UnsupportedValue` 57 | 58 | Represents unsupported (invalid) expressions passed as annotation values. -------------------------------------------------------------------------------- /Writerside/topics/KaAnonymousFunctionSymbol.md: -------------------------------------------------------------------------------- 1 | # KaAnonymousFunctionSymbol 2 | 3 | Represents a [lambda or an anonymous function](https://kotlinlang.org/docs/lambdas.html#lambda-expressions-and-anonymous-functions) 4 | declaration. 5 | 6 | ## Hierarchy 7 | 8 | Inherits from [KaFunctionSymbol](KaFunctionSymbol.md). 9 | 10 | ## Default values 11 | 12 | | Member | Value | 13 | |---------------------|--------------------------| 14 | | `callableId` | `null` | 15 | | `location` | `KaSymbolLocation.LOCAL` | 16 | -------------------------------------------------------------------------------- /Writerside/topics/KaAnonymousObjectSymbol.md: -------------------------------------------------------------------------------- 1 | # KaAnonymousObjectSymbol 2 | 3 | Represents an anonymous object declaration, such as: 4 | 5 | ```Kotlin 6 | object : Runnable { 7 | override fun run() {} 8 | } 9 | ``` 10 | 11 | ## Hierarchy 12 | 13 | Inherits from [KaClassSymbol](KaClassSymbol.md). -------------------------------------------------------------------------------- /Writerside/topics/KaBackingFieldSymbol.md: -------------------------------------------------------------------------------- 1 | # KaBackingFieldSymbol 2 | 3 | Represents a [backing field](https://kotlinlang.org/docs/properties.html#backing-fields) declaration. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaVariableSymbol](KaVariableSymbol.md). 8 | 9 | ## Members 10 | 11 | `val owningProperty: KaKotlinPropertySymbol` 12 | : The owning property declaration. 13 | 14 | ## Default values 15 | 16 | | Member | Value | 17 | |---------------------|-----------------------------------------| 18 | | `callableId` | `null` | 19 | | `contextReceivers` | `emptyList()` | 20 | | `isExtension` | `false` | 21 | | `isVal` | `true` | 22 | | `name` | `"field"` | 23 | | `location` | `KaSymbolLocation.PROPERTY` | 24 | | `receiverParameter` | `null` | 25 | | `origin` | `KaSymbolOrigin.PROPERTY_BACKING_FIELD` | -------------------------------------------------------------------------------- /Writerside/topics/KaCall.md: -------------------------------------------------------------------------------- 1 | # KaCall 2 | 3 | Represents a call within Kotlin code. It encompasses various types of calls, including function calls, property 4 | accesses, and other invocations. The Analysis API provides a hierarchy of `KtCall` subtypes to model different call 5 | kinds. 6 | 7 | 8 | graph TB 9 | KaCall 10 | KaCall --> KaCallableMemberCall 11 | KaCallableMemberCall --> KaVariableAccessCall 12 | KaCallableMemberCall --> KaFunctionCall 13 | KaFunctionCall --> KaSimpleFunctionCall 14 | KaFunctionCall --> KaAnnotationCall 15 | KaFunctionCall --> KaDelegatedConstructorCall 16 | KaCall --> KaCompoundVariableAccessCall 17 | KaCall --> KaCompoundArrayAccessCall 18 | -------------------------------------------------------------------------------- /Writerside/topics/KaCallableMemberCall.md: -------------------------------------------------------------------------------- 1 | # KaCallableMemberCall 2 | 3 | ## Hierarchy 4 | 5 | Inherits [KaCall](KaCall.md). 6 | 7 | ## Members 8 | 9 | `val partiallyAppliedSymbol: KaPartiallyAppliedSymbol` 10 | : A symbol wrapper, containing substituted declaration signature (parameter types for functions, return type for 11 | functions and properties), and the actual dispatch receiver. 12 | 13 | `val typeArgumentsMapping: Map` 14 | : A map containing type arguments, including the inferred ones. -------------------------------------------------------------------------------- /Writerside/topics/KaCallableSymbol.md: -------------------------------------------------------------------------------- 1 | # KaCallableSymbol 2 | 3 | A base class for symbols that represent callable declarations, such as functions and properties. 4 | 5 | ## Hierarchy 6 | 7 | A sealed class. 8 | Inherits from [KaDeclarationSymbol](KaDeclarationSymbol.md). 9 | 10 | Notable inheritors: [KaFunctionSymbol](KaFunctionSymbol.md), [KaVariableSymbol](KaVariableSymbol.md). 11 | 12 | ## Members 13 | 14 | `val callableId: CallableId?` 15 | : The fully-qualified name of a declaration, or `null` if the declaration is a local one. 16 | 17 | `val returnType: KaType` 18 | : The declaration's return type. For properties, the type of the property. 19 | 20 | `val isExtension: Boolean` 21 | : `true` if the declaration is an extension function or an extension property. 22 | 23 | `val receiverParameter: KaReceiverParameterSymbol?` 24 | : The receiver parameter, or `null` if the declaration is not an extension. 25 | 26 | ## Type utilities 27 | 28 | `val KaCallableSymbol.receiverType: KaType?` 29 | : The receiver parameter type, or `null` if the declaration is not an extension. 30 | 31 | ## Relation utilities 32 | 33 | `val KaCallableSymbol.directlyOverriddenSymbols: Sequence` 34 | : A sequence of declarations directly overridden by the given declaration. 35 | : E.g., if `A.foo` overrides `B.foo`, and `B.foo` overrides `C.foo`, only `B.foo` will be returned as a directly 36 | overridden declaration for `C.foo`. 37 | 38 | `val KaCallableSymbol.allOverriddenSymbols: Sequence` 39 | : A sequence of declarations overridden by the given declaration, both directly and indirectly. 40 | : E.g., if `A.foo` overrides `B.foo`, and `B.foo` overrides `C.foo`, both `A.foo` and `B.foo` will be returned as 41 | overridden declarations for `C.foo`. 42 | 43 | `val KaCallableSymbol.fakeOverrideOriginal: KaCallableSymbol` 44 | : The original declared symbol for a substitution or intersection override. 45 | : Fake overrides are unwrapped until the original declared symbol is found. For callables that are not fake overrides, 46 | returns the given callable itself. 47 | 48 | `val KaCallableSymbol.intersectionOverriddenSymbols: List` 49 | : ```Kotlin 50 | interface Foo { fun foo(value: T) } 51 | interface Bar { fun foo(value: String) } 52 | interface Both : Foo, Bar 53 | ``` 54 | : The `Both` interface contains an automatically generated intersection override declaration `foo()`. -------------------------------------------------------------------------------- /Writerside/topics/KaCapturedType.md: -------------------------------------------------------------------------------- 1 | # KaCapturedType 2 | 3 | Represents a [captured type](https://kotlinlang.org/spec/type-system.html#type-capturing). 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaType](KaType.md). 8 | 9 | ## Members 10 | 11 | `val projection: KaTypeProjection` 12 | : The source type argument. -------------------------------------------------------------------------------- /Writerside/topics/KaClassErrorType.md: -------------------------------------------------------------------------------- 1 | # KaErrorType 2 | 3 | Represents a class type failed to resolve correctly. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaErrorType](KaErrorType.md). 8 | 9 | ## Members 10 | 11 | `val candidateSymbols: Collection` 12 | : A list of candidate classes for the unresolved type. -------------------------------------------------------------------------------- /Writerside/topics/KaClassLikeSymbol.md: -------------------------------------------------------------------------------- 1 | # KaClassLikeSymbol 2 | 3 | Represents a class, object, interface, or a type alias declaration. 4 | 5 | ## Hierarchy 6 | 7 | A sealed class. 8 | Inherits from [KaClassifierSymbol](KaClassifierSymbol.md). 9 | 10 | Notable inheritors: [KaClassSymbol](KaClassSymbol.md), [KaTypeAliasSymbol](KaTypeAliasSymbol.md). 11 | 12 | ## Members 13 | 14 | `val classId: ClassId?` 15 | : The fully-qualified name of a declaration, or `null` if the declaration is local. 16 | 17 | ## Utilities 18 | 19 | `val KaClassLikeSymbol.samConstructor: KaSamConstructorSymbol?` 20 | : Associated `KaSamConstructorSymbol` if the given `KaClassLikeSymbol` is a functional interface type (SAM). -------------------------------------------------------------------------------- /Writerside/topics/KaClassSymbol.md: -------------------------------------------------------------------------------- 1 | # KaClassSymbol 2 | 3 | Represents a class, object, or interface declaration. 4 | 5 | ## Use Cases 6 | 7 | * **Analyzing class hierarchies.** Use `superTypes` to navigate the inheritance hierarchy of a class and analyze its 8 | relationships with other classes and interfaces. 9 | * **Exploring class members.** Use `declaredMemberScope` and `memberScope` to access members of a class, 10 | including functions, properties, and nested classes. 11 | 12 | ## Hierarchy 13 | 14 | Inherits from [KaClassLikeSymbol](KaClassLikeSymbol.md). 15 | 16 | Notable inheritors: [KaNamedClassSymbol](KaNamedClassSymbol.md), [KaAnonymousObjectSymbol](KaAnonymousObjectSymbol.md). 17 | 18 | ## Members 19 | 20 | `val classKind: KaClassKind` 21 | : The class kind (ordinary class, interface, enum class, etc.). 22 | 23 | `val superTypes: List` 24 | : A list of the direct supertypes of the class. If the class has no explicit supertypes, the supertype will be `Any`, or 25 | a special supertype such as `Enum` for enum classes. 26 | 27 | ## Type utilities 28 | 29 | `fun KaClassSymbol.isSubClassOf(superClass: KaClassSymbol): Boolean` 30 | : Check if the given class has `superClass` as its superclass in its inheritance hierarchy. 31 | 32 | `fun KaClassSymbol.isDirectSubClassOf(superClass: KaClassSymbol): Boolean` 33 | : Check if the given class has `superClass` listed as its direct superclass. 34 | 35 | ## Scope utilities 36 | 37 | `val KaDeclarationContainerSymbol.memberScope: KaScope` 38 | : A scope with non-static callables and nested classes. Also includes members inherited from the supertypes. 39 | 40 | `val KaDeclarationContainerSymbol.declaredMemberScope: KaScope` 41 | : A scope containing non-static callables and nested classes. 42 | Unlike `memberScope`, the returned scope does **not** contain members inherited from supertypes. 43 | 44 | `val KaDeclarationContainerSymbol.staticMemberScope: KaScope` 45 | : A scope containing static members, possibly including members from supertypes. 46 | The behavior differs based on whether the declaration is a Kotlin or Java one. 47 | : For **Kotlin** classes, the scope contains static declarations declared only in the given declaration itself. 48 | : For **Java** classes, the scope also contains callables from supertypes, excluding static callables from super-interfaces. 49 | This follows Kotlin's rules about static inheritance in Java classes, where static callables are propagated from 50 | superclasses, but nested classes are not. 51 | 52 | `val KaDeclarationContainerSymbol.staticDeclaredMemberScope: KaScope` 53 | : A scope containing static members of the given declaration. Unlike `staticMemberScope`, the returned scope does 54 | **not** contain members from supertypes. 55 | 56 | `val KaDeclarationContainerSymbol.combinedMemberScope: KaScope` 57 | : A scope containing all declarations from both `memberScope` and `staticMemberScope`. 58 | 59 | `val KaDeclarationContainerSymbol.combinedDeclaredMemberScope: KaScope` 60 | : A scope containing both non-static and static members of the given declaration. 61 | Unlike `combinedMemberScope`, the returned scope does **not** contain members from supertypes. 62 | 63 | `val KaDeclarationContainerSymbol.delegatedMemberScope: KaScope` 64 | : A scope containing synthetic fields created by interface delegation. 65 | 66 | ## Other utilities 67 | 68 | `val KaClassSymbol.annotationApplicableTargets: Set?` 69 | : A set of applicable targets for an annotation class symbol, or `null` if the symbol is not an annotation class. 70 | : **Experimental API**. -------------------------------------------------------------------------------- /Writerside/topics/KaClassType.md: -------------------------------------------------------------------------------- 1 | # KaClassType 2 | 3 | Represents a Kotlin generic class type, such as `String`, `List`, or a function type (like `(String) -> Int`). 4 | 5 | Can be created using [buildClassType](Types.md#building-class-types). 6 | 7 | ## Hierarchy 8 | 9 | Inherits from [KaType](KaType.md). 10 | 11 | Notable subtypes: [KaUsualClassType](KaUsualClassType.md) for non-function types and [KaFunctionType](KaFunctionType.md) 12 | for function types. 13 | 14 | ## Members 15 | 16 | `val symbol: KaClassLikeSymbol` 17 | : The class for which the given type is built. 18 | 19 | `val classId: ClassId` 20 | : The qualified name of the class. 21 | 22 | `val typeArguments: List` 23 | : A list of type arguments. -------------------------------------------------------------------------------- /Writerside/topics/KaClassifierSymbol.md: -------------------------------------------------------------------------------- 1 | # KaClassifierSymbol 2 | 3 | Represents a declaration producing a type (including classes, objects, interfaces, type aliases, and type parameters). 4 | 5 | ## Usage 6 | 7 | `KaClassifierSymbol` is typically not used directly. Instead, you should use its subclasses to access more specific 8 | information about the classifier declaration. 9 | 10 | ## Hierarchy 11 | 12 | A sealed class. 13 | Inherits from [KaDeclarationSymbol](KaDeclarationSymbol.md). 14 | 15 | Notable inheritors: [KaClassLikeSymbol](KaClassLikeSymbol.md), [KaTypeParameterSymbol](KaTypeParameterSymbol.md). -------------------------------------------------------------------------------- /Writerside/topics/KaCompoundArrayAccessCall.md: -------------------------------------------------------------------------------- 1 | # KaCompoundArrayAccessCall 2 | 3 | Represents a compound array-like access convention involving calls both to `get()` and `set()` functions, 4 | e.g., `a[1] += "foo"`. 5 | 6 | ## Members 7 | 8 | `val getPartiallyAppliedSymbol: KaPartiallyAppliedFunctionSymbol` 9 | : The `get` function that's invoked when reading values corresponding to the given `indexArguments`. 10 | 11 | `val setPartiallyAppliedSymbol: KaPartiallyAppliedFunctionSymbol` 12 | : The `set` function that's invoked when writing values corresponding to the given [indexArguments] and computed value from the 13 | * operation. 14 | 15 | `val compoundOperation: KaCompoundOperation` 16 | : The compound operation kind. Also see [KaCompoundOperation](KaCompoundVariableAccessCall.md#kacompoundoperation). -------------------------------------------------------------------------------- /Writerside/topics/KaCompoundVariableAccessCall.md: -------------------------------------------------------------------------------- 1 | # KaCompoundVariableAccessCall 2 | 3 | Represents a compound access to a mutable variable within Kotlin code. These accesses 4 | combine reading, modifying, and writing back the variable's value in a single expression, using operators 5 | like `+=`, `-=`, `++`, or `--`. 6 | 7 | ## Hierarchy 8 | 9 | Inherits [KaCall](KaCall.md). 10 | 11 | ## Members 12 | 13 | `val compoundOperation: KaCompoundOperation` 14 | : The compound operation kind. 15 | 16 | ## `KaCompoundOperation` 17 | 18 | The `compoundOperation` property returns an instance of `KaCompoundOperation` which might be: 19 | 20 | * `KaCompoundAssignOperation`: A compound assignment operation (`+=`, `*=`, etc.). 21 | * `KaCompoundUnaryOperation`: An infix and postfix increment (`++`) and decrement (`--`) operations. -------------------------------------------------------------------------------- /Writerside/topics/KaConstructorSymbol.md: -------------------------------------------------------------------------------- 1 | # KaConstructorSymbol 2 | 3 | Represents a class [constructor](https://kotlinlang.org/docs/classes.html#constructors) declaration. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaFunctionSymbol](KaFunctionSymbol.md). 8 | 9 | ## Members 10 | 11 | `val isPrimary: Boolean` 12 | : `true` if the constructor is a primary constructor. 13 | 14 | `val containingClassId: ClassId?` 15 | : The fully-qualified name of a containing class, or `null` if the class is local. 16 | 17 | ## Default values 18 | 19 | | Member | Value | 20 | |---------------------|--------------------------| 21 | | `callableId` | `null` | 22 | | `contextReceivers` | `emptyList()` | 23 | | `isExtension` | `false` | 24 | | `location` | `KaSymbolLocation.CLASS` | 25 | | `receiverParameter` | `null` | 26 | -------------------------------------------------------------------------------- /Writerside/topics/KaDeclarationSymbol.md: -------------------------------------------------------------------------------- 1 | # KaDeclarationSymbol 2 | 3 | Represents a declaration, such as a class, function, or property. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaSymbol](KaSymbol.md), [KaAnnotated](Annotations.md#kaannotated). 8 | 9 | ## Members 10 | 11 | `val annotations: KaAnnotationList` 12 | : A list of applied annotations. 13 | 14 | `val modality: KaSymbolModality` 15 | : Effective declaration modality (e.g., final, sealed, or open). 16 | 17 | `val visibility: KaSymbolVisibility` 18 | : Effective declaration visibility (e.g., public, protected, or private). 19 | 20 | `val isExpect: Boolean` 21 | : `true` if the declaration is an `expect` one. 22 | 23 | `val isActual: Boolean` 24 | : `true` if the declaration is an `actual` one. 25 | 26 | `val KaDeclarationSymbol.typeParameters: List` 27 | : A list of type parameters for `KaTypeParameterOwnerSymbol`, an empty list otherwise. 28 | : **Experimental API**. 29 | 30 | ## Utilities 31 | 32 | `fun KaDeclarationSymbol.render(renderer: KaDeclarationRenderer = KaDeclarationRendererForSource.WITH_QUALIFIED_NAMES): String` 33 | : Render the given declaration to a `String`. The particular rendering strategy is defined by the `renderer`. 34 | : **Experimental API**. -------------------------------------------------------------------------------- /Writerside/topics/KaDefinitelyNotNullType.md: -------------------------------------------------------------------------------- 1 | # KaDefinitelyNotNullType 2 | 3 | Represents a [definitely not-null](https://kotlinlang.org/docs/generics.html#definitely-non-nullable-types) type. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaType](KaType.md). 8 | 9 | ## Members 10 | 11 | `val original: KaType` 12 | : The nullable upper bound. -------------------------------------------------------------------------------- /Writerside/topics/KaDelegatedConstructorCall.md: -------------------------------------------------------------------------------- 1 | # KaDelegatedConstructorCall 2 | 3 | Represents a call to another constructor within the same class, or to a superclass constructor. 4 | This corresponds to the use of `this(...)` or `super(...)` within a constructor's body to delegate initialization to 5 | another constructor. 6 | 7 | ## Hierarchy 8 | 9 | Inherits [KaFunctionCall](KaFunctionCall.md). 10 | 11 | ## Members 12 | 13 | `val kind: Kind` 14 | : The call kind (`SUPER_CALL` or `THIS_CALL`). -------------------------------------------------------------------------------- /Writerside/topics/KaDiagnostic.md: -------------------------------------------------------------------------------- 1 | # KaDiagnostic 2 | 3 | A diagnostic message reported by the compiler checker. 4 | 5 | ## Members 6 | 7 | `val factoryName: String` 8 | : The name of the diagnostic factory that produced the diagnostic. 9 | 10 | `val severity: KaSeverity` 11 | : The severity of the diagnostic (e.g., `ERROR`, `WARNING`). 12 | 13 | `val defaultMessage: String` 14 | : The default text message associated with the diagnostic. -------------------------------------------------------------------------------- /Writerside/topics/KaDiagnosticWithPsi.md: -------------------------------------------------------------------------------- 1 | # KaDiagnosticWithPsi 2 | 3 | ## Hierarchy 4 | 5 | Inherits from [KaDiagnostic](KaDiagnostic.md). 6 | 7 | ## Members 8 | 9 | `val psi: PSI` 10 | : The `PsiElement` on which the diagnostic is reported. 11 | 12 | `val textRanges: Collection` 13 | : Text ranges within the `psi` element relevant to the diagnostic. -------------------------------------------------------------------------------- /Writerside/topics/KaDynamicType.md: -------------------------------------------------------------------------------- 1 | # KaDynamicType 2 | 3 | Represents a [dynamic](https://kotlinlang.org/docs/dynamic-type.html) type. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaType](KaType.md). -------------------------------------------------------------------------------- /Writerside/topics/KaEnumEntrySymbol.md: -------------------------------------------------------------------------------- 1 | # KaEnumEntrySymbol 2 | 3 | Represents an [enum entry](https://kotlinlang.org/docs/enum-classes.html) declaration. 4 | 5 | 6 | In the Kotlin PSI, a KtEnumEntry is a KtClass, as it was so In the old compiler. 7 | In the Analysis API, though, similarly to the K2 compiler, it is a KaVariableSymbol. 8 | 9 | 10 | ## Hierarchy 11 | 12 | Inherits from [KaVariableSymbol](KaVariableSymbol.md). 13 | 14 | ## Members 15 | 16 | `val enumEntryInitializer: KaEnumEntryInitializerSymbol?` 17 | : The enum entry initializer, or `null` if the entry does not have a body. 18 | 19 | ## Default values 20 | 21 | | Member | Value | 22 | |---------------------|--------------------------| 23 | | `callableId` | `null` | 24 | | `contextReceivers` | `emptyList()` | 25 | | `isExtension` | `false` | 26 | | `isVal` | `true` | 27 | | `location` | `KaSymbolLocation.CLASS` | 28 | | `receiverParameter` | `null` | -------------------------------------------------------------------------------- /Writerside/topics/KaErrorType.md: -------------------------------------------------------------------------------- 1 | # KaErrorType 2 | 3 | Represents a type failed to resolve correctly. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaType](KaType.md). -------------------------------------------------------------------------------- /Writerside/topics/KaFlexibleType.md: -------------------------------------------------------------------------------- 1 | # KaFlexibleType 2 | 3 | Represents a [flexible type](https://kotlinlang.org/spec/type-system.html#flexible-types) 4 | (or a so-called [platform type](https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types)), a range 5 | of types from the `lowerBound` to the `upperBound` (both inclusive). 6 | 7 | Also check [nullability utilities](KaType.md#nullability-utilities) in `KaType`. 8 | 9 | ## Hierarchy 10 | 11 | Inherits from [KaType](KaType.md). 12 | 13 | ## Members 14 | 15 | `val lowerBound: KaType` 16 | : The lower bound (such as, `String` in `String!`). 17 | 18 | `val upperBound: KaType` 19 | : The upper bound (such as, `String?` in `String!`). -------------------------------------------------------------------------------- /Writerside/topics/KaFunctionCall.md: -------------------------------------------------------------------------------- 1 | # KaFunctionCall 2 | 3 | `KaFunctionCall` represents a call to a function within Kotlin code. This includes calls to regular functions, 4 | constructors, constructors of super classes, and annotations. 5 | 6 | ## Hierarchy 7 | 8 | Inherits [KaCallableMemberCall](KaCallableMemberCall.md). 9 | 10 | ## Members 11 | 12 | `val argumentMapping: Map>` 13 | : A map associating argument expressions with the corresponding parameter signatures. -------------------------------------------------------------------------------- /Writerside/topics/KaFunctionSymbol.md: -------------------------------------------------------------------------------- 1 | # KaFunctionSymbol 2 | 3 | Represents a function-like declaration, including named and anonymous functions, constructors, and property accessors. 4 | 5 | ## Hierarchy 6 | 7 | A sealed class. 8 | Inherits from [KaCallableSymbol](KaCallableSymbol.md). 9 | 10 | Notable inheritors: [KaNamedFunctionSymbol](KaNamedFunctionSymbol.md), [KaConstructorSymbol](KaConstructorSymbol.md), 11 | [KaPropertyAccessorSymbol](KaPropertyAccessorSymbol.md). 12 | 13 | ## Members 14 | 15 | `val valueParameters: List` 16 | : A list of declared value parameters. 17 | 18 | `val hasStableParameterNames: Boolean` 19 | : `true` if the declaration has stable parameter names, so they can be used in a named parameter call syntax 20 | (e.g., `User(name = "Joe")` instead of `User("Joe")`). Parameter names are always stable for Kotlin declarations, and 21 | usually unstable for all other declaration sources. -------------------------------------------------------------------------------- /Writerside/topics/KaFunctionType.md: -------------------------------------------------------------------------------- 1 | # KaFunctionType 2 | 3 | Represents Kotlin function types, such as `(String) -> Int` or `suspend () -> List`. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaClassType](KaClassType.md). 8 | 9 | ## Members 10 | 11 | `val isSuspend: Boolean` 12 | : `true` if the type is a suspend function type. 13 | 14 | `val isReflectType: Boolean` 15 | : `true` if the type is a reflect function type (`kotlin.reflection.KFunctionN`). 16 | 17 | `val arity: Int` 18 | : The number of type parameters. 19 | 20 | `val parameterTypes: List` 21 | : A list of parameter types. Not to confuse with `typeArguments` which also include the function return type. 22 | 23 | `val returnType: KaType` 24 | : The function return type. 25 | 26 | `val hasReceiver: Boolean` 27 | : `true` if the given type is an extension function type. 28 | 29 | `val receiverType: KaType?` 30 | : The extension receiver type, or `null` if the given type is not an extension function type. 31 | 32 | `val hasContextReceivers: Boolean` 33 | : `true` if the function type has context receiver parameters. 34 | : **Experimental API**. 35 | 36 | `val contextReceivers: List` 37 | : A list of context receiver parameters. 38 | : **Experimental API**. -------------------------------------------------------------------------------- /Writerside/topics/KaIntersectionType.md: -------------------------------------------------------------------------------- 1 | # KaIntersectionType 2 | 3 | Represents an [intersection type](https://kotlinlang.org/spec/type-system.html#intersection-types). 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaType](KaType.md). 8 | 9 | ## Members 10 | 11 | `val conjuncts: List` 12 | : A list of individual types participating in the intersection. -------------------------------------------------------------------------------- /Writerside/topics/KaLocalVariableSymbol.md: -------------------------------------------------------------------------------- 1 | # KaLocalVariableSymbol 2 | 3 | Represents a local variable. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaVariableSymbol](KaVariableSymbol.md). 8 | 9 | ## Default values 10 | 11 | | Member | Value | 12 | |---------------------|--------------------------| 13 | | `callableId` | `null` | 14 | | `contextReceivers` | `emptyList()` | 15 | | `isExtension` | `false` | 16 | | `location` | `KaSymbolLocation.LOCAL` | 17 | | `receiverParameter` | `null` | -------------------------------------------------------------------------------- /Writerside/topics/KaNamedClassSymbol.md: -------------------------------------------------------------------------------- 1 | # KaNamedClassSymbol 2 | 3 | Represents a named class, object, or interface declaration. 4 | Basically, covers all class-like declarations, excluding anonymous objects. 5 | 6 | ## Use Cases 7 | 8 | * **Checking for specific class features.** Use properties like `isData`, `isInner`, and `isCompanion` to determine if 9 | the class has specific characteristics. 10 | 11 | Also see use cases for the [KaClassSymbol](KaClassSymbol.md#use-cases) supertype. 12 | 13 | ## Hierarchy 14 | 15 | Inherits from [KaClassSymbol](KaClassSymbol.md). 16 | 17 | ## Members 18 | 19 | `val name: Name` 20 | : The simple declaration name, e.g., `String` for `kotlin.String`. 21 | 22 | `val companionObject: KaNamedClassSymbol?` 23 | : The nested companion object, or `null` if there is no companion object. 24 | 25 | `val contextReceivers: List` 26 | : A list of context receivers. 27 | : **Experimental API**. 28 | 29 | `val isExternal: Boolean` 30 | : `true` if the declaration has the `external` modifier. 31 | 32 | `val isData: Boolean` 33 | : `true` if the declaration is a `data class`. 34 | 35 | `val isInline: Boolean` 36 | : `true` if the declaration is an `inline class`. 37 | 38 | `val isFun: Boolean` 39 | : `true` if the declaration is a `fun interface`. 40 | 41 | `val isInner: Boolean` 42 | : `true` if the declaration is an inner class. 43 | 44 | `val typeParameters: List` 45 | : A list of declared type parameters. 46 | 47 | ## Type utilities 48 | 49 | `val KaNamedClassSymbol.defaultType: KaType` 50 | : A class type where type parameters are substituted with matching type parameter types, e.g., `List` for the `List` 51 | class. 52 | 53 | ## Relation utilities 54 | 55 | `val KaNamedClassSymbol.sealedClassInheritors: List` 56 | : Inheritors of the given sealed class. -------------------------------------------------------------------------------- /Writerside/topics/KaNamedFunctionSymbol.md: -------------------------------------------------------------------------------- 1 | # KaNamedFunctionSymbol 2 | 3 | Represents a named [function](https://kotlinlang.org/docs/functions.html) declaration, such as a top-level function, a 4 | class method, or a named local function. 5 | 6 | ## Hierarchy 7 | 8 | Inherits from [KaFunctionSymbol](KaFunctionSymbol.md). 9 | 10 | ## Members 11 | 12 | `val name: Name` 13 | : The function name. 14 | 15 | `val typeParameters: List` 16 | : A list of declared type parameters. 17 | 18 | `val isExternal: Boolean` 19 | : `true` if the function is an external function. 20 | 21 | `val isInfix: Boolean` 22 | : `true` if the function is an infix function. 23 | 24 | `val isInline: Boolean` 25 | : `true` if the function is an inline function. 26 | 27 | `val isOverride: Boolean` 28 | : `true` if the function is an override. 29 | 30 | `val isSuspend: Boolean` 31 | : `true` if the function is a suspend function. 32 | 33 | `val isStatic: Boolean` 34 | : `true` if the function is a static function. 35 | 36 | `val isOperator: Boolean` 37 | : `true` if the function is an operator function. 38 | 39 | `val isTailRec: Boolean` 40 | : `true` if the function is marked with `tailrec`. 41 | 42 | `val isBuiltinFunctionInvoke: Boolean` 43 | : `true` if the function is the `invoke()` method defined on the Kotlin built-in functional type. 44 | 45 | `val contractEffects: List` 46 | : A list of defined [contracts](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.contracts/). -------------------------------------------------------------------------------- /Writerside/topics/KaPropertyAccessorSymbol.md: -------------------------------------------------------------------------------- 1 | # KaPropertyAccessorSymbol 2 | 3 | Represents a property [getter or setter](https://kotlinlang.org/docs/properties.html#getters-and-setters) declaration. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaFunctionSymbol](KaFunctionSymbol.md). 8 | 9 | Inheritors: `KaPropertyGetterSymbol` (for getters), `KaPropertySetterSymbol` (for setters). 10 | 11 | ## Members 12 | 13 | `val isDefault: Boolean` 14 | : `true` if the accessor is implicitly generated. 15 | 16 | `val isInline: Boolean` 17 | : `true` if the property is an inline property. 18 | 19 | `val isOverride: Boolean` 20 | : `true` if the property accessor is an override. 21 | 22 | `val hasBody: Boolean` 23 | : `true` if the property accessor has body. Such as, the following property has an explicit getter without a body: 24 | : ```Kotlin 25 | val name: String = "Foo" 26 | @Throws(RuntimeException::class) get 27 | ``` 28 | 29 | `val containingClassId: ClassId?` 30 | : The fully-qualified name of a containing class, or `null` if the class is local. 31 | 32 | ## Default values 33 | 34 | | Member | Value | 35 | |---------------------|-----------------------------| 36 | | `contextReceivers` | `emptyList()` | 37 | | `isExtension` | `false` | 38 | | `location` | `KaSymbolLocation.PROPERTY` | 39 | | `receiverParameter` | `null` | -------------------------------------------------------------------------------- /Writerside/topics/KaPropertySymbol.md: -------------------------------------------------------------------------------- 1 | # KaPropertySymbol 2 | 3 | Represents a property declaration. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaVariableSymbol](KaVariableSymbol.md). 8 | 9 | ## Members 10 | 11 | `val typeParameters: List` 12 | : A list of declared type parameters. 13 | 14 | `val initializer: KaInitializerValue?` 15 | : The property initializer. 16 | 17 | `val hasGetter: Boolean` 18 | : `true` if the property has a getter. 19 | 20 | `val getter: KaPropertyGetterSymbol?` 21 | : The property getter. 22 | 23 | `val hasSetter: Boolean` 24 | : `true` if the property has a setter. 25 | 26 | `val setter: KaPropertySetterSymbol?` 27 | : The property setter. 28 | 29 | `val hasBackingField: Boolean` 30 | : `true` if the property has a backing field. 31 | 32 | `val backingFieldSymbol: KaBackingFieldSymbol?` 33 | : The backing field symbol. 34 | 35 | `val isDelegatedProperty: Boolean` 36 | : `true` if the property has a delegate. 37 | 38 | `val isFromPrimaryConstructor: Boolean` 39 | : `true` if the property is defined in a class primary constructor. 40 | 41 | `val isOverride: Boolean` 42 | : `true` if the property is an override. 43 | 44 | `val isStatic: Boolean` 45 | : `true` if the property is static. 46 | 47 | ## Utilities 48 | 49 | `val KaPropertySymbol.getterDeprecationStatus: DeprecationInfo?` 50 | : Deprecation status for the property getter, or `nil` if the getter is not deprecated. 51 | : **Experimental API**. 52 | 53 | `val KaPropertySymbol.setterDeprecationStatus: DeprecationInfo?` 54 | : Deprecation status for the property setter, or `nil` if the getter is not deprecated. 55 | : **Experimental API**. -------------------------------------------------------------------------------- /Writerside/topics/KaSimpleFunctionCall.md: -------------------------------------------------------------------------------- 1 | # KaSimpleFunctionCall 2 | 3 | Represents a simple, direct call to a function, without any delegation or special syntax involved. 4 | 5 | ## Hierarchy 6 | 7 | Inherits [KaFunctionCall](KaFunctionCall.md). 8 | 9 | ## Members 10 | 11 | `val isImplicitInvoke: Boolean` 12 | : `true` if the call is an [implicit invoke call](https://kotlinlang.org/docs/operator-overloading.html#invoke-operator) 13 | on a value that has an `invoke` member function. -------------------------------------------------------------------------------- /Writerside/topics/KaSymbol.md: -------------------------------------------------------------------------------- 1 | # KaSymbol 2 | 3 | A base interface of the symbol hierarchy. 4 | 5 | ## Members 6 | 7 | `val location: KaSymbolLocation` 8 | : A symbol location kind (e.g., top-level or class member). 9 | 10 | `val origin: KaSymbolOrigin` 11 | : A place the symbol comes from (e.g., a source, a library, or a compiler plugin). 12 | 13 | `val psi: PsiElement?` 14 | : A PSI element corresponding to the declaration. Might be `null` for certain, usually synthetic, origins. 15 | 16 | `fun createPointer(): KaSymbolPointer` 17 | : Create a declaration pointer which can be used to retrieve the symbol back in another `KaSession`. 18 | 19 | ## Relation utilities 20 | 21 | `val KaSymbol.containingSymbol: KaSymbol?` 22 | : A containing symbol: 23 | * For top-level declarations, a `KaFileSymbol`, or a `KaScriptSymbol` if the file is a script file; 24 | * For scripts, a `KaFileSymbol`; 25 | * For class members, a containing class; 26 | * For local declarations, a declaration it was declared in. 27 | 28 | `val KaSymbol.containingDeclaration: KaDeclarationSymbol?` 29 | : A containing declaration: 30 | * For top-level declarations, a containing `KaScriptSymbol` or `null` for non-script declarations; 31 | * For class members, a containing class; 32 | * For local declarations, a declaration it was declared in. 33 | 34 | `val KaSymbol.containingFile: KaFileSymbol?` 35 | : The containing file symbol, or `null` if the given file symbol is already a `KaFileSymbol`. 36 | 37 | `val KaSymbol.containingModule: KaModule` 38 | : The containing module. 39 | 40 | ## Other utilities 41 | 42 | `val KaSymbol.deprecationStatus: DeprecationInfo?` 43 | : Deprecation status for the given symbol, or `null` if the declaration is not deprecated. 44 | : **Experimental API**. 45 | 46 | `fun KaSymbol.deprecationStatus(annotationUseSiteTarget: AnnotationUseSiteTarget?): DeprecationInfo?` 47 | : Deprecation status for the given symbol related to the specified annotation use-site target, 48 | or `null` if the declaration is not deprecated. 49 | : **Experimental API**. 50 | 51 | ## `KaSymbolLocation` 52 | 53 | The `location` property indicates the relation between the declaration represented by a symbol and its container (a 54 | file, a class, etc.). 55 | 56 | | Member | Description | 57 | |-------------|-----------------------------------------------------------------------------| 58 | | `TOP_LEVEL` | A declaration placed directly in a file, or in a script. | 59 | | `CLASS` | A member of some class, object, or interface. | 60 | | `PROPERTY` | A part of some property declaration (e.g., an accessor or a backing field). | 61 | | `LOCAL` | A declaration inside some callable declaration body. | 62 | 63 | ## `KaSymbolOrigin` 64 | 65 | The `origin` property indicates the origin of the symbol. 66 | Below you can find a comprehensive list of possible `KaSymbolOrigin` values and their descriptions. 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 79 | 80 | 81 | 82 | 92 | 93 | 94 | 95 | 99 | 100 | 101 | 102 | 106 | 107 | 108 | 109 | 113 | 114 | 115 | 116 | 127 | 128 | 129 | 130 | 141 | 142 | 143 | 144 | 156 | 157 | 158 | 159 | 175 | 176 | 177 | 178 | 200 | 201 | 202 | 203 | 218 | 219 | 220 | 221 | 224 | 225 | 226 | 227 | 230 | 231 | 232 | 233 | 238 | 239 |
MemberDescription
SOURCE 76 |

A declaration directly written in Kotlin source code.

77 |

Examples: Classes, functions, properties, and other declarations defined in Kotlin source files.

78 |
SOURCE_MEMBER_GENERATED 83 |

A declaration automatically generated by the Kotlin compiler as a member of another declaration.

84 |

Examples:

85 |
    86 |
  • Default constructors of classes.
  • 87 |
  • copy(), componentN(), and other synthetic functions for data classes.
  • 88 |
  • values() and valueOf() functions for enum classes.
  • 89 |
  • Implicit it parameter for lambda expressions with a single parameter.
  • 90 |
91 |
LIBRARY 96 |

A declaration from a compiled Kotlin library (.jar or .klib file).

97 |

Examples: Classes, functions, properties, and other declarations defined in Kotlin source files.

98 |
JAVA_SOURCE 103 |

A declaration from Java source code.

104 |

Examples: Classes, methods, and fields defined in Java source files.

105 |
JAVA_LIBRARY 110 |

A declaration from a compiled Java library.

111 |

Examples: Classes, methods, and fields from Java libraries, or from the JDK.

112 |
SAM_CONSTRUCTOR 117 |

A synthetic function generated by the SAM (Single Abstract Method) conversion. 118 | This occurs when a lambda expression is passed as an argument where a functional interface is expected.

119 |

Example:

120 | 121 | val runnable = Runnable { 122 | println("Hello") 123 | } 124 | 125 |

In this case, the lambda expression is converted to a synthetic function that implements the Runnable interface.

126 |
INTERSECTION_OVERRIDE 131 |

A synthetic declaration automatically created by the Kotlin compiler for callable intersections.

132 |

Example:

133 | 134 | interface A { fun x() } 135 | interface B { fun x() } 136 | interface C : A, B 137 | 138 |

In C, there appears the function C.foo, an intersection of A.foo 139 | and B.foo, with the INTERSECTION_OVERRIDE origin.

140 |
SUBSTITUTION_OVERRIDE 145 |

A synthetic declaration automatically created by the Kotlin compiler for callable type substitutions.

146 |

Example:

147 | 148 | { fun x(): T } 150 | interface B : A 151 | ]]> 152 | 153 |

Interface B will have a member B.foo(): Int with a substituted return type 154 | with the SUBSTITUTION_OVERRIDE origin.

155 |
DELEGATED 160 |

A member generated by the compiler for interface delegation. This occurs 161 | when a class delegates the implementation of an interface to another object.

162 |

Example:

163 | 164 | 171 | 172 |

The compiler generates a member function perform() in MyClass that calls the 173 | perform() function from delegate.

174 |
JAVA_SYNTHETIC_PROPERTY 179 |

A synthetic property generated by the compiler for a Java field with a getter or setter. 180 | This allows Java fields to be accessed like Kotlin properties.

181 |

Example:

182 | 183 | 196 | 197 |

The compiler generates a synthetic property field with a getter and setter based on the Java 198 | methods getField() and setField().

199 |
PROPERTY_BACKING_FIELD 204 |

A backing field of a property declaration (a field that stores the value of the property).

205 |

Example:

206 | 207 | 214 | 215 |

The field identifier in the getter and setter refers to the backing field of 216 | the property.

217 |
PLUGIN 222 |

A declaration generated by a compiler plugin.

223 |
JS_DYNAMIC 228 |

A declaration from a dynamic Kotlin/JS scope.

229 |
NATIVE_FORWARD_DECLARATION 234 |

A Kotlin/Native forward declaration. See the 235 | forward declarations 236 | section in the Kotlin documentation.

237 |
-------------------------------------------------------------------------------- /Writerside/topics/KaType.md: -------------------------------------------------------------------------------- 1 | # KaType 2 | 3 | Represents a Kotlin type. It serves as the base interface for various specific type. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaAnnotated](Annotations.md#kaannotated). 8 | 9 | ## Members 10 | 11 | `val abbreviation: KaUsualClassType?` 12 | : The abbreviated type for the given expanded type, or `null` if this type has not been expanded, or the 13 | abbreviated type cannot be resolved. 14 | : An abbreviated type is an expanded type alias application. For example, if we have a type 15 | alias `typealias MyString = String` and its application `MyString`, `String` would be the type alias expansion and `MyString` its 16 | abbreviated type. 17 | 18 | `val nullability: KaTypeNullability` 19 | : The type nullability: `NULLABLE`, `NON_NULLABLE`, `UNKNOWN` (for flexible types). 20 | 21 | ## Subtypes 22 | 23 | The `KaType` interface has several subtypes that represent different kinds of types in Kotlin: 24 | 25 | * **KaClassType**: Represents a Kotlin class type, encompassing classes, interfaces, objects, and enum classes. 26 | * **KaUsualClassType**: Represents a class type that is not a function type. 27 | * **KaFunctionType**: Represents Kotlin function types, including regular functions, suspend functions, and those with 28 | receivers. 29 | * **KaTypeParameterType**: Represents a type parameter type, such as `T` in the 30 | declaration `class Box(val element: T)`. 31 | * **KaDefinitelyNotNullType**: Represents a type that is known to be non-nullable at a particular point in the program. 32 | * **KaCapturedType**: Represents a type that is captured during type inference, often occurring when working with 33 | generics and variance. 34 | * **KaFlexibleType**: Represents a type with flexibility in its bounds, commonly used for platform types or types with 35 | uncertain nullability. 36 | * **KaIntersectionType**: Represents a type formed by the intersection of multiple types. 37 | * **KaDynamicType**: Represents the dynamic type in Kotlin, used for interoperability with dynamically-typed languages 38 | or platforms. 39 | * **KaErrorType**: Represents an unresolved type of some kind. 40 | 41 | ## Transformation utilities 42 | 43 | `val Iterable.commonSupertype: KaType` 44 | : The common super type of the given collection of [KaType]. The collection must not be empty. 45 | 46 | `fun KaType.withNullability(newNullability: KaTypeNullability): KaType` 47 | : Returns the given type with the modified nullability. 48 | 49 | ## Nullability utilities 50 | 51 | `val KaType.canBeNull: Boolean` 52 | : `true` if a public value of the given type can potentially be `null`. 53 | : This means this type is not a subtype of [Any]. However, it does not mean one can assign `null` to a variable of this 54 | type because it may be unknown if this type can accept `null`. 55 | 56 | `val KaType.isMarkedNullable: Boolean` 57 | : `true` if the given type is explicitly marked as nullable. This means it is safe to assign `null` to a variable with this type. 58 | 59 | `val KaType.hasFlexibleNullability: Boolean` 60 | : `true` if the given type is a flexible 61 | ([platform](https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types)) type, can both safe and 62 | ordinary calls are valid on it. 63 | 64 | `fun KaType.upperBoundIfFlexible(): KaType` 65 | : Returns the upper bound if the given type is a flexible type, and the given type itself otherwise. 66 | 67 | `fun KaType.lowerBoundIfFlexible(): KaType` 68 | : Returns the lower bound if the given type is a flexible type, and the given type itself otherwise. 69 | 70 | ## Type relation utilities 71 | 72 | `fun KaType.semanticallyEquals(other: KaType, errorTypePolicy: KaSubtypingErrorTypePolicy = KaSubtypingErrorTypePolicy.STRICT): Boolean` 73 | : Check semantic type equality. Returns `true` if the given type can be used instead of `other`. 74 | 75 | `fun KaType.isSubtypeOf(supertype: KaType, errorTypePolicy: KaSubtypingErrorTypePolicy = KaSubtypingErrorTypePolicy.STRICT): Boolean` 76 | : Check if the given type is a subtype of the `supertype`. 77 | 78 | `fun KaType.isClassType(classId: ClassId): Boolean` 79 | : `true` if the given type is a class type with the given `ClassId`, or its nullable version. 80 | 81 | `fun KaType.hasCommonSubtypeWith(that: KaType): Boolean` 82 | : Check whether the given type is compatible with the other type. Compatibility means the types can have a common subtype. 83 | 84 | `val KaType.directSupertypes: Sequence` 85 | : Direct super types of the given type. For example, for `MutableList` it will be `List` and 86 | `MutableCollection`. 87 | 88 | `val KaType.allSupertypes: Sequence` 89 | : All supertypes of the given type. 90 | 91 | `val KaType.isArrayOrPrimitiveArray: Boolean` 92 | : `true` if the given type is an array or a primitive array type. 93 | 94 | `val KaType.isNestedArray: Boolean` 95 | : `true` if the given type is an array or a primitive array type, and if its element is also an array type. 96 | 97 | `val KaType.isPrimitive: Boolean` 98 | : `true` if the given [KaType] is one of these types: `Byte`, `Short`, `Int`, `Long`, `Float`, `Double`, `Char`, 99 | `Boolean`, or a nullable version of them. 100 | 101 | `val KaType.isAnyType`
102 | `val KaType.isNothingType`
103 | `val KaType.isUnitType`
104 | `val KaType.isByteType`
105 | `val KaType.isUByteType`
106 | `val KaType.isShortType`
107 | `val KaType.isUShortType`
108 | `val KaType.isIntType`
109 | `val KaType.isUIntType`
110 | `val KaType.isLongType`
111 | `val KaType.isULongType`
112 | `val KaType.isFloatType`
113 | `val KaType.isDoubleType`
114 | `val KaType.isCharType`
115 | `val KaType.isBooleanType`
116 | `val KaType.isCharSequenceType`
117 | `val KaType.isStringType` 118 | : `true` if the given type is the specified Kotlin type or its nullable version. 119 | 120 | `val KaType.isFunctionalInterface: Boolean` 121 | : `true` if the given type is a functional interface type (SAM type), e.g., `Runnable`. 122 | 123 | `val KaType.isFunctionType: Boolean` 124 | : `true` if this type is a `kotlin.Function` type. 125 | 126 | `val KaType.isKFunctionType: Boolean` 127 | : `true` if this type is a `kotlin.reflect.KFunction` type. 128 | 129 | `val KaType.isSuspendFunctionType: Boolean` 130 | : `true` if this type is a `kotlin.coroutines.SuspendFunction` type. 131 | 132 | `val KaType.isKSuspendFunctionType: Boolean` 133 | : `true` if this type is a `kotlin.reflect.KSuspendFunction` type. 134 | 135 | `val KaType.functionTypeKind: FunctionTypeKind?` 136 | : The `FunctionTypeKind` of the given type, or `null` if the type is not a function type. 137 | : **Experimental API**. 138 | 139 | ## Scope utilities 140 | 141 | `val KaType.scope: KaTypeScope?` 142 | : Return a `KaTypeScope` for a given type. The type scope includes all members which are declared and callable on a given type. 143 | : Comparing to a `KaScope`, in the `KaTypeScope` all use-site type parameters are substituted. 144 | : **Experimental API**. 145 | 146 | `val KaType.syntheticJavaPropertiesScope: KaTypeScope?` 147 | : A `KaTypeScope` with synthetic Java properties created for a given type. 148 | 149 | ## Other utilities 150 | 151 | `val builtinTypes: KaBuiltinTypes` 152 | : An instance providing access to all built-in Kotlin types, including number types, `Any`, `Nothing`, `String` 153 | and others. 154 | 155 | `val KaType.arrayElementType: KaType?` 156 | : The array element type for a primitive type array or `Array`, `null` otherwise. 157 | 158 | `val KaType.expandedSymbol: KaClassSymbol?` 159 | : The class symbol backing the given type, or `null` if the type has no expansion. 160 | 161 | `val KaType.fullyExpandedType: KaType` 162 | : The type with type aliases recursively expanded. 163 | 164 | `val KaType.isDenotable: Boolean` 165 | : `true` if this type is denotable. In other words, it can be written in Kotlin by a developer. Flexible type is an 166 | example of a non-denotable type. 167 | 168 | `val KaType.enhancedType: KaType?` 169 | : The warning-level enhanced type for the given type, or `null` if it is absent. 170 | : **Experimental API**. 171 | 172 | `val KaType.enhancedTypeOrSelf: KaType?` 173 | : The warning-level enhanced type for the given type, or the given type itself if it is absent. 174 | : **Experimental API**. 175 | 176 | `fun KaType.render(renderer: KaTypeRenderer = KaTypeRendererForSource.WITH_QUALIFIED_NAMES, position: Variance): String` 177 | : Render the given type to a `String`. The particular rendering strategy is defined by the `renderer`. 178 | : **Experimental API**. -------------------------------------------------------------------------------- /Writerside/topics/KaTypeAliasSymbol.md: -------------------------------------------------------------------------------- 1 | # KaTypeAliasSymbol 2 | 3 | Represents a type alias declaration. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaClassLikeSymbol](KaClassLikeSymbol.md). 8 | 9 | ## Members 10 | 11 | `val name: Name` 12 | : The simple type alias declaration name. 13 | 14 | `val expandedType: KaType` 15 | : The type from right-hand site of the type alias. If the given type alias has type parameters, 16 | those type parameters will be present in the result type. 17 | 18 | `val typeParameters: List` 19 | : A list of declared type parameters. -------------------------------------------------------------------------------- /Writerside/topics/KaTypeParameterSymbol.md: -------------------------------------------------------------------------------- 1 | # KaTypeParameterSymbol 2 | 3 | Represents a type parameter of a class, function, property, or a type alias. 4 | 5 | ## Hierarchy 6 | 7 | Inherits from [KaClassifierSymbol](KaClassifierSymbol.md). 8 | 9 | ## Members 10 | 11 | `val name: Name` 12 | : The declaration name. 13 | 14 | `val upperBounds: List` 15 | : A list of upper bound types. 16 | 17 | `val variance: Variance` 18 | : The [declaration-site variance](https://kotlinlang.org/docs/generics.html#declaration-site-variance) 19 | (invariant, covariant `out`, contravariant `in`). 20 | 21 | `val isReified: Boolean` 22 | : `true` if the type parameter has the `reified` modifier (applicable only to callable type parameters). -------------------------------------------------------------------------------- /Writerside/topics/KaTypeParameterType.md: -------------------------------------------------------------------------------- 1 | # KaTypeParameterType 2 | 3 | Represents a type parameter type, such as `T` in the declaration `class Box(val element: T)`. 4 | 5 | Can be created using [buildTypeParameterType](Types.md#building-type-parameter-types). 6 | 7 | ## Hierarchy 8 | 9 | Inherits from [KaType](KaType.md). 10 | 11 | ## Members 12 | 13 | `val name: Name` 14 | : The type parameter name. 15 | 16 | `val symbol: KaTypeParameterSymbol` 17 | : The type parameter symbol. -------------------------------------------------------------------------------- /Writerside/topics/KaTypeProjection.md: -------------------------------------------------------------------------------- 1 | # KaTypeProjection 2 | 3 | `KaTypeProjection` represents a type argument used in the context of a class or function type. It provides information 4 | about the type and its variance. 5 | 6 | ## Members 7 | 8 | `val type: KaType?` 9 | : The projected type, or `null` for the star projection. 10 | 11 | ## Subclasses 12 | 13 | ### `KtStarTypeProjection` 14 | 15 | Represents a [star projection](https://kotlinlang.org/docs/generics.html#star-projections) (`*`) used in type arguments. 16 | It indicates that the specific type is not important or unknown. 17 | 18 | ### `KaTypeArgumentWithVariance` 19 | 20 | Represents a type argument with an explicit type and 21 | [variance](https://kotlinlang.org/docs/generics.html#use-site-variance-type-projections). 22 | 23 | `val type: KaType` 24 | : The projected type. 25 | 26 | `val variance: Variance` 27 | : The `Variance` of the type argument. It can be: 28 | * `OUT_VARIANCE`: The type argument is used as a "covariant", `out` type parameter. 29 | * `IN_VARIANCE`: The type argument is used as a "contravariant", `in` type parameter. 30 | * `INVARIANT`: The type argument is used as an "invariant" type parameter. -------------------------------------------------------------------------------- /Writerside/topics/KaUsualClassType.md: -------------------------------------------------------------------------------- 1 | # KaUsualClassType 2 | 3 | Represents a Kotlin generic class type, such as `String` or `List`. 4 | 5 | `KaUsualClassType` does not have unique members and is used mostly for instance check purposes. 6 | 7 | ## Hierarchy 8 | 9 | Inherits from [KaClassType](KaClassType.md). -------------------------------------------------------------------------------- /Writerside/topics/KaValueParameterSymbol.md: -------------------------------------------------------------------------------- 1 | # KaValueParameterSymbol 2 | 3 | Represents a value parameter of a function, constructor, and a property setter. 4 | 5 | In Kotlin, we generally use the phrase "value parameter", as function have both value and 6 | [type parameters](KaTypeParameterSymbol.md). 7 | 8 | ## Hierarchy 9 | 10 | Inherits from [KaVariableSymbol](KaVariableSymbol.md). 11 | 12 | ## Members 13 | 14 | `val name: Name` 15 | : The value parameter name. 16 | 17 | `val isNoinline: Boolean` 18 | : `true` if the value parameter has the 19 | [`noinline`](https://kotlinlang.org/docs/inline-functions.html#noinline) modifier. 20 | 21 | `val isCrossinline: Boolean` 22 | : `true` if the value parameter has the 23 | [`crossinline`](https://kotlinlang.org/docs/inline-functions.html#non-local-returns) modifier. 24 | 25 | `val hasDefaultValue: Boolean` 26 | : `true` if the parameter has the default value. 27 | 28 | `val isVararg: Boolean` 29 | : `true` if the parameter has the `vararg` modifier. 30 | 31 | `val isImplicitLambdaParameter: Boolean` 32 | : `true` if the parameter is the implicitly generated `it` lambda parameter. 33 | 34 | ## Default values 35 | 36 | | Member | Value | 37 | |---------------------|--------------------------| 38 | | `callableId` | `null` | 39 | | `contextReceivers` | `emptyList()` | 40 | | `isExtension` | `false` | 41 | | `isVal` | `true` | 42 | | `location` | `KaSymbolLocation.LOCAL` | 43 | | `receiverParameter` | `null` | -------------------------------------------------------------------------------- /Writerside/topics/KaVariableAccessCall.md: -------------------------------------------------------------------------------- 1 | # KaVariableAccessCall 2 | 3 | Represents a simple access to a variable within Kotlin code (reading or writing a variable's value). 4 | 5 | ## Hierarchy 6 | 7 | Inherits [KaCallableMemberCall](KaCallableMemberCall.md). -------------------------------------------------------------------------------- /Writerside/topics/KaVariableSymbol.md: -------------------------------------------------------------------------------- 1 | # KaVariableSymbol 2 | 3 | Represents a variable-like declaration, including properties, local variables, and value parameters. 4 | 5 | ## Hierarchy 6 | 7 | A sealed class. 8 | Inherits from [KaCallableSymbol](KaCallableSymbol.md). 9 | 10 | Notable inheritors: [KaPropertySymbol](KaPropertySymbol.md), [KaValueParameterSymbol](KaValueParameterSymbol.md). 11 | 12 | ## Members 13 | 14 | `val name: Name` 15 | : The declaration name. 16 | 17 | `val isVal: Boolean` 18 | : `true` if the declaration is read-only (is not marked with `var`). -------------------------------------------------------------------------------- /Writerside/topics/Migrating-from-K1.md: -------------------------------------------------------------------------------- 1 | # Migrating from K1 2 | 3 | For many years, the only practical way to analyze Kotlin code in IntelliJ IDEA and other tools was to use the Kotlin 4 | compiler's internals, an unsafe API not designed for external usage. 5 | 6 | The Analysis API, on the other hand, offers a much cleaner and robust set of utilities. It exposes almost the same set 7 | of concepts. Thus, if you already have code that depends on the Kotlin compiler, migrating it to the new API should not 8 | be time-consuming. This migration guide outlines the differences between the APIs and explains how to port the 9 | descriptor-based resolution logic to the Analysis API. 10 | 11 | Once an IntelliJ plugin has been migrated to the Analysis API, it will need to [declare its compatibility with the K2 12 | Kotlin mode](Declaring-K2-Compatibility.md) in the `plugin.xml`. 13 | Otherwise, the plugin will not be loaded when the K2 mode is active. 14 | 15 | ## The Conceptual Difference 16 | 17 | The cornerstone of the old compiler API is a `BindingContext`, a universal dictionary: 18 | 19 | - `BindingContext` maps syntactic declarations (`KtDeclaration`) to their semantic parts, `DeclarationDescriptor`s. For 20 | instance, for a `KtFunction` that represents a function in code, there is a `FunctionDescriptor` with semantic 21 | information, which includes resolved parameter and return types. 22 | - In a similar fashion, a type reference (`KtTypeReference`) is mapped to a `KotlinType` with resolved type attributes. 23 | - For calls, including `KtCallExpression`, there is a `ResolvedCall` object containing data collected by call resolution 24 | and inference machinery. 25 | 26 | A `BindingContext` merely acts as a storage that is filled up during declaration analysis. In the compiler, an instance 27 | of `BindingContext` goes through the whole compilation pipeline, collecting more and more semantic information, and 28 | used later for code generation. The IDE does not, however, analyze the entire project at once, as it would take a lot 29 | of time. Instead, a declaration is analyzed only when some IDE feature needs to understand it better. 30 | 31 | Therefore, in the IDE, a `BindingContext` only contains mappings for declarations that have already been analyzed. The 32 | correct filling and use of the dictionary is the caller's responsibility. 33 | 34 | Moreover, classes such as `DeclarationDescriptor` and `KotlinType` do not have any specific lifecycle, so there's 35 | nothing stopping them from being passed around or cached. This is unfortunate because these classes usually retain the 36 | entire compiler resolution session, a very heavy tree of objects. As sporadic errors on outdated descriptor usage are 37 | rare, it becomes easy to inadvertently create a substantial memory leak. 38 | 39 | The Analysis API significantly simplifies this by offering a single [`analyze {}`](Fundamentals.md#kasession) entry 40 | point. Inside the analysis block, all declarations are analyzed on-demand, eliminating occasional "descriptor was not 41 | found for declaration" errors. Further, entities representing declarations and 42 | types [can only be accessed](Fundamentals.md#kalifetimeowner) from within the owning analysis block. This way, 43 | The Analysis API not only guards against memory leaks but also ensures that all analysis results are consistent. 44 | 45 | ## Analysis Entry Point 46 | 47 | The Kotlin 1.0 compiler itself does not offer any stable code analysis entry points. However, the Kotlin IntelliJ IDEA 48 | plugin, which is built on top of the compiler, does provide several: 49 | 50 | ```Kotlin 51 | // Simply returns a 'BindingContext' containing "certain" information about the element 52 | fun KtElement.analyze(bodyResolveMode: BodyResolveMode): BindingContext 53 | 54 | // Returns the semantic declaration abstraction, calls 'analyze()' under the hood 55 | fun KtDeclaration.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode): DeclarationDescriptor? 56 | 57 | // Returns the resolved call information, also delegates to 'analyze()' 58 | fun KtElement.resolveToCall(bodyResolveMode: BodyResolveMode): ResolvedCall? 59 | ``` 60 | 61 | These are not the only ones available – there are numerous more sophisticated ones, 62 | including `analyzeWithAllCompilerChecks()`, `analyzeWithContent()`, `analyzeInContext()`, and others. 63 | 64 | In contrast, the Analysis API offers a single `analyze {}` entry point. Most of the API surface is accessible inside the 65 | lambda, including the `symbol` extension property that maps a `KtDeclaration` to its symbol: 66 | 67 | ```Kotlin 68 | analyze(declaration) { 69 | // 'KaSymbol' is similar to 'DeclarationDescriptor' 70 | val symbol: KaSymbol = declaration.symbol 71 | } 72 | ``` 73 | 74 | This is not just a syntax difference. The Analysis API requires all analysis-related code to be housed in a single 75 | location. You can, of course, extract parts of the logic to separate functions, and even create your set of utilities. 76 | Nevertheless, you cannot freely mix symbols from unrelated analysis sessions. 77 | 78 | While this change might seem like a significant new restriction, it actually has always been in place. Careless handling 79 | of `BindingContext` and its contents was often a source of exceptions, incorrect behavior, and leaks. Therefore, the new 80 | API naturally guides you on how to analyze the code correctly. 81 | 82 | You can read more about the API entity lifetime in the [KaLifetimeOwner](Fundamentals.md#kalifetimeowner) documentation 83 | section. 84 | 85 | ## Declarations 86 | 87 | Both the old compiler API and the Analysis API are built on top of `PsiElement`, the API in IntelliJ IDEA responsible 88 | for creating syntax trees. However, unlike some other language implementations, Kotlin distinctly separates PSI and 89 | semantic declaration representation. Refer to the [Symbols vs. PSI](Symbols.md#symbols-vs-psi) section for additional 90 | information. 91 | 92 | In the old compiler, this semantic representation is called `DeclarationDescriptor`. There are specific interfaces for 93 | each declaration type, including `ClassDescriptor`, `FunctionDescriptor`, and `PropertyDescriptor`. Descriptors are 94 | obtained from a `BindingContext`: 95 | 96 | ```Kotlin 97 | val descriptor: DeclarationDescriptor = 98 | bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] 99 | ``` 100 | 101 | In the Analysis API, a concept similar to descriptors is named `KaSymbol`. Just like descriptors, there 102 | are `KaClassSymbol`, `KaFunctionSymbol`, and `KaPropertySymbol`. 103 | 104 | To get a symbol for a `KtDeclaration`, simply use the `symbol` extension property. 105 | `symbol` is overloaded for subtypes of `KaSymbol`, meaning that if you call it on some specific declaration type, 106 | you will get a more precise symbol type. For instance: 107 | 108 | ```Kotlin 109 | val property: KtProperty = ... 110 | 111 | analyze(property) { 112 | val symbol = property.symbol 113 | // symbol is a 'KaPropertySymbol' 114 | } 115 | ``` 116 | 117 | For a `KtClassOrObject`, however, `symbol` will return just a `KaDeclarationSymbol`. 118 | The reason for this is Kotlin PSI's legacy: A `KtEnumEntry` is a subtype of `KtClassOrObject`, whereas in K2, an enum 119 | entry is a variable. So, you may wish to use `ktClassOrObject.classSymbol` instead, as it will return 120 | a `KaClassSymbol?`. 121 | 122 | Approach the [symbol](Symbols.md) documentation for more detailed information about symbols. 123 | 124 | ### Declaration Names 125 | 126 | In the old compiler, `FqName` was often used to store fully-qualified declaration names. Although it is a 127 | straightforward abstraction, `FqName` cannot differentiate between package and classifier components. For instance, 128 | in `foo.Bar.Baz`, `Bar` could either be a package or an outer class name. While Kotlin's coding 129 | conventions [discourage](https://kotlinlang.org/docs/coding-conventions.html#naming-rules) capitalized package names, 130 | technically it remains possible. Consequently, the Analysis API employs a different abstraction for storing qualified 131 | names, namely `ClassId` for classes and `CallableId` for functions and properties. 132 | 133 | To construct a `ClassId`, merely pass its text representation to `ClassId.fromString()`. The slashes `/` separate 134 | package components, whereas dots `.` distinguish nested class names. 135 | 136 | ```Kotlin 137 | val intClassId = ClassId.fromString("kotlin/Int") 138 | val nestedClassId = ClassId.fromString("foo/bar/Outer.Nested") 139 | ``` 140 | 141 | The [`StandardClassIds`](https://github.com/JetBrains/kotlin/blob/master/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt) 142 | class provides `ClassId`s for many common class names from the Kotlin standard library. 143 | 144 | You can construct a `CallableId` by supplying either an outer `ClassId` or a package `FqName` and a callable name. 145 | 146 | ```Kotlin 147 | val suspendCallableId = CallableId(FqName("kotlin"), Name.identifier("suspend")) 148 | val equalsCallableId = CallableId(ClassId("kotlin/Any"), Name.identifier("equals")) 149 | ``` 150 | 151 | ### Classes 152 | 153 | Class-related hierarchies are quite similar in both K1 and K2 APIs. 154 | 155 | 156 | graph LR 157 | ClassifierDescriptor 158 | ClassifierDescriptor --> ClassDescriptor 159 | ClassifierDescriptor --> TypeParameterDescriptor 160 | ClassifierDescriptor --> TypeAliasDescriptor 161 | 162 | 163 | The difference is that in the Analysis API, named and anonymous classes have distinct subclasses. 164 | 165 | 166 | graph LR 167 | KaClassifierSymbol 168 | KaClassifierSymbol --> KaClassSymbol 169 | KaClassSymbol --> KaNamedClassSymbol 170 | KaClassSymbol --> KaAnonymousObjectSymbol 171 | KaClassifierSymbol --> KaTypeParameterSymbol 172 | KaClassifierSymbol --> KaTypeAliasSymbol 173 | 174 | 175 | Getting simple and qualified class names 176 | : Old API: `classDescriptor.name`, `classDescriptor.classId`, `classDescriptor.fqNameSafe` 177 | : Analysis API: `classSymbol.name`, `classSymbol.classId` (`FqName` represents nested classes ambiguously, always 178 | use `ClassId`) 179 | 180 | Checking class kind 181 | : Old API: `classDescriptor.kind == ClassKind.INTERFACE` 182 | : Analysis API: `classSymbol.classKind == KaClassKind.INTERFACE` 183 | 184 | Checking ordinary class traits 185 | : Old API: `classDescriptor.isData` 186 | : Analysis API: `(classSymbol as? KaNamedClassSymbol)?.isData` (anonymous classes cannot be `data`) 187 | 188 | Getting class supertypes 189 | : Old API: `classDescriptor.typeConstructor.supertypes` 190 | : Analysis API: `classSymbol.superTypes` 191 | : There is no `TypeConstructor` abstraction in the Analysis API. Use symbols directly. 192 | 193 | Getting class declarations 194 | : Old API: `classDescriptor.unsubstitutedMemberScope.getContributedDescriptors()` 195 | : Analysis API: `classSymbol.memberScope.declarations` (or `classifiers`, `callables` for specific kinds) 196 | 197 | ### Functions 198 | 199 | Both APIs have almost the same set of classes representing functions, constructors and property accessors. 200 | 201 | 202 | graph LR 203 | FunctionDescriptor 204 | FunctionDescriptor --> SimpleFunctionDescriptor 205 | SimpleFunctionDescriptor --> AnonymousFunctionDescriptor 206 | SimpleFunctionDescriptor --> SamConstructorDescriptor 207 | FunctionDescriptor --> ConstructorDescriptor 208 | FunctionDescriptor --> VariableAccessorDescriptor 209 | VariableAccessorDescriptor --> PropertyAccessorDescriptor 210 | PropertyAccessorDescriptor --> PropertyGetterDescriptor 211 | PropertyAccessorDescriptor --> PropertySetterDescriptor 212 | 213 | 214 | In the Analysis API, the hierarchy is rather flat. The most significant change is that anonymous function is not an 215 | ordinary "named" function anymore. 216 | 217 | 218 | graph LR 219 | KaFunctionSymbol 220 | KaFunctionSymbol --> KaNamedFunctionSymbol 221 | KaFunctionSymbol --> KaAnonymousFunctionSymbol 222 | KaFunctionSymbol --> KaConstructorSymbol 223 | KaFunctionSymbol --> KaSamConstructorSymbol 224 | KaFunctionSymbol --> KaPropertyAccessorSymbol 225 | KaPropertyAccessorSymbol --> KaPropertyGetterSymbol 226 | KaPropertyAccessorSymbol --> KaPropertySetterSymbol 227 | 228 | 229 | Getting simple and qualified callable names 230 | : Old API: `functionDescriptor.fqNameSafe` 231 | : Analysis API: `functionDescriptor.callableId` 232 | 233 | Getting parameter and return types 234 | : Old API: `functionDescriptor.valueParameters.map { it.type }`, `functionDescriptor.returnType` 235 | : Analysis API: `functionSymbol.valueParameters.map { it.returnType }`, `functionSymbol.returnType` 236 | 237 | Checking function visibility 238 | : Old API: `functionDescriptor.visibility == DescriptorVisibilities.PUBLIC` 239 | : Analysis API: `functionSymbol.visibility == KaSymbolVisibility.PUBLIC` 240 | 241 | Checking function traits 242 | : Old API: `functionDescriptor.isInline` 243 | : Analysis API: `functionSymbol.isInline` 244 | 245 | ### Variables 246 | 247 | In the old API, the variable hierarchy was quite basic. 248 | 249 | 250 | graph LR 251 | FieldDescriptor 252 | VariableDescriptor 253 | VariableDescriptor --> LocalVariableDescriptor 254 | VariableDescriptor --> PropertyDescriptor 255 | PropertyDescriptor --> JavaPropertyDescriptor 256 | PropertyDescriptor --> SyntheticJavaPropertyDescriptor 257 | VariableDescriptor --> ValueParameterDescriptor 258 | 259 | 260 | In the Analysis API, backing fields, receiver parameters enum entries became a part of the variable hierarchy. 261 | The changes reflect evolution of these concepts in the language and the K2 compiler. 262 | 263 | 264 | graph LR 265 | KaVariableSymbol 266 | KaVariableSymbol --> KaLocalVariableSymbol 267 | KaVariableSymbol --> KaPropertySymbol 268 | KaPropertySymbol --> KaKotlinPropertySymbol 269 | KaPropertySymbol --> KaSyntheticJavaPropertySymbol 270 | KaVariableSymbol --> KaParameterSymbol 271 | KaParameterSymbol --> KaValueParameterSymbol 272 | KaParameterSymbol --> KaReceiverParameterSymbol 273 | KaVariableSymbol --> KaBackingFieldSymbol 274 | KaVariableSymbol --> KaJavaFieldSymbol 275 | KaVariableSymbol --> KaEnumEntrySymbol 276 | 277 | 278 | Getting getter and setter 279 | : Old API: `propertyDescriptor.getter`, `propertyDescriptor.setter` 280 | : Analysis API: `propertySymbol.getter`, `propertySymbol.setter` 281 | 282 | Getting a return type 283 | : Old API: `propertyDescriptor.type` 284 | : Analysis API: `propertySymbol.returnType` 285 | 286 | ### Calls and references 287 | 288 | Check out the difference between reference and call resolution in the 289 | [References and calls](References-And-Calls.md) article. 290 | 291 | The old API offered a single `ResolveCall` class that represented all kinds of calls (successful and error calls, 292 | simple and compound calls). For compound calls, `ResolveCall` itself represents only one of calls, 293 | while additional data was available in quite obscure places, like `CallTransformer.CallForImplicitInvoke`. 294 | 295 | The Analysis API makes the distinction between calls explicit, making it harder to forget about more sophisticated 296 | call kinds. 297 | 298 | 299 | graph TB 300 | KaCall 301 | KaCall --> KaCallableMemberCall 302 | KaCallableMemberCall --> KaVariableAccessCall 303 | KaCallableMemberCall --> KaFunctionCall 304 | KaFunctionCall --> KaSimpleFunctionCall 305 | KaFunctionCall --> KaAnnotationCall 306 | KaFunctionCall --> KaDelegatedConstructorCall 307 | KaCall --> KaCompoundVariableAccessCall 308 | KaCall --> KaCompoundArrayAccessCall 309 | 310 | 311 | In addition, the Analysis API separates successful and error calls. In the IDE, the user edits and refactors code all 312 | the time, and source files often contain unresolved or ambiguous references. Handling them properly (or skipping them) 313 | during static checks is important. 314 | 315 | Resolving a reference 316 | : Old API: `bindingContext[BindingContext.REFERENCE_TARGET, referenceExpression]` 317 | : Analysis API: `referenceExpression.mainReference.resolveToSymbol()` 318 | 319 | Resolving a successful call 320 | : Old API: `expression.getResolvedCall(bindingContext)?.takeIf { it.isReallySuccess() }` 321 | : Analysis API: `expression.resolveToCall().successfulCallOrNull()` 322 | 323 | Getting parameter-argument mapping 324 | : Old API: 325 | ```Kotlin 326 | val call = unaryExpression.getResolvedCall(bindingContext) ?: return 327 | call.valueArguments 328 | ``` 329 | : Analysis API: 330 | ```Kotlin 331 | val call = expression.resolveToCall()?.successfulFunctionCallOrNull() ?: return 332 | call.argumentMapping 333 | ``` 334 | 335 | Getting dispatch and extension receivers 336 | : Old API: 337 | ```Kotlin 338 | val call: ResolvedCall<*> = ... 339 | operatorCall.dispatchReceiver 340 | operatorCall.extensionReceiver 341 | ``` 342 | : Analysis API: 343 | ```Kotlin 344 | val call: KaCallableMemberCall<*, *> = ... 345 | call.partiallyAppliedSymbol.dispatchReceiver 346 | call.partiallyAppliedSymbol.extensionReceiver 347 | ``` 348 | 349 | ### Types 350 | 351 | The old compiler had a sophisticated hierarchy of `KotlinType`s, including wrapped, deferred and delegating types. 352 | The Analysis API provides much simpler API that actually represents all language types. 353 | 354 | 355 | graph LR 356 | KaType 357 | KaType --> KaClassType 358 | KaClassType --> KaUsualClassType 359 | KaClassType --> KaFunctionType 360 | KaType --> KaTypeParameterType 361 | KaType --> KaFlexibleType 362 | KaType --> KaIntersectionType 363 | KaType --> KaCapturedType 364 | KaType --> KaDynamicType 365 | KaType --> KaErrorType 366 | KaErrorType --> KaClassErrorType 367 | 368 | 369 | The `KaType` is a base interface for all Kotlin types. The most common type kind is a `KaClassType`, which represents 370 | not-null and nullable class types, such as `kotlin.Int` or `List?`. 371 | 372 | Check the [type](Types.md) documentation for more details. 373 | 374 | Resolving a type reference 375 | : Old API: `context[BindingContext.TYPE, typeReference]` 376 | : Analysis API: `typeReference.type` 377 | 378 | Getting an expression type 379 | : Old API: `expression.getType(bindingContext)` 380 | : Analysis API: `expression.expressionType` 381 | 382 | Checking for a built-in type 383 | : Old API: `KotlinBuiltIns.isUnit(type)` 384 | : Analysis API: `type.isUnitType` 385 | 386 | Checking for a primitive type 387 | : Old API: `KotlinBuiltIns.isPrimitiveType(type)` 388 | : Analysis API: `type.isPrimitive` 389 | 390 | ### Misc 391 | 392 | Getting a containing declaration 393 | : Old API: `descriptor.containingDeclaration` 394 | : Analysis API: `symbol.containingDeclaration` or `symbol.containingSymbol` 395 | 396 | Checking for annotation presence 397 | : Old API: `descriptor.annotations.hasAnnotation(FqName("kotlin.jvm.JvmName"))` 398 | : Analysis API: `ClassId.fromString("kotlin/jvm/JvmName") in symbol.annotations` 399 | : Check the [Annotations](Annotations.md) documentation for more details. 400 | 401 | ## Example 402 | 403 | Below, the same annotation check is implemented with the old compiler API, and with the Analysis API. 404 | 405 | ### Using the old compiler API 406 | 407 | ```Kotlin 408 | val SPECIAL_ANNOTATION_NAME = FqName("my.app.Special") 409 | 410 | fun hasAnnotation(declaration: KtDeclaration): Boolean { 411 | val bindingContext = declaration.analyze() 412 | val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] 413 | ?: return false 414 | 415 | return descriptor.annotations.hasAnnotation(SPECIAL_ANNOTATION_NAME) 416 | } 417 | ``` 418 | 419 | ### Using Analysis API 420 | 421 | ```Kotlin 422 | val SPECIAL_ANNOTATION_CLASS_ID = ClassId.fromString("my/app/Special") 423 | 424 | fun hasAnnotation(declaration: KtDeclaration): Boolean { 425 | analyze(declaration) { 426 | return SPECIAL_ANNOTATION_CLASS_ID in declaration.symbol.annotations 427 | } 428 | } 429 | ``` -------------------------------------------------------------------------------- /Writerside/topics/Other.md: -------------------------------------------------------------------------------- 1 | # Other 2 | 3 | This section contains other useful functionality the Analysis API provides. -------------------------------------------------------------------------------- /Writerside/topics/Receivers.md: -------------------------------------------------------------------------------- 1 | # Receivers 2 | 3 | Receivers play a vital role in Kotlin, enabling extension functions and member functions. The Analysis API 4 | provides abstractions for different kinds of receivers, allowing you to analyze them in your code. 5 | 6 | ## Types of Receivers 7 | 8 | There are two primary types of receivers in Kotlin: 9 | 10 | * **Dispatch receiver:** Represents the instance of a class on which a member function is called. It's implicitly passed 11 | to the member function and accessible using the `this` keyword. 12 | * **Extension receiver:** Represents the object that an extension function extends. It's explicitly declared in the 13 | function signature and accessible using the `this` keyword within the function body. 14 | 15 | In addition, there are context receivers, which are deprecated and will be eventually replaced with 16 | [context parameters](https://github.com/Kotlin/KEEP/blob/context-parameters/proposals/context-parameters.md). 17 | 18 | ### Dispatch Receiver 19 | 20 | A dispatch receiver is associated with member functions, which are functions defined within a class. When a member 21 | function is called on an object, the object itself becomes the dispatch receiver. 22 | 23 | **Example:** 24 | 25 | ```kotlin 26 | class MyClass { 27 | fun memberFunction() { 28 | // `this` refers to the dispatch receiver (instance of MyClass) 29 | println(this) 30 | } 31 | } 32 | 33 | val myObject = MyClass() 34 | myObject.memberFunction() // `myObject` is the dispatch receiver 35 | ``` 36 | 37 | ### Extension Receiver 38 | 39 | An extension receiver is associated with extension functions, which are functions that extend the functionality of a 40 | class without modifying the class itself. The extension receiver is the object being extended. 41 | 42 | **Example:** 43 | 44 | ```kotlin 45 | fun String.extensionFunction() { 46 | // `this` refers to the extension receiver (instance of String) 47 | println(this.length) 48 | } 49 | 50 | val myString = "Hello" 51 | myString.extensionFunction() // `myString` is the extension receiver 52 | ``` 53 | 54 | ## Key Differences 55 | 56 | While both dispatch and extension receivers are accessible using the `this` keyword within the function body, there 57 | are a few differences. 58 | 59 | * **Declaration.** Dispatch receivers are implicit and don't appear in the function signature. Extension receivers are 60 | explicitly declared in the function signature. 61 | * **Purpose.** Dispatch receivers are used for member functions that operate on the state of an object. Extension 62 | receivers are used to add new functions to existing classes. 63 | 64 | ## Analysis API Representation 65 | 66 | The Analysis API represents receivers using the `KaReceiverValue` sealed class. The specific subclasses are: 67 | 68 | * **KaExplicitReceiverValue:** Represents an explicit receiver expression, e.g., `foo` in `foo.toString()`; 69 | * **KaImplicitReceiverValue:** Represents an implicit receiver, such as in `toString()` (without an explicit receiver). 70 | 71 | ## Declarations with both receivers 72 | 73 | Member extension functions can have both dispatch and extension receivers. For example: 74 | 75 | ```kotlin 76 | class MyClass { 77 | fun String.extensionFunction() { 78 | // `this` refers to the String receiver (extension receiver) 79 | // `this@MyClass` refers to the MyClass instance (dispatch receiver) 80 | println(this.length + this@MyClass.hashCode()) 81 | } 82 | } 83 | ``` 84 | 85 | In the Analysis API, you can access both receivers using the corresponding properties of `KtCallableMemberCall`: 86 | 87 | ```kotlin 88 | val callInfo = ... 89 | when (callInfo) { 90 | is KtSuccessCallInfo -> { 91 | val call = callInfo.call 92 | if (call is KtSimpleFunctionCall) { 93 | val dispatchReceiver = call.partiallyAppliedSymbol.dispatchReceiver 94 | val extensionReceiver = call.partiallyAppliedSymbol.extensionReceiver 95 | // Use dispatchReceiver and extensionReceiver 96 | } 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /Writerside/topics/References-And-Calls.md: -------------------------------------------------------------------------------- 1 | # References and calls 2 | 3 | The Analysis API offers two mechanisms for resolving references within Kotlin code: reference resolution and call 4 | resolution. While they both deal with connecting names to declarations, they serve distinct purposes and provide 5 | different levels of information. 6 | 7 | ## Reference resolution 8 | 9 | **Reference resolution** focuses on resolving a reference, such as an identifier or a qualified expression, to the 10 | corresponding declaration symbol. It primarily answers the question, "What declaration does this reference point to?" 11 | 12 | To get a reference target, call `resolveToSymbols()` or `resolveToSymbol()` on a `mainReference` of a reference 13 | expression: 14 | 15 | ```kotlin 16 | val expression: KtReferenceExpression = ... 17 | 18 | analyze(expression) { 19 | val symbols: Collection = expression 20 | .mainReference.resolveToSymbols() 21 | 22 | // Identical to resolveToSymbols().singleOrNull() 23 | val symbol: KaSymbol? = expression 24 | .mainReference.resolveToSymbol() 25 | } 26 | ``` 27 | 28 | Normally, each correct reference resolves to a single symbol. In case of candidate ambiguity, though, there might be 29 | several targets. 30 | 31 | ## Call resolution 32 | 33 | **Call resolution** delves deeper into analyzing a call expression. It not only identifies the target declaration but 34 | also provides detailed information about the call, such as substituted parameter and return types and type argument 35 | mappings. 36 | 37 | To get resolved call information, call the `resolveToCall()` function: 38 | 39 | ```kotlin 40 | val expression: KtCallExpression = ... 41 | 42 | analyze(expression) { 43 | val callInfo: KaCallInfo? = expression.resolveToCall() 44 | } 45 | ``` 46 | 47 | The resulting `KaCallInfo` is either a `KaSuccessCallInfo` containing a single successfully resolved call, or 48 | a `KaErrorCallInfo` containing a list of candidate calls if there are any, and resolution diagnostic information. 49 | 50 | To simplify handling logic, the Analysis API offers a few utilities. 51 | 52 | `val KaCallInfo.calls: List` 53 | : A list of call candidates. For a successful call, a single resolved call. 54 | 55 | `fun KaCallInfo.singleCallOrNull(): T?`
56 | `fun KaCallInfo.singleFunctionCallOrNull(): KaFunctionCall<*>?`
57 | `fun KaCallInfo.singleVariableAccessCall(): KaVariableAccessCall?` 58 | : Get a single call of the specified type (not necessarily successful). 59 | 60 | `fun KaCallInfo.successfulCallOrNull(): T?`
61 | `fun KaCallInfo.successfulFunctionCallOrNull(): KaFunctionCall<*>?`
62 | `fun KaCallInfo.successfulVariableAccessCall(): KaVariableAccessCall?` 63 | : Get a successful call of the specified type. 64 | 65 | ## Choosing Between Reference and Call Resolution 66 | 67 | The choice between reference and call resolution depends on your specific needs. 68 | 69 | * **Use reference resolution when**: 70 | * You simply need to identify the declaration referenced by a name or expression. 71 | * You are working with references that are not call expressions (e.g., type references). 72 | * **Use call resolution when**: 73 | * You require detailed information about a call, such as argument mapping or type arguments. 74 | * You need to handle overload resolution and type inference. 75 | * You are working with implicit calls (e.g., `foo()` where `foo` is a variable with a functional type). 76 | 77 | In general, call resolution provides more comprehensive information about a call expression, while reference resolution 78 | is more lightweight and suitable for simpler scenarios. -------------------------------------------------------------------------------- /Writerside/topics/Scopes.md: -------------------------------------------------------------------------------- 1 | # Scopes 2 | 3 | A scope acts as a container for declarations, including functions, properties, classes, and type aliases. When resolving 4 | a reference to a name, the compiler searches through a series of scopes to find the corresponding declaration. The order 5 | and types of scopes considered depend on the context of the reference. 6 | 7 | In the Analysis API, scopes are visible through the `KaScope` interface. To get a scope, use the 8 | [scope utilities](KaClassSymbol.md#scope-utilities) defined on classes and scripts. 9 | 10 | ## Members 11 | 12 | `val declarations: Sequence` 13 | : All declarations available in the scope. 14 | 15 | `val classifiers: Sequence` 16 | : All classifier declarations available in the scope. 17 | 18 | `fun classifiers(nameFilter: (Name) -> Boolean): Sequence` 19 | : Classifier declarations available in the scope, filtered with the supplied `nameFilter`. 20 | 21 | `val callables: Sequence` 22 | : All callable declarations available in the scope. 23 | 24 | `fun callables(nameFilter: (Name) -> Boolean): Sequence` 25 | : Callable declarations available in the scope, filtered with the supplied `nameFilter`. 26 | 27 | `val constructors: Sequence` 28 | : Constructor declarations available in the scope. -------------------------------------------------------------------------------- /Writerside/topics/Statistics.md: -------------------------------------------------------------------------------- 1 | # Statistics 2 | 3 | When run with the IntelliJ Kotlin plugin, the Analysis API optionally allows gathering statistics (such as metrics) 4 | about analysis activity. All data is saved **locally** in a log file. It is *not* sent over any network connection. 5 | Furthermore, the feature requires an explicit opt-in. 6 | 7 | These statistics allow us as Analysis API developers to better understand how the Analysis API handles certain 8 | workloads. For you as a user of the Analysis API, the statistics can also provide some insights into how your plugin 9 | uses the Analysis API. The log files are easily shareable, allowing you to send them to us if you encounter any 10 | problems (especially around performance and memory consumption) or include them in your YouTrack issues. 11 | 12 | As of now, we are tracking only a few metrics, but we're planning to add many more. It's also worth noting that only the 13 | K2 backend of the Analysis API collects statistics. 14 | 15 | The feature is built on the same OpenTelemetry-based framework as IntelliJ's tracing and metrics collection, so using 16 | the approach described in this guide can also help with IntelliJ-specific statistics such as virtual file system 17 | metrics. The framework is mainly developed for internal use: it is not a public API and JetBrains makes no compatibility 18 | guarantees. Nonetheless, you're welcome to use it as an external user. 19 | 20 | ## Configuration 21 | 22 | To enable the local Analysis API statistics collection in IntelliJ IDEA, open the 23 | [Registry](https://stackoverflow.com/questions/28415695/how-do-you-set-a-value-in-the-intellij-registry) and enable the 24 | following setting: 25 | 26 | ``` 27 | kotlin.analysis.statistics 28 | ``` 29 | 30 | If the registry setting isn't listed, it is likely that that version of IntelliJ is not recent enough. 31 | 32 | After enabling the setting, restart the IDE. It will automatically begin to collect Analysis API metrics and write them 33 | to a local log file. 34 | 35 | By default, metrics are collected every 60 seconds. This is a coarse-grained view and may not be sufficient for every 36 | use case. To specify more granular collection, the interval can be adjusted with a 37 | [system property](https://www.jetbrains.com/help/idea/tuning-the-ide.html#configure-jvm-options). For example, to 38 | specify an interval of one second (1000ms): 39 | 40 | ``` 41 | -Didea.diagnostic.opentelemetry.metrics-reporting-period-ms=1000 42 | ``` 43 | 44 | It is recommended to enable `kotlin.analysis.statistics` only when needed, as it will impact performance. For example, 45 | we increment counters in hot spots like symbol providers. The metrics reporting period also contributes to the 46 | performance impact, not only for Analysis API statistics, but more broadly all metrics that IntelliJ locally collects 47 | with OpenTelemetry. So it's best to use these settings only temporarily. 48 | 49 | ## Locating & plotting metrics 50 | 51 | The collected metrics will be written into a CSV file in IntelliJ's 52 | [log folder](https://intellij-support.jetbrains.com/hc/en-us/articles/207241085-Locating-IDE-log-files). The file should 53 | be called `open-telemetry-metrics.-