Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions platform/jewel/foundation/api-dump.txt
Original file line number Diff line number Diff line change
Expand Up @@ -700,9 +700,12 @@
f:org.jetbrains.jewel.foundation.theme.ThemeColorPalette
- sf:$stable:I
- sf:Companion:org.jetbrains.jewel.foundation.theme.ThemeColorPalette$Companion
- sf:PALETTE_KEY_PREFIX:java.lang.String
- <init>(java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.Map):V
- f:blue-vNxB06k(I):J
- f:blueOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid breaking binary changes, we need to keep the old APIs, but deprecate them with DeprecationLevel.HIDDEN

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so that means that I should just add new methods (grayOrNull(Int, Int) etc) and also keep the old ones (grayOrNull(Int) etc)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for example:

@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun grayOrNull(index: Int): Color? = gray.getOrNull(index - 1)

public fun grayOrNull(index: Int, fractional: Int = 0): Color? =
    if (fractional == 0) {
        gray.getOrNull(index - 1)
    } else {
        rawMap["$PALETTE_KEY_PREFIX.Gray$index.$fractional"]
    }

The hidden symbols will still disappear from the dumps, but they will be included in the binary and invisible from code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image but I still get changes in api-dump like that - is it expected?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — @faogustavo has helpfully listed a legend on how to read the dumps here:

* - marked with @ApiStatus.Experimental.
b - synthetic (as in binary visible). Members with both ACC_SYNTHETIC and ACC_BRIDGE are not included in the dump.
p - protected. Nothing for public because it's the default. private and package-private members are not included.
s - static.
@ - annotation.
e - enum.
f - final.
a - abstract.
c - class. Nothing for interface because it should be the default.

So, you're deprecating with HIDDEN level the existing blueOrNull(Int) — that's why it gets the b added to its existing f (DeprecationLevel.HIDDEN is a clever trick that (ab)uses the concept of a synthetic method in JVM bytecode). This is expected.

Next, you added blueOrNull(Int, Int = 0) where the second parameter has a default value; this is reflected in JVM bytecode as:

  1. A f:blueOrNull-6MYuD4A(I,I) with two Int parameters, both non-optional
  2. A f:blueOrNull-6MYuD4A$default(...) that is generated by the compiler to implement the default parameter behaviour
    • This is a synthetic static method that you can safely ignore:
      image

The weird -6MYuD4A suffixes are also added by the Kotlin Compiler; it's called mangling and you can read more about it here: https://ncorti.com/blog/name-mangling-in-kotlin

- f:blueOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 706 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:blueOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:blueOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- equals(java.lang.Object):Z
- f:getBlue():java.util.List
- f:getGray():java.util.List
Expand All @@ -714,21 +717,35 @@
- f:getTeal():java.util.List
- f:getYellow():java.util.List
- f:gray-vNxB06k(I):J
- f:grayOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:grayOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 720 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:grayOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:grayOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:green-vNxB06k(I):J
- f:greenOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:greenOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 724 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:greenOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:greenOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- hashCode():I
- f:lookup-ijrfgN4(java.lang.String):androidx.compose.ui.graphics.Color
- f:orange-vNxB06k(I):J
- f:orangeOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:orangeOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 730 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:orangeOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:orangeOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:purple-vNxB06k(I):J
- f:purpleOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:purpleOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 734 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:purpleOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:purpleOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:red-vNxB06k(I):J
- f:redOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:redOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 738 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:redOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:redOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:teal-vNxB06k(I):J
- f:tealOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:tealOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 742 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:tealOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:tealOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:yellow-vNxB06k(I):J
- f:yellowOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
- f:yellowOrNull-6MYuD4A(I,I):androidx.compose.ui.graphics.Color

Check failure on line 746 in platform/jewel/foundation/api-dump.txt

View workflow job for this annotation

GitHub Actions / Annotate breaking API changes with IJP dumps

Breaking API change

This looks like a breaking API change, make sure it's intended.
- bs:yellowOrNull-6MYuD4A$default(org.jetbrains.jewel.foundation.theme.ThemeColorPalette,I,I,I,java.lang.Object):androidx.compose.ui.graphics.Color
- bf:yellowOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
f:org.jetbrains.jewel.foundation.theme.ThemeColorPalette$Companion
- f:getEmpty():org.jetbrains.jewel.foundation.theme.ThemeColorPalette
f:org.jetbrains.jewel.foundation.theme.ThemeDefinition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.Color
import org.jetbrains.jewel.foundation.GenerateDataFunctions

private val colorKeyRegex: Regex
get() = "([a-z]+)(\\d+)".toRegex(RegexOption.IGNORE_CASE)
get() = "([a-z]+)(\\d+)(?:\\.(\\d+))?".toRegex(RegexOption.IGNORE_CASE)

/**
* A palette of colors provided by the theme.
Expand All @@ -16,15 +16,15 @@ private val colorKeyRegex: Regex
* number of colors in each list depends on the implementation in the LaF. It is therefore important to use the
* `*OrNull` accessors to avoid [IndexOutOfBoundsException]s.
*
* @property gray A list of gray colors, from lightest to darkest.
* @property blue A list of blue colors.
* @property green A list of green colors.
* @property red A list of red colors.
* @property yellow A list of yellow colors.
* @property orange A list of orange colors.
* @property purple A list of purple colors.
* @property teal A list of teal colors.
* @property rawMap A map of all colors in the palette, with their original keys.
* @property gray A list of gray colors with integer indices, from lightest to darkest.
* @property blue A list of blue colors with integer indices.
* @property green A list of green colors with integer indices.
* @property red A list of red colors with integer indices.
* @property yellow A list of yellow colors with integer indices.
* @property orange A list of orange colors with integer indices.
* @property purple A list of purple colors with integer indices.
* @property teal A list of teal colors with integer indices.
* @property rawMap A map of all colors in the palette, including fractional indices colors, with their original keys.
*/
@Suppress("MemberVisibilityCanBePrivate", "KDocUnresolvedReference")
@Immutable
Expand Down Expand Up @@ -68,8 +68,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun grayOrNull(index: Int): Color? = gray.getOrNull(index - 1)

/**
* Retrieves a gray color from the palette by its index and optional fractional part, or `null` if the color is not
* found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Gray1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun grayOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) gray.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Gray$index.$fractional"]

/**
* Retrieves a blue color from the palette by its index. Note that this function is not safe to use and can throw an
* [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -98,8 +113,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun blueOrNull(index: Int): Color? = blue.getOrNull(index - 1)

/**
* Retrieves a blue color from the palette by its index and optional fractional part, or `null` if the color is not
* found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Blue1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun blueOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) blue.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Blue$index.$fractional"]

/**
* Retrieves a green color from the palette by its index. Note that this function is not safe to use and can throw
* an [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -128,8 +158,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun greenOrNull(index: Int): Color? = green.getOrNull(index - 1)

/**
* Retrieves a green color from the palette by its index and optional fractional part, or `null` if the color is not
* found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Green1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun greenOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) green.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Green$index.$fractional"]

/**
* Retrieves a red color from the palette by its index. Note that this function is not safe to use and can throw an
* [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -158,8 +203,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun redOrNull(index: Int): Color? = red.getOrNull(index - 1)

/**
* Retrieves a red color from the palette by its index and optional fractional part, or `null` if the color is not
* found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Red1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun redOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) red.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Red$index.$fractional"]

/**
* Retrieves a yellow color from the palette by its index. Note that this function is not safe to use and can throw
* an [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -188,8 +248,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun yellowOrNull(index: Int): Color? = yellow.getOrNull(index - 1)

/**
* Retrieves a yellow color from the palette by its index and optional fractional part, or `null` if the color is
* not found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Yellow1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun yellowOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) yellow.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Yellow$index.$fractional"]

/**
* Retrieves an orange color from the palette by its index. Note that this function is not safe to use and can throw
* an [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -218,8 +293,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun orangeOrNull(index: Int): Color? = orange.getOrNull(index - 1)

/**
* Retrieves an orange color from the palette by its index and optional fractional part, or `null` if the color is
* not found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Orange1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun orangeOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) orange.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Orange$index.$fractional"]

/**
* Retrieves a purple color from the palette by its index. Note that this function is not safe to use and can throw
* an [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -248,8 +338,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun purpleOrNull(index: Int): Color? = purple.getOrNull(index - 1)

/**
* Retrieves a purple color from the palette by its index and optional fractional part, or `null` if the color is
* not found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Purple1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun purpleOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) purple.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Purple$index.$fractional"]

/**
* Retrieves a teal color from the palette by its index. Note that this function is not safe to use and can throw an
* [IndexOutOfBoundsException] at runtime if the Look and Feel does not provide a full palette.
Expand Down Expand Up @@ -278,8 +383,23 @@ public class ThemeColorPalette(
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @return The [Color] at the specified index, or `null` if the index is out of bounds.
*/
@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun tealOrNull(index: Int): Color? = teal.getOrNull(index - 1)

/**
* Retrieves a teal color from the palette by its index and optional fractional part, or `null` if the color is not
* found.
*
* Palette indices start at 1; how many entries exist for a color depends on the Look and Feel. Some LaFs may only
* have a partial palette, or none at all.
*
* @param index The 1-based index of the color to retrieve. Only values of 1 and above are valid.
* @param fractional The optional fractional part of the index (e.g., 25 for Teal1.25). The default value is 0.
* @return The [Color] at the specified index, or `null` if the index is out of bounds or the color is not found.
*/
public fun tealOrNull(index: Int, fractional: Int = 0): Color? =
if (fractional == 0) teal.getOrNull(index - 1) else rawMap["$PALETTE_KEY_PREFIX.Teal$index.$fractional"]

/**
* Looks up a color in the palette by its key. The key can be in the format "colorNameN" (e.g., "gray1", "blue12")
* or a raw key from the Look and Feel theme.
Expand All @@ -288,24 +408,25 @@ public class ThemeColorPalette(
* @return The [Color] associated with the key, or `null` if the key is not found.
*/
public fun lookup(colorKey: String): Color? {
val result = colorKeyRegex.matchEntire(colorKey.trim())
val result = colorKeyRegex.matchEntire(colorKey.trim().removePrefix("$PALETTE_KEY_PREFIX."))
val colorGroup = result?.groupValues?.getOrNull(1)?.lowercase()
val colorIndex = result?.groupValues?.getOrNull(2)?.toIntOrNull()
val fractionalIndex = result?.groupValues?.getOrNull(3)?.toIntOrNull() ?: 0

if (colorGroup == null || colorIndex == null) {
return rawMap[colorKey]
}

return when (colorGroup) {
"grey",
"gray" -> grayOrNull(colorIndex)
"blue" -> blueOrNull(colorIndex)
"green" -> greenOrNull(colorIndex)
"red" -> redOrNull(colorIndex)
"yellow" -> yellowOrNull(colorIndex)
"orange" -> orangeOrNull(colorIndex)
"purple" -> purpleOrNull(colorIndex)
"teal" -> tealOrNull(colorIndex)
"gray" -> grayOrNull(colorIndex, fractionalIndex)
"blue" -> blueOrNull(colorIndex, fractionalIndex)
"green" -> greenOrNull(colorIndex, fractionalIndex)
"red" -> redOrNull(colorIndex, fractionalIndex)
"yellow" -> yellowOrNull(colorIndex, fractionalIndex)
"orange" -> orangeOrNull(colorIndex, fractionalIndex)
"purple" -> purpleOrNull(colorIndex, fractionalIndex)
"teal" -> tealOrNull(colorIndex, fractionalIndex)
else -> null
}
}
Expand Down Expand Up @@ -357,6 +478,8 @@ public class ThemeColorPalette(
}

public companion object {
public const val PALETTE_KEY_PREFIX: String = "ColorPalette"

public val Empty: ThemeColorPalette =
ThemeColorPalette(
gray = emptyList(),
Expand Down
Loading
Loading