From ce09612804cec9a321644a50f097f2a2fcacbb27 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 25 Mar 2016 18:48:08 +0300 Subject: [PATCH] Write ReadMe about what constitutes the public API and what is an incompatible change --- .../binary-compatibility-validator/ReadMe.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 libraries/tools/binary-compatibility-validator/ReadMe.md diff --git a/libraries/tools/binary-compatibility-validator/ReadMe.md b/libraries/tools/binary-compatibility-validator/ReadMe.md new file mode 100644 index 00000000000..82ccaf8db91 --- /dev/null +++ b/libraries/tools/binary-compatibility-validator/ReadMe.md @@ -0,0 +1,70 @@ +# Kotlin Public API binary compatibility validation tool + +This tool allows to dump binary API of a Kotlin library that is public in sense of Kotlin visibilities +and ensure that the binary API wasn't changed in a way that make this change binary incompatible. + +## What constitutes the public API + +### Classes + +A class is considered to be effectively public if all of the following conditions are met: + + - it has public or protected JVM access (`ACC_PUBLIC` or `ACC_PROTECTED`) + - it has one of the following visibilities in Kotlin: + - no visibility (means no Kotlin declaration corresponds to this compiled class) + - *public* + - *protected* + - *internal*, only in case if the class is annotated with `InlineExposed` + - it isn't a local class + - it isn't a synthetic class with mappings for `when` tableswitches (`$WhenMappings`) + - it contains at least one effectively public member, in case if the class corresponds + to a kotlin *file* with top-level members or a *multifile facade* + - in case if the class is a member in another class, it is contained in the *effectively public* class + - in case if the class is a protected member in another class, it is contained in the *non-final* class + +### Members + +A member of the class (i.e. a field or a method) is considered to be effectively public +if all of the following conditions are met: + + - it has public or protected JVM access (`ACC_PUBLIC` or `ACC_PROTECTED`) + - it has one of the following visibilities in Kotlin: + - no visibility (means no Kotlin declaration corresponds to this class member) + - *public* + - *protected* + - *internal*, only in case if the class is annotated with `InlineExposed` + + > Note that Kotlin visibility of a field exposed by `lateinit` property is the visibility of it's setter. + - in case if the member is protected, it is contained in *non-final* class + - it isn't a synthetic access method for a private field + +## What makes an incompatible change to the public binary API + +### Class changes + +For a class a binary incompatible change is: + + - changing the full class name (including package and containing classes) + - changing the superclass, so that the class no longer has the previous superclass in + the inheritance chain + - changing the set of implemented interfaces so that the class + no longer implements interfaces it had implemented before + - changing one of the following access flags: + - `ACC_PUBLIC`, `ACC_PROTECTED`, `ACC_PRIVATE` — lessening the class visibility + - `ACC_FINAL` — making non-final class final + - `ACC_ABSTRACT` — making non-abstract class abstract + - `ACC_INTERFACE` — changing class to interface and vice versa + - `ACC_ANNOTATION` — changing annotation to interface and vice versa + +### Class member changes + +For a class member a binary incompatible change is: + + - changing its name + - changing its descriptor (erased return type and parameter types for methods); + this includes changing field to method and vice versa + - changing one of the following access flags: + - `ACC_PUBLIC`, `ACC_PROTECTED`, `ACC_PRIVATE` — lessening the member visibility + - `ACC_FINAL` — making non-final field or method final + - `ACC_ABSTRACT` — making non-abstract method abstract + - `ACC_STATIC` — changing instance member to static and vice versa \ No newline at end of file