Skip to content

Commit

Permalink
[ABI Validation] Implemented Kotlin Gradle Plugin part for old BCV dumps
Browse files Browse the repository at this point in the history
- added extensions to JVM, Android and Multiplatform Kotlin extensions
- added creation of ABI Validation tasks for old BCV dump format
- added dependencies on `install` tasks of abi-tools modules

Resolves #KT-71168
  • Loading branch information
shanshin authored and Space Team committed Feb 13, 2025
1 parent 5c7e5c5 commit 397af51
Show file tree
Hide file tree
Showing 36 changed files with 2,200 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ package org.jetbrains.kotlin.abi.tools.api
/**
* Set of filtering rules that restrict ABI declarations included into a dump.
*
* It consists of a combination of rules for including and excluding declarations.
* The rules combine inclusion and exclusion of declarations.
* Each filter can be written as a filter for the class name (see [includedClasses] or [excludedClasses]), or an annotation filter (see [includedAnnotatedWith] or [excludedAnnotatedWith]).
*
* In order for a declaration (class, field, property or function) to get into the dump, it must pass the inclusion **and** exclusion filters.
*
* Declaration passes the exclusion filter if it does not match any of class name (see [excludedClasses]) or annotation (see [excludedAnnotatedWith]) filter rule.
* A declaration passes the exclusion filters if it does not match any class names (see [excludedClasses]) or annotation (see [excludedAnnotatedWith]) filter rules.
*
* Declaration passes the inclusion filters if there is no inclusion rules, or it matches any inclusion rule, or at least one of its members (actual for class declaration) matches inclusion rule.
* A declaration passes the inclusion filters if there is no inclusion rules, or it matches any inclusion rule, or at least one of its members (actual for class declaration) matches any inclusion rule.
*
* @since 2.1.20
*/
Expand All @@ -25,7 +25,7 @@ public class AbiFilters(
* Classes that do not match the specified names, that do not have an annotation from [includedAnnotatedWith]
* and do not have members marked with an annotation from [includedAnnotatedWith] are excluded from the dump.
*
* The name filter works by comparing qualified class name with the value in the filter.
* The name filter compares the qualified class name with the value in the filter:
*
* For Kotlin classes, fully qualified names are used.
* It is important to keep in mind that dots are used everywhere as separators, even in the case of a nested class.
Expand All @@ -34,7 +34,7 @@ public class AbiFilters(
* For classes from Java sources, canonical names are used.
* The main motivation is a similar approach to writing the class name - dots are used everywhere as delimiters.
*
* It is allowed to use name templates, for this purpose wildcards `**`, `*` and `?` are added.
* Name templates are allowed, with support for wildcards such as `**`, `*`, and `?`:
* - `**` - zero or any number of characters
* - `*` - zero or any number of characters excluding dot. Using to specify simple class name.
* - `?` - any single character.
Expand All @@ -44,7 +44,7 @@ public class AbiFilters(
/**
* Excludes a class from a dump by its name.
*
* The name filter works by comparing qualified class name with the value in the filter.
* The name filter compares the qualified class name with the value in the filter:
*
* For Kotlin classes, fully qualified names are used.
* It is important to keep in mind that dots are used everywhere as separators, even in the case of a nested class.
Expand All @@ -53,7 +53,7 @@ public class AbiFilters(
* For classes from Java sources, canonical names are used.
* The main motivation is a similar approach to writing the class name - dots are used everywhere as delimiters.
*
* It is allowed to use name templates, for this purpose wildcards `**`, `*` and `?` are added.
* Name templates are allowed, with support for wildcards such as `**`, `*`, and `?`:
* - `**` - zero or any number of characters
* - `*` - zero or any number of characters excluding dot. Using to specify simple class name.
* - `?` - any single character.
Expand All @@ -65,11 +65,9 @@ public class AbiFilters(
*
* Any declaration that is not marked with one of the these annotations and does not match the [includedClasses] is excluded from the dump.
*
* If a class, a top-level function, a top-level property or a class member is annotated with one of specified annotations - then this declaration matches the filter.
* The declaration can be a class, a class member (function or property), a top-level function or a top-level property.
*
* For exclusion filter it means that a class will be excluded from a dump, for inclusion filter it will keep a class or a member in a dump.
*
* It is allowed to use name templates, for this purpose wildcards `**`, `*` and `?` are added.
* Name templates are allowed, with support for wildcards such as `**`, `*`, and `?`:
* - `**` - zero or any number of characters
* - `*` - zero or any number of characters excluding dot. Using to specify simple class name.
* - `?` - any single character.
Expand All @@ -81,11 +79,10 @@ public class AbiFilters(
/**
* Excludes a declaration by annotations placed on it.
*
* If a class, a top-level function, a top-level property or a class member is annotated with one of specified annotations - then this declaration matches the filter.
*
* For exclusion filter it means that class will be excluded from dump, for inclusion filter it will keep class or member in dump.
* It means that a class, a class member (function or property), a top-level function or a top-level property
* marked by a specific annotation will be excluded from the dump.
*
* It is allowed to use name templates, for this purpose wildcards `**`, `*` and `?` are added.
* Name templates are allowed, with support for wildcards such as `**`, `*`, and `?`:
* - `**` - zero or any number of characters
* - `*` - zero or any number of characters excluding dot. Using to specify simple class name.
* - `?` - any single character.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public interface AbiToolsV2 {
public fun loadKlibDump(dump: CharSequence): KlibDump

/**
* Get an ABI from a KLib file with specified [target].
* Get an ABI from a zipped or unpacked KLib specified in [klib] with specified [target].
*
* To control which declarations are passed to the dump, [filters] could be used. By default, no filters will be applied.
*
* @throws IllegalStateException if a KLib could not be loaded from [klibFile].
* @throws java.io.FileNotFoundException if [klibFile] does not exist.
* @throws IllegalStateException if a KLib could not be loaded from [klib].
* @throws java.io.FileNotFoundException if file or directory [klib] does not exist.
*/
public fun extractKlibAbi(klibFile: File, target: KlibTarget, filters: AbiFilters = AbiFilters.Companion.EMPTY): KlibDump
public fun extractKlibAbi(klib: File, target: KlibTarget, filters: AbiFilters = AbiFilters.Companion.EMPTY): KlibDump
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ internal object ToolsV2 : AbiToolsV2 {
}

override fun extractKlibAbi(
klibFile: File,
klib: File,
target: KlibTarget,
filters: AbiFilters,
): KlibDump {
val dump = KlibDumpImpl.fromKlib(klibFile, filters)
val dump = KlibDumpImpl.fromKlib(klib, filters)
dump.renameSingleTarget(target)
return dump
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ private class Filter(filters: AbiFilters) : AbiReadingFilter {

if (declaration is AbiFunction || declaration is AbiProperty) {
if (filtersMatcher.hasAnnotationFilters) {
val annotationNames = declaration.annotatedWith().map { annotation -> annotation.qualifiedName.toKotlinQualifiedName() }
var annotationNames = declaration.annotatedWith().names()

val backingField = (declaration as? AbiProperty)?.backingField
if (backingField != null) {
// add field's annotations
annotationNames = annotationNames + backingField.annotatedWith().names()
}

if (filtersMatcher.isExcludedByAnnotations(annotationNames)) return true
}
}
Expand All @@ -60,12 +67,14 @@ private class Filter(filters: AbiFilters) : AbiReadingFilter {
}

if (filtersMatcher.hasAnnotationFilters) {
val annotationNames = declaration.annotatedWith().map { annotation -> annotation.qualifiedName.toKotlinQualifiedName() }
val annotationNames = declaration.annotatedWith().names()
if (filtersMatcher.isExcludedByAnnotations(annotationNames)) return true
}

return false
}

private fun List<AbiAnnotation>.names(): List<String> = map { annotation -> annotation.qualifiedName.toKotlinQualifiedName() }
}

private fun AbiQualifiedName.toKotlinQualifiedName(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,90 @@ public final class org/jetbrains/kotlin/gradle/dsl/KotlinVersion$Companion {
public final fun getDEFAULT ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinVersion;
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiFilterSetSpec {
public abstract fun getAnnotatedWith ()Lorg/gradle/api/provider/SetProperty;
public abstract fun getClasses ()Lorg/gradle/api/provider/SetProperty;
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec {
public abstract fun excluded (Lkotlin/jvm/functions/Function1;)V
public abstract fun excluded (Lorg/gradle/api/Action;)V
public abstract fun getExcluded ()Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFilterSetSpec;
public abstract fun getIncluded ()Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFilterSetSpec;
public abstract fun included (Lkotlin/jvm/functions/Function1;)V
public abstract fun included (Lorg/gradle/api/Action;)V
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec$DefaultImpls {
public static fun excluded (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec;Lkotlin/jvm/functions/Function1;)V
public static fun excluded (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec;Lorg/gradle/api/Action;)V
public static fun included (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec;Lkotlin/jvm/functions/Function1;)V
public static fun included (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec;Lorg/gradle/api/Action;)V
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationExtension : org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec {
public abstract fun getVariants ()Lorg/gradle/api/NamedDomainObjectContainer;
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationExtension$DefaultImpls {
public static fun filters (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationExtension;Lorg/gradle/api/Action;)V
public static fun legacyDump (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationExtension;Lorg/gradle/api/Action;)V
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationKlibKindExtension {
public abstract fun getEnabled ()Lorg/gradle/api/provider/Property;
public abstract fun getKeepUnsupportedTargets ()Lorg/gradle/api/provider/Property;
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationLegacyDumpExtension {
public abstract fun getLegacyCheckTaskProvider ()Lorg/gradle/api/tasks/TaskProvider;
public abstract fun getLegacyDumpTaskProvider ()Lorg/gradle/api/tasks/TaskProvider;
public abstract fun getLegacyUpdateTaskProvider ()Lorg/gradle/api/tasks/TaskProvider;
public abstract fun getReferenceDumpDir ()Lorg/gradle/api/file/DirectoryProperty;
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformExtension : org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec {
public abstract fun getVariants ()Lorg/gradle/api/NamedDomainObjectContainer;
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformExtension$DefaultImpls {
public static fun filters (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformExtension;Lorg/gradle/api/Action;)V
public static fun klib (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformExtension;Lorg/gradle/api/Action;)V
public static fun legacyDump (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformExtension;Lorg/gradle/api/Action;)V
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec : org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec {
public abstract fun getKlib ()Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationKlibKindExtension;
public abstract fun klib (Lorg/gradle/api/Action;)V
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec$DefaultImpls {
public static fun filters (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec;Lorg/gradle/api/Action;)V
public static fun klib (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec;Lorg/gradle/api/Action;)V
public static fun legacyDump (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationMultiplatformVariantSpec;Lorg/gradle/api/Action;)V
}

public abstract interface class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec : org/gradle/api/Named {
public static final field Companion Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec$Companion;
public static final field MAIN_VARIANT_NAME Ljava/lang/String;
public abstract fun filters (Lorg/gradle/api/Action;)V
public abstract fun getFilters ()Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiFiltersSpec;
public abstract fun getLegacyDump ()Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationLegacyDumpExtension;
public abstract fun legacyDump (Lorg/gradle/api/Action;)V
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec$Companion {
public static final field MAIN_VARIANT_NAME Ljava/lang/String;
}

public final class org/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec$DefaultImpls {
public static fun filters (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec;Lorg/gradle/api/Action;)V
public static fun legacyDump (Lorg/jetbrains/kotlin/gradle/dsl/abi/AbiValidationVariantSpec;Lorg/gradle/api/Action;)V
}

public abstract interface annotation class org/jetbrains/kotlin/gradle/dsl/abi/ExperimentalAbiValidation : java/lang/annotation/Annotation {
}

public final class org/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode : java/lang/Enum {
public static final field ERROR Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
public static final field IGNORE Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
Expand Down Expand Up @@ -1606,6 +1690,15 @@ public final class org/jetbrains/kotlin/gradle/tasks/UsesKotlinJavaToolchain$Def
public static fun getKotlinJavaToolchain (Lorg/jetbrains/kotlin/gradle/tasks/UsesKotlinJavaToolchain;)Lorg/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchain;
}

public abstract interface class org/jetbrains/kotlin/gradle/tasks/abi/KotlinLegacyAbiCheckTask : org/gradle/api/Task {
public abstract fun getActualDir ()Lorg/gradle/api/provider/Provider;
public abstract fun getReferenceDir ()Lorg/gradle/api/provider/Provider;
}

public abstract interface class org/jetbrains/kotlin/gradle/tasks/abi/KotlinLegacyAbiDumpTask : org/gradle/api/Task {
public abstract fun getDumpDir ()Lorg/gradle/api/provider/Provider;
}

public abstract interface class org/jetbrains/kotlin/project/model/LanguageSettings {
public abstract fun getApiVersion ()Ljava/lang/String;
public abstract fun getEnabledLanguageFeatures ()Ljava/util/Set;
Expand Down
Loading

0 comments on commit 397af51

Please sign in to comment.