Declaration References
Declaration reference represents a link between codebase declarations. Konsist allows to precisely verify properties of linked type. This type can be used in function or property declaration or child/parent class or interface. For example
1. Verify if all types of function parameters are interfaces:
Konsist
.scopeFromProject()
.functions()
.parameters
.types
.assertTrue {
it.isInterface
}2. Access properties of parents (parent classes and child interfaces). Below snippet checks if parent class has internal modifier:
fun `all parrent interfaces are internal`() {
Konsist
.scopeFromProject()
.classes()
.parentInterfaces()
.assertTrue {
it.hasInternalModifier()
}
}3. Access properties of children (child classes and child interfaces). Below snippet checks if all interfaces have children that resided in ..somepackage.. package:
Konsist
.scopeFromProject()
.interfaces()
.assertTrue {
it.hasAllChildren(indirectChildren = true) { child ->
child.resideInPackage("..somepackage..")
}
}Type Representation
Kotlin types can defined in multiple ways. Consider foo property with Foo type:
val foo: FooThe Foo type can be defined by:
class
interface
object
type alias
import alias
kotlin types (Kotlin basic type or Kotlin collections type)
function type
external library (type defined outside project codebase) represents declaration which is not defined in the project
The Foo type can be represented by one of KoXDeclaration classes:
KoClassDeclaration
KoInterfaceDeclaration
KoObjectDeclaration
KoTypeAliasDeclaration
KoImportAliasDeclaration
KoKotlinTypeDeclaration
KoFunctionDeclaration
KoExternalDeclaration
Each of these types possesses a largely distinct set of characteristics; for instance, classes and interfaces can include annotations, whereas import aliases cannot.
To access properties the specific declaration type, the declaration cast to more specific type is required (from generic KoTypeDeclaration). Example below assumes that Foo is represented by the Foo class:
Konsist
.scopeFromProject()
.properties()
.types
.assertTrue { koTypeDeclaration ->
val koClass = koTypeDeclaration as KoClassDeclaration
koClass.hasAllAnnotations {
it.representsTypeOf<String>()
}
}To facilitate testing Konsist API provides set of dedicated casting extensions. The above code can be simplified:
Konsist
.scopeFromProject()
.properties()
.types
.assertTrue { koTypeDeclaration ->
koTypeDeclaration
.asClassDeclaration
?.hasAllAnnotations {
it.representsTypeOf<String>()
}
}Here is the list of all casting extensions:
Type Represented By Class
Source code:
internal class FooUsage:
val foo: Foo? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it.asClassDeclaration?.hasInternalModifier
}Type Represented By Interface
Source code:
internal interface FooUsage:
val foo: Foo? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it.asInterfaceDeclaration?.hasInternalModifier
}Type Represented By Object
This scenario is uncommon, but still possible.
Source code:
internal object FooUsage:
val foo: Foo? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it.asObjectDeclaration?.hasInternalModifier
}Type Represented By Type Alias
Source code:
internal object FooUsage:
typealias MyFoo = Foo
val foo: MyFoo? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it
.sourceTypeAlias
.type
.sourceInterface
.hasInternalModifier
}Type Represented By Import Alias
Source code:
internal object FooUsage:
import com.app.Foo as MyFoo
val foo: MyFoo? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it
.asTypeAliasDeclaration
.type
.asInterfaceDeclaration
.hasInternalModifier
}Type Represented By Kotlin Type
Source code:
// Kotlin internal source code for StringUsage:
val foo: String? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it.asKotlinTypeDeclaration.name == "String"
}Type Represented Function Type
Source code:
// Kotlin internal source codeUsage:
val foo: () -> Unit? = nullKonsist test:
scope
.properties()
.types
.assertTrue {
it
.sourceFunctionType
.parameterTypes
.isEmpty()
}Type Represented By External Type
External type represents the type defined outside of the project codebase, usually by external library. Konsist is not able to parse this type, so type information is limited (Konsist is not able to parse the compiled file).
For Example:
class MyViewModel: ViewModelThe Android ViewModel class is provided by androidx.lifecycle:lifecycle-viewmodel-ktx dependency, so Konsist has limited information.
Last updated