Light classes in IntelliJ IDEA represent PSI not backed by any real files.
Also, they are “light” in the sense that they don't have to implement all APIs of Java PSI.
Light classes are essential for Java resolver interoperability. They allow Java code to analyze references to Kotlin code.
In particular, they provide support for:
Java Highlighting: Java code can seamlessly call and reference Kotlin code in the editor
Nested Kotlin resolution: There might be cross-references between Kotlin and Java code, using different code analyzers for each language.
Example:
// FILE: KotlinUsage.kt class KotlinUsage: JavaClass() { fun foo() { bar() } }
// FILE: JavaClass.java public class JavaClass extends KotlinBaseClass { }
// FILE: KotlinBaseClass.kt open class KotlinBaseClass { fun bar() {} }
To resolve bar()
in foo()
, the Kotlin resolver would ask JavaClass
about its hierarchy. To answer that, the Java resolver would need to resolve KotlinBaseClass
, which cannot be done without light classes.
PsiElement
s created for source declarations, light classes provide a read-only view of Kotlin declarations. Calling mutating methods on them will result in an exceptionKotlinAsJavaSupport
to find light classes by FQNPsiElement?
utilitiesSome common sense guidelines:
The latest implementation of light classes is powered by the Analysis API. Currently, it is used only for sources (KT-77787).
The main benefit of using the Analysis API is that compiler plugins are supported out of the box by SLC.
A limitation is that SLC must adhere to the resolution contracts of the Kotlin compiler. This means that some scenarios are sensitive to the amount of resolution work performed. In the worst case, this can cause contract violations.
Example: 8afeffee.
The most sensitive place is class members creation (e.g., SymbolLightClassForClassOrObject#getOwnMethods) as it is heavily used in the Java resolver.
The implementation is registered in SymbolKotlinAsJavaSupport.
The implementation of light classes which uses .class
Kotlin output to build Java stubs and provide Java PSI mapping “out of the box”. The implementation is straightforward but has some limitations due to its simplicity. Mainly, it doesn't support constructs that are stored in the bytecode differently than they would be in Java. For instance, type annotations are not supported.
The entry point is DecompiledLightClassesFactory
The next evolution step: KT-77787 Replace DLC with SLC
The K1 implementation of light classes which is built on top of Kotlin PSI.
Location: compiler/light-classes