diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 277f01d1ee..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: ['submitted', 'bug'] -assignees: '' - ---- - - - -**Describe the bug** -A clear and concise description of what the bug is. - -**Affected platforms** - -- Desktop (Windows, Linux, macOS) -- iOS -- Web (K/Wasm) - Canvas based API -- Web (K/JS) - Canvas based API -- Web (K/JS) - HTML library - -**Versions** -- Libraries: - - Compose Multiplatform version: - - Navigation Multiplatform version (for related issues): - - ... -- Kotlin version: -- OS version(s) (required for Desktop and iOS issues): -- OS architecture (x86 or arm64): -- Device (model or simulator for iOS issues): -- JDK (for desktop issues): - -**To Reproduce** -Steps to reproduce the behavior: -1. Run this code snippet: - ```kt - @Composable - fun BugReproduction() { - // ... - } - ``` -2. Click on '...' -3. Scroll down to '...' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..725144d983 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Create + url: https://youtrack.jetbrains.com/newIssue?project=CMP + about: Please report new issues to the JetBrains YouTrack diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md deleted file mode 100644 index d039a554c8..0000000000 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: Enhancement -about: 'New feature or request' -title: '' -labels: 'submitted, enhancement' -assignees: '' - ---- diff --git a/.github/ISSUE_TEMPLATE/performance.md b/.github/ISSUE_TEMPLATE/performance.md deleted file mode 100644 index 7cd4658e8b..0000000000 --- a/.github/ISSUE_TEMPLATE/performance.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: Performance problem -about: Create a report to help us improve -title: '' -labels: ['submitted', 'performance'] -assignees: '' - ---- - -**Describe the problem** -Explain the performance issue you're experiencing, including the following details: - -- What specific issue did you encounter? (e.g. missing frames, high CPU usage, memory leaks) -- Have you noticed any patterns or specific circumstances under which the problem occurs? - -**Affected platforms** -Select one of the platforms below: -- All -- Desktop -- Web (K/Wasm) - Canvas based API -- Web (K/JS) - Canvas based API -- Web (K/JS) - HTML library -- iOS -- Other - -If the problem is Android-only, report it in the [Jetpack Compose tracker](https://issuetracker.google.com/issues/new?component=612128) - -**Versions** -- Kotlin version: -- Compose Multiplatform version: -- OS version(s) (required for Desktop and iOS issues): -- OS architecture (x86 or arm64): -- JDK (for desktop issues): - -**Sample code** -If possible, provide a small piece of code that reproduces the problem. If the code snippet is too large to paste here, please link to a Gist, a GitHub repo, or any other public code repository. - -**Reproduction steps** -Please provide a detailed step-by-step guide on how to reproduce the issue you are experiencing. - -**Video** -If you're reporting slow app work or missing frames, please provide a video of the problem. - -**Profiling data** -Please provide any relevant profiling data that might be helpful. This could include information like FPS, memory usage, CPU time, or any other data that could provide insight into the performance issue. - -**Additional information** -Provide any other details that you think might be helpful for us to understand the problem. This could include things like the system configuration, external factors, etc. diff --git a/.github/workflows/gradle-plugin.yml b/.github/workflows/gradle-plugin.yml index d5d688cc4a..53a51f7196 100644 --- a/.github/workflows/gradle-plugin.yml +++ b/.github/workflows/gradle-plugin.yml @@ -17,8 +17,8 @@ jobs: fail-fast: false matrix: os: [ubuntu-20.04, macos-14, windows-2022] - gradle: [7.4, 8.7] - agp: [8.1.0, 8.4.0] + gradle: [7.4, 8.8] + agp: [8.1.0, 8.5.0] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index a818e8f7a1..3ad7671eca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,148 @@ +# 1.7.0-alpha01 (July 2024) + +_Changes since 1.6.11_ + +## Highlights + +- [Compose Multiplatform resources are stored in the android assets now. This fixes Android Studio Preview and cases such as a rendering resource files in WebViews or Media Players](https://github.com/JetBrains/compose-multiplatform/pull/4965) +- [Shared Element Transitions](https://developer.android.com/develop/ui/compose/animation/shared-elements) +- [Safe Args in Navigation Compose](https://developer.android.com/guide/navigation/design/type-safety) + +## Breaking changes + +### Android + +- [Minimal supported AGP raised to 8.1.0](https://github.com/JetBrains/compose-multiplatform/pull/4840) + +## Features + +### iOS + +- [Initial iOS floating cursor support](https://github.com/JetBrains/compose-multiplatform-core/pull/1312) +- [Added `accessibilityEnabled: Boolean = true` argument to `UIKitView` and `UIKitViewController`](https://github.com/JetBrains/compose-multiplatform-core/pull/1350) +- [`preferredStatusBarStyle`, `preferredStatysBarAnimation` and `prefersStatusBarHidden` are added to `ComposeUIViewControllerDelegate` to allow status bar appearance modification](https://github.com/JetBrains/compose-multiplatform-core/pull/1378) + +### Desktop + +- [Add constructor with `RenderSettings` to `ComposePanel`. Added a class `RenderSettings` with `val isVsyncEnabled: Boolean?`. When set to `true` gives a hint to renderer implementation of the particular `ComposePanel` to reduce the latency between the input and visual changes in exchange for possible screen tearing](https://github.com/JetBrains/compose-multiplatform-core/pull/1377) +- [Add public `moveEnabled` and `positionPercentage` setters in `SplitPaneState`](https://github.com/JetBrains/compose-multiplatform/pull/3974) + +### Resources + +- [Speed resources web rendering up by the reading a cached value instantly](https://github.com/JetBrains/compose-multiplatform/pull/4893) +- [If there is no resource with suitable density, use resource with the most suitable density, otherwise use default (similar to the Android logic)](https://github.com/JetBrains/compose-multiplatform/pull/4969) +- [Add a customization for resources directories. Now it is possible to use e.g downloaded resources](https://github.com/JetBrains/compose-multiplatform/pull/5016) + +## Fixes + +### Multiple Platforms + +- [Fix "ComposePanel. Focus moves to child after focusing/unfocusing the main window"](https://github.com/JetBrains/compose-multiplatform-core/pull/1398) +- [Don't show code completion for non-existenst API in `commonMain` that fails on Android with `NoSuchMethodException`](https://github.com/JetBrains/compose-multiplatform-core/pull/1328) +- [Fix order of interop elements in some cases](https://github.com/JetBrains/compose-multiplatform-core/pull/1340) +- [Fixed `Popup` jerking during ripple effect animation](https://github.com/JetBrains/compose-multiplatform-core/pull/1385) +- [Fix applying `ShaderBrush` to part of `AnnotatedString`](https://github.com/JetBrains/compose-multiplatform-core/pull/1389) +- [Fix text `brush` animation and optimized updating some visual text properties (applying time is reduced up to 40%)](https://github.com/JetBrains/compose-multiplatform-core/pull/1395) +- [Fix initial cursor position in the empty `TextField` with explicitly set `TextAlignment`](https://github.com/JetBrains/compose-multiplatform-core/pull/1354) +- [Fix focus for editable `TextField` inside `ExposedDropdownMenuBox`](https://github.com/JetBrains/compose-multiplatform-core/pull/1423) + +### iOS + +- [Pressing directional keys on a physical keyboard connected to iOS device doesn't cause a crash](https://github.com/JetBrains/compose-multiplatform-core/pull/1383) +- [Dismissing popup or dialogue within a very short timespan after its creation doesn't cause a crash](https://github.com/JetBrains/compose-multiplatform-core/pull/1384) +- [Fix missing invalidations during native view resize](https://github.com/JetBrains/compose-multiplatform-core/pull/1387) +- [Fixed a memory spike when continuously resizing the `ComposeUIViewController` (such as when used in modal sheet presentation context with different detents)](https://github.com/JetBrains/compose-multiplatform-core/pull/1390) +- [visibility of selection handles in single-line textfields with LTR + RTL text in iOS](https://github.com/JetBrains/compose-multiplatform-core/pull/1331) + +### Desktop + +- [Fix possible `UninitializedPropertyAccessException` in `desktopTest`](https://github.com/JetBrains/compose-multiplatform-core/pull/1343) +- [Fixed `ComposePanel.requestFocus()`, making it correctly assign focus to the first focusable child](https://github.com/JetBrains/compose-multiplatform-core/pull/1352) +- [When using `ComposePanel` inside a Swing application on macOS, VoiceOver will now correctly go into the `ComposePanel` when traversing accessible elements](https://github.com/JetBrains/compose-multiplatform-core/pull/1362) +- [When using `ComposePanel` inside a Swing application on Windows with NVDA turned on, focus will now correctly go into the `ComposePanel` when traversing with (ctrl)-shift-tab](https://github.com/JetBrains/compose-multiplatform-core/pull/1363) +- [Correctly save `WindowState` with unspecified `size` instead of crashing](https://github.com/JetBrains/compose-multiplatform-core/pull/1394) +- [Fix `IndexOutOfBoundsException` crash on Windows when traversing a11y elements](https://github.com/JetBrains/compose-multiplatform-core/pull/1415) + +### Web + +- [Process `keydown` and `keyup` keys for identified keys from virtual keyboard](https://github.com/JetBrains/compose-multiplatform-core/pull/1380) +- [Allow preloading the fallback fonts. This enables the usage of emojis and other unicode characters without manually composing the Text with AnnotatedString](https://github.com/JetBrains/compose-multiplatform-core/pull/1400) +- [Make sure the web app distribution doesn't contain a duplicate `skiko.wasm`](https://github.com/JetBrains/compose-multiplatform/pull/4958) + +### Resources + +- [Delete `contextClassLoader` usage on JVM targets](https://github.com/JetBrains/compose-multiplatform/pull/4895) +- [Create an empty resource dir with "podspec" task instead "podInstall"](https://github.com/JetBrains/compose-multiplatform/pull/4900) +- [Fix resource accessors escaping. Now it is possible to use resources with names: "package", "is", "item_$xxx" etc](https://github.com/JetBrains/compose-multiplatform/pull/4901) +- [Read exactly requested count of bytes from InputStream on jvm platforms](https://github.com/JetBrains/compose-multiplatform/pull/4943) + +### Gradle Plugin + +- [Make sure tryGetSkikoRuntimeIfNeeded is executed only during the task execution](https://github.com/JetBrains/compose-multiplatform/pull/4918) +- [Delete outdated build services](https://github.com/JetBrains/compose-multiplatform/pull/4959) + +## Dependencies + +- Gradle Plugin `org.jetbrains.compose`, version `1.7.0-alpha01`. Based on Jetpack Compose libraries: + - [Compiler 1.5.14](https://developer.android.com/jetpack/androidx/releases/compose-compiler#1.5.14) + - [Runtime 1.7.0-beta03](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.7.0-beta03) + - [UI 1.7.0-beta03](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.7.0-beta03) + - [Foundation 1.7.0-beta03](https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.7.0-beta03) + - [Material 1.7.0-beta03](https://developer.android.com/jetpack/androidx/releases/compose-material#1.7.0-beta03) + - [Material3 1.3.0-beta03](https://developer.android.com/jetpack/androidx/releases/compose-material3#1.3.0-beta03) + +- Lifecycle libraries `org.jetbrains.androidx.lifecycle:lifecycle-*:2.8.0`. Based on [Jetpack Lifecycle 2.8.0](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0) +- Navigation libraries `org.jetbrains.androidx.navigation:navigation-*:2.8.0-alpha08`. Based on [Jetpack Navigation 2.8.0-beta03](https://developer.android.com/jetpack/androidx/releases/navigation#2.8.0-beta03) + +___ + +# 1.6.11 (June 2024) + +_Changes since 1.6.10_ + +## Fixes + +### Multiple Platforms + +- [Fix endless re-layout when layout is invalidated by measure, which includes measuring `TextField(singleLine=true)` with `IntrinsicSize`](https://github.com/JetBrains/compose-multiplatform-core/pull/1355) +- [Fix container size for `Dialog` centering inside `ImageComposeScene`](https://github.com/JetBrains/compose-multiplatform-core/pull/1375) + +### iOS + +- [Fix crash on iOS 12 caused by usage unavailable `UIMenuController` API](https://github.com/JetBrains/compose-multiplatform-core/pull/1361) + +### Desktop + +- [Fix `DropdownMenu`/`Popup` positioning when a window is moved to a screen with a different density](https://github.com/JetBrains/compose-multiplatform-core/pull/1333) +- [Fix possible scrolling without animation on some mouse models](https://github.com/JetBrains/compose-multiplatform-core/pull/1326) + +### Web + +- [Fixed crash when `DatePicker` text field receives illegal input](https://github.com/JetBrains/compose-multiplatform-core/pull/1368) + +### Resources + +- [Fix a cached font if the resource acessor was changed](https://github.com/JetBrains/compose-multiplatform/pull/4864) + +### Gradle Plugin + +- [Fix Compose Compiler configuration for Kotlin < 2.0 when kotlin-android or kotlin-js gradle plugins are applied](https://github.com/JetBrains/compose-multiplatform/pull/4879) + +## Dependencies + +- Gradle Plugin `org.jetbrains.compose`, version `1.6.11`. Based on Jetpack Compose libraries: + - [Compiler 1.5.14](https://developer.android.com/jetpack/androidx/releases/compose-compiler#1.5.14) + - [Runtime 1.6.7](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.6.7) + - [UI 1.6.7](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.6.7) + - [Foundation 1.6.7](https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.6.7) + - [Material 1.6.7](https://developer.android.com/jetpack/androidx/releases/compose-material#1.6.7) + - [Material3 1.2.1](https://developer.android.com/jetpack/androidx/releases/compose-material3#1.2.1) + +- Lifecycle libraries `org.jetbrains.androidx.lifecycle:lifecycle-*:2.8.0`. Based on [Jetpack Lifecycle 2.8.0](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0) +- Navigation libraries `org.jetbrains.androidx.navigation:navigation-*:2.7.0-alpha07`. Based on [Jetpack Navigation 2.7.7](https://developer.android.com/jetpack/androidx/releases/navigation#2.7.7) + +___ + # 1.6.10 (May 2024) _Changes since 1.6.2_ diff --git a/benchmarks/ios/jvm-vs-kotlin-native/build.gradle.kts b/benchmarks/ios/jvm-vs-kotlin-native/build.gradle.kts index 2b4f81ce91..f2e0a3ea6c 100644 --- a/benchmarks/ios/jvm-vs-kotlin-native/build.gradle.kts +++ b/benchmarks/ios/jvm-vs-kotlin-native/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("multiplatform") + id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.compose") } diff --git a/benchmarks/ios/jvm-vs-kotlin-native/gradle.properties b/benchmarks/ios/jvm-vs-kotlin-native/gradle.properties index ea3799cf6b..bca924c522 100644 --- a/benchmarks/ios/jvm-vs-kotlin-native/gradle.properties +++ b/benchmarks/ios/jvm-vs-kotlin-native/gradle.properties @@ -1,13 +1,7 @@ -compose.version=1.4.1 -kotlin.version=1.8.20 +compose.version=1.6.11 +kotlin.version=2.0.0 agp.version=7.0.4 org.gradle.jvmargs=-Xmx3g -kotlin.code.style=official -kotlin.native.useEmbeddableCompilerJar=true -kotlin.native.enableDependencyPropagation=false -kotlin.mpp.enableGranularSourceSetsMetadata=true -# Enable kotlin/native experimental memory model -kotlin.native.binary.memoryModel=experimental compose.desktop.verbose=true android.useAndroidX=true kotlin.js.webpack.major.version=4 diff --git a/benchmarks/ios/jvm-vs-kotlin-native/settings.gradle.kts b/benchmarks/ios/jvm-vs-kotlin-native/settings.gradle.kts index b39db44fad..5234bd02ca 100644 --- a/benchmarks/ios/jvm-vs-kotlin-native/settings.gradle.kts +++ b/benchmarks/ios/jvm-vs-kotlin-native/settings.gradle.kts @@ -10,6 +10,7 @@ pluginManagement { plugins { val kotlinVersion = extra["kotlin.version"] as String kotlin("multiplatform").version(kotlinVersion) + id("org.jetbrains.kotlin.plugin.compose").version(kotlinVersion) val composeVersion = extra["compose.version"] as String id("org.jetbrains.compose").version(composeVersion) } diff --git a/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/resources/compose-multiplatform.xml b/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/composeResources/drawable/compose-multiplatform.xml similarity index 100% rename from benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/resources/compose-multiplatform.xml rename to benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/composeResources/drawable/compose-multiplatform.xml diff --git a/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt b/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt index ea3144ff18..29e13d2244 100644 --- a/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt +++ b/benchmarks/ios/jvm-vs-kotlin-native/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt @@ -13,6 +13,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import compose_benchmarks.generated.resources.Res +import compose_benchmarks.generated.resources.compose_multiplatform import kotlinx.coroutines.delay import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource @@ -29,7 +31,7 @@ fun AnimatedVisibility() { Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { AnimatedVisibility(showImage) { Image( - painterResource("compose-multiplatform.xml"), + painterResource(Res.drawable.compose_multiplatform), null ) } diff --git a/benchmarks/kn-performance/build.gradle.kts b/benchmarks/kn-performance/build.gradle.kts index 2b4f81ce91..f2e0a3ea6c 100644 --- a/benchmarks/kn-performance/build.gradle.kts +++ b/benchmarks/kn-performance/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("multiplatform") + id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.compose") } diff --git a/benchmarks/kn-performance/gradle.properties b/benchmarks/kn-performance/gradle.properties index 17ba8bd122..334ef1c1f1 100644 --- a/benchmarks/kn-performance/gradle.properties +++ b/benchmarks/kn-performance/gradle.properties @@ -1,5 +1,5 @@ -compose.version=1.5.10 -kotlin.version=1.9.20 +compose.version=1.6.11 +kotlin.version=2.0.0 org.gradle.jvmargs=-Xmx3g kotlin.native.useEmbeddableCompilerJar=true compose.desktop.verbose=true diff --git a/benchmarks/kn-performance/settings.gradle.kts b/benchmarks/kn-performance/settings.gradle.kts index b39db44fad..5234bd02ca 100644 --- a/benchmarks/kn-performance/settings.gradle.kts +++ b/benchmarks/kn-performance/settings.gradle.kts @@ -10,6 +10,7 @@ pluginManagement { plugins { val kotlinVersion = extra["kotlin.version"] as String kotlin("multiplatform").version(kotlinVersion) + id("org.jetbrains.kotlin.plugin.compose").version(kotlinVersion) val composeVersion = extra["compose.version"] as String id("org.jetbrains.compose").version(composeVersion) } diff --git a/benchmarks/kn-performance/src/commonMain/resources/compose-multiplatform.xml b/benchmarks/kn-performance/src/commonMain/composeResources/drawable/compose-multiplatform.xml similarity index 100% rename from benchmarks/kn-performance/src/commonMain/resources/compose-multiplatform.xml rename to benchmarks/kn-performance/src/commonMain/composeResources/drawable/compose-multiplatform.xml diff --git a/benchmarks/kn-performance/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt b/benchmarks/kn-performance/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt index ea3144ff18..29e13d2244 100644 --- a/benchmarks/kn-performance/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt +++ b/benchmarks/kn-performance/src/commonMain/kotlin/benchmarks/animation/AnimatedVisibility.kt @@ -13,6 +13,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import compose_benchmarks.generated.resources.Res +import compose_benchmarks.generated.resources.compose_multiplatform import kotlinx.coroutines.delay import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource @@ -29,7 +31,7 @@ fun AnimatedVisibility() { Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { AnimatedVisibility(showImage) { Image( - painterResource("compose-multiplatform.xml"), + painterResource(Res.drawable.compose_multiplatform), null ) } diff --git a/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt b/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt index 226bb5c343..dd14048434 100644 --- a/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt +++ b/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt @@ -1,17 +1,34 @@ package org.jetbrains.compose.splitpane.demo import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.Button import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.* +import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Text +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.input.pointer.PointerIcon import androidx.compose.ui.input.pointer.pointerHoverIcon +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.window.singleWindowApplication -import org.jetbrains.compose.splitpane.* +import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi +import org.jetbrains.compose.splitpane.HorizontalSplitPane +import org.jetbrains.compose.splitpane.VerticalSplitPane +import org.jetbrains.compose.splitpane.rememberSplitPaneState import java.awt.Cursor private fun Modifier.cursorForHorizontalResize(): Modifier = @@ -24,40 +41,69 @@ fun main() = singleWindowApplication( MaterialTheme { val splitterState = rememberSplitPaneState() val hSplitterState = rememberSplitPaneState() - HorizontalSplitPane( - splitPaneState = splitterState - ) { - first(20.dp) { - Box(Modifier.background(Color.Red).fillMaxSize()) - } - second(50.dp) { - VerticalSplitPane(splitPaneState = hSplitterState) { - first(50.dp) { - Box(Modifier.background(Color.Blue).fillMaxSize()) - } - second(20.dp) { - Box(Modifier.background(Color.Green).fillMaxSize()) - } + var delta by remember { mutableStateOf("20") } + var percentage by remember { mutableStateOf("0.20") } + Row { + Column(verticalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.padding(10.dp).width(180.dp)) { + Text("Action panel", fontWeight = FontWeight.Bold) + Button(onClick = { splitterState.moveEnabled = !splitterState.moveEnabled }) { + Text(if (splitterState.moveEnabled) "Freeze V" else "Unfreeze V") + } + Button(onClick = { hSplitterState.moveEnabled = !hSplitterState.moveEnabled }) { + Text(if (hSplitterState.moveEnabled) "Freeze H" else "Unfreeze H") + } + + OutlinedTextField(value = delta, onValueChange = { delta = it }, label = { Text("Delta") }) + Button(onClick = { delta.toFloatOrNull()?.let { splitterState.dispatchRawMovement(it) } }) { + Text("Add delta V") + } + Button(onClick = { delta.toFloatOrNull()?.let { hSplitterState.dispatchRawMovement(it) } }) { + Text("Add delta H") + } + + OutlinedTextField(value = percentage, onValueChange = { percentage = it }, label = { Text("Fraction") }) + Button(onClick = { percentage.toFloatOrNull()?.let { splitterState.positionPercentage = it } }) { + Text("Set fraction V") + } + Button(onClick = { percentage.toFloatOrNull()?.let { hSplitterState.positionPercentage = it } }) { + Text("Set fraction H") } } - splitter { - visiblePart { - Box( - Modifier - .width(1.dp) - .fillMaxHeight() - .background(MaterialTheme.colors.background) - ) + HorizontalSplitPane( + splitPaneState = splitterState + ) { + first(20.dp) { + Box(Modifier.background(Color.Red).fillMaxSize()) } - handle { - Box( - Modifier - .markAsHandle() - .cursorForHorizontalResize() - .background(SolidColor(Color.Gray), alpha = 0.50f) - .width(9.dp) - .fillMaxHeight() - ) + second(50.dp) { + VerticalSplitPane(splitPaneState = hSplitterState) { + first(50.dp) { + Box(Modifier.background(Color.Blue).fillMaxSize()) + } + second(20.dp) { + Box(Modifier.background(Color.Green).fillMaxSize()) + } + } + } + splitter { + visiblePart { + Box( + Modifier + .width(1.dp) + .fillMaxHeight() + .background(MaterialTheme.colors.background) + ) + } + handle { + Box( + Modifier + .markAsHandle() + .cursorForHorizontalResize() + .background(SolidColor(Color.Gray), alpha = 0.50f) + .width(9.dp) + .fillMaxHeight() + ) + } } } } diff --git a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt index 6d9d8815c3..0ea874f708 100644 --- a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt +++ b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt @@ -11,10 +11,11 @@ class SplitPaneState( ) { var moveEnabled by mutableStateOf(moveEnabled) - internal set - var positionPercentage by mutableStateOf(initialPositionPercentage) - internal set + private var _positionPercentage by mutableStateOf(initialPositionPercentage) + var positionPercentage: Float + get() = _positionPercentage + set(value) { _positionPercentage = value.coerceIn(0f, 1f) } internal var minPosition: Float = 0f diff --git a/components/build.gradle.kts b/components/build.gradle.kts index d09b33a6dc..8bba7d8509 100644 --- a/components/build.gradle.kts +++ b/components/build.gradle.kts @@ -1,10 +1,11 @@ plugins { kotlin("multiplatform") apply false id("com.android.library") apply false + id("org.jetbrains.kotlinx.binary-compatibility-validator") apply false } subprojects { - version = findProperty("deploy.version") ?: property("compose.version")!! + version = findProperty("deploy.version")!! plugins.withId("java") { configureIfExists { diff --git a/components/gradle.properties b/components/gradle.properties index 8604e6cf0e..478504a76f 100644 --- a/components/gradle.properties +++ b/components/gradle.properties @@ -8,12 +8,12 @@ android.useAndroidX=true #Versions kotlin.version=1.9.23 -compose.version=1.6.10-beta02 agp.version=8.2.2 +compose.version=1.6.10 +deploy.version=0.1.0-SNAPSHOT #Compose org.jetbrains.compose.experimental.jscanvas.enabled=true -org.jetbrains.compose.experimental.wasm.enabled=true org.jetbrains.compose.experimental.macos.enabled=true compose.desktop.verbose=true compose.useMavenLocal=false diff --git a/components/gradle/libs.versions.toml b/components/gradle/libs.versions.toml index 643996da53..6ecd0569a6 100644 --- a/components/gradle/libs.versions.toml +++ b/components/gradle/libs.versions.toml @@ -13,4 +13,6 @@ androidx-activity-compose = { module = "androidx.activity:activity-compose", ver androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test" } androidx-compose-ui-test = { module = "androidx.compose.ui:ui-test", version.ref = "androidx-compose" } androidx-compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "androidx-compose" } -androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "androidx-compose" } \ No newline at end of file +androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "androidx-compose" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "androidx-compose" } +androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview", version.ref = "androidx-compose" } \ No newline at end of file diff --git a/components/resources/demo/shared/build.gradle.kts b/components/resources/demo/shared/build.gradle.kts index cc87a66ef0..5dc1580b80 100644 --- a/components/resources/demo/shared/build.gradle.kts +++ b/components/resources/demo/shared/build.gradle.kts @@ -52,6 +52,10 @@ kotlin { desktopMain.dependencies { implementation(compose.desktop.common) } + androidMain.dependencies { + implementation(libs.androidx.ui.tooling) + implementation(libs.androidx.ui.tooling.preview) + } val nonAndroidMain by creating { dependsOn(commonMain.get()) @@ -73,6 +77,12 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.11" + } } compose.experimental { diff --git a/components/resources/demo/shared/src/androidMain/kotlin/org/jetbrains/compose/resources/demo/shared/main.android.kt b/components/resources/demo/shared/src/androidMain/kotlin/org/jetbrains/compose/resources/demo/shared/main.android.kt index 37f0bf45d7..e61279fa17 100644 --- a/components/resources/demo/shared/src/androidMain/kotlin/org/jetbrains/compose/resources/demo/shared/main.android.kt +++ b/components/resources/demo/shared/src/androidMain/kotlin/org/jetbrains/compose/resources/demo/shared/main.android.kt @@ -5,9 +5,27 @@ package org.jetbrains.compose.resources.demo.shared +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.PreviewContextConfigurationEffect @Composable fun MainView() { UseResources() } + +@Preview(showBackground = true) +@Composable +fun ImagesResPreview() { + ImagesRes(PaddingValues()) +} + +@OptIn(ExperimentalResourceApi::class) +@Preview(showBackground = true) +@Composable +fun FileResPreview() { + PreviewContextConfigurationEffect() + FileRes(PaddingValues()) +} diff --git a/components/resources/library/api/android/library.api b/components/resources/library/api/android/library.api new file mode 100644 index 0000000000..0acbd5b930 --- /dev/null +++ b/components/resources/library/api/android/library.api @@ -0,0 +1,112 @@ +public final class org/jetbrains/compose/resources/AndroidContextProviderKt { + public static final fun PreviewContextConfigurationEffect (Landroidx/compose/runtime/Composer;I)V +} + +public final class org/jetbrains/compose/resources/DensityQualifier$Companion { + public final fun selectByDensity (F)Lorg/jetbrains/compose/resources/DensityQualifier; + public final fun selectByValue (I)Lorg/jetbrains/compose/resources/DensityQualifier; +} + +public final class org/jetbrains/compose/resources/DrawableResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I +} + +public abstract interface annotation class org/jetbrains/compose/resources/ExperimentalResourceApi : java/lang/annotation/Annotation { +} + +public final class org/jetbrains/compose/resources/FontResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I +} + +public final class org/jetbrains/compose/resources/FontResourcesKt { + public static final fun getFontResourceBytes (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/FontResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class org/jetbrains/compose/resources/FontResources_androidKt { + public static final fun Font-DnXFreY (Lorg/jetbrains/compose/resources/FontResource;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/runtime/Composer;II)Landroidx/compose/ui/text/font/Font; +} + +public final class org/jetbrains/compose/resources/ImageResourcesKt { + public static final fun getDrawableResourceBytes (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/DrawableResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun imageResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/ImageBitmap; + public static final fun painterResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/painter/Painter; + public static final fun vectorResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/vector/ImageVector; +} + +public abstract interface annotation class org/jetbrains/compose/resources/InternalResourceApi : java/lang/annotation/Annotation { +} + +public final class org/jetbrains/compose/resources/MissingResourceException : java/lang/Exception { + public static final field $stable I + public fun (Ljava/lang/String;)V +} + +public final class org/jetbrains/compose/resources/PluralStringResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/PluralStringResourcesKt { + public static final fun getPluralString (Lorg/jetbrains/compose/resources/PluralStringResource;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/PluralStringResource;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun pluralStringResource (Lorg/jetbrains/compose/resources/PluralStringResource;ILandroidx/compose/runtime/Composer;I)Ljava/lang/String; + public static final fun pluralStringResource (Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; +} + +public abstract interface class org/jetbrains/compose/resources/Qualifier { +} + +public abstract class org/jetbrains/compose/resources/Resource { + public static final field $stable I + public synthetic fun (Ljava/lang/String;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I +} + +public final class org/jetbrains/compose/resources/ResourceEnvironment { + public static final field $stable I + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I +} + +public final class org/jetbrains/compose/resources/ResourceEnvironmentKt { + public static final fun getSystemResourceEnvironment ()Lorg/jetbrains/compose/resources/ResourceEnvironment; + public static final fun rememberResourceEnvironment (Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/compose/resources/ResourceEnvironment; +} + +public final class org/jetbrains/compose/resources/StringArrayResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/StringArrayResourcesKt { + public static final fun getStringArray (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringArrayResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getStringArray (Lorg/jetbrains/compose/resources/StringArrayResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun stringArrayResource (Lorg/jetbrains/compose/resources/StringArrayResource;Landroidx/compose/runtime/Composer;I)Ljava/util/List; +} + +public final class org/jetbrains/compose/resources/StringResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/StringResourcesKt { + public static final fun getString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/StringResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun stringResource (Lorg/jetbrains/compose/resources/StringResource;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; + public static final fun stringResource (Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/ThemeQualifier$Companion { + public final fun selectByValue (Z)Lorg/jetbrains/compose/resources/ThemeQualifier; +} + +public final class org/jetbrains/compose/resources/vector/xmldom/MalformedXMLException : java/lang/Exception { + public static final field $stable I + public fun (Ljava/lang/String;)V +} + diff --git a/components/resources/library/api/desktop/library.api b/components/resources/library/api/desktop/library.api new file mode 100644 index 0000000000..fd7b4771ff --- /dev/null +++ b/components/resources/library/api/desktop/library.api @@ -0,0 +1,108 @@ +public final class org/jetbrains/compose/resources/DensityQualifier$Companion { + public final fun selectByDensity (F)Lorg/jetbrains/compose/resources/DensityQualifier; + public final fun selectByValue (I)Lorg/jetbrains/compose/resources/DensityQualifier; +} + +public final class org/jetbrains/compose/resources/DrawableResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I +} + +public abstract interface annotation class org/jetbrains/compose/resources/ExperimentalResourceApi : java/lang/annotation/Annotation { +} + +public final class org/jetbrains/compose/resources/FontResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I +} + +public final class org/jetbrains/compose/resources/FontResourcesKt { + public static final fun getFontResourceBytes (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/FontResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class org/jetbrains/compose/resources/FontResources_skikoKt { + public static final fun Font-DnXFreY (Lorg/jetbrains/compose/resources/FontResource;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/runtime/Composer;II)Landroidx/compose/ui/text/font/Font; +} + +public final class org/jetbrains/compose/resources/ImageResourcesKt { + public static final fun getDrawableResourceBytes (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/DrawableResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun imageResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/ImageBitmap; + public static final fun painterResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/painter/Painter; + public static final fun vectorResource (Lorg/jetbrains/compose/resources/DrawableResource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/vector/ImageVector; +} + +public abstract interface annotation class org/jetbrains/compose/resources/InternalResourceApi : java/lang/annotation/Annotation { +} + +public final class org/jetbrains/compose/resources/MissingResourceException : java/lang/Exception { + public static final field $stable I + public fun (Ljava/lang/String;)V +} + +public final class org/jetbrains/compose/resources/PluralStringResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/PluralStringResourcesKt { + public static final fun getPluralString (Lorg/jetbrains/compose/resources/PluralStringResource;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/PluralStringResource;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getPluralString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun pluralStringResource (Lorg/jetbrains/compose/resources/PluralStringResource;ILandroidx/compose/runtime/Composer;I)Ljava/lang/String; + public static final fun pluralStringResource (Lorg/jetbrains/compose/resources/PluralStringResource;I[Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; +} + +public abstract interface class org/jetbrains/compose/resources/Qualifier { +} + +public abstract class org/jetbrains/compose/resources/Resource { + public static final field $stable I + public synthetic fun (Ljava/lang/String;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I +} + +public final class org/jetbrains/compose/resources/ResourceEnvironment { + public static final field $stable I + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I +} + +public final class org/jetbrains/compose/resources/ResourceEnvironmentKt { + public static final fun getSystemResourceEnvironment ()Lorg/jetbrains/compose/resources/ResourceEnvironment; + public static final fun rememberResourceEnvironment (Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/compose/resources/ResourceEnvironment; +} + +public final class org/jetbrains/compose/resources/StringArrayResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/StringArrayResourcesKt { + public static final fun getStringArray (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringArrayResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getStringArray (Lorg/jetbrains/compose/resources/StringArrayResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun stringArrayResource (Lorg/jetbrains/compose/resources/StringArrayResource;Landroidx/compose/runtime/Composer;I)Ljava/util/List; +} + +public final class org/jetbrains/compose/resources/StringResource : org/jetbrains/compose/resources/Resource { + public static final field $stable I + public final fun getKey ()Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/StringResourcesKt { + public static final fun getString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/ResourceEnvironment;Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/StringResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getString (Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun stringResource (Lorg/jetbrains/compose/resources/StringResource;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; + public static final fun stringResource (Lorg/jetbrains/compose/resources/StringResource;[Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/String; +} + +public final class org/jetbrains/compose/resources/ThemeQualifier$Companion { + public final fun selectByValue (Z)Lorg/jetbrains/compose/resources/ThemeQualifier; +} + +public final class org/jetbrains/compose/resources/vector/xmldom/MalformedXMLException : java/lang/Exception { + public static final field $stable I + public fun (Ljava/lang/String;)V +} + diff --git a/components/resources/library/api/library.klib.api b/components/resources/library/api/library.klib.api new file mode 100644 index 0000000000..a9c8d66c89 --- /dev/null +++ b/components/resources/library/api/library.klib.api @@ -0,0 +1,108 @@ +// Klib ABI Dump +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, wasmJs] +// Rendering settings: +// - Signature version: 2 +// - Show manifest properties: true +// - Show declarations: true + +// Library unique name: +abstract interface org.jetbrains.compose.resources/Qualifier // org.jetbrains.compose.resources/Qualifier|null[0] +final class org.jetbrains.compose.resources.vector.xmldom/MalformedXMLException : kotlin/Exception { // org.jetbrains.compose.resources.vector.xmldom/MalformedXMLException|null[0] + constructor (kotlin/String?) // org.jetbrains.compose.resources.vector.xmldom/MalformedXMLException.|(kotlin.String?){}[0] +} +final class org.jetbrains.compose.resources/DrawableResource : org.jetbrains.compose.resources/Resource // org.jetbrains.compose.resources/DrawableResource|null[0] +final class org.jetbrains.compose.resources/FontResource : org.jetbrains.compose.resources/Resource // org.jetbrains.compose.resources/FontResource|null[0] +final class org.jetbrains.compose.resources/MissingResourceException : kotlin/Exception { // org.jetbrains.compose.resources/MissingResourceException|null[0] + constructor (kotlin/String) // org.jetbrains.compose.resources/MissingResourceException.|(kotlin.String){}[0] +} +final class org.jetbrains.compose.resources/PluralStringResource : org.jetbrains.compose.resources/Resource { // org.jetbrains.compose.resources/PluralStringResource|null[0] + final val key // org.jetbrains.compose.resources/PluralStringResource.key|{}key[0] + final fun (): kotlin/String // org.jetbrains.compose.resources/PluralStringResource.key.|(){}[0] +} +final class org.jetbrains.compose.resources/ResourceEnvironment { // org.jetbrains.compose.resources/ResourceEnvironment|null[0] + final fun equals(kotlin/Any?): kotlin/Boolean // org.jetbrains.compose.resources/ResourceEnvironment.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // org.jetbrains.compose.resources/ResourceEnvironment.hashCode|hashCode(){}[0] +} +final class org.jetbrains.compose.resources/StringArrayResource : org.jetbrains.compose.resources/Resource { // org.jetbrains.compose.resources/StringArrayResource|null[0] + final val key // org.jetbrains.compose.resources/StringArrayResource.key|{}key[0] + final fun (): kotlin/String // org.jetbrains.compose.resources/StringArrayResource.key.|(){}[0] +} +final class org.jetbrains.compose.resources/StringResource : org.jetbrains.compose.resources/Resource { // org.jetbrains.compose.resources/StringResource|null[0] + final val key // org.jetbrains.compose.resources/StringResource.key|{}key[0] + final fun (): kotlin/String // org.jetbrains.compose.resources/StringResource.key.|(){}[0] +} +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRule$stableprop[0] +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRuleList$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRuleList$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRuleList$stableprop[0] +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRuleParseException$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRuleParseException$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRuleParseException$stableprop[0] +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_And$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_And$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRule_Condition_And$stableprop[0] +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_Or$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_Or$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRule_Condition_Or$stableprop[0] +final const val org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_Relation$stableprop // org.jetbrains.compose.resources.plural/org_jetbrains_compose_resources_plural_PluralRule_Condition_Relation$stableprop|#static{}org_jetbrains_compose_resources_plural_PluralRule_Condition_Relation$stableprop[0] +final const val org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_MalformedXMLException$stableprop // org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_MalformedXMLException$stableprop|#static{}org_jetbrains_compose_resources_vector_xmldom_MalformedXMLException$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_AsyncCache$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_AsyncCache$stableprop|#static{}org_jetbrains_compose_resources_AsyncCache$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_DrawCache$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_DrawCache$stableprop|#static{}org_jetbrains_compose_resources_DrawCache$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_DrawableResource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_DrawableResource$stableprop|#static{}org_jetbrains_compose_resources_DrawableResource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_FontResource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_FontResource$stableprop|#static{}org_jetbrains_compose_resources_FontResource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Bitmap$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Bitmap$stableprop|#static{}org_jetbrains_compose_resources_ImageCache_Bitmap$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Svg$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Svg$stableprop|#static{}org_jetbrains_compose_resources_ImageCache_Svg$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Vector$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_ImageCache_Vector$stableprop|#static{}org_jetbrains_compose_resources_ImageCache_Vector$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_LanguageQualifier$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_LanguageQualifier$stableprop|#static{}org_jetbrains_compose_resources_LanguageQualifier$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_MissingResourceException$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_MissingResourceException$stableprop|#static{}org_jetbrains_compose_resources_MissingResourceException$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_PluralStringResource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_PluralStringResource$stableprop|#static{}org_jetbrains_compose_resources_PluralStringResource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_RegionQualifier$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_RegionQualifier$stableprop|#static{}org_jetbrains_compose_resources_RegionQualifier$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_Resource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_Resource$stableprop|#static{}org_jetbrains_compose_resources_Resource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_ResourceEnvironment$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_ResourceEnvironment$stableprop|#static{}org_jetbrains_compose_resources_ResourceEnvironment$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_ResourceItem$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_ResourceItem$stableprop|#static{}org_jetbrains_compose_resources_ResourceItem$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringArrayResource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringArrayResource$stableprop|#static{}org_jetbrains_compose_resources_StringArrayResource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Array$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Array$stableprop|#static{}org_jetbrains_compose_resources_StringItem_Array$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Plurals$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Plurals$stableprop|#static{}org_jetbrains_compose_resources_StringItem_Plurals$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Value$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringItem_Value$stableprop|#static{}org_jetbrains_compose_resources_StringItem_Value$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringResource$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_StringResource$stableprop|#static{}org_jetbrains_compose_resources_StringResource$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_SvgElement$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_SvgElement$stableprop|#static{}org_jetbrains_compose_resources_SvgElement$stableprop[0] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_SvgPainter$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_SvgPainter$stableprop|#static{}org_jetbrains_compose_resources_SvgPainter$stableprop[0] +final fun org.jetbrains.compose.resources/Font(org.jetbrains.compose.resources/FontResource, androidx.compose.ui.text.font/FontWeight?, androidx.compose.ui.text.font/FontStyle, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.ui.text.font/Font // org.jetbrains.compose.resources/Font|Font(org.jetbrains.compose.resources.FontResource;androidx.compose.ui.text.font.FontWeight?;androidx.compose.ui.text.font.FontStyle;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/getSystemResourceEnvironment(): org.jetbrains.compose.resources/ResourceEnvironment // org.jetbrains.compose.resources/getSystemResourceEnvironment|getSystemResourceEnvironment(){}[0] +final fun org.jetbrains.compose.resources/imageResource(org.jetbrains.compose.resources/DrawableResource, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.graphics/ImageBitmap // org.jetbrains.compose.resources/imageResource|imageResource(org.jetbrains.compose.resources.DrawableResource;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/painterResource(org.jetbrains.compose.resources/DrawableResource, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.graphics.painter/Painter // org.jetbrains.compose.resources/painterResource|painterResource(org.jetbrains.compose.resources.DrawableResource;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/pluralStringResource(org.jetbrains.compose.resources/PluralStringResource, kotlin/Int, androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/pluralStringResource|pluralStringResource(org.jetbrains.compose.resources.PluralStringResource;kotlin.Int;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/pluralStringResource(org.jetbrains.compose.resources/PluralStringResource, kotlin/Int, kotlin/Array..., androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/pluralStringResource|pluralStringResource(org.jetbrains.compose.resources.PluralStringResource;kotlin.Int;kotlin.Array...;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/rememberResourceEnvironment(androidx.compose.runtime/Composer?, kotlin/Int): org.jetbrains.compose.resources/ResourceEnvironment // org.jetbrains.compose.resources/rememberResourceEnvironment|rememberResourceEnvironment(androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/stringArrayResource(org.jetbrains.compose.resources/StringArrayResource, androidx.compose.runtime/Composer?, kotlin/Int): kotlin.collections/List // org.jetbrains.compose.resources/stringArrayResource|stringArrayResource(org.jetbrains.compose.resources.StringArrayResource;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/stringResource(org.jetbrains.compose.resources/StringResource, androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/stringResource|stringResource(org.jetbrains.compose.resources.StringResource;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/stringResource(org.jetbrains.compose.resources/StringResource, kotlin/Array..., androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/stringResource|stringResource(org.jetbrains.compose.resources.StringResource;kotlin.Array...;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun org.jetbrains.compose.resources/vectorResource(org.jetbrains.compose.resources/DrawableResource, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.graphics.vector/ImageVector // org.jetbrains.compose.resources/vectorResource|vectorResource(org.jetbrains.compose.resources.DrawableResource;androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final suspend fun org.jetbrains.compose.resources/getDrawableResourceBytes(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/DrawableResource): kotlin/ByteArray // org.jetbrains.compose.resources/getDrawableResourceBytes|getDrawableResourceBytes(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.DrawableResource){}[0] +final suspend fun org.jetbrains.compose.resources/getFontResourceBytes(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/FontResource): kotlin/ByteArray // org.jetbrains.compose.resources/getFontResourceBytes|getFontResourceBytes(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.FontResource){}[0] +final suspend fun org.jetbrains.compose.resources/getPluralString(org.jetbrains.compose.resources/PluralStringResource, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/getPluralString|getPluralString(org.jetbrains.compose.resources.PluralStringResource;kotlin.Int){}[0] +final suspend fun org.jetbrains.compose.resources/getPluralString(org.jetbrains.compose.resources/PluralStringResource, kotlin/Int, kotlin/Array...): kotlin/String // org.jetbrains.compose.resources/getPluralString|getPluralString(org.jetbrains.compose.resources.PluralStringResource;kotlin.Int;kotlin.Array...){}[0] +final suspend fun org.jetbrains.compose.resources/getPluralString(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/PluralStringResource, kotlin/Int): kotlin/String // org.jetbrains.compose.resources/getPluralString|getPluralString(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.PluralStringResource;kotlin.Int){}[0] +final suspend fun org.jetbrains.compose.resources/getPluralString(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/PluralStringResource, kotlin/Int, kotlin/Array...): kotlin/String // org.jetbrains.compose.resources/getPluralString|getPluralString(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.PluralStringResource;kotlin.Int;kotlin.Array...){}[0] +final suspend fun org.jetbrains.compose.resources/getString(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/StringResource): kotlin/String // org.jetbrains.compose.resources/getString|getString(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.StringResource){}[0] +final suspend fun org.jetbrains.compose.resources/getString(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/StringResource, kotlin/Array...): kotlin/String // org.jetbrains.compose.resources/getString|getString(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.StringResource;kotlin.Array...){}[0] +final suspend fun org.jetbrains.compose.resources/getString(org.jetbrains.compose.resources/StringResource): kotlin/String // org.jetbrains.compose.resources/getString|getString(org.jetbrains.compose.resources.StringResource){}[0] +final suspend fun org.jetbrains.compose.resources/getString(org.jetbrains.compose.resources/StringResource, kotlin/Array...): kotlin/String // org.jetbrains.compose.resources/getString|getString(org.jetbrains.compose.resources.StringResource;kotlin.Array...){}[0] +final suspend fun org.jetbrains.compose.resources/getStringArray(org.jetbrains.compose.resources/ResourceEnvironment, org.jetbrains.compose.resources/StringArrayResource): kotlin.collections/List // org.jetbrains.compose.resources/getStringArray|getStringArray(org.jetbrains.compose.resources.ResourceEnvironment;org.jetbrains.compose.resources.StringArrayResource){}[0] +final suspend fun org.jetbrains.compose.resources/getStringArray(org.jetbrains.compose.resources/StringArrayResource): kotlin.collections/List // org.jetbrains.compose.resources/getStringArray|getStringArray(org.jetbrains.compose.resources.StringArrayResource){}[0] +open annotation class org.jetbrains.compose.resources/ExperimentalResourceApi : kotlin/Annotation { // org.jetbrains.compose.resources/ExperimentalResourceApi|null[0] + constructor () // org.jetbrains.compose.resources/ExperimentalResourceApi.|(){}[0] +} +open annotation class org.jetbrains.compose.resources/InternalResourceApi : kotlin/Annotation { // org.jetbrains.compose.resources/InternalResourceApi|null[0] + constructor () // org.jetbrains.compose.resources/InternalResourceApi.|(){}[0] +} +sealed class org.jetbrains.compose.resources/Resource { // org.jetbrains.compose.resources/Resource|null[0] + open fun equals(kotlin/Any?): kotlin/Boolean // org.jetbrains.compose.resources/Resource.equals|equals(kotlin.Any?){}[0] + open fun hashCode(): kotlin/Int // org.jetbrains.compose.resources/Resource.hashCode|hashCode(){}[0] +} +// Targets: [js, wasmJs] +final const val org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_ElementImpl$stableprop // org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_ElementImpl$stableprop|#static{}org_jetbrains_compose_resources_vector_xmldom_ElementImpl$stableprop[0] +// Targets: [js, wasmJs] +final const val org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_NodeImpl$stableprop // org.jetbrains.compose.resources.vector.xmldom/org_jetbrains_compose_resources_vector_xmldom_NodeImpl$stableprop|#static{}org_jetbrains_compose_resources_vector_xmldom_NodeImpl$stableprop[0] +// Targets: [js, wasmJs] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_Intl_Locale$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_Intl_Locale$stableprop|#static{}org_jetbrains_compose_resources_Intl_Locale$stableprop[0] +// Targets: [js, wasmJs] +final const val org.jetbrains.compose.resources/org_jetbrains_compose_resources_WebResourcesConfiguration$stableprop // org.jetbrains.compose.resources/org_jetbrains_compose_resources_WebResourcesConfiguration$stableprop|#static{}org_jetbrains_compose_resources_WebResourcesConfiguration$stableprop[0] +// Targets: [js, wasmJs] +final fun org.jetbrains.compose.resources/configureWebResources(kotlin/Function1) // org.jetbrains.compose.resources/configureWebResources|configureWebResources(kotlin.Function1){}[0] +// Targets: [js, wasmJs] +final object org.jetbrains.compose.resources/WebResourcesConfiguration { // org.jetbrains.compose.resources/WebResourcesConfiguration|null[0] + final fun resourcePathMapping(kotlin/Function1) // org.jetbrains.compose.resources/WebResourcesConfiguration.resourcePathMapping|resourcePathMapping(kotlin.Function1){}[0] +} diff --git a/components/resources/library/build.gradle.kts b/components/resources/library/build.gradle.kts index b23ba687eb..c53dcba642 100644 --- a/components/resources/library/build.gradle.kts +++ b/components/resources/library/build.gradle.kts @@ -1,3 +1,4 @@ +import kotlinx.validation.ExperimentalBCVApi import org.jetbrains.compose.ExperimentalComposeLibrary import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl @@ -6,10 +7,9 @@ plugins { id("org.jetbrains.compose") id("maven-publish") id("com.android.library") + id("org.jetbrains.kotlinx.binary-compatibility-validator") } -val composeVersion = extra["compose.version"] as String - kotlin { jvm("desktop") androidTarget { @@ -185,6 +185,7 @@ android { assets.srcDir("src/androidInstrumentedTest/assets") } named("test") { resources.srcDir(commonTestResources) } + named("main") { manifest.srcFile("src/androidMain/AndroidManifest.xml") } } } @@ -194,9 +195,10 @@ configureMavenPublication( name = "Resources for Compose JB" ) -// adding it here to make sure skiko is unpacked and available in web tests -compose.experimental { - web.application {} +apiValidation { + @OptIn(ExperimentalBCVApi::class) + klib { enabled = true } + nonPublicMarkers.add("org.jetbrains.compose.resources.InternalResourceApi") } //utility task to generate CLDRPluralRuleLists.kt file by 'CLDRPluralRules/plurals.xml' diff --git a/components/resources/library/src/androidMain/AndroidManifest.xml b/components/resources/library/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000000..ed54901fe4 --- /dev/null +++ b/components/resources/library/src/androidMain/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/AndroidContextProvider.kt b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/AndroidContextProvider.kt new file mode 100644 index 0000000000..df9cc46c4c --- /dev/null +++ b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/AndroidContextProvider.kt @@ -0,0 +1,81 @@ +package org.jetbrains.compose.resources + +import android.annotation.SuppressLint +import android.content.ContentProvider +import android.content.ContentValues +import android.content.Context +import android.content.pm.ProviderInfo +import android.database.Cursor +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalInspectionMode + +internal val androidContext get() = AndroidContextProvider.ANDROID_CONTEXT + +/** + * The function configures the android context + * to be used for non-composable resource read functions + * + * e.g. `Res.readBytes(...)` + * + * Example usage: + * ``` + * @Preview + * @Composable + * fun MyPreviewComponent() { + * PreviewContextConfigurationEffect() + * //... + * } + * ``` + */ +@ExperimentalResourceApi +@Composable +fun PreviewContextConfigurationEffect() { + if (LocalInspectionMode.current) { + AndroidContextProvider.ANDROID_CONTEXT = LocalContext.current + } +} + +//https://andretietz.com/2017/09/06/autoinitialise-android-library/ +internal class AndroidContextProvider : ContentProvider() { + companion object { + @SuppressLint("StaticFieldLeak") + var ANDROID_CONTEXT: Context? = null + } + + override fun onCreate(): Boolean { + ANDROID_CONTEXT = context + return true + } + + override fun attachInfo(context: Context, info: ProviderInfo?) { + if (info == null) { + throw NullPointerException("AndroidContextProvider ProviderInfo cannot be null.") + } + // So if the authorities equal the library internal ones, the developer forgot to set his applicationId + if ("org.jetbrains.compose.components.resources.resources.AndroidContextProvider" == info.authority) { + throw IllegalStateException("Incorrect provider authority in manifest. Most likely due to a " + + "missing applicationId variable your application\'s build.gradle.") + } + + super.attachInfo(context, info) + } + + override fun query( + uri: Uri, + projection: Array?, + selection: String?, + selectionArgs: Array?, + sortOrder: String? + ): Cursor? = null + override fun getType(uri: Uri): String? = null + override fun insert(uri: Uri, values: ContentValues?): Uri? = null + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = 0 + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array? + ): Int = 0 +} \ No newline at end of file diff --git a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt index c85d34c1e8..64f87e5440 100644 --- a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt +++ b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.text.font.* @Composable actual fun Font(resource: FontResource, weight: FontWeight, style: FontStyle): Font { val environment = LocalComposeEnvironment.current.rememberEnvironment() - val path = remember(environment) { resource.getResourceItemByEnvironment(environment).path } - return Font(path, LocalContext.current.assets, weight, style) + val path = remember(environment, resource) { resource.getResourceItemByEnvironment(environment).path } + val assets = LocalContext.current.assets + return Font(path, assets, weight, style) } \ No newline at end of file diff --git a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ImageResources.android.kt b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ImageResources.android.kt index 0e411ce719..fa8d7c8824 100644 --- a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ImageResources.android.kt +++ b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ImageResources.android.kt @@ -6,8 +6,17 @@ import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.unit.Density -internal actual fun ByteArray.toImageBitmap(): ImageBitmap = - BitmapFactory.decodeByteArray(this, 0, size).asImageBitmap() +internal actual fun ByteArray.toImageBitmap(resourceDensity: Int, targetDensity: Int): ImageBitmap { + val options = BitmapFactory.Options().apply { + //https://youtrack.jetbrains.com/issue/CMP-5657 + //android only downscales drawables. If there is only low dpi resource then use it as is (not upscale) + if (resourceDensity > targetDensity) { + inDensity = resourceDensity + inTargetDensity = targetDensity + } + } + return BitmapFactory.decodeByteArray(this, 0, size, options).asImageBitmap() +} internal actual class SvgElement diff --git a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt index 5ec66d7f02..d8e5741966 100644 --- a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt +++ b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt @@ -1,51 +1,96 @@ package org.jetbrains.compose.resources -import java.io.File +import android.content.res.AssetManager +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal +import java.io.FileNotFoundException import java.io.InputStream internal actual fun getPlatformResourceReader(): ResourceReader = object : ResourceReader { + private val assets: AssetManager by lazy { + val context = androidContext ?: error( + "Android context is not initialized. " + + "If it happens in the Preview mode then call PreviewContextConfigurationEffect() function." + ) + context.assets + } + override suspend fun read(path: String): ByteArray { val resource = getResourceAsStream(path) - return resource.readBytes() + return resource.use { input -> input.readBytes() } } override suspend fun readPart(path: String, offset: Long, size: Long): ByteArray { val resource = getResourceAsStream(path) val result = ByteArray(size.toInt()) resource.use { input -> - input.skip(offset) - input.read(result, 0, size.toInt()) + input.skipBytes(offset) + input.readBytes(result, 0, size.toInt()) } return result } + //skipNBytes requires API 34 + private fun InputStream.skipBytes(offset: Long) { + var skippedBytes = 0L + while (skippedBytes < offset) { + val count = skip(offset - skippedBytes) + if (count == 0L) break + skippedBytes += count + } + } + + //readNBytes requires API 34 + private fun InputStream.readBytes(byteArray: ByteArray, offset: Int, size: Int) { + var readBytes = 0 + while (readBytes < size) { + val count = read(byteArray, offset + readBytes, size - readBytes) + if (count <= 0) break + readBytes += count + } + } + override fun getUri(path: String): String { - val classLoader = getClassLoader() - val resource = classLoader.getResource(path) ?: run { - //try to find a font in the android assets - if (File(path).isFontResource()) { - classLoader.getResource("assets/$path") - } else null - } ?: throw MissingResourceException(path) - return resource.toURI().toString() + val uri = if (assets.hasFile(path)) { + Uri.parse("file:///android_asset/$path") + } else { + val classLoader = getClassLoader() + val resource = classLoader.getResource(path) ?: throw MissingResourceException(path) + resource.toURI() + } + return uri.toString() } private fun getResourceAsStream(path: String): InputStream { - val classLoader = getClassLoader() - val resource = classLoader.getResourceAsStream(path) ?: run { - //try to find a font in the android assets - if (File(path).isFontResource()) { - classLoader.getResourceAsStream("assets/$path") - } else null - } ?: throw MissingResourceException(path) - return resource + return try { + assets.open(path) + } catch (e: FileNotFoundException) { + val classLoader = getClassLoader() + classLoader.getResourceAsStream(path) ?: throw MissingResourceException(path) + } } - private fun File.isFontResource(): Boolean { - return this.parentFile?.name.orEmpty().startsWith("font") + private fun getClassLoader(): ClassLoader { + return this.javaClass.classLoader ?: error("Cannot find class loader") } - private fun getClassLoader(): ClassLoader { - return Thread.currentThread().contextClassLoader ?: this.javaClass.classLoader!! + private fun AssetManager.hasFile(path: String): Boolean { + var inputStream: InputStream? = null + val result = try { + inputStream = open(path) + true + } catch (e: FileNotFoundException) { + false + } finally { + inputStream?.close() + } + return result + } +} + +internal actual val ProvidableCompositionLocal.currentOrPreview: ResourceReader + @Composable get() { + PreviewContextConfigurationEffect() + return current } -} \ No newline at end of file diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt index 96f653d87e..9a2de24183 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt @@ -55,11 +55,18 @@ private val emptyImageBitmap: ImageBitmap by lazy { ImageBitmap(1, 1) } */ @Composable fun imageResource(resource: DrawableResource): ImageBitmap { - val resourceReader = LocalResourceReader.current - val imageBitmap by rememberResourceState(resource, resourceReader, { emptyImageBitmap }) { env -> - val path = resource.getResourceItemByEnvironment(env).path - val cached = loadImage(path, resourceReader) { - ImageCache.Bitmap(it.toImageBitmap()) + val resourceReader = LocalResourceReader.currentOrPreview + val resourceEnvironment = rememberResourceEnvironment() + val imageBitmap by rememberResourceState( + resource, resourceReader, resourceEnvironment, { emptyImageBitmap } + ) { env -> + val item = resource.getResourceItemByEnvironment(env) + val resourceDensityQualifier = item.qualifiers.firstOrNull { it is DensityQualifier } as? DensityQualifier + val resourceDensity = resourceDensityQualifier?.dpi ?: DensityQualifier.MDPI.dpi + val screenDensity = resourceEnvironment.density.dpi + val path = item.path + val cached = loadImage(path, "$path-${screenDensity}dpi", resourceReader) { + ImageCache.Bitmap(it.toImageBitmap(resourceDensity, screenDensity)) } as ImageCache.Bitmap cached.bitmap } @@ -78,11 +85,11 @@ private val emptyImageVector: ImageVector by lazy { */ @Composable fun vectorResource(resource: DrawableResource): ImageVector { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val density = LocalDensity.current val imageVector by rememberResourceState(resource, resourceReader, density, { emptyImageVector }) { env -> val path = resource.getResourceItemByEnvironment(env).path - val cached = loadImage(path, resourceReader) { + val cached = loadImage(path, path, resourceReader) { ImageCache.Vector(it.toXmlElement().toImageVector(density)) } as ImageCache.Vector cached.vector @@ -98,11 +105,11 @@ private val emptySvgPainter: Painter by lazy { BitmapPainter(emptyImageBitmap) } @Composable private fun svgPainter(resource: DrawableResource): Painter { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val density = LocalDensity.current val svgPainter by rememberResourceState(resource, resourceReader, density, { emptySvgPainter }) { env -> val path = resource.getResourceItemByEnvironment(env).path - val cached = loadImage(path, resourceReader) { + val cached = loadImage(path, path, resourceReader) { ImageCache.Svg(it.toSvgElement().toSvgPainter(density)) } as ImageCache.Svg cached.painter @@ -126,7 +133,7 @@ suspend fun getDrawableResourceBytes( return DefaultResourceReader.read(resourceItem.path) } -internal expect fun ByteArray.toImageBitmap(): ImageBitmap +internal expect fun ByteArray.toImageBitmap(resourceDensity: Int, targetDensity: Int): ImageBitmap internal expect fun ByteArray.toXmlElement(): Element internal expect fun ByteArray.toSvgElement(): SvgElement @@ -145,6 +152,7 @@ internal fun dropImageCache() { private suspend fun loadImage( path: String, + cacheKey: String, resourceReader: ResourceReader, decode: (ByteArray) -> ImageCache -): ImageCache = imageCache.getOrLoad(path) { decode(resourceReader.read(path)) } +): ImageCache = imageCache.getOrLoad(cacheKey) { decode(resourceReader.read(path)) } diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/PluralStringResources.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/PluralStringResources.kt index 27be9337f5..fa12b8c11b 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/PluralStringResources.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/PluralStringResources.kt @@ -26,7 +26,7 @@ class PluralStringResource */ @Composable fun pluralStringResource(resource: PluralStringResource, quantity: Int): String { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val pluralStr by rememberResourceState(resource, quantity, { "" }) { env -> loadPluralString(resource, quantity, resourceReader, env) } @@ -93,7 +93,7 @@ private suspend fun loadPluralString( */ @Composable fun pluralStringResource(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val args = formatArgs.map { it.toString() } val pluralStr by rememberResourceState(resource, quantity, args, { "" }) { env -> loadPluralString(resource, quantity, args, resourceReader, env) diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/Qualifier.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/Qualifier.kt index 150f144bc3..a3c314b8c9 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/Qualifier.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/Qualifier.kt @@ -3,14 +3,48 @@ package org.jetbrains.compose.resources interface Qualifier @InternalResourceApi -data class LanguageQualifier( +class LanguageQualifier( val language: String -) : Qualifier +) : Qualifier { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as LanguageQualifier + + return language == other.language + } + + override fun hashCode(): Int { + return language.hashCode() + } + + override fun toString(): String { + return "LanguageQualifier(language='$language')" + } +} @InternalResourceApi -data class RegionQualifier( +class RegionQualifier( val region: String -) : Qualifier +) : Qualifier { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as RegionQualifier + + return region == other.region + } + + override fun hashCode(): Int { + return region.hashCode() + } + + override fun toString(): String { + return "RegionQualifier(region='$region')" + } +} @InternalResourceApi enum class ThemeQualifier : Qualifier { diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt index 20ac17ca09..e658ad3e11 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt @@ -97,7 +97,7 @@ internal fun Resource.getResourceItemByEnvironment(environment: ResourceEnvironm .also { if (it.size == 1) return it.first() } .filterBy(environment.theme) .also { if (it.size == 1) return it.first() } - .filterBy(environment.density) + .filterByDensity(environment.density) .also { if (it.size == 1) return it.first() } .let { items -> if (items.isEmpty()) { @@ -125,12 +125,59 @@ private fun List.filterBy(qualifier: Qualifier): List.filterByDensity(density: DensityQualifier): List { + val items = this + var withQualifier = emptyList() + + // filter with the same or better density + val exactAndHigherQualifiers = DensityQualifier.entries + .filter { it.dpi >= density.dpi } + .sortedBy { it.dpi } + + for (qualifier in exactAndHigherQualifiers) { + withQualifier = items.filter { item -> item.qualifiers.any { it == qualifier } } + if (withQualifier.isNotEmpty()) break + } + if (withQualifier.isNotEmpty()) return withQualifier + + // filter with low density + val lowQualifiers = DensityQualifier.entries + .minus(DensityQualifier.LDPI) + .filter { it.dpi < density.dpi } + .sortedByDescending { it.dpi } + for (qualifier in lowQualifiers) { + withQualifier = items.filter { item -> item.qualifiers.any { it == qualifier } } + if (withQualifier.isNotEmpty()) break + } + if (withQualifier.isNotEmpty()) return withQualifier + + //items with no DensityQualifier (default) + // The system assumes that default resources (those from a directory without configuration qualifiers) + // are designed for the baseline pixel density (mdpi) and resizes those bitmaps + // to the appropriate size for the current pixel density. + // https://developer.android.com/training/multiscreen/screendensities#DensityConsiderations + val withNoDensity = items.filter { item -> + item.qualifiers.none { it is DensityQualifier } + } + if (withNoDensity.isNotEmpty()) return withNoDensity + + //items with LDPI density + return items.filter { item -> + item.qualifiers.any { it == DensityQualifier.LDPI } + } +} + // we need to filter by language and region together because there is slightly different logic: // 1) if there is the exact match language+region then use it // 2) if there is the language WITHOUT region match then use it // 3) in other cases use items WITHOUT language and region qualifiers at all // issue: https://github.com/JetBrains/compose-multiplatform/issues/4571 -private fun List.filterByLocale(language: LanguageQualifier, region: RegionQualifier): List { +private fun List.filterByLocale( + language: LanguageQualifier, + region: RegionQualifier +): List { val withLanguage = filter { item -> item.qualifiers.any { it == language } } diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceReader.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceReader.kt index 7c2979e586..9c7bf1b4d5 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceReader.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceReader.kt @@ -1,5 +1,7 @@ package org.jetbrains.compose.resources +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.staticCompositionLocalOf class MissingResourceException(path: String) : Exception("Missing resource with path: $path") @@ -34,3 +36,7 @@ internal val DefaultResourceReader = getPlatformResourceReader() //ResourceReader provider will be overridden for tests internal val LocalResourceReader = staticCompositionLocalOf { DefaultResourceReader } + +//For an android preview we need to initialize the resource reader with the local context +internal expect val ProvidableCompositionLocal.currentOrPreview: ResourceReader + @Composable get diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringArrayResources.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringArrayResources.kt index e89aa5c600..2077db5531 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringArrayResources.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringArrayResources.kt @@ -30,7 +30,7 @@ class StringArrayResource */ @Composable fun stringArrayResource(resource: StringArrayResource): List { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val array by rememberResourceState(resource, { emptyList() }) { env -> loadStringArray(resource, resourceReader, env) } diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt index 3cce39b722..6f44a23b89 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt @@ -23,7 +23,7 @@ class StringResource */ @Composable fun stringResource(resource: StringResource): String { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val str by rememberResourceState(resource, { "" }) { env -> loadString(resource, resourceReader, env) } @@ -75,7 +75,7 @@ private suspend fun loadString( */ @Composable fun stringResource(resource: StringResource, vararg formatArgs: Any): String { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val args = formatArgs.map { it.toString() } val str by rememberResourceState(resource, args, { "" }) { env -> loadString(resource, args, resourceReader, env) diff --git a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt b/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt index 712e8a8cbf..bc7c7ddb85 100644 --- a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt +++ b/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt @@ -59,6 +59,44 @@ class ComposeResourceTest { ) } + @Test + fun testImageResourceDensity() = runComposeUiTest { + val testResourceReader = TestResourceReader() + val imgRes = DrawableResource( + "test_id", setOf( + ResourceItem(setOf(DensityQualifier.XXXHDPI), "2.png", -1, -1), + ResourceItem(setOf(DensityQualifier.MDPI), "1.png", -1, -1), + ) + ) + val mdpiEnvironment = object : ComposeEnvironment { + @Composable + override fun rememberEnvironment() = ResourceEnvironment( + language = LanguageQualifier("en"), + region = RegionQualifier("US"), + theme = ThemeQualifier.LIGHT, + density = DensityQualifier.MDPI + ) + } + + var environment by mutableStateOf(TestComposeEnvironment) + setContent { + CompositionLocalProvider( + LocalResourceReader provides testResourceReader, + LocalComposeEnvironment provides environment + ) { + Image(painterResource(imgRes), null) + } + } + waitForIdle() + environment = mdpiEnvironment + waitForIdle() + + assertEquals( + expected = listOf("2.png", "1.png"), //XXXHDPI - fist, MDPI - next + actual = testResourceReader.readPaths + ) + } + @Test fun testStringResourceCache() = runComposeUiTest { val testResourceReader = TestResourceReader() @@ -293,7 +331,7 @@ class ComposeResourceTest { var uri2 = "" setContent { CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview uri1 = resourceReader.getUri("1.png") uri2 = resourceReader.getUri("2.png") } diff --git a/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt b/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt index 25d4ef44c1..f90b9d516c 100644 --- a/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt +++ b/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt @@ -5,15 +5,15 @@ import java.io.InputStream internal actual fun getPlatformResourceReader(): ResourceReader = object : ResourceReader { override suspend fun read(path: String): ByteArray { val resource = getResourceAsStream(path) - return resource.readBytes() + return resource.use { input -> input.readBytes() } } override suspend fun readPart(path: String, offset: Long, size: Long): ByteArray { val resource = getResourceAsStream(path) val result = ByteArray(size.toInt()) resource.use { input -> - input.skip(offset) - input.read(result, 0, size.toInt()) + input.skipNBytes(offset) + input.readNBytes(result, 0, size.toInt()) } return result } @@ -30,6 +30,6 @@ internal actual fun getPlatformResourceReader(): ResourceReader = object : Resou } private fun getClassLoader(): ClassLoader { - return Thread.currentThread().contextClassLoader ?: this.javaClass.classLoader!! + return this.javaClass.classLoader ?: error("Cannot find class loader") } } \ No newline at end of file diff --git a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt index 5390361c63..c5e9e1682e 100644 --- a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt +++ b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt @@ -31,7 +31,7 @@ private val defaultEmptyFont by lazy { Font("org.jetbrains.compose.emptyFont", B @Composable actual fun Font(resource: FontResource, weight: FontWeight, style: FontStyle): Font { - val resourceReader = LocalResourceReader.current + val resourceReader = LocalResourceReader.currentOrPreview val fontFile by rememberResourceState(resource, weight, style, { defaultEmptyFont }) { env -> val path = resource.getResourceItemByEnvironment(env).path val fontBytes = resourceReader.read(path) diff --git a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ImageResources.skiko.kt b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ImageResources.skiko.kt index a046534554..3ac9eefc10 100644 --- a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ImageResources.skiko.kt +++ b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ImageResources.skiko.kt @@ -6,10 +6,37 @@ import androidx.compose.ui.graphics.toComposeImageBitmap import androidx.compose.ui.unit.Density import org.jetbrains.skia.Data import org.jetbrains.skia.Image +import org.jetbrains.skia.Paint +import org.jetbrains.skia.Rect +import org.jetbrains.skia.SamplingMode +import org.jetbrains.skia.Surface import org.jetbrains.skia.svg.SVGDOM -internal actual fun ByteArray.toImageBitmap(): ImageBitmap = - Image.makeFromEncoded(this).toComposeImageBitmap() +internal actual fun ByteArray.toImageBitmap(resourceDensity: Int, targetDensity: Int): ImageBitmap { + val image = Image.makeFromEncoded(this) + + val targetImage: Image + //https://youtrack.jetbrains.com/issue/CMP-5657 + //android only downscales drawables. If there is only low dpi resource then use it as is (not upscale) + //we need a consistent behavior on all platforms + if (resourceDensity > targetDensity) { + val scale = targetDensity.toFloat() / resourceDensity.toFloat() + val targetH = image.height * scale + val targetW = image.width * scale + val srcRect = Rect.Companion.makeWH(image.width.toFloat(), image.height.toFloat()) + val dstRect = Rect.Companion.makeWH(targetW, targetH) + + targetImage = Surface.makeRasterN32Premul(targetW.toInt(), targetH.toInt()).run { + val paint = Paint().apply { isAntiAlias = true } + canvas.drawImageRect(image, srcRect, dstRect, SamplingMode.LINEAR, paint, true) + makeImageSnapshot() + } + } else { + targetImage = image + } + + return targetImage.toComposeImageBitmap() +} internal actual class SvgElement(val svgdom: SVGDOM) diff --git a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ResourceReader.skiko.kt b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ResourceReader.skiko.kt new file mode 100644 index 0000000000..17d29d49ef --- /dev/null +++ b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/ResourceReader.skiko.kt @@ -0,0 +1,7 @@ +package org.jetbrains.compose.resources + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal + +internal actual val ProvidableCompositionLocal.currentOrPreview: ResourceReader + @Composable get() = current \ No newline at end of file diff --git a/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt b/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt index 8317c96d2a..3ef99c9a73 100644 --- a/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt +++ b/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt @@ -1,10 +1,12 @@ package org.jetbrains.compose.resources import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.launch @Composable internal actual fun rememberResourceState( @@ -13,11 +15,14 @@ internal actual fun rememberResourceState( block: suspend (ResourceEnvironment) -> T ): State { val environment = LocalComposeEnvironment.current.rememberEnvironment() - val state = remember(key1) { mutableStateOf(getDefault()) } - LaunchedEffect(key1) { - state.value = block(environment) + val scope = rememberCoroutineScope() + return remember(key1) { + val mutableState = mutableStateOf(getDefault()) + scope.launch(start = CoroutineStart.UNDISPATCHED) { + mutableState.value = block(environment) + } + mutableState } - return state } @Composable @@ -28,11 +33,14 @@ internal actual fun rememberResourceState( block: suspend (ResourceEnvironment) -> T ): State { val environment = LocalComposeEnvironment.current.rememberEnvironment() - val state = remember(key1, key2) { mutableStateOf(getDefault()) } - LaunchedEffect(key1, key2) { - state.value = block(environment) + val scope = rememberCoroutineScope() + return remember(key1, key2) { + val mutableState = mutableStateOf(getDefault()) + scope.launch(start = CoroutineStart.UNDISPATCHED) { + mutableState.value = block(environment) + } + mutableState } - return state } @Composable @@ -44,9 +52,12 @@ internal actual fun rememberResourceState( block: suspend (ResourceEnvironment) -> T ): State { val environment = LocalComposeEnvironment.current.rememberEnvironment() - val state = remember(key1, key2, key3) { mutableStateOf(getDefault()) } - LaunchedEffect(key1, key2, key3) { - state.value = block(environment) + val scope = rememberCoroutineScope() + return remember(key1, key2, key3) { + val mutableState = mutableStateOf(getDefault()) + scope.launch(start = CoroutineStart.UNDISPATCHED) { + mutableState.value = block(environment) + } + mutableState } - return state } \ No newline at end of file diff --git a/components/settings.gradle.kts b/components/settings.gradle.kts index 2e5b391e1d..12272f6b5b 100644 --- a/components/settings.gradle.kts +++ b/components/settings.gradle.kts @@ -14,6 +14,12 @@ pluginManagement { kotlin("multiplatform").version(extra["kotlin.version"] as String) id("org.jetbrains.compose").version(extra["compose.version"] as String) id("com.android.library").version(extra["agp.version"] as String) + id("org.jetbrains.kotlinx.binary-compatibility-validator").version("0.15.0-Beta.2") + } + + val gradlePluginDir = rootDir.resolve("../gradle-plugins") + if (gradlePluginDir.exists()) { + includeBuild(gradlePluginDir) } } diff --git a/components/ui-tooling-preview/library/build.gradle.kts b/components/ui-tooling-preview/library/build.gradle.kts index 964b992ea0..1007eadc3b 100644 --- a/components/ui-tooling-preview/library/build.gradle.kts +++ b/components/ui-tooling-preview/library/build.gradle.kts @@ -7,8 +7,6 @@ plugins { id("com.android.library") } -val composeVersion = extra["compose.version"] as String - kotlin { jvm("desktop") androidTarget { diff --git a/examples/chat/iosApp/iosApp/Info.plist b/examples/chat/iosApp/iosApp/Info.plist index 9a269f5eaa..412e378128 100644 --- a/examples/chat/iosApp/iosApp/Info.plist +++ b/examples/chat/iosApp/iosApp/Info.plist @@ -20,6 +20,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/examples/codeviewer/iosApp/iosApp/Info.plist b/examples/codeviewer/iosApp/iosApp/Info.plist index 9a269f5eaa..412e378128 100644 --- a/examples/codeviewer/iosApp/iosApp/Info.plist +++ b/examples/codeviewer/iosApp/iosApp/Info.plist @@ -20,6 +20,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/examples/graphics-2d/iosApp/iosApp/Info.plist b/examples/graphics-2d/iosApp/iosApp/Info.plist index 9a269f5eaa..412e378128 100644 --- a/examples/graphics-2d/iosApp/iosApp/Info.plist +++ b/examples/graphics-2d/iosApp/iosApp/Info.plist @@ -20,6 +20,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/examples/imageviewer/iosApp/iosApp/Info.plist b/examples/imageviewer/iosApp/iosApp/Info.plist index 5b28bf5219..8540150120 100644 --- a/examples/imageviewer/iosApp/iosApp/Info.plist +++ b/examples/imageviewer/iosApp/iosApp/Info.plist @@ -22,6 +22,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + NSCameraUsageDescription This app uses camera for capturing photos UIApplicationSceneManifest diff --git a/examples/imageviewer/shared/src/androidMain/AndroidManifest.xml b/examples/imageviewer/shared/src/androidMain/AndroidManifest.xml index 019e56b1ce..3d3da33adc 100755 --- a/examples/imageviewer/shared/src/androidMain/AndroidManifest.xml +++ b/examples/imageviewer/shared/src/androidMain/AndroidManifest.xml @@ -10,6 +10,11 @@ android:name="example.imageviewer.ImageViewerFileProvider" android:authorities="example.imageviewer.fileprovider" android:exported="false" - android:grantUriPermissions="true"> + android:grantUriPermissions="true"> + + + \ No newline at end of file diff --git a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/Dependencies.kt b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/Dependencies.kt index 6117af6fcc..0a70b52de3 100644 --- a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/Dependencies.kt +++ b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/Dependencies.kt @@ -39,6 +39,7 @@ abstract class Dependencies { } override fun saveImage(picture: PictureData.Camera, image: PlatformStorableImage) { + pictures.add(0, picture) imageStorage.saveImage(picture, image) } diff --git a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/DesktopImageStorage.kt b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/DesktopImageStorage.kt index f25b0593aa..ee26308365 100644 --- a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/DesktopImageStorage.kt +++ b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/DesktopImageStorage.kt @@ -1,6 +1,5 @@ package example.imageviewer -import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.toAwtImage import androidx.compose.ui.graphics.toComposeImageBitmap @@ -13,25 +12,24 @@ private const val maxStorableImageSizePx = 2000 private const val storableThumbnailSizePx = 200 class DesktopImageStorage( - private val pictures: SnapshotStateList, private val ioScope: CoroutineScope ) : ImageStorage { - private val largeImages = mutableMapOf() - private val thumbnails = mutableMapOf() + private val largeImages = mutableMapOf() + private val thumbnails = mutableMapOf() override fun saveImage(picture: PictureData.Camera, image: PlatformStorableImage) { if (image.imageBitmap.width == 0 || image.imageBitmap.height == 0) { return } ioScope.launch { - largeImages[picture] = image.imageBitmap.fitInto(maxStorableImageSizePx) - thumbnails[picture] = image.imageBitmap.fitInto(storableThumbnailSizePx) - pictures.add(0, picture) + largeImages[picture.id] = image.imageBitmap.fitInto(maxStorableImageSizePx) + thumbnails[picture.id] = image.imageBitmap.fitInto(storableThumbnailSizePx) } } override fun delete(picture: PictureData.Camera) { - // For now, on Desktop pictures saving in memory. We don't need additional delete logic. + largeImages.remove(picture.id) + thumbnails.remove(picture.id) } override fun rewrite(picture: PictureData.Camera) { @@ -39,11 +37,11 @@ class DesktopImageStorage( } override suspend fun getThumbnail(picture: PictureData.Camera): ImageBitmap { - return thumbnails[picture]!! + return thumbnails[picture.id]!! } override suspend fun getImage(picture: PictureData.Camera): ImageBitmap { - return largeImages[picture]!! + return largeImages[picture.id]!! } } diff --git a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/view/ImageViewer.desktop.kt b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/view/ImageViewer.desktop.kt index ccf93f9aef..ff7800d460 100755 --- a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/view/ImageViewer.desktop.kt +++ b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/view/ImageViewer.desktop.kt @@ -104,7 +104,7 @@ private fun getDependencies( toastState.value = ToastState.Shown(text) } } - override val imageStorage: DesktopImageStorage = DesktopImageStorage(pictures, ioScope) + override val imageStorage: DesktopImageStorage = DesktopImageStorage(ioScope) override val sharePicture: SharePicture = object : SharePicture { override fun share(context: PlatformContext, picture: PictureData) { // On Desktop share feature not supported diff --git a/examples/imageviewer/shared/src/desktopTest/kotlin/ImageViewerTest.kt b/examples/imageviewer/shared/src/desktopTest/kotlin/ImageViewerTest.kt index e0ebfc53b4..c94d9f3800 100644 --- a/examples/imageviewer/shared/src/desktopTest/kotlin/ImageViewerTest.kt +++ b/examples/imageviewer/shared/src/desktopTest/kotlin/ImageViewerTest.kt @@ -1,7 +1,12 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick -import example.imageviewer.* +import example.imageviewer.Dependencies +import example.imageviewer.DesktopImageStorage +import example.imageviewer.ImageViewerCommon +import example.imageviewer.Notification +import example.imageviewer.PopupNotification +import example.imageviewer.SharePicture import example.imageviewer.filter.PlatformContext import example.imageviewer.model.PictureData import kotlinx.coroutines.CoroutineScope @@ -18,9 +23,10 @@ class ImageViewerTest { override fun showPopUpMessage(text: String) { } } - override val imageStorage: DesktopImageStorage = DesktopImageStorage(pictures, CoroutineScope(Dispatchers.Main)) + override val imageStorage: DesktopImageStorage = + DesktopImageStorage(CoroutineScope(Dispatchers.Main)) override val sharePicture: SharePicture = object : SharePicture { - override fun share(context: PlatformContext, picture: PictureData) { } + override fun share(context: PlatformContext, picture: PictureData) {} } } diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt index 1f40b9740a..c42b994987 100755 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt @@ -52,22 +52,23 @@ fun getDependencies(ioScope: CoroutineScope, toastState: MutableState + withContext(Dispatchers.Main) { + val window = UIApplication.sharedApplication.windows.last() as? UIWindow + val currentViewController = window?.rootViewController + val activityViewController = UIActivityViewController( + activityItems = listOf( + UIImage.imageWithContentsOfFile(imageUrl), + picture.description + ), + applicationActivities = null + ) + currentViewController?.presentViewController( + viewControllerToPresent = activityViewController, + animated = true, + completion = null, + ) + } } } } diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt index 59b0d7c1be..732c467613 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import platform.CoreGraphics.CGRectMake @@ -36,7 +35,7 @@ private const val storableThumbnailSizePx = 180 private const val jpegCompressionQuality = 60 class IosImageStorage( - private val pictures: SnapshotStateList, + pictures: SnapshotStateList, private val ioScope: CoroutineScope ) : ImageStorage { @@ -77,7 +76,6 @@ class IosImageStorage( picture.jpgFile.writeJpeg(fitInto(maxStorableImageSizePx)) picture.thumbnailJpgFile.writeJpeg(fitInto(storableThumbnailSizePx)) } - pictures.add(0, picture) picture.jsonFile.writeText(picture.toJson()) } } @@ -121,6 +119,21 @@ class IosImageStorage( } }.readData() } + + suspend fun getNSURLToShare(picture: PictureData): NSURL = withContext(Dispatchers.IO) { + when (picture) { + is PictureData.Camera -> { + picture.jpgFile + } + + is PictureData.Resource -> { + NSURL( + fileURLWithPath = NSBundle.mainBundle.resourcePath + "/" + picture.resource, + isDirectory = false + ) + } + } + } } @OptIn(ExperimentalForeignApi::class) diff --git a/examples/imageviewer/webApp/build.gradle.kts b/examples/imageviewer/webApp/build.gradle.kts index 4d3f358ddc..52f28985ef 100644 --- a/examples/imageviewer/webApp/build.gradle.kts +++ b/examples/imageviewer/webApp/build.gradle.kts @@ -26,16 +26,17 @@ kotlin { wasmJs { moduleName = "imageviewer" browser { - commonWebpackConfig { - devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { - static = (static ?: mutableListOf()).apply { - // Serve sources to debug inside browser - add(rootDirPath) - add(rootDirPath + "/shared/") - add(rootDirPath + "/webApp/") - } - } - } + // TODO: uncomment when https://youtrack.jetbrains.com/issue/KT-68614 is fixed (it doesn't work with configuration cache) +// commonWebpackConfig { +// devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { +// static = (static ?: mutableListOf()).apply { +// // Serve sources to debug inside browser +// add(rootDirPath) +// add(rootDirPath + "/shared/") +// add(rootDirPath + "/webApp/") +// } +// } +// } } binaries.executable() } diff --git a/examples/jetsnack/common/src/commonMain/kotlin/com/example/jetsnack/ui/components/Button.kt b/examples/jetsnack/common/src/commonMain/kotlin/com/example/jetsnack/ui/components/Button.kt index dd1889e39e..73fa507eea 100644 --- a/examples/jetsnack/common/src/commonMain/kotlin/com/example/jetsnack/ui/components/Button.kt +++ b/examples/jetsnack/common/src/commonMain/kotlin/com/example/jetsnack/ui/components/Button.kt @@ -86,11 +86,14 @@ fun JetsnackButton( value = MaterialTheme.typography.button ) { Row( + @Suppress("DEPRECATION_ERROR") Modifier .defaultMinSize( minWidth = ButtonDefaults.MinWidth, minHeight = ButtonDefaults.MinHeight ) + // TODO This should be replaced by non-deprecated alternative after the original example migrates to Jetpack Compose 1.7: + // https://github.com/android/compose-samples/blob/3bc6b7d7c74571ea74776ec5b15518b40de4d31b/Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Button.kt#L95 .indication(interactionSource, rememberRipple()) .padding(contentPadding), horizontalArrangement = Arrangement.Center, diff --git a/examples/jetsnack/ios/iosApp/Info.plist b/examples/jetsnack/ios/iosApp/Info.plist index 5b28bf5219..8540150120 100644 --- a/examples/jetsnack/ios/iosApp/Info.plist +++ b/examples/jetsnack/ios/iosApp/Info.plist @@ -22,6 +22,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + NSCameraUsageDescription This app uses camera for capturing photos UIApplicationSceneManifest diff --git a/examples/todoapp-lite/iosApp/iosApp/Info.plist b/examples/todoapp-lite/iosApp/iosApp/Info.plist index 9a269f5eaa..412e378128 100644 --- a/examples/todoapp-lite/iosApp/iosApp/Info.plist +++ b/examples/todoapp-lite/iosApp/iosApp/Info.plist @@ -20,6 +20,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/examples/widgets-gallery/iosApp/iosApp/Info.plist b/examples/widgets-gallery/iosApp/iosApp/Info.plist index 9a269f5eaa..412e378128 100644 --- a/examples/widgets-gallery/iosApp/iosApp/Info.plist +++ b/examples/widgets-gallery/iosApp/iosApp/Info.plist @@ -20,6 +20,8 @@ 1 LSRequiresIPhoneOS + CADisableMinimumFrameDurationOnPhone + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/.gitignore b/experimental/examples/intellij-plugin-with-experimental-shared-base/.gitignore deleted file mode 100644 index 65ca50d416..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build/ -.gradle/ -.idea/ \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/.run/runIde.run.xml b/experimental/examples/intellij-plugin-with-experimental-shared-base/.run/runIde.run.xml deleted file mode 100644 index 52aca017c2..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/.run/runIde.run.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/README.md b/experimental/examples/intellij-plugin-with-experimental-shared-base/README.md deleted file mode 100644 index 8af73b48ec..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Example Compose Multiplatform based plugin for IntelliJ Idea. - -A plugin, demonstrating an Intellij plugin, showing a dialog window written with Compose. - -The only difference from [examples/intellij-plugin](../intellij-plugin) is that -this version does not bundle Compose runtime, which makes the plugin smaller -and allows sharing Compose runtime between multiple plugins -(Compose class files and native libraries are not loaded by each plugin). - -### Usage - -1. Start test IDE: - * Run the following command in terminal: `./gradlew runIde` - * Or choose **runIde** configuration in IDE and run it. - ![ide-run-configuration.png](screenshots/ide-run-configuration.png) -2. Create a new project or open any existing; -3. Select `Show Compose Demo...` from the `Tools` menu. - -![screen1](../intellij-plugin/screenshots/toolsshow.png) -![screen2](../intellij-plugin/screenshots/screenshot.png) diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/build.gradle.kts b/experimental/examples/intellij-plugin-with-experimental-shared-base/build.gradle.kts deleted file mode 100644 index 5cc4674c24..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -import org.jetbrains.compose.compose - -plugins { - id("org.jetbrains.intellij") version "1.6.0" - java - kotlin("jvm") - id("org.jetbrains.compose") - id("idea") -} - -group = "org.jetbrains.compose.intellij.platform" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() - google() - maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") } -} - -dependencies { -// compileOnly(compose.desktop.currentOs) runtime dependency is provided by org.jetbrains.compose.intellij.platform - testImplementation(kotlin("test")) -} - -// See https://github.com/JetBrains/gradle-intellij-plugin/ -intellij { - version.set("2021.3") - plugins.set( - listOf( - "org.jetbrains.compose.intellij.platform:0.1.0", - "org.jetbrains.kotlin" - ) - ) -} - -tasks.withType { - kotlinOptions.jvmTarget = "11" -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle.properties b/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle.properties deleted file mode 100644 index 121b219d4e..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -kotlin.stdlib.default.dependency=false -kotlin.code.style=official -kotlin.version=1.8.0 -compose.version=1.3.0 - diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.jar b/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 62d4c05355..0000000000 Binary files a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.properties b/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index ae04661ee7..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew b/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew deleted file mode 100755 index 4f906e0c81..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew.bat b/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew.bat deleted file mode 100644 index 107acd32c4..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/screenshots/ide-run-configuration.png b/experimental/examples/intellij-plugin-with-experimental-shared-base/screenshots/ide-run-configuration.png deleted file mode 100644 index 9dc9453a38..0000000000 Binary files a/experimental/examples/intellij-plugin-with-experimental-shared-base/screenshots/ide-run-configuration.png and /dev/null differ diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/settings.gradle.kts b/experimental/examples/intellij-plugin-with-experimental-shared-base/settings.gradle.kts deleted file mode 100644 index dd1ac3675a..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/settings.gradle.kts +++ /dev/null @@ -1,8 +0,0 @@ -rootProject.name = "ComposeDemoPlugin" - -pluginManagement { - plugins { - kotlin("jvm").version(extra["kotlin.version"] as String) - id("org.jetbrains.compose").version(extra["compose.version"] as String) - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/ComposeDemoAction.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/ComposeDemoAction.kt deleted file mode 100644 index 581c8cbe91..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/ComposeDemoAction.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.jetbrains.compose - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.Surface -import androidx.compose.ui.Modifier -import androidx.compose.ui.awt.ComposePanel -import androidx.compose.ui.layout.Layout -import androidx.compose.ui.layout.MeasurePolicy -import androidx.compose.ui.layout.onGloballyPositioned -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.project.DumbAwareAction -import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.DialogWrapper -import com.jetbrains.compose.theme.WidgetTheme -import com.jetbrains.compose.widgets.Buttons -import com.jetbrains.compose.widgets.LazyScrollable -import com.jetbrains.compose.widgets.Loaders -import com.jetbrains.compose.widgets.TextInputs -import com.jetbrains.compose.widgets.Toggles -import java.awt.Dimension -import javax.swing.JComponent -import javax.swing.SwingUtilities - - -/** - * @author Konstantin Bulenkov - */ -class ComposeDemoAction : DumbAwareAction() { - override fun actionPerformed(e: AnActionEvent) { - DemoDialog(e.project).show() - } - - class DemoDialog(project: Project?) : DialogWrapper(project) { - init { - title = "Demo" - init() - } - - override fun createCenterPanel(): JComponent { - return ComposePanel().apply { - setBounds(0, 0, 800, 600) - setContent { - WidgetTheme(darkTheme = true) { - Surface(modifier = Modifier.fillMaxSize()) { - Row { - Column( - modifier = Modifier.fillMaxHeight().weight(1f) - ) { - Buttons() - Loaders() - TextInputs() - Toggles() - } - Box( - modifier = Modifier.fillMaxHeight().weight(1f) - ) { - LazyScrollable() - } - } - } - } - } - } - } - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/IntellijTheme.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/IntellijTheme.kt deleted file mode 100644 index 8969581b72..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/IntellijTheme.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.intellij.openapi.project.Project -import com.jetbrains.compose.theme.WidgetTheme -import org.intellij.datavis.r.inlays.components.GraphicsManager - -@Composable -fun IntellijTheme(project: Project, content: @Composable () -> Unit) { - val isDarkMode = try { - GraphicsManager.getInstance(project)?.isDarkModeEnabled ?: false - } catch (t: Throwable) { - false - } - WidgetTheme(darkTheme = isDarkMode) { - Surface(modifier = Modifier.fillMaxSize()) { - content() - } - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorLineMarkerProvider.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorLineMarkerProvider.kt deleted file mode 100644 index 1ab8977c62..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorLineMarkerProvider.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.color - -import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.awt.ComposePanel -import androidx.compose.ui.graphics.Color -import com.intellij.codeInsight.daemon.LineMarkerInfo -import com.intellij.codeInsight.daemon.LineMarkerProvider -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.markup.GutterIconRenderer -import com.intellij.openapi.ui.DialogWrapper -import com.intellij.psi.PsiElement -import com.jetbrains.compose.IntellijTheme -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.uast.* -import java.awt.Component -import java.awt.Graphics -import javax.swing.Icon -import javax.swing.JComponent - -class ColorLineMarkerProvider : LineMarkerProvider { - - override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? { - val project = element.project - val ktPsiFactory = KtPsiFactory(project) - val uElement: UElement = element.toUElement() ?: return null - if (uElement is UCallExpression) { - if (uElement.kind == UastCallKind.METHOD_CALL && uElement.methodIdentifier?.name == "Color") { - val colorLongValue = (uElement.valueArguments.firstOrNull() as? ULiteralExpression)?.getLongValue() - val previousColor = try { - Color(colorLongValue!!) - } catch (t: Throwable) { - Color(0xffffffff) - } - - val iconSize = 20 - return LineMarkerInfo( - element, - element.textRange, - object : Icon { - override fun paintIcon(c: Component?, g: Graphics?, x: Int, y: Int) { - g?.color = java.awt.Color( - previousColor.red, - previousColor.green, - previousColor.blue, - previousColor.alpha - ) - g?.fillRect(0, 0, iconSize, iconSize) - } - - override fun getIconWidth(): Int = iconSize - override fun getIconHeight(): Int = iconSize - }, - null, - { _, psiElement: PsiElement -> - - - class ChooseColorDialog() : DialogWrapper(project) { - val colorState = mutableStateOf(previousColor) - - init { - title = "Choose color" - init() - } - - override fun createCenterPanel(): JComponent = - ComposePanel().apply { - setBounds(0, 0, 400, 400) - setContent { - IntellijTheme(project) { - ColorPicker(colorState) - } - } - } - } - - val chooseColorDialog = ChooseColorDialog() - val result = chooseColorDialog.showAndGet() - if (result) { - val color = chooseColorDialog.colorState.value - ApplicationManager.getApplication().runWriteAction { - psiElement.replace( - ktPsiFactory.createExpression( - "Color(${color.toHexString()})" - ) - ) - } - } - }, - GutterIconRenderer.Alignment.RIGHT, - { "change color literal" } - ) - } - } - return null - } - - override fun collectSlowLineMarkers( - elements: MutableList, - result: MutableCollection> - ) { - - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorPicker.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorPicker.kt deleted file mode 100644 index 9ef49add6e..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/ColorPicker.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.color - -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.material.Divider -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.input.pointer.isPrimaryPressed -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.unit.dp - -private const val VALUE_BAND_RATIO = 0.07f -private val DEFAULT_COLORS = - listOf(Color.Red, Color.Green, Color.Blue, Color.Black, Color.Gray, Color.Yellow, Color.Cyan, Color.Magenta) - -@Composable -fun ColorPicker(colorState: MutableState) { - var currentColor: Color by remember { colorState } - Column { - Row { - DEFAULT_COLORS.forEach { - Box(Modifier.size(30.dp).background(color = it).clickable { - currentColor = it - }) - } - } - Divider(Modifier.size(2.dp)) - Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text("Result color:") - Divider(Modifier.size(2.dp)) - TextField(modifier = Modifier.width(120f.dp), value = currentColor.toHexString(), onValueChange = {}) - Divider(Modifier.size(2.dp)) - val size = 60f - Box(Modifier.size(size.dp).background(color = currentColor)) - } - Divider(Modifier.size(2.dp)) - var width by remember { mutableStateOf(300) } - var height by remember { mutableStateOf(256) } - val rainbowWidth by derivedStateOf { (width * (1 - VALUE_BAND_RATIO)).toInt() } - val bandWidth by derivedStateOf { width * VALUE_BAND_RATIO } - fun calcHue(x: Float) = limit0to1(x / rainbowWidth) * HSV.HUE_MAX_VALUE - fun calcSaturation(y: Float) = 1 - limit0to1(y / height) - fun calcValue(y: Float) = 1 - limit0to1(y / height) - Row(Modifier.fillMaxSize()) { - Canvas(Modifier.fillMaxSize().pointerInput(Unit) { - width = size.width - height = size.height - awaitPointerEventScope { - while (true) { - val event = awaitPointerEvent() - if (event.buttons.isPrimaryPressed) { - val position = event.changes.first().position - if (position.x < rainbowWidth) { - currentColor = try { - currentColor.toHsv().copy( - hue = calcHue(position.x), - saturation = calcSaturation(position.y) - ).toRgb() - } catch (t: Throwable) { - t.printStackTrace() - println("exception $t") - currentColor - } - } else { - currentColor = - currentColor.toHsv().copy( - value = calcValue(position.y) - ).toRgb() - } - } - } - } - }) { - for (x in 0..rainbowWidth) { - for (y in 0..height) { - drawRect( - color = currentColor.toHsv().copy( - hue = calcHue(x.toFloat()), - saturation = calcSaturation(y.toFloat()) - ).toRgb(), - topLeft = Offset(x.toFloat(), y.toFloat()), - size = Size(1f, 1f) - ) - } - } - val valueBandX = rainbowWidth + 1 - for (y in 0..height) { - drawRect( - color = currentColor.toHsv().copy(value = calcValue(y.toFloat())).toRgb(), - topLeft = Offset(valueBandX.toFloat(), y.toFloat()), - size = Size(bandWidth, 1f) - ) - } - val circleX = (currentColor.toHsv().hue / 360) * rainbowWidth - val circleY = (1 - currentColor.toHsv().saturation) * height - drawCircle( - center = Offset(circleX, circleY), - color = Color.Black, - radius = 5f, - style = Stroke(width = 3f) - ) - } - } - } -} - -fun Color.toHexString() = "0x" + toArgb().toUInt().toString(16) -fun limit(value: Float, min: Float, max: Float) = minOf( - maxOf(value, min), - max -) - -fun limit0to1(value: Float) = limit(value = value, 0f, 1f) diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/HSV.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/HSV.kt deleted file mode 100644 index 86fef306c4..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/color/HSV.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.color - -import androidx.compose.ui.graphics.Color -import kotlin.math.abs - -data class HSV( - /** - * 0.0 .. 360.0 - */ - val hue: Float, - /** - * 0.0 .. 1.0 - */ - val saturation: Float, - /** - * 0.0 . 1.0¬ - */ - val value: Float -) { - companion object { - const val HUE_MAX_VALUE = 360f - } -} - -/** - * Convert to HSV color space - * https://www.rapidtables.com/convert/color/rgb-to-hsv.html - */ -fun Color.toHsv(): HSV { - val max = maxOf(red, green, blue) - val min = minOf(red, green, blue) - val delta = max - min - val h = when { - delta == 0f -> 0f - max == red -> 60 * ((green - blue) / delta).mod(6f) - max == green -> 60 * ((blue - red) / delta + 2) - max == blue -> 60 * ((red - green) / delta + 4) - else -> 0f - } - val s = when { - max == 0f -> 0f - else -> delta / max - } - val v = max - return HSV( - hue = h, - saturation = s, - value = v - ) -} - -/** - * Convert to RGB color space - * https://www.rapidtables.com/convert/color/hsv-to-rgb.html - */ -fun HSV.toRgb(): Color { - val c = value * saturation - val x = minOf(c * (1 - abs((hue / 60).mod(2f) - 1)), 1f) - val m = value - c - val tempColor = when { - hue >= 0 && hue < 60 -> Color(c, x, 0f) - hue >= 60 && hue < 120 -> Color(x, c, 0f) - hue >= 120 && hue < 180 -> Color(0f, c, x) - hue >= 180 && hue < 240 -> Color(0f, x, c) - hue >= 240 && hue < 300 -> Color(x, 0f, c) - else -> Color(c, 0f, x) - } - return Color(minOf(m + tempColor.red, 1f), minOf(m + tempColor.green, 1f), minOf(m + tempColor.blue, 1f)) -} - diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/ComposeToolWindow.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/ComposeToolWindow.kt deleted file mode 100644 index c7e66f37c9..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/ComposeToolWindow.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.panel - -import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.awt.ComposePanel -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.project.DumbAware -import com.intellij.openapi.project.Project -import com.intellij.openapi.wm.ToolWindow -import com.intellij.openapi.wm.ToolWindowFactory -import com.intellij.ui.content.ContentFactory -import com.jetbrains.compose.IntellijTheme -import java.awt.Dimension - -class ComposeToolWindow : ToolWindowFactory, DumbAware { - - override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { - ApplicationManager.getApplication().invokeLater { - toolWindow.contentManager.addContent( - ContentFactory.SERVICE.getInstance().createContent( - ComposePanel().apply { - size = Dimension(300, 300) - setContent { - IntellijTheme(project) { - CounterPanel(stateWithIdeLifecycle) - } - } - }, - "Compose tool window", - false - ) - ) - } - } - - companion object { - val stateWithIdeLifecycle = mutableStateOf(CounterState()) - } - -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterPanel.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterPanel.kt deleted file mode 100644 index 24be64a9f9..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterPanel.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.panel - -import androidx.compose.foundation.layout.Column -import androidx.compose.material.Button -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.* - -@Composable -fun CounterPanel(stateWithIdeLifecycle: MutableState) { - var stateInline by remember { mutableStateOf(CounterState()) } - Column { - Text("Counter with IDE lifecycle: ${stateWithIdeLifecycle.value.counter}") - Button(onClick = { - stateWithIdeLifecycle.value = stateWithIdeLifecycle.value.copy( - counter = stateWithIdeLifecycle.value.counter + 1 - ) - }) { - Text("Increment state with IDE lifecycle") - } - Text("Counter with @Composable lifecycle: ${stateInline.counter}") - Button(onClick = { - stateInline = stateInline.copy( - counter = stateInline.counter + 1 - ) - }) { - Text("Increment state with @Composable lifecycle") - } - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterState.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterState.kt deleted file mode 100644 index 5466e579f9..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/panel/CounterState.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.panel - -data class CounterState( - val counter: Int = 0 -) diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Color.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Color.kt deleted file mode 100644 index 9ed4581b85..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Color.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jetbrains.compose.theme - -import androidx.compose.ui.graphics.Color - -val green200 = Color(0xffa5d6a7) -val green500 = Color(0xff4caf50) -val green700 = Color(0xff388e3c) - -val teal200 = Color(0xff80deea) diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Shape.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Shape.kt deleted file mode 100644 index 3ac8795fc7..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Shape.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.jetbrains.compose.theme - -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Shapes -import androidx.compose.ui.unit.dp - -val shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) -) \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Theme.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Theme.kt deleted file mode 100644 index 78a3ec5181..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Theme.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.jetbrains.compose.theme - -import androidx.compose.material.MaterialTheme -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import com.jetbrains.compose.theme.intellij.SwingColor - -private val DarkGreenColorPalette = darkColors( - primary = green200, - primaryVariant = green700, - secondary = teal200, - onPrimary = Color.Black, - onSecondary = Color.White, - error = Color.Red, -) - -private val LightGreenColorPalette = lightColors( - primary = green500, - primaryVariant = green700, - secondary = teal200, - onPrimary = Color.White, - onSurface = Color.Black -) - -@Composable -fun WidgetTheme( - darkTheme: Boolean = false, - content: @Composable() () -> Unit, -) { - val colors = if (darkTheme) DarkGreenColorPalette else LightGreenColorPalette - val swingColor = SwingColor() - - MaterialTheme( - colors = colors.copy( - background = swingColor.background, - onBackground = swingColor.onBackground, - surface = swingColor.background, - onSurface = swingColor.onBackground, - ), - typography = typography, - shapes = shapes, - content = content - ) -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Type.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Type.kt deleted file mode 100644 index 4bc429afa8..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/Type.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.jetbrains.compose.theme - -import androidx.compose.material.Typography -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -val typography = Typography( - body1 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp - ), - body2 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 14.sp - ), - button = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.W500, - fontSize = 14.sp - ), - caption = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 12.sp, - ), - subtitle1 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - color = Color.Gray - ), - subtitle2 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 14.sp, - color = Color.Gray - ), -) \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/SwingColor.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/SwingColor.kt deleted file mode 100644 index 0aac1aaf50..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/SwingColor.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.jetbrains.compose.theme.intellij - -import androidx.compose.runtime.* -import androidx.compose.ui.graphics.Color -import com.intellij.ide.ui.LafManagerListener -import com.intellij.openapi.application.ApplicationManager -import javax.swing.UIManager -import java.awt.Color as AWTColor - -interface SwingColor { - val background: Color - val onBackground: Color -} - -@Composable -fun SwingColor(): SwingColor { - val swingColor = remember { SwingColorImpl() } - - val messageBus = remember { - ApplicationManager.getApplication().messageBus.connect() - } - - remember(messageBus) { - messageBus.subscribe( - LafManagerListener.TOPIC, - ThemeChangeListener(swingColor::updateCurrentColors) - ) - } - - DisposableEffect(messageBus) { - onDispose { - messageBus.disconnect() - } - } - - return swingColor -} - -private class SwingColorImpl : SwingColor { - private val _backgroundState: MutableState = mutableStateOf(getBackgroundColor) - private val _onBackgroundState: MutableState = mutableStateOf(getOnBackgroundColor) - - override val background: Color get() = _backgroundState.value - override val onBackground: Color get() = _onBackgroundState.value - - private val getBackgroundColor get() = getColor(BACKGROUND_KEY) - private val getOnBackgroundColor get() = getColor(ON_BACKGROUND_KEY) - - fun updateCurrentColors() { - _backgroundState.value = getBackgroundColor - _onBackgroundState.value = getOnBackgroundColor - } - - private val AWTColor.asComposeColor: Color get() = Color(red, green, blue, alpha) - private fun getColor(key: String): Color = UIManager.getColor(key).asComposeColor - - companion object { - private const val BACKGROUND_KEY = "Panel.background" - private const val ON_BACKGROUND_KEY = "Panel.foreground" - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/ThemeChangeListener.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/ThemeChangeListener.kt deleted file mode 100644 index 95a8324114..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/theme/intellij/ThemeChangeListener.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.jetbrains.compose.theme.intellij - -import com.intellij.ide.ui.LafManager -import com.intellij.ide.ui.LafManagerListener - -internal class ThemeChangeListener( - val updateColors: () -> Unit -) : LafManagerListener { - override fun lookAndFeelChanged(source: LafManager) { - updateColors() - } -} - diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Buttons.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Buttons.kt deleted file mode 100644 index 89fc8c2c11..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Buttons.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.jetbrains.compose.widgets - -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Button -import androidx.compose.material.TextButton -import androidx.compose.material.OutlinedButton -import androidx.compose.material.Text -import androidx.compose.material.Icon -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.FavoriteBorder -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun Buttons() { - Row { - val btnEnabled = remember { mutableStateOf(true) } - Button( - onClick = { btnEnabled.value = !btnEnabled.value}, - modifier = Modifier.padding(8.dp), - enabled = btnEnabled.value - ) { - Icon( - imageVector = Icons.Default.FavoriteBorder, - contentDescription = "FavoriteBorder", - modifier = Modifier.padding(end = 4.dp) - ) - Text(text = "Button") - } - val btnTextEnabled = remember { mutableStateOf(true) } - TextButton( - onClick = { btnTextEnabled.value = !btnTextEnabled.value }, - modifier = Modifier.padding(8.dp), - enabled = btnTextEnabled.value - ) { - Text(text = "Text Button") - } - OutlinedButton( - onClick = { - btnEnabled.value = true - btnTextEnabled.value = true - }, - modifier = Modifier.padding(8.dp) - ) { - Icon( - imageVector = Icons.Default.Refresh, - contentDescription = "Refresh", - modifier = Modifier.padding(0.dp) - ) - } - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/LazyScrollable.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/LazyScrollable.kt deleted file mode 100644 index e5bba421a0..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/LazyScrollable.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.jetbrains.compose.widgets - -import androidx.compose.desktop.DesktopTheme -import androidx.compose.foundation.background -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.rememberScrollbarAdapter -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.VerticalScrollbar -import androidx.compose.material.Text -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun LazyScrollable() { - MaterialTheme { - DesktopTheme { - Box( - modifier = Modifier.fillMaxSize() - .padding(10.dp) - ) { - - val state = rememberLazyListState() - val itemCount = 100 - - LazyColumn(Modifier.fillMaxSize().padding(end = 12.dp), state) { - items(itemCount) { x -> - TextBox("Item in ScrollableColumn #$x") - Spacer(modifier = Modifier.height(5.dp)) - } - } - VerticalScrollbar( - modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(), - adapter = rememberScrollbarAdapter( - scrollState = state - ) - ) - } - } - } -} - -@Composable -private fun TextBox(text: String = "Item") { - Surface( - color = Color(135, 135, 135, 40), - shape = RoundedCornerShape(4.dp) - ) { - Box( - modifier = Modifier.height(32.dp) - .fillMaxWidth() - .padding(start = 10.dp), - contentAlignment = Alignment.CenterStart - ) { - Text(text = text) - } - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Loaders.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Loaders.kt deleted file mode 100644 index a18252459b..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Loaders.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.jetbrains.compose.widgets - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.size -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.LinearProgressIndicator -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun Loaders() { - Row( - modifier = Modifier.fillMaxWidth().padding(16.dp) - ) { - Box( - modifier = Modifier.height(30.dp), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp, 20.dp), - strokeWidth = 4.dp - ) - } - Box( - modifier = Modifier - .height(30.dp) - .padding(start = 8.dp), - contentAlignment = Alignment.Center - ) { - LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) - } - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/TextInputs.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/TextInputs.kt deleted file mode 100644 index 5ca7a9aad6..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/TextInputs.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.jetbrains.compose.widgets - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.OutlinedTextField -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.unit.dp - -@Composable -fun TextInputs() { - Column( - modifier = Modifier.fillMaxWidth().padding(16.dp) - ) { - var name by remember { mutableStateOf(TextFieldValue("")) } - var password by remember { mutableStateOf(TextFieldValue("")) } - - TextField( - value = name, - onValueChange = { newValue -> name = newValue }, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - textStyle = TextStyle(fontFamily = FontFamily.SansSerif), - label = { Text("Account:") }, - placeholder = { Text("account name") } - ) - - OutlinedTextField( - value = password, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - label = { Text(text = "Password:") }, - placeholder = { Text(text = "your password") }, - textStyle = TextStyle(fontFamily = FontFamily.SansSerif), - visualTransformation = PasswordVisualTransformation(), - onValueChange = { - password = it - }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password) - ) - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Toggles.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Toggles.kt deleted file mode 100644 index b4a7febac2..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/kotlin/com/jetbrains/compose/widgets/Toggles.kt +++ /dev/null @@ -1,90 +0,0 @@ -package com.jetbrains.compose.widgets - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.Checkbox -import androidx.compose.material.MaterialTheme -import androidx.compose.material.RadioButton -import androidx.compose.material.Slider -import androidx.compose.material.Switch -import androidx.compose.material.SwitchDefaults -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun Toggles() { - Column { - Row { - Column( - modifier = Modifier.padding(16.dp) - ) { - var checked by remember { mutableStateOf(true) } - Checkbox( - checked = checked, - modifier = Modifier.padding(8.dp), - onCheckedChange = { checked = !checked } - ) - var switched by remember { mutableStateOf(true) } - Switch( - checked = switched, - colors = SwitchDefaults.colors(checkedThumbColor = MaterialTheme.colors.primary), - modifier = Modifier.padding(8.dp), - onCheckedChange = { switched = it } - ) - } - Column( - modifier = Modifier.padding(16.dp) - ) { - var selected by remember { mutableStateOf("Kotlin") } - Row(verticalAlignment = Alignment.CenterVertically) { - RadioButton(selected = selected == "Kotlin", onClick = { selected = "Kotlin" }) - Text( - text = "Kotlin", - modifier = Modifier.clickable(onClick = { selected = "Kotlin" }).padding(start = 4.dp) - ) - } - Row(verticalAlignment = Alignment.CenterVertically) { - RadioButton(selected = selected == "Java", onClick = { selected = "Java" }) - Text( - text = "Java", - modifier = Modifier.clickable(onClick = { selected = "Java" }).padding(start = 4.dp) - ) - } - Row(verticalAlignment = Alignment.CenterVertically) { - RadioButton(selected = selected == "Swift", onClick = { selected = "Swift" }) - Text( - text = "Swift", - modifier = Modifier.clickable(onClick = { selected = "Swift" }).padding(start = 4.dp) - ) - } - } - } - - var sliderState by remember { mutableStateOf(0f) } - Slider(value = sliderState, modifier = Modifier.fillMaxWidth().padding(8.dp), - onValueChange = { newValue -> - sliderState = newValue - } - ) - - var sliderState2 by remember { mutableStateOf(20f) } - Slider(value = sliderState2, modifier = Modifier.fillMaxWidth().padding(8.dp), - valueRange = 0f..100f, - steps = 5, - onValueChange = { newValue -> - sliderState2 = newValue - } - ) - } -} \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/META-INF/plugin.xml b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/META-INF/plugin.xml deleted file mode 100644 index 5932048466..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/META-INF/plugin.xml +++ /dev/null @@ -1,29 +0,0 @@ - - com.jetbrains.ComposeDemoPlugin - Jetpack Compose for Desktop Demo - JetBrains - - - - - com.intellij.modules.platform - org.jetbrains.compose.intellij.platform - org.jetbrains.kotlin - - - - - - - - - - - - - \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/icons/compose.svg b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/icons/compose.svg deleted file mode 100644 index 2154d497bd..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/main/resources/icons/compose.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/ColorPickerUITest.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/ColorPickerUITest.kt deleted file mode 100644 index 68ca6d2387..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/ColorPickerUITest.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.color - -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.WindowState -import androidx.compose.ui.window.application - -fun main() = application { - val windowState = remember { WindowState(width = 400.dp, height = 400.dp) } - Window( - onCloseRequest = ::exitApplication, - title = "ColorPicker", - state = windowState - ) { - ColorPicker(mutableStateOf(Color(0xffaabbcc))) - } -} diff --git a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/HSVTest.kt b/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/HSVTest.kt deleted file mode 100644 index b1c491b1fe..0000000000 --- a/experimental/examples/intellij-plugin-with-experimental-shared-base/src/test/kotlin/com/jetbrains/compose/color/HSVTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package com.jetbrains.compose.color - -import androidx.compose.ui.graphics.Color -import org.junit.Test -import kotlin.test.assertEquals - -class HSVTest { - - @Test - fun testGreenToHsv() { - val greenRgb = Color(0xff00ff00) - val result = greenRgb.toHsv() - assertEquals(HSV(120f, 1f, 1f), result) - assertEquals(greenRgb, result.toRgb()) - } - -} diff --git a/gradle-plugins/compose/build.gradle.kts b/gradle-plugins/compose/build.gradle.kts index b49fe5f0e6..de5b015a58 100644 --- a/gradle-plugins/compose/build.gradle.kts +++ b/gradle-plugins/compose/build.gradle.kts @@ -43,12 +43,6 @@ val embeddedDependencies by configurations.creating { isTransitive = false } -val kgpResourcesDevVersion = "2.0.0-dev-17632" -//KMP resources API available since ^kgpResourcesDevVersion -repositories { - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/") -} - dependencies { // By default, Gradle resolves plugins only via Gradle Plugin Portal. // To avoid declaring an additional repo, all dependencies must: @@ -63,7 +57,7 @@ dependencies { compileOnly(gradleApi()) compileOnly(localGroovy()) - compileOnly(kotlin("gradle-plugin", kgpResourcesDevVersion)) + compileOnly(kotlin("gradle-plugin")) compileOnly(kotlin("native-utils")) compileOnly(libs.plugin.android) compileOnly(libs.plugin.android.api) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerCompatibility.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerCompatibility.kt index b92424f092..3be60601ff 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerCompatibility.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerCompatibility.kt @@ -24,7 +24,7 @@ internal object ComposeCompilerCompatibility { "1.9.21" to "1.5.4", "1.9.22" to "1.5.8.1", "1.9.23" to "1.5.13.5", - "1.9.24" to "1.5.14", + "1.9.24" to "1.5.14.1-beta02", "2.0.0-Beta1" to "1.5.4-dev1-kt2.0.0-Beta1", "2.0.0-Beta4" to "1.5.9-kt-2.0.0-Beta4", "2.0.0-Beta5" to "1.5.11-kt-2.0.0-Beta5", diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt index 8fb8434b95..37c87a3a0b 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt @@ -8,12 +8,12 @@ package org.jetbrains.compose import org.gradle.api.Project import org.gradle.api.provider.Provider import org.jetbrains.compose.internal.ComposeCompilerArtifactProvider +import org.jetbrains.compose.internal.KOTLIN_ANDROID_PLUGIN_ID +import org.jetbrains.compose.internal.KOTLIN_JS_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID import org.jetbrains.compose.internal.Version import org.jetbrains.compose.internal.ideaIsInSyncProvider -import org.jetbrains.compose.internal.mppExtOrNull -import org.jetbrains.compose.internal.service.ConfigurationProblemReporterService import org.jetbrains.compose.internal.webExt import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation @@ -24,14 +24,18 @@ import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact import org.jetbrains.kotlin.gradle.plugin.SubpluginOption import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile internal fun Project.configureComposeCompilerPlugin() { - plugins.withId(KOTLIN_MPP_PLUGIN_ID) { plugin -> - configureComposeCompilerPlugin(plugin as KotlinBasePlugin) - } - plugins.withId(KOTLIN_JVM_PLUGIN_ID) { plugin -> - configureComposeCompilerPlugin(plugin as KotlinBasePlugin) + //only one of them can be applied to the project + listOf( + KOTLIN_MPP_PLUGIN_ID, + KOTLIN_JVM_PLUGIN_ID, + KOTLIN_ANDROID_PLUGIN_ID, + KOTLIN_JS_PLUGIN_ID + ).forEach { pluginId -> + plugins.withId(pluginId) { plugin -> + configureComposeCompilerPlugin(plugin as KotlinBasePlugin) + } } } @@ -77,33 +81,9 @@ class ComposeCompilerKotlinSupportPlugin : KotlinCompilerPluginSupportPlugin { } applicableForPlatformTypes = composeExt.platformTypes - - collectUnsupportedCompilerPluginUsages(target) } } - private fun collectUnsupportedCompilerPluginUsages(project: Project) { - fun Project.hasNonJvmTargets(): Boolean { - val nonJvmTargets = setOf(KotlinPlatformType.native, KotlinPlatformType.js, KotlinPlatformType.wasm) - return mppExtOrNull?.targets?.any { - it.platformType in nonJvmTargets - } ?: false - } - - fun SubpluginArtifact.isNonJBComposeCompiler(): Boolean { - return !groupId.startsWith("org.jetbrains.compose.compiler") - } - - ConfigurationProblemReporterService.registerUnsupportedPluginProvider( - project, - project.provider { - composeCompilerArtifactProvider.compilerArtifact.takeIf { - project.hasNonJvmTargets() && it.isNonJBComposeCompiler() - } - } - ) - } - override fun getCompilerPluginId(): String = "androidx.compose.compiler.plugins.kotlin" @@ -146,14 +126,3 @@ class ComposeCompilerKotlinSupportPlugin : KotlinCompilerPluginSupportPlugin { private fun options(vararg options: Pair): List = options.map { SubpluginOption(it.first, it.second) } } - -private const val COMPOSE_COMPILER_COMPATIBILITY_LINK = - "https://github.com/JetBrains/compose-jb/blob/master/VERSIONING.md#using-compose-multiplatform-compiler" - -internal fun createWarningAboutNonCompatibleCompiler(currentCompilerPluginGroupId: String): String { - return """ -WARNING: Usage of the Custom Compose Compiler plugin ('$currentCompilerPluginGroupId') -with non-JVM targets (Kotlin/Native, Kotlin/JS, Kotlin/WASM) is not supported. -For more information, please visit: $COMPOSE_COMPILER_COMPATIBILITY_LINK -""".trimMargin() -} diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt index 086c529207..41e9afd7ef 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt @@ -21,8 +21,6 @@ import org.jetbrains.compose.desktop.preview.internal.initializePreview import org.jetbrains.compose.experimental.dsl.ExperimentalExtension import org.jetbrains.compose.experimental.internal.* import org.jetbrains.compose.internal.* -import org.jetbrains.compose.internal.service.ConfigurationProblemReporterService -import org.jetbrains.compose.internal.service.GradlePropertySnapshotService import org.jetbrains.compose.internal.utils.currentTarget import org.jetbrains.compose.resources.ResourcesExtension import org.jetbrains.compose.resources.configureComposeResources @@ -35,15 +33,8 @@ import org.jetbrains.kotlin.gradle.plugin.* internal val composeVersion get() = ComposeBuildConfig.composeVersion -private fun initBuildServices(project: Project) { - ConfigurationProblemReporterService.init(project) - GradlePropertySnapshotService.init(project) -} - abstract class ComposePlugin : Plugin { override fun apply(project: Project) { - initBuildServices(project) - val composeExtension = project.extensions.create("compose", ComposeExtension::class.java, project) val desktopExtension = composeExtension.extensions.create("desktop", DesktopExtension::class.java) val androidExtension = composeExtension.extensions.create("android", AndroidExtension::class.java) @@ -60,7 +51,6 @@ abstract class ComposePlugin : Plugin { composeExtension.extensions.create("web", WebExtension::class.java) project.configureComposeCompilerPlugin() - project.configureNativeCompilerCaching() project.configureComposeResources(resourcesExtension) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/FileAssociation.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/FileAssociation.kt new file mode 100644 index 0000000000..a9e2bbff22 --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/FileAssociation.kt @@ -0,0 +1,11 @@ +package org.jetbrains.compose.desktop.application.dsl + +import java.io.File +import java.io.Serializable + +internal data class FileAssociation( + val mimeType: String, + val extension: String, + val description: String, + val iconFile: File?, +) : Serializable diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/JvmApplicationDistributions.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/JvmApplicationDistributions.kt index e9fb935df6..f59b838b6a 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/JvmApplicationDistributions.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/JvmApplicationDistributions.kt @@ -6,6 +6,7 @@ package org.jetbrains.compose.desktop.application.dsl import org.gradle.api.Action +import java.io.File internal val DEFAULT_RUNTIME_MODULES = arrayOf( "java.base", "java.desktop", "java.logging", "jdk.crypto.ec" @@ -32,4 +33,14 @@ abstract class JvmApplicationDistributions : AbstractDistributions() { fun windows(fn: Action) { fn.execute(windows) } + + @JvmOverloads + fun fileAssociation( + mimeType: String, extension: String, description: String, + linuxIconFile: File? = null, windowsIconFile: File? = null, macOSIconFile: File? = null, + ) { + linux.fileAssociation(mimeType, extension, description, linuxIconFile) + windows.fileAssociation(mimeType, extension, description, windowsIconFile) + macOS.fileAssociation(mimeType, extension, description, macOSIconFile) + } } \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt index f8b3e3450b..d70ca65adf 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt @@ -8,6 +8,7 @@ package org.jetbrains.compose.desktop.application.dsl import org.gradle.api.Action import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory +import java.io.File import javax.inject.Inject abstract class AbstractPlatformSettings { @@ -17,6 +18,13 @@ abstract class AbstractPlatformSettings { val iconFile: RegularFileProperty = objects.fileProperty() var packageVersion: String? = null var installationPath: String? = null + + internal val fileAssociations: MutableSet = mutableSetOf() + + @JvmOverloads + fun fileAssociation(mimeType: String, extension: String, description: String, iconFile: File? = null) { + fileAssociations.add(FileAssociation(mimeType, extension, description, iconFile)) + } } abstract class AbstractMacOSPlatformSettings : AbstractPlatformSettings() { diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/InfoPlistBuilder.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/InfoPlistBuilder.kt index e349305730..aca1d8e858 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/InfoPlistBuilder.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/InfoPlistBuilder.kt @@ -5,14 +5,58 @@ package org.jetbrains.compose.desktop.application.internal +import org.jetbrains.compose.desktop.application.internal.InfoPlistBuilder.InfoPlistValue.* import java.io.File import kotlin.reflect.KProperty +private const val indent = " " +private fun indentForLevel(level: Int) = indent.repeat(level) + internal class InfoPlistBuilder(private val extraPlistKeysRawXml: String? = null) { - private val values = LinkedHashMap() + internal sealed class InfoPlistValue { + abstract fun asPlistEntry(nestingLevel: Int): String + data class InfoPlistListValue(val elements: List) : InfoPlistValue() { + override fun asPlistEntry(nestingLevel: Int): String = + if (elements.isEmpty()) "${indentForLevel(nestingLevel)}" + else elements.joinToString( + separator = "\n", + prefix = "${indentForLevel(nestingLevel)}\n", + postfix = "\n${indentForLevel(nestingLevel)}" + ) { + it.asPlistEntry(nestingLevel + 1) + } + + constructor(vararg elements: InfoPlistValue) : this(elements.asList()) + } + + data class InfoPlistMapValue(val elements: Map) : InfoPlistValue() { + override fun asPlistEntry(nestingLevel: Int): String = + if (elements.isEmpty()) "${indentForLevel(nestingLevel)}" + else elements.entries.joinToString( + separator = "\n", + prefix = "${indentForLevel(nestingLevel)}\n", + postfix = "\n${indentForLevel(nestingLevel)}", + ) { (key, value) -> + "${indentForLevel(nestingLevel + 1)}${key.name}\n${value.asPlistEntry(nestingLevel + 1)}" + } + + constructor(vararg elements: Pair) : this(elements.toMap()) + } + + data class InfoPlistStringValue(val value: String) : InfoPlistValue() { + override fun asPlistEntry(nestingLevel: Int): String = if (value.isEmpty()) "${indentForLevel(nestingLevel)}" else "${indentForLevel(nestingLevel)}$value" + } + } + + private val values = LinkedHashMap() + + operator fun get(key: InfoPlistKey): InfoPlistValue? = values[key] + operator fun set(key: InfoPlistKey, value: String?) = set(key, value?.let(::InfoPlistStringValue)) + operator fun set(key: InfoPlistKey, value: List?) = set(key, value?.let(::InfoPlistListValue)) + operator fun set(key: InfoPlistKey, value: Map?) = + set(key, value?.let(::InfoPlistMapValue)) - operator fun get(key: InfoPlistKey): String? = values[key] - operator fun set(key: InfoPlistKey, value: String?) { + operator fun set(key: InfoPlistKey, value: InfoPlistValue?) { if (value != null) { values[key] = value } else { @@ -26,13 +70,13 @@ internal class InfoPlistBuilder(private val extraPlistKeysRawXml: String? = null appendLine("") appendLine("") appendLine("") - appendLine(" ") + appendLine("${indentForLevel(1)}") for ((k, v) in values) { - appendLine(" ${k.name}") - appendLine(" $v") + appendLine("${indentForLevel(2)}${k.name}") + appendLine(v.asPlistEntry(2)) } extraPlistKeysRawXml?.let { appendLine(it) } - appendLine(" ") + appendLine("${indentForLevel(1)}") appendLine("") } } @@ -48,6 +92,13 @@ internal object PlistKeys { val LSMinimumSystemVersion by this val CFBundleDevelopmentRegion by this val CFBundleAllowMixedLocalizations by this + val CFBundleDocumentTypes by this + val CFBundleTypeRole by this + val CFBundleTypeExtensions by this + val CFBundleTypeIconFile by this + val CFBundleTypeMIMETypes by this + val CFBundleTypeName by this + val CFBundleTypeOSTypes by this val CFBundleExecutable by this val CFBundleIconFile by this val CFBundleIdentifier by this diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt index d53ad3dd62..83d51089ef 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt @@ -375,6 +375,7 @@ internal fun JvmApplicationContext.configurePlatformSettings( packageTask.linuxRpmLicenseType.set(provider { linux.rpmLicenseType }) packageTask.iconFile.set(linux.iconFile.orElse(defaultResources.get { linuxIcon })) packageTask.installationPath.set(linux.installationPath) + packageTask.fileAssociations.set(provider { linux.fileAssociations }) } } OS.Windows -> { @@ -388,6 +389,7 @@ internal fun JvmApplicationContext.configurePlatformSettings( packageTask.winUpgradeUuid.set(provider { win.upgradeUuid }) packageTask.iconFile.set(win.iconFile.orElse(defaultResources.get { windowsIcon })) packageTask.installationPath.set(win.installationPath) + packageTask.fileAssociations.set(provider { win.fileAssociations }) } } OS.MacOS -> { @@ -414,6 +416,7 @@ internal fun JvmApplicationContext.configurePlatformSettings( packageTask.nonValidatedMacSigningSettings = app.nativeDistributions.macOS.signing packageTask.iconFile.set(mac.iconFile.orElse(defaultResources.get { macIcon })) packageTask.installationPath.set(mac.installationPath) + packageTask.fileAssociations.set(provider { mac.fileAssociations }) } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt index ad56727c05..20c3926cd9 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt @@ -9,19 +9,23 @@ import org.gradle.api.file.* import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider +import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* import org.gradle.api.tasks.Optional import org.gradle.process.ExecResult import org.gradle.work.ChangeType import org.gradle.work.InputChanges +import org.jetbrains.compose.desktop.application.dsl.FileAssociation import org.jetbrains.compose.desktop.application.dsl.MacOSSigningSettings import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.internal.* +import org.jetbrains.compose.desktop.application.internal.InfoPlistBuilder.InfoPlistValue.* import org.jetbrains.compose.desktop.application.internal.files.* import org.jetbrains.compose.desktop.application.internal.files.MacJarSignFileCopyingProcessor import org.jetbrains.compose.desktop.application.internal.JvmRuntimeProperties import org.jetbrains.compose.desktop.application.internal.validation.validate import org.jetbrains.compose.internal.utils.* +import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated import java.io.* import java.nio.file.LinkOption import java.util.* @@ -244,6 +248,39 @@ abstract class AbstractJPackageTask @Inject constructor( @get:Optional val javaRuntimePropertiesFile: RegularFileProperty = objects.fileProperty() + @get:Input + internal val fileAssociations: SetProperty = objects.setProperty(FileAssociation::class.java) + + private val iconMapping by lazy { + val icons = fileAssociations.get().mapNotNull { it.iconFile }.distinct() + if (icons.isEmpty()) return@lazy emptyMap() + val iconTempNames: List = mutableListOf().apply { + val usedNames = mutableSetOf("${packageName.get()}.icns") + for (icon in icons) { + if (!icon.exists()) continue + if (usedNames.add(icon.name)) { + add(icon.name) + continue + } + val nameWithoutExtension = icon.nameWithoutExtension + val extension = icon.extension + for (n in 1UL..ULong.MAX_VALUE) { + val newName = "$nameWithoutExtension ($n).$extension" + if (usedNames.add(newName)) { + add(newName) + break + } + } + } + } + val appDir = destinationDir.ioFile.resolve("${packageName.get()}.app") + val iconsDir = appDir.resolve("Contents").resolve("Resources") + if (iconsDir.exists()) { + iconsDir.deleteRecursively() + } + icons.zip(iconTempNames) { icon, newName -> icon to iconsDir.resolve(newName) }.toMap() + } + private lateinit var jvmRuntimeInfo: JvmRuntimeProperties @get:Optional @@ -273,6 +310,9 @@ abstract class AbstractJPackageTask @Inject constructor( @get:LocalState protected val skikoDir: Provider = project.layout.buildDirectory.dir("compose/tmp/skiko") + @get:LocalState + protected val propertyFilesDir: Provider = project.layout.buildDirectory.dir("compose/tmp/propertyFiles") + @get:Internal private val libsDir: Provider = workingDir.map { it.dir("libs") @@ -368,6 +408,33 @@ abstract class AbstractJPackageTask @Inject constructor( cliArg("--license-file", licenseFile) cliArg("--resource-dir", jpackageResources) + val propertyFilesDirJava = propertyFilesDir.ioFile + fileOperations.clearDirs(propertyFilesDir) + + val fileAssociationFiles = fileAssociations.get() + .groupBy { it.extension } + .mapValues { (extension, associations) -> + associations.mapIndexed { index, association -> + propertyFilesDirJava.resolve("FA${extension}${if (index > 0) index.toString() else ""}.properties") + .apply { + val withoutIcon = """ + mime-type=${association.mimeType} + extension=${association.extension} + description=${association.description} + """.trimIndent() + writeText( + if (association.iconFile == null) withoutIcon + else "${withoutIcon}\nicon=${association.iconFile.normalizedPath()}" + ) + } + } + }.values.flatten() + + for (fileAssociationFile in fileAssociationFiles) { + cliArg("--file-associations", fileAssociationFile) + } + + when (currentOS) { OS.Linux -> { cliArg("--linux-shortcut", linuxShortcut) @@ -569,6 +636,15 @@ abstract class AbstractJPackageTask @Inject constructor( macSigner.sign(runtimeDir, runtimeEntitlementsFile, forceEntitlements = true) macSigner.sign(appDir, appEntitlementsFile, forceEntitlements = true) + + if (iconMapping.isNotEmpty()) { + for ((originalIcon, newIcon) in iconMapping) { + if (originalIcon.exists()) { + newIcon.ensureParentDirsCreated() + originalIcon.copyTo(newIcon) + } + } + } } override fun initState() { @@ -620,6 +696,23 @@ abstract class AbstractJPackageTask @Inject constructor( ?: "Copyright (C) $year" plist[PlistKeys.NSSupportsAutomaticGraphicsSwitching] = "true" plist[PlistKeys.NSHighResolutionCapable] = "true" + val fileAssociationMutableSet = fileAssociations.get() + if (fileAssociationMutableSet.isNotEmpty()) { + plist[PlistKeys.CFBundleDocumentTypes] = fileAssociationMutableSet + .groupBy { it.mimeType to it.description } + .map { (key, extensions) -> + val (mimeType, description) = key + val iconPath = extensions.firstNotNullOfOrNull { it.iconFile }?.let { iconMapping[it]?.name } + InfoPlistMapValue( + PlistKeys.CFBundleTypeRole to InfoPlistStringValue("Editor"), + PlistKeys.CFBundleTypeExtensions to InfoPlistListValue(extensions.map { InfoPlistStringValue(it.extension) }), + PlistKeys.CFBundleTypeIconFile to InfoPlistStringValue(iconPath ?: "$packageName.icns"), + PlistKeys.CFBundleTypeMIMETypes to InfoPlistStringValue(mimeType), + PlistKeys.CFBundleTypeName to InfoPlistStringValue(description), + PlistKeys.CFBundleTypeOSTypes to InfoPlistListValue(InfoPlistStringValue("****")), + ) + } + } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/internal/configurePreview.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/internal/configurePreview.kt index 83f06a9805..80977d917d 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/internal/configurePreview.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/internal/configurePreview.kt @@ -34,7 +34,7 @@ private fun registerConfigurePreviewTask( ) { previewTask -> runtimeFiles.configureUsageBy(previewTask) { (runtimeJars, _) -> previewClasspath = runtimeJars - skikoRuntime = tryGetSkikoRuntimeIfNeeded() + skikoRuntime.set(project.provider { tryGetSkikoRuntimeIfNeeded() }) } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/tasks/AbstractConfigureDesktopPreviewTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/tasks/AbstractConfigureDesktopPreviewTask.kt index 02bab85264..a61e5f732d 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/tasks/AbstractConfigureDesktopPreviewTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/preview/tasks/AbstractConfigureDesktopPreviewTask.kt @@ -19,7 +19,7 @@ abstract class AbstractConfigureDesktopPreviewTask : AbstractComposeDesktopTask( internal lateinit var previewClasspath: FileCollection @get:InputFiles - internal lateinit var skikoRuntime: FileCollection + internal abstract val skikoRuntime: Property @get:Internal internal val javaHome: Property = objects.notNullProperty().apply { @@ -58,10 +58,12 @@ abstract class AbstractConfigureDesktopPreviewTask : AbstractComposeDesktopTask( javaExecutable = javaExecutable(javaHome.get()), hostClasspath = hostClasspath.files.asSequence().pathString() ) + + val skikoRuntimeFiles = skikoRuntime.get() val previewClasspathString = (previewClasspath.files.asSequence() + uiTooling.files.asSequence() + - skikoRuntime.files.asSequence() + skikoRuntimeFiles.files.asSequence() ).pathString() val gradleLogger = logger diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/configureNativeCompilerCaching.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/configureNativeCompilerCaching.kt deleted file mode 100644 index 1ecde81ccd..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/configureNativeCompilerCaching.kt +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.experimental.internal - -import org.gradle.api.Project -import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID -import org.jetbrains.compose.internal.mppExt -import org.jetbrains.compose.internal.utils.KGPPropertyProvider -import org.jetbrains.compose.internal.utils.configureEachWithType -import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.presetName - -private const val PROJECT_CACHE_KIND_PROPERTY_NAME = "kotlin.native.cacheKind" -private const val COMPOSE_NATIVE_MANAGE_CACHE_KIND = "compose.kotlin.native.manageCacheKind" -private const val NONE_VALUE = "none" - -// Compose runtime supports these k/native targets: -// https://github.com/JetBrains/compose-multiplatform-core/blob/jb-main/compose/runtime/runtime/build.gradle#L75 -private val SUPPORTED_NATIVE_TARGETS = setOf( - // ios - KonanTarget.IOS_X64, - KonanTarget.IOS_ARM64, - KonanTarget.IOS_SIMULATOR_ARM64, - // macos - KonanTarget.MACOS_X64, - KonanTarget.MACOS_ARM64, - // tvos - KonanTarget.TVOS_X64, - KonanTarget.TVOS_ARM64, - KonanTarget.TVOS_SIMULATOR_ARM64, - // watchOS - KonanTarget.WATCHOS_ARM64, - KonanTarget.WATCHOS_ARM32, - KonanTarget.WATCHOS_X64, - KonanTarget.WATCHOS_SIMULATOR_ARM64, - // mingw - KonanTarget.MINGW_X64, - // linux - KonanTarget.LINUX_X64, -) - -internal val SUPPORTED_NATIVE_CACHE_KIND_PROPERTIES = - SUPPORTED_NATIVE_TARGETS.map { it.targetCacheKindPropertyName } + - PROJECT_CACHE_KIND_PROPERTY_NAME - -internal fun Project.configureNativeCompilerCaching() { - if (findProperty(COMPOSE_NATIVE_MANAGE_CACHE_KIND) == "false") return - - plugins.withId(KOTLIN_MPP_PLUGIN_ID) { - val kotlinPluginVersion = kotlinVersionNumbers(project.getKotlinPluginVersion()) - mppExt.targets.configureEachWithType { - if (konanTarget in SUPPORTED_NATIVE_TARGETS) { - checkExplicitCacheKind() - if (kotlinPluginVersion < KotlinVersion(1, 9, 20)) { - // Pre-1.9.20 Kotlin compiler caches have known compatibility issues - // See KT-57329, KT-61270 - disableKotlinNativeCache() - } - } - } - } -} - -private fun KotlinNativeTarget.checkExplicitCacheKind() { - // To determine cache kind KGP checks kotlin.native.cacheKind. first, then kotlin.native.cacheKind - // For each property it tries to read Project.property, then checks local.properties - // See https://github.com/JetBrains/kotlin/blob/d4d30dcfcf1afb083f09279c6f1ba05031efeabb/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt#L416 - val cacheKindProperties = listOf(targetCacheKindPropertyName, PROJECT_CACHE_KIND_PROPERTY_NAME) - val propertyProviders = listOf( - KGPPropertyProvider.GradleProperties(project), - KGPPropertyProvider.LocalProperties(project) - ) - - for (cacheKindProperty in cacheKindProperties) { - for (provider in propertyProviders) { - val value = provider.valueOrNull(cacheKindProperty) - if (value != null) { - error(explicitCacheKindErrorMessage(cacheKindProperty, value, provider)) - } - } - } -} - -private fun explicitCacheKindErrorMessage( - cacheKindProperty: String, - value: String, - provider: KGPPropertyProvider -) = """ - |Error: '$cacheKindProperty' is explicitly set to '$value'. - |This option significantly slows the Kotlin/Native compiler. - |Compose Multiplatform Gradle plugin manages this property automatically based on a Kotlin compiler version being used. - | * Recommended action: remove explicit '$cacheKindProperty=$value' from ${provider.location}. - | * Alternative action: disable cache kind management by adding '$COMPOSE_NATIVE_MANAGE_CACHE_KIND=false' to your 'gradle.properties'. -""".trimMargin() - - -private val KotlinNativeTarget.targetCacheKindPropertyName: String - get() = konanTarget.targetCacheKindPropertyName - -private val KonanTarget.targetCacheKindPropertyName: String - get() = "$PROJECT_CACHE_KIND_PROPERTY_NAME.${presetName}" - -private fun KotlinNativeTarget.disableKotlinNativeCache() { - val existingValue = project.findProperty(targetCacheKindPropertyName)?.toString() - if (NONE_VALUE.equals(existingValue, ignoreCase = true)) return - - if (targetCacheKindPropertyName in project.properties) { - project.setProperty(targetCacheKindPropertyName, NONE_VALUE) - } else { - project.extensions.extraProperties.set(targetCacheKindPropertyName, NONE_VALUE) - } -} - -internal fun kotlinVersionNumbers(version: String): KotlinVersion { - val m = Regex("(\\d+)\\.(\\d+)\\.(\\d+)").find(version) ?: error("Kotlin version has unexpected format: '$version'") - val (_, majorPart, minorPart, patchPart) = m.groupValues - return KotlinVersion( - major = majorPart.toIntOrNull() ?: error("Could not parse major part '$majorPart' of Kotlin plugin version: '$version'"), - minor = minorPart.toIntOrNull() ?: error("Could not parse minor part '$minorPart' of Kotlin plugin version: '$version'"), - patch = patchPart.toIntOrNull() ?: error("Could not parse patch part '$patchPart' of Kotlin plugin version: '$version'"), - ) -} diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/constants.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/constants.kt index 50acdecdcf..e71dcc3563 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/constants.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/constants.kt @@ -7,6 +7,7 @@ package org.jetbrains.compose.internal internal const val KOTLIN_MPP_PLUGIN_ID = "org.jetbrains.kotlin.multiplatform" internal const val KOTLIN_JVM_PLUGIN_ID = "org.jetbrains.kotlin.jvm" +internal const val KOTLIN_ANDROID_PLUGIN_ID = "org.jetbrains.kotlin.android" internal const val KOTLIN_JS_PLUGIN_ID = "org.jetbrains.kotlin.js" internal const val COMPOSE_PLUGIN_ID = "org.jetbrains.compose" diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/AbstractComposeMultiplatformBuildService.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/AbstractComposeMultiplatformBuildService.kt deleted file mode 100644 index 8a987034be..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/AbstractComposeMultiplatformBuildService.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.internal.service - -import org.gradle.api.Project -import org.gradle.api.services.BuildService -import org.gradle.api.services.BuildServiceParameters -import org.gradle.api.services.BuildServiceRegistration -import org.gradle.tooling.events.FinishEvent -import org.gradle.tooling.events.OperationCompletionListener - -// The service implements OperationCompletionListener just so Gradle would materialize the service even if the service is not used by any task or transformation - abstract class AbstractComposeMultiplatformBuildService

: BuildService

, OperationCompletionListener, AutoCloseable { - override fun onFinish(event: FinishEvent) {} - override fun close() {} -} - -internal inline fun > serviceName(instance: Service? = null): String = - fqName(instance) - -internal inline fun , reified Params : BuildServiceParameters> registerServiceIfAbsent( - project: Project, - crossinline initParams: Params.() -> Unit = {} -): BuildServiceRegistration { - if (findRegistration(project) == null) { - val newService = project.gradle.sharedServices.registerIfAbsent(fqName(), Service::class.java) { - it.parameters.initParams() - } - // Workaround to materialize a service even if it is not bound to a task - BuildEventsListenerRegistryProvider.getInstance(project).onTaskCompletion(newService) - } - - return getExistingServiceRegistration(project) -} - -internal inline fun , reified Params : BuildServiceParameters> getExistingServiceRegistration( - project: Project -): BuildServiceRegistration { - val registration = findRegistration(project) - ?: error("Service '${serviceName()}' was not initialized") - return registration.verified(project) -} - -private inline fun , reified Params : BuildServiceParameters> BuildServiceRegistration<*, *>.verified( - project: Project -): BuildServiceRegistration { - val parameters = parameters - // We are checking the type of parameters instead of the type of service - // to avoid materializing the service. - // After a service instance is created all changes made to its parameters won't be visible to - // that particular service instance. - // This is undesirable in some cases. For example, when reporting configuration problems, - // we want to collect all configuration issues from all projects first, then report issues all at once - // in execution phase. - if (parameters !is Params) { - // Compose Gradle plugin was probably loaded more than once - // See https://github.com/JetBrains/compose-multiplatform/issues/3459 - if (fqName(parameters) == fqName()) { - val rootScript = project.rootProject.buildFile - error(""" - Compose Multiplatform Gradle plugin has been loaded in multiple classloaders. - To avoid classloading issues, declare Compose Gradle Plugin in root build file $rootScript. - """.trimIndent()) - } else { - error("Shared build service '${serviceName()}' parameters have unexpected type: ${fqName(parameters)}") - } - } - - @Suppress("UNCHECKED_CAST") - return this as BuildServiceRegistration -} - -private inline fun , reified P : BuildServiceParameters> findRegistration( - project: Project -): BuildServiceRegistration<*, *>? = - project.gradle.sharedServices.registrations.findByName(fqName()) - -private inline fun fqName(instance: T? = null) = T::class.java.canonicalName diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/BuildEventsListenerRegistryProvider.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/BuildEventsListenerRegistryProvider.kt deleted file mode 100644 index 8473334131..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/BuildEventsListenerRegistryProvider.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.internal.service - -import org.gradle.api.Project -import org.gradle.build.event.BuildEventsListenerRegistry -import javax.inject.Inject - -// a hack to get BuildEventsListenerRegistry conveniently, which can only be injected by Gradle -@Suppress("UnstableApiUsage") -internal abstract class BuildEventsListenerRegistryProvider @Inject constructor(val registry: BuildEventsListenerRegistry) { - companion object { - fun getInstance(project: Project): BuildEventsListenerRegistry = - project.objects.newInstance(BuildEventsListenerRegistryProvider::class.java).registry - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/ConfigurationProblemReporterService.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/ConfigurationProblemReporterService.kt deleted file mode 100644 index e61528f6cc..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/ConfigurationProblemReporterService.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.internal.service - -import org.gradle.api.Project -import org.gradle.api.logging.Logging -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Provider -import org.gradle.api.provider.SetProperty -import org.gradle.api.services.BuildServiceParameters -import org.jetbrains.compose.createWarningAboutNonCompatibleCompiler -import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact - -abstract class ConfigurationProblemReporterService : AbstractComposeMultiplatformBuildService() { - interface Parameters : BuildServiceParameters { - val unsupportedPluginWarningProviders: ListProperty> - val warnings: SetProperty - } - - private val log = Logging.getLogger(this.javaClass) - - override fun close() { - warnAboutUnsupportedCompilerPlugin() - logWarnings() - } - - private fun warnAboutUnsupportedCompilerPlugin() { - for (warningProvider in parameters.unsupportedPluginWarningProviders.get()) { - val warning = warningProvider.orNull - if (warning != null) { - log.warn(warning) - } - } - } - - private fun logWarnings() { - for (warning in parameters.warnings.get()) { - log.warn(warning) - } - } - companion object { - fun init(project: Project) { - registerServiceIfAbsent(project) { - // WORKAROUND! Call getter at least once, because of Issue: https://github.com/gradle/gradle/issues/27099 - warnings - } - } - - private inline fun configureParameters(project: Project, fn: Parameters.() -> Unit) { - getExistingServiceRegistration(project) - .parameters.fn() - } - - fun reportWarning(project: Project, message: String) { - configureParameters(project) { warnings.add(message) } - } - - fun registerUnsupportedPluginProvider(project: Project, unsupportedPlugin: Provider) { - configureParameters(project) { - unsupportedPluginWarningProviders.add(unsupportedPlugin.map { unsupportedCompiler -> - unsupportedCompiler?.groupId?.let { createWarningAboutNonCompatibleCompiler(it) } - }) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/GradlePropertySnapshotService.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/GradlePropertySnapshotService.kt deleted file mode 100644 index 32e7cfa559..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/service/GradlePropertySnapshotService.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.internal.service - -import org.gradle.api.Project -import org.gradle.api.provider.MapProperty -import org.gradle.api.services.BuildServiceParameters -import org.jetbrains.compose.experimental.internal.SUPPORTED_NATIVE_CACHE_KIND_PROPERTIES -import org.jetbrains.compose.internal.utils.loadProperties -import org.jetbrains.compose.internal.utils.localPropertiesFile - -internal abstract class GradlePropertySnapshotService : AbstractComposeMultiplatformBuildService() { - interface Parameters : BuildServiceParameters { - val gradlePropertiesCacheKindSnapshot: MapProperty - val localPropertiesCacheKindSnapshot: MapProperty - } - - internal val gradleProperties: Map = parameters.gradlePropertiesCacheKindSnapshot.get() - internal val localProperties: Map = parameters.localPropertiesCacheKindSnapshot.get() - - companion object { - fun init(project: Project) { - registerServiceIfAbsent(project) { - // WORKAROUND! Call getter at least once, because of Issue: https://github.com/gradle/gradle/issues/27099 - gradlePropertiesCacheKindSnapshot - localPropertiesCacheKindSnapshot - initParams(project) - } - } - - fun getInstance(project: Project): GradlePropertySnapshotService = - getExistingServiceRegistration(project).service.get() - - private fun Parameters.initParams(project: Project) { - // we want to record original properties (explicitly set by a user) - // before we possibly change them in configureNativeCompilerCaching.kt - val rootProject = project.rootProject - val localProperties = loadProperties(rootProject.localPropertiesFile) - for (cacheKindProperty in SUPPORTED_NATIVE_CACHE_KIND_PROPERTIES) { - rootProject.findProperty(cacheKindProperty)?.toString()?.let { value -> - gradlePropertiesCacheKindSnapshot.put(cacheKindProperty, value) - } - localProperties[cacheKindProperty]?.toString()?.let { value -> - localPropertiesCacheKindSnapshot.put(cacheKindProperty, value) - } - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/utils/KGPPropertyProvider.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/utils/KGPPropertyProvider.kt deleted file mode 100644 index d0431a41fc..0000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/utils/KGPPropertyProvider.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.internal.utils - -import org.gradle.api.Project -import org.jetbrains.compose.internal.service.GradlePropertySnapshotService - -/** - * Reads Kotlin Gradle plugin properties. - * - * Kotlin Gradle plugin supports reading property from two sources: - * 1. Gradle properties. Normally located in gradle.properties file, - * but can also be provided via command-line, /gradle.properties - * or can be set via Gradle API. - * 2. local.properties file. local.properties file is not supported by Gradle out-of-the-box. - * Nevertheless, it became a widespread convention. - */ -internal abstract class KGPPropertyProvider { - abstract fun valueOrNull(propertyName: String): String? - abstract val location: String - - class GradleProperties(private val project: Project) : KGPPropertyProvider() { - override fun valueOrNull(propertyName: String): String? = - GradlePropertySnapshotService.getInstance(project).gradleProperties[propertyName] - override val location: String = "gradle.properties" - } - - class LocalProperties(private val project: Project) : KGPPropertyProvider() { - override fun valueOrNull(propertyName: String): String? = - GradlePropertySnapshotService.getInstance(project).localProperties[propertyName] - override val location: String = "local.properties" - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt index f1d9f2855b..6bec880943 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt @@ -1,107 +1,78 @@ package org.jetbrains.compose.resources import com.android.build.api.variant.AndroidComponentsExtension -import com.android.build.gradle.BaseExtension +import com.android.build.api.variant.Variant import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask import com.android.build.gradle.internal.lint.LintModelWriterTask -import org.gradle.api.DefaultTask import org.gradle.api.Project -import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemOperations -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* -import org.jetbrains.compose.internal.utils.registerTask +import org.gradle.api.tasks.Copy +import org.jetbrains.compose.internal.utils.dir import org.jetbrains.compose.internal.utils.uppercaseFirstChar -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation -import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull -import org.jetbrains.kotlin.gradle.utils.ObservableSet -import javax.inject.Inject -@OptIn(ExperimentalKotlinGradlePluginApi::class) -internal fun Project.configureAndroidComposeResources( +internal fun Project.getAndroidVariantComposeResources( kotlinExtension: KotlinMultiplatformExtension, - androidExtension: BaseExtension -) { - // 1) get the Kotlin Android Target Compilation -> [A] - // 2) get default source set name for the 'A' - // 3) find the associated Android SourceSet in the AndroidExtension -> [B] - // 4) get all source sets in the 'A' and add its resources to the 'B' - kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).all { androidTarget -> - androidTarget.compilations.all { compilation: KotlinJvmAndroidCompilation -> - compilation.defaultSourceSet.androidSourceSetInfoOrNull?.let { kotlinAndroidSourceSet -> - androidExtension.sourceSets - .matching { it.name == kotlinAndroidSourceSet.androidSourceSetName } - .all { androidSourceSet -> - (compilation.allKotlinSourceSets as? ObservableSet)?.forAll { kotlinSourceSet -> - val preparedComposeResources = getPreparedComposeResourcesDir(kotlinSourceSet) - androidSourceSet.resources.srcDirs(preparedComposeResources) - - //fix for AGP < 8.0 - //usually 'androidSourceSet.resources.srcDir(preparedCommonResources)' should be enough - compilation.androidVariant.processJavaResourcesProvider.configure { - it.dependsOn(preparedComposeResources) - } - } - } - } + variant: Variant +): FileCollection = project.files({ + kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).flatMap { androidTarget -> + androidTarget.compilations.flatMap { compilation -> + if (compilation.androidVariant.name == variant.name) { + compilation.allKotlinSourceSets.map { kotlinSourceSet -> + getPreparedComposeResourcesDir(kotlinSourceSet) + } + } else emptyList() } } +}) - //copy fonts from the compose resources dir to android assets +internal fun Project.getKgpAndroidVariantComposeResources( + variant: Variant +): FileCollection = project.files({ + val taskName = "${variant.name}AssetsCopyForAGP" + if (tasks.names.contains(taskName)) tasks.named(taskName).map { it.outputs.files } + else files() +}) + +internal fun Project.configureAndroidComposeResources( + getVariantComposeResources: (Variant) -> FileCollection +) { + //copy all compose resources to android assets val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return androidComponents.onVariants { variant -> - val variantResources = project.files() - - kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).all { androidTarget -> - androidTarget.compilations.all { compilation: KotlinJvmAndroidCompilation -> - if (compilation.androidVariant.name == variant.name) { - project.logger.info("Configure fonts for variant ${variant.name}") - (compilation.allKotlinSourceSets as? ObservableSet)?.forAll { kotlinSourceSet -> - val preparedComposeResources = getPreparedComposeResourcesDir(kotlinSourceSet) - variantResources.from(preparedComposeResources) - } - } - } - } + val camelVariantName = variant.name.uppercaseFirstChar() + val variantAssets = getVariantComposeResources(variant) + val variantAssetsDir = layout.buildDirectory.dir(RES_GEN_DIR).dir(variant.name + "AndroidAssets") - val copyFonts = registerTask( - "copy${variant.name.uppercaseFirstChar()}FontsToAndroidAssets" - ) { - from.set(variantResources) + val copyVariantAssets = tasks.register( + "copy${camelVariantName}ComposeResourcesToAndroidAssets", + Copy::class.java + ) { task -> + task.from(variantAssets) + task.into(variantAssetsDir) } - variant.sources?.assets?.addGeneratedSourceDirectory( - taskProvider = copyFonts, - wiredWith = CopyAndroidFontsToAssetsTask::outputDirectory - ) - //exclude a duplication of fonts in apks - variant.packaging.resources.excludes.add("**/font*/*") - } -} -//Copy task doesn't work with 'variant.sources?.assets?.addGeneratedSourceDirectory' API -internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() { - @get:Inject - abstract val fileSystem: FileSystemOperations + //https://issuetracker.google.com/348208777 + val staticDir = variantAssetsDir.get().asFile + staticDir.mkdirs() + variant.sources.assets?.addStaticSourceDirectory(staticDir.path) - @get:InputFiles - @get:IgnoreEmptyDirectories - abstract val from: Property - - @get:OutputDirectory - abstract val outputDirectory: DirectoryProperty - - @TaskAction - fun action() { - fileSystem.copy { - it.includeEmptyDirs = false - it.from(from) - it.include("**/font*/*") - it.into(outputDirectory) + val agpTaskNames = listOf( + //fix agp task dependencies for build and allTests tasks + "merge${camelVariantName}Assets", + "package${camelVariantName}Assets", + //fix agp task dependencies for AndroidStudio preview + "compile${camelVariantName}Sources", + ) + tasks.configureEach { task -> + if (task.name in agpTaskNames) { + task.dependsOn(copyVariantAssets) + } + //fix linter task dependencies for `build` task + if (task is AndroidLintAnalysisTask || task is LintModelWriterTask) { + task.mustRunAfter(copyVariantAssets) + } } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt index 4b67866036..2a85d3e2bd 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt @@ -1,24 +1,17 @@ package org.jetbrains.compose.resources -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask -import com.android.build.gradle.internal.lint.LintModelWriterTask import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.TaskProvider import org.gradle.util.GradleVersion -import org.jetbrains.compose.ComposePlugin import org.jetbrains.compose.desktop.application.internal.ComposeProperties import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin -import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.extraProperties -import java.io.File internal const val COMPOSE_RESOURCES_DIR = "composeResources" internal const val RES_GEN_DIR = "generated/compose/resourceGenerator" @@ -46,7 +39,16 @@ private fun Project.onKgpApplied(config: Provider, kgp: Kotl if (kmpResourcesAreAvailable) { configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, config) - onAgpApplied { fixAndroidLintTaskDependencies() } + onAgpApplied { + //workaround to fix AndroidStudio preview works with compose resources: + //it copies android assets and mark it as a static assets dir + //yes, the same resources will be registered in AGP twice: from KGP and here as static dirs + //but it works fine and there are no problems during merge android assets + configureAndroidComposeResources { variant -> + getKgpAndroidVariantComposeResources(variant) + } + fixAndroidLintTaskDependencies() + } } else { if (!disableMultimoduleResources) { if (!hasKmpResources) logger.info( @@ -66,8 +68,10 @@ private fun Project.onKgpApplied(config: Provider, kgp: Kotl val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME configureComposeResources(kotlinExtension, commonMain, config) - onAgpApplied { androidExtension -> - configureAndroidComposeResources(kotlinExtension, androidExtension) + onAgpApplied { + configureAndroidComposeResources { variant -> + getAndroidVariantComposeResources(kotlinExtension, variant) + } fixAndroidLintTaskDependencies() } } @@ -75,11 +79,10 @@ private fun Project.onKgpApplied(config: Provider, kgp: Kotl configureSyncIosComposeResources(kotlinExtension) } -private fun Project.onAgpApplied(block: (androidExtension: BaseExtension) -> Unit) { +private fun Project.onAgpApplied(block: () -> Unit) { androidPluginIds.forEach { pluginId -> plugins.withId(pluginId) { - val androidExtension = project.extensions.getByType(BaseExtension::class.java) - block(androidExtension) + block() } } } @@ -90,8 +93,6 @@ private fun Project.onKotlinJvmApplied(config: Provider) { configureComposeResources(kotlinExtension, main, config) } -// sourceSet.resources.srcDirs doesn't work for Android targets. -// Android resources should be configured separately private fun Project.configureComposeResources( kotlinExtension: KotlinProjectExtension, resClassSourceSetName: String, @@ -100,7 +101,16 @@ private fun Project.configureComposeResources( logger.info("Configure compose resources") configureComposeResourcesGeneration(kotlinExtension, resClassSourceSetName, config, false) + // mark prepared resources as sourceSet.resources + // 1) it automatically packs the resources to JVM jars + // 2) it configures the webpack to use the resources + // 3) for native targets we will use source set resources to pack them into the final app. see IosResources.kt + // 4) for the android it DOESN'T pack resources! we copy resources to assets in AndroidResources.kt kotlinExtension.sourceSets.all { sourceSet -> - sourceSet.resources.srcDirs(getPreparedComposeResourcesDir(sourceSet)) + // the HACK is here because KGP copy androidMain java resources to Android target + // if the resources were registered in the androidMain source set before the target declaration + afterEvaluate { + sourceSet.resources.srcDirs(getPreparedComposeResourcesDir(sourceSet)) + } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt index 8c28fa4f04..9b45b9be32 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt @@ -6,8 +6,14 @@ import org.jetbrains.compose.ComposePlugin import org.jetbrains.compose.internal.IDEA_IMPORT_TASK_NAME import org.jetbrains.compose.internal.IdeaImportTask import org.jetbrains.compose.internal.utils.uppercaseFirstChar +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget +import org.jetbrains.kotlin.tooling.core.withClosure import java.io.File internal fun Project.configureComposeResourcesGeneration( @@ -54,7 +60,7 @@ internal fun Project.configureComposeResourcesGeneration( } //common resources must be converted (XML -> CVR) - val preparedResourcesTask = registerPrepareComposeResourcesTask(sourceSet) + val preparedResourcesTask = registerPrepareComposeResourcesTask(sourceSet, config) val preparedResources = preparedResourcesTask.flatMap { it.outputDir.asFile } configureResourceAccessorsGeneration( sourceSet, @@ -67,6 +73,8 @@ internal fun Project.configureComposeResourcesGeneration( ) } + configureResourceCollectorsGeneration(kotlinExtension, shouldGenerateCode, packageName, makeAccessorsPublic) + //setup task execution during IDE import tasks.configureEach { importTask -> if (importTask.name == IDEA_IMPORT_TASK_NAME) { @@ -90,17 +98,21 @@ private fun Project.configureResClassGeneration( GenerateResClassTask::class.java ) { task -> task.packageName.set(packageName) - task.shouldGenerateCode.set(shouldGenerateCode) task.makeAccessorsPublic.set(makeAccessorsPublic) task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/commonResClass")) if (generateModulePath) { task.packagingDir.set(packagingDir) } + task.onlyIf { shouldGenerateCode.get() } } //register generated source set - resClassSourceSet.kotlin.srcDir(genTask.map { it.codeDir }) + resClassSourceSet.kotlin.srcDir( + genTask.zip(shouldGenerateCode) { task, flag -> + if (flag) listOf(task.codeDir) else emptyList() + } + ) } private fun Project.configureResourceAccessorsGeneration( @@ -115,12 +127,11 @@ private fun Project.configureResourceAccessorsGeneration( logger.info("Configure resource accessors generation for ${sourceSet.name}") val genTask = tasks.register( - "generateResourceAccessorsFor${sourceSet.name.uppercaseFirstChar()}", + sourceSet.getResourceAccessorsGenerationTaskName(), GenerateResourceAccessorsTask::class.java ) { task -> task.packageName.set(packageName) task.sourceSetName.set(sourceSet.name) - task.shouldGenerateCode.set(shouldGenerateCode) task.makeAccessorsPublic.set(makeAccessorsPublic) task.resDir.set(resourcesDir) task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/${sourceSet.name}ResourceAccessors")) @@ -128,8 +139,147 @@ private fun Project.configureResourceAccessorsGeneration( if (generateModulePath) { task.packagingDir.set(packagingDir) } + task.onlyIf { shouldGenerateCode.get() } } //register generated source set - sourceSet.kotlin.srcDir(genTask.map { it.codeDir }) + sourceSet.kotlin.srcDir( + genTask.zip(shouldGenerateCode) { task, flag -> + if (flag) listOf(task.codeDir) else emptyList() + } + ) +} + +private fun KotlinSourceSet.getResourceAccessorsGenerationTaskName(): String { + return "generateResourceAccessorsFor${this.name.uppercaseFirstChar()}" +} + +//we have to generate actual resource collector functions for each leaf source set +private fun Project.configureResourceCollectorsGeneration( + kotlinExtension: KotlinProjectExtension, + shouldGenerateCode: Provider, + packageName: Provider, + makeAccessorsPublic: Provider +) { + if (kotlinExtension is KotlinMultiplatformExtension) { + kotlinExtension.sourceSets + .matching { it.name == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME } + .all { commonMainSourceSet -> + configureExpectResourceCollectorsGeneration( + commonMainSourceSet, + shouldGenerateCode, + packageName, + makeAccessorsPublic + ) + } + + kotlinExtension.targets.all { target -> + if (target is KotlinAndroidTarget) { + kotlinExtension.sourceSets.matching { it.name == "androidMain" }.all { androidMain -> + configureActualResourceCollectorsGeneration( + androidMain, + shouldGenerateCode, + packageName, + makeAccessorsPublic, + true + ) + } + } else if (target !is KotlinMetadataTarget) { + target.compilations.matching { it.name == KotlinCompilation.MAIN_COMPILATION_NAME }.all { compilation -> + configureActualResourceCollectorsGeneration( + compilation.defaultSourceSet, + shouldGenerateCode, + packageName, + makeAccessorsPublic, + true + ) + } + } + } + } else if (kotlinExtension is KotlinSingleTargetExtension<*>) { + //JVM only projects + kotlinExtension.target.compilations + .findByName(KotlinCompilation.MAIN_COMPILATION_NAME) + ?.let { compilation -> + configureActualResourceCollectorsGeneration( + compilation.defaultSourceSet, + shouldGenerateCode, + packageName, + makeAccessorsPublic, + false + ) + } + } + +} + +private fun Project.configureExpectResourceCollectorsGeneration( + sourceSet: KotlinSourceSet, + shouldGenerateCode: Provider, + packageName: Provider, + makeAccessorsPublic: Provider +) { + logger.info("Configure expect resource collectors generation for ${sourceSet.name}") + + + val genTask = tasks.register( + "generateExpectResourceCollectorsFor${sourceSet.name.uppercaseFirstChar()}", + GenerateExpectResourceCollectorsTask::class.java + ) { task -> + task.packageName.set(packageName) + task.makeAccessorsPublic.set(makeAccessorsPublic) + task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/${sourceSet.name}ResourceCollectors")) + task.onlyIf { shouldGenerateCode.get() } + } + + //register generated source set + sourceSet.kotlin.srcDir( + genTask.zip(shouldGenerateCode) { task, flag -> + if (flag) listOf(task.codeDir) else emptyList() + } + ) +} + +private fun Project.configureActualResourceCollectorsGeneration( + sourceSet: KotlinSourceSet, + shouldGenerateCode: Provider, + packageName: Provider, + makeAccessorsPublic: Provider, + useActualModifier: Boolean +) { + val taskName = "generateActualResourceCollectorsFor${sourceSet.name.uppercaseFirstChar()}" + if (tasks.names.contains(taskName)) { + logger.info("Actual resource collectors generation for ${sourceSet.name} is already configured") + return + } + logger.info("Configure actual resource collectors generation for ${sourceSet.name}") + + val accessorDirs = project.files({ + val allSourceSets = sourceSet.withClosure { it.dependsOn } + allSourceSets.mapNotNull { item -> + val accessorsTaskName = item.getResourceAccessorsGenerationTaskName() + if (tasks.names.contains(accessorsTaskName)) { + tasks.named(accessorsTaskName, GenerateResourceAccessorsTask::class.java).map { it.codeDir } + } else null + } + }) + + val genTask = tasks.register( + taskName, + GenerateActualResourceCollectorsTask::class.java + ) { task -> + task.packageName.set(packageName) + task.makeAccessorsPublic.set(makeAccessorsPublic) + task.useActualModifier.set(useActualModifier) + task.resourceAccessorDirs.from(accessorDirs) + task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/${sourceSet.name}ResourceCollectors")) + task.onlyIf { shouldGenerateCode.get() } + } + + //register generated source set + sourceSet.kotlin.srcDir( + genTask.zip(shouldGenerateCode) { task, flag -> + if (flag) listOf(task.codeDir) else emptyList() + } + ) } \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt index 5ce79a5268..676715343f 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt @@ -20,9 +20,6 @@ internal abstract class GenerateResClassTask : IdeaImportTask() { @get:Optional abstract val packagingDir: Property - @get:Input - abstract val shouldGenerateCode: Property - @get:Input abstract val makeAccessorsPublic: Property @@ -34,15 +31,11 @@ internal abstract class GenerateResClassTask : IdeaImportTask() { dir.deleteRecursively() dir.mkdirs() - if (shouldGenerateCode.get()) { - logger.info("Generate $RES_FILE_NAME.kt") + logger.info("Generate $RES_FILE_NAME.kt") - val pkgName = packageName.get() - val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" - val isPublic = makeAccessorsPublic.get() - getResFileSpec(pkgName, RES_FILE_NAME, moduleDirectory, isPublic).writeTo(dir) - } else { - logger.info("Generation Res class is disabled") - } + val pkgName = packageName.get() + val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" + val isPublic = makeAccessorsPublic.get() + getResFileSpec(pkgName, RES_FILE_NAME, moduleDirectory, isPublic).writeTo(dir) } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt index 9aca01b3ff..6d346c5069 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt @@ -9,7 +9,6 @@ import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.SkipWhenEmpty -import org.gradle.api.tasks.TaskAction import org.jetbrains.compose.internal.IdeaImportTask import java.io.File import java.nio.file.Path @@ -26,9 +25,6 @@ internal abstract class GenerateResourceAccessorsTask : IdeaImportTask() { @get:Optional abstract val packagingDir: Property - @get:Input - abstract val shouldGenerateCode: Property - @get:Input abstract val makeAccessorsPublic: Property @@ -49,37 +45,33 @@ internal abstract class GenerateResourceAccessorsTask : IdeaImportTask() { kotlinDir.deleteRecursively() kotlinDir.mkdirs() - if (shouldGenerateCode.get()) { - logger.info("Generate accessors for $rootResDir") + logger.info("Generate accessors for $rootResDir") - //get first level dirs - val dirs = rootResDir.listNotHiddenFiles() + //get first level dirs + val dirs = rootResDir.listNotHiddenFiles() - dirs.forEach { f -> - if (!f.isDirectory) { - error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") - } + dirs.forEach { f -> + if (!f.isDirectory) { + error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") } - - //type -> id -> resource item - val resources: Map>> = dirs - .flatMap { dir -> - dir.listNotHiddenFiles() - .mapNotNull { it.fileToResourceItems(rootResDir.toPath()) } - .flatten() - } - .groupBy { it.type } - .mapValues { (_, items) -> items.groupBy { it.name } } - - val pkgName = packageName.get() - val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" - val isPublic = makeAccessorsPublic.get() - getAccessorsSpecs( - resources, pkgName, sourceSet, moduleDirectory, isPublic - ).forEach { it.writeTo(kotlinDir) } - } else { - logger.info("Generation accessors for $rootResDir is disabled") } + + //type -> id -> resource item + val resources: Map>> = dirs + .flatMap { dir -> + dir.listNotHiddenFiles() + .mapNotNull { it.fileToResourceItems(rootResDir.toPath()) } + .flatten() + } + .groupBy { it.type } + .mapValues { (_, items) -> items.groupBy { it.name } } + + val pkgName = packageName.get() + val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" + val isPublic = makeAccessorsPublic.get() + getAccessorsSpecs( + resources, pkgName, sourceSet, moduleDirectory, isPublic + ).forEach { it.writeTo(kotlinDir) } } private fun File.fileToResourceItems( diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceCollectorsTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceCollectorsTask.kt new file mode 100644 index 0000000000..19b9a371a1 --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceCollectorsTask.kt @@ -0,0 +1,103 @@ +package org.jetbrains.compose.resources + +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.jetbrains.compose.internal.IdeaImportTask +import org.jetbrains.compose.internal.utils.uppercaseFirstChar + +internal abstract class GenerateExpectResourceCollectorsTask : IdeaImportTask() { + @get:Input + abstract val packageName: Property + + @get:Input + abstract val makeAccessorsPublic: Property + + @get:OutputDirectory + abstract val codeDir: DirectoryProperty + + override fun safeAction() { + val kotlinDir = codeDir.get().asFile + + logger.info("Clean directory $kotlinDir") + kotlinDir.deleteRecursively() + kotlinDir.mkdirs() + + logger.info("Generate expect ResourceCollectors for $kotlinDir") + + val pkgName = packageName.get() + val isPublic = makeAccessorsPublic.get() + val spec = getExpectResourceCollectorsFileSpec(pkgName, "ExpectResourceCollectors", isPublic) + spec.writeTo(kotlinDir) + } +} + +internal abstract class GenerateActualResourceCollectorsTask : IdeaImportTask() { + @get:Input + abstract val packageName: Property + + @get:Input + abstract val makeAccessorsPublic: Property + + @get:Input + abstract val useActualModifier: Property + + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val resourceAccessorDirs: ConfigurableFileCollection + + @get:OutputDirectory + abstract val codeDir: DirectoryProperty + + override fun safeAction() { + val kotlinDir = codeDir.get().asFile + val inputDirs = resourceAccessorDirs.files + + logger.info("Clean directory $kotlinDir") + kotlinDir.deleteRecursively() + kotlinDir.mkdirs() + + val inputFiles = inputDirs.flatMap { dir -> + dir.walkTopDown().filter { !it.isHidden && it.isFile && it.extension == "kt" }.toList() + } + logger.info("Generate actual ResourceCollectors for $kotlinDir") + val funNames = inputFiles.mapNotNull { inputFile -> + if (inputFile.nameWithoutExtension.contains('.')) { + val (fileName, suffix) = inputFile.nameWithoutExtension.split('.') + val type = ResourceType.values().firstOrNull { fileName.startsWith(it.accessorName, true) } + val name = "_collect${suffix.uppercaseFirstChar()}${fileName}Resources" + + if (type == null) { + logger.warn("Unknown resources type: `$inputFile`") + null + } else if (!inputFile.readText().contains(name)) { + logger.warn("A function '$name' is not found in the `$inputFile` file!") + null + } else { + logger.info("Found collector function: `$name`") + type to name + } + } else { + logger.warn("Unknown file name: `$inputFile`") + null + } + }.groupBy({ it.first }, { it.second }) + + val pkgName = packageName.get() + val isPublic = makeAccessorsPublic.get() + val useActual = useActualModifier.get() + val spec = getActualResourceCollectorsFileSpec( + pkgName, + "ActualResourceCollectors", + isPublic, + useActual, + funNames + ) + spec.writeTo(kotlinDir) + } +} diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt index 1ecdd84f35..559f0471b3 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt @@ -1,6 +1,19 @@ package org.jetbrains.compose.resources -import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.AnnotationSpec +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.FunSpec +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.MAP +import com.squareup.kotlinpoet.MUTABLE_MAP +import com.squareup.kotlinpoet.MemberName +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.PropertySpec +import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.asClassName +import com.squareup.kotlinpoet.withIndent import org.jetbrains.compose.internal.utils.uppercaseFirstChar import java.nio.file.Path import java.util.* @@ -45,6 +58,9 @@ private val resourceItemClass = ClassName("org.jetbrains.compose.resources", "Re private val experimentalAnnotation = AnnotationSpec.builder( ClassName("org.jetbrains.compose.resources", "ExperimentalResourceApi") ).build() +private val internalAnnotation = AnnotationSpec.builder( + ClassName("org.jetbrains.compose.resources", "InternalResourceApi") +).build() private fun CodeBlock.Builder.addQualifiers(resourceItem: ResourceItem): CodeBlock.Builder { val languageQualifier = ClassName("org.jetbrains.compose.resources", "LanguageQualifier") @@ -240,17 +256,34 @@ private fun getChunkFileSpec( typeObject.addModifiers(KModifier.PRIVATE) val properties = idToResources.keys.map { resName -> PropertySpec.builder(resName, type.getClassName()) - .delegate("\nlazy·{ init_$resName() }") + .delegate("\nlazy·{ %N() }", "init_$resName") .build() } typeObject.addProperties(properties) }.build() chunkFile.addType(objectSpec) + //__collect${chunkClassName}Resources function + chunkFile.addFunction( + FunSpec.builder("_collect${chunkClassName}Resources") + .addAnnotation(internalAnnotation) + .addModifiers(KModifier.INTERNAL) + .addParameter( + "map", + MUTABLE_MAP.parameterizedBy(String::class.asClassName(), type.getClassName()) + ) + .also { collectFun -> + idToResources.keys.forEach { resName -> + collectFun.addStatement("map.put(%S, $chunkClassName.%N)", resName, resName) + } + } + .build() + ) + idToResources.forEach { (resName, items) -> val accessor = PropertySpec.builder(resName, type.getClassName(), resModifier) .receiver(ClassName(packageName, "Res", type.accessorName)) - .getter(FunSpec.getterBuilder().addStatement("return $chunkClassName.$resName").build()) + .getter(FunSpec.getterBuilder().addStatement("return $chunkClassName.%N", resName).build()) .build() chunkFile.addProperty(accessor) @@ -260,8 +293,8 @@ private fun getChunkFileSpec( .addStatement( CodeBlock.builder() .add("return %T(\n", type.getClassName()).withIndent { - add("\"${type}:${resName}\",") - if (type.requiresKeyName()) add(" \"$resName\",") + add("%S,", "$type:$resName") + if (type.requiresKeyName()) add(" %S,", resName) withIndent { add("\nsetOf(\n").withIndent { items.forEach { item -> @@ -285,6 +318,79 @@ private fun getChunkFileSpec( }.build() } +internal fun getExpectResourceCollectorsFileSpec( + packageName: String, + fileName: String, + isPublic: Boolean +): FileSpec { + val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL + return FileSpec.builder(packageName, fileName).also { file -> + ResourceType.values().forEach { type -> + val typeClassName = type.getClassName() + file.addProperty( + PropertySpec + .builder( + "all${typeClassName.simpleName}s", + MAP.parameterizedBy(String::class.asClassName(), typeClassName), + KModifier.EXPECT, + resModifier + ) + .addAnnotation(experimentalAnnotation) + .receiver(ClassName(packageName, "Res")) + .build() + ) + } + }.build() +} + +internal fun getActualResourceCollectorsFileSpec( + packageName: String, + fileName: String, + isPublic: Boolean, + useActualModifier: Boolean, //e.g. java only project doesn't need actual modifiers + typeToCollectorFunctions: Map> +): FileSpec = FileSpec.builder(packageName, fileName).also { file -> + val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL + + file.addAnnotation( + AnnotationSpec.builder(ClassName("kotlin", "OptIn")) + .addMember("org.jetbrains.compose.resources.InternalResourceApi::class") + .build() + ) + + ResourceType.values().forEach { type -> + val typeClassName = type.getClassName() + val initBlock = CodeBlock.builder() + .addStatement("lazy {").withIndent { + addStatement("val map = mutableMapOf()", typeClassName) + typeToCollectorFunctions.get(type).orEmpty().forEach { item -> + addStatement("%N(map)", item) + } + addStatement("return@lazy map") + } + .addStatement("}") + .build() + + val mods = if (useActualModifier) { + listOf(KModifier.ACTUAL, resModifier) + } else { + listOf(resModifier) + } + + val property = PropertySpec + .builder( + "all${typeClassName.simpleName}s", + MAP.parameterizedBy(String::class.asClassName(), typeClassName), + mods + ) + .addAnnotation(experimentalAnnotation) + .receiver(ClassName(packageName, "Res")) + .delegate(initBlock) + .build() + file.addProperty(property) + } +}.build() + private fun sortResources( resources: Map>> ): TreeMap>> { diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResources.kt index bdb114d4ac..ae31edbafb 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResources.kt @@ -6,10 +6,15 @@ import org.gradle.api.plugins.ExtensionAware import org.gradle.api.provider.Provider import org.gradle.api.tasks.Copy import org.jetbrains.compose.desktop.application.internal.ComposeProperties -import org.jetbrains.compose.internal.utils.* +import org.jetbrains.compose.internal.utils.dependsOn +import org.jetbrains.compose.internal.utils.joinLowerCamelCase +import org.jetbrains.compose.internal.utils.registerOrConfigure +import org.jetbrains.compose.internal.utils.uppercaseFirstChar import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension -import org.jetbrains.kotlin.gradle.plugin.mpp.* +import org.jetbrains.kotlin.gradle.plugin.mpp.Framework +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable import org.jetbrains.kotlin.konan.target.KonanTarget import java.io.File @@ -83,13 +88,16 @@ internal fun Project.configureSyncIosComposeResources( framework { podFramework -> val syncDir = podFramework.getFinalResourcesDir().get().asFile.relativeTo(projectDir) val specAttr = "['${syncDir.path}']" - extraSpecAttributes["resources"] = specAttr - project.tasks.named("podInstall").configure { + val specAttributes = extraSpecAttributes + val buildFile = project.buildFile + val projectPath = project.path + specAttributes["resources"] = specAttr + project.tasks.named("podspec").configure { it.doFirst { - if (extraSpecAttributes["resources"] != specAttr) error( + if (specAttributes["resources"] != specAttr) error( """ |Kotlin.cocoapods.extraSpecAttributes["resources"] is not compatible with Compose Multiplatform's resources management for iOS. - | * Recommended action: remove extraSpecAttributes["resources"] from '${project.buildFile}' and run '${project.path}:podInstall' once; + | * Recommended action: remove extraSpecAttributes["resources"] from '$buildFile' and run '$projectPath:podInstall' once; | * Alternative action: turn off Compose Multiplatform's resources management for iOS by adding '${ComposeProperties.SYNC_RESOURCES_PROPERTY}=false' to your gradle.properties; """.trimMargin() ) @@ -131,7 +139,7 @@ private fun KotlinNativeTarget.isIosSimulatorTarget(): Boolean = konanTarget === KonanTarget.IOS_X64 || konanTarget === KonanTarget.IOS_SIMULATOR_ARM64 private fun KotlinNativeTarget.isIosDeviceTarget(): Boolean = - konanTarget === KonanTarget.IOS_ARM64 || konanTarget === KonanTarget.IOS_ARM32 + konanTarget === KonanTarget.IOS_ARM64 private fun KotlinNativeTarget.isIosTarget(): Boolean = isIosSimulatorTarget() || isIosDeviceTarget() \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResourcesTasks.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResourcesTasks.kt index 90681d3166..b024e9412b 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResourcesTasks.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/IosResourcesTasks.kt @@ -4,8 +4,16 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.* -import org.gradle.api.tasks.* +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.konan.target.KonanTarget import javax.inject.Inject @@ -95,7 +103,6 @@ private fun getRequestedKonanTargetsByXcode(platform: String, archs: List when (arch) { "arm64", "arm64e" -> KonanTarget.IOS_ARM64 - "armv7", "armv7s" -> KonanTarget.IOS_ARM32 else -> error("Unknown iOS device arch: '$arch'") } }) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt index 3a945db560..5ace0c22a9 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt @@ -32,28 +32,26 @@ internal fun Project.configureKmpResources( logger.info("Configure resources publication for '${target.targetName}' target") val packedResourceDir = config.getModuleResourcesDir(project) - kmpResources.publishResourcesAsKotlinComponent( - target, - { sourceSet -> - KotlinTargetResourcesPublication.ResourceRoot( - getPreparedComposeResourcesDir(sourceSet), - emptyList(), - //for android target exclude fonts - if (target is KotlinAndroidTarget) listOf("**/font*/*") else emptyList() - ) - }, - packedResourceDir - ) - - if (target is KotlinAndroidTarget) { - //for android target publish fonts in assets - logger.info("Configure fonts relocation for '${target.targetName}' target") + if (target !is KotlinAndroidTarget) { + kmpResources.publishResourcesAsKotlinComponent( + target, + { sourceSet -> + KotlinTargetResourcesPublication.ResourceRoot( + getPreparedComposeResourcesDir(sourceSet), + emptyList(), + emptyList() + ) + }, + packedResourceDir + ) + } else { + //for android target publish resources in assets kmpResources.publishInAndroidAssets( target, { sourceSet -> KotlinTargetResourcesPublication.ResourceRoot( getPreparedComposeResourcesDir(sourceSet), - listOf("**/font*/*"), + emptyList(), emptyList() ) }, diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt index 11131350fe..0d447b6a3c 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt @@ -1,6 +1,7 @@ package org.jetbrains.compose.resources import org.gradle.api.Project +import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.FileTree @@ -25,11 +26,19 @@ import javax.inject.Inject import javax.xml.parsers.DocumentBuilderFactory internal fun Project.registerPrepareComposeResourcesTask( - sourceSet: KotlinSourceSet + sourceSet: KotlinSourceSet, + config: Provider ): TaskProvider { - val resDir = "${sourceSet.name}/$COMPOSE_RESOURCES_DIR" - val userComposeResourcesDir = project.projectDir.resolve("src/$resDir") - val preparedComposeResourcesDir = layout.buildDirectory.dir("$RES_GEN_DIR/preparedResources/$resDir") + val userComposeResourcesDir: Provider = config.flatMap { ext -> + ext.customResourceDirectories[sourceSet.name] ?: provider { + //default path + layout.projectDirectory.dir("src/${sourceSet.name}/$COMPOSE_RESOURCES_DIR") + } + } + + val preparedComposeResourcesDir = layout.buildDirectory.dir( + "$RES_GEN_DIR/preparedResources/${sourceSet.name}/$COMPOSE_RESOURCES_DIR" + ) val convertXmlValueResources = tasks.register( "convertXmlValueResourcesFor${sourceSet.name.uppercaseFirstChar()}", @@ -61,11 +70,11 @@ internal fun Project.registerPrepareComposeResourcesTask( } internal fun Project.getPreparedComposeResourcesDir(sourceSet: KotlinSourceSet): Provider = tasks - .named( - getPrepareComposeResourcesTaskName(sourceSet), - PrepareComposeResourcesTask::class.java - ) - .flatMap { it.outputDir.asFile } + .named( + getPrepareComposeResourcesTaskName(sourceSet), + PrepareComposeResourcesTask::class.java + ) + .flatMap { it.outputDir.asFile } private fun getPrepareComposeResourcesTaskName(sourceSet: KotlinSourceSet) = "prepareComposeResourcesTaskFor${sourceSet.name.uppercaseFirstChar()}" diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesDSL.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesDSL.kt index 17abaf96ff..88406e1125 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesDSL.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesDSL.kt @@ -1,6 +1,7 @@ package org.jetbrains.compose.resources import org.gradle.api.Project +import org.gradle.api.file.Directory import org.gradle.api.provider.Provider import java.io.File @@ -36,6 +37,18 @@ abstract class ResourcesExtension { * - `never`: Never generate the Res class. */ var generateResClass: ResourceClassGeneration = auto + + internal val customResourceDirectories: MutableMap> = mutableMapOf() + + /** + * Associates a custom resource directory with a specific source set. + * + * @param sourceSetName the name of the source set to associate the custom resource directory with + * @param directoryProvider the provider that provides the custom directory + */ + fun customDirectory(sourceSetName: String, directoryProvider: Provider) { + customResourceDirectories[sourceSetName] = directoryProvider + } } internal fun Provider.getResourcePackage(project: Project) = map { config -> diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt index 2c163824fc..79b68b8227 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt @@ -13,12 +13,11 @@ import org.gradle.api.artifacts.component.ModuleComponentIdentifier import org.gradle.api.provider.Provider import org.jetbrains.compose.ComposeBuildConfig import org.jetbrains.compose.ComposeExtension -import org.jetbrains.compose.web.tasks.UnpackSkikoWasmRuntimeTask -import org.jetbrains.compose.internal.utils.* +import org.jetbrains.compose.internal.utils.detachedComposeDependency import org.jetbrains.compose.internal.utils.registerTask -import org.jetbrains.compose.internal.utils.uppercaseFirstChar import org.jetbrains.compose.web.WebExtension -import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget +import org.jetbrains.compose.web.tasks.UnpackSkikoWasmRuntimeTask +import org.jetbrains.kotlin.gradle.tasks.IncrementalSyncTask internal fun Project.configureWeb( composeExt: ComposeExtension, @@ -48,11 +47,12 @@ internal fun Project.configureWeb( } // configure only if there is k/wasm or k/js target: - webExt.targetsToConfigure(project) - .configureWebApplication(project, shouldRunUnpackSkiko) + if (webExt.targetsToConfigure(project).isNotEmpty()) { + configureWebApplication(project, shouldRunUnpackSkiko) + } } -internal fun Collection.configureWebApplication( +internal fun configureWebApplication( project: Project, shouldRunUnpackSkiko: Provider ) { @@ -63,28 +63,22 @@ internal fun Collection.configureWebApplication( skikoJsWasmRuntimeConfiguration.defaultDependencies { it.addLater(skikoJsWasmRuntimeDependency) } - forEach { - val mainCompilation = it.compilations.getByName("main") - val testCompilation = it.compilations.getByName("test") - val unpackedRuntimeDir = project.layout.buildDirectory.dir("compose/skiko-wasm/${it.targetName}") - val taskName = "unpackSkikoWasmRuntime${it.targetName.uppercaseFirstChar()}" - mainCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir) - testCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir) - - val unpackRuntime = project.registerTask(taskName) { - onlyIf { - shouldRunUnpackSkiko.get() - } - skikoRuntimeFiles = skikoJsWasmRuntimeConfiguration - outputDir.set(unpackedRuntimeDir) - } - project.tasks.named(mainCompilation.processResourcesTaskName).configure { processResourcesTask -> - processResourcesTask.dependsOn(unpackRuntime) - } - project.tasks.named(testCompilation.processResourcesTaskName).configure { processResourcesTask -> - processResourcesTask.dependsOn(unpackRuntime) + val unpackedRuntimeDir = project.layout.buildDirectory.dir("compose/skiko-wasm") + val taskName = "unpackSkikoWasmRuntime" + + val unpackRuntime = project.registerTask(taskName) { + onlyIf { + shouldRunUnpackSkiko.get() } + + skikoRuntimeFiles = skikoJsWasmRuntimeConfiguration + outputDir.set(unpackedRuntimeDir) + } + + project.tasks.withType(IncrementalSyncTask::class.java) { + it.dependsOn(unpackRuntime) + it.from.from(unpackedRuntimeDir) } } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt index 0653807888..1eeb113f8b 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt @@ -12,20 +12,31 @@ import org.jetbrains.compose.internal.utils.currentArch import org.jetbrains.compose.internal.utils.currentOS import org.jetbrains.compose.internal.utils.currentTarget import org.jetbrains.compose.internal.utils.uppercaseFirstChar -import org.jetbrains.compose.test.utils.* - -import java.io.File -import java.util.* +import org.jetbrains.compose.test.utils.GradlePluginTestBase +import org.jetbrains.compose.test.utils.JDK_11_BYTECODE_VERSION +import org.jetbrains.compose.test.utils.ProcessRunResult +import org.jetbrains.compose.test.utils.TestProject +import org.jetbrains.compose.test.utils.assertEqualTextFiles +import org.jetbrains.compose.test.utils.assertNotEqualTextFiles +import org.jetbrains.compose.test.utils.checkContains +import org.jetbrains.compose.test.utils.checkExists +import org.jetbrains.compose.test.utils.checkNotExists +import org.jetbrains.compose.test.utils.checks +import org.jetbrains.compose.test.utils.modify +import org.jetbrains.compose.test.utils.readClassFileVersion +import org.jetbrains.compose.test.utils.runProcess import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assumptions import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import java.io.File +import java.util.* import java.util.jar.JarFile class DesktopApplicationTest : GradlePluginTestBase() { @Test - fun smokeTestRunTask() = with(testProject(TestProjects.jvm)) { + fun smokeTestRunTask() = with(testProject("application/jvm")) { file("build.gradle").modify { it + """ afterEvaluate { @@ -62,7 +73,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun testRunMpp() = with(testProject(TestProjects.mpp)) { + fun testRunMpp() = with(testProject("application/mpp")) { val logLine = "Kotlin MPP app is running!" gradle("run").checks { check.taskSuccessful(":run") @@ -84,60 +95,8 @@ class DesktopApplicationTest : GradlePluginTestBase() { } } - /** - * Test the version of Compose Compiler published by Google. - * See https://developer.android.com/jetpack/androidx/releases/compose-kotlin - */ - @Test - fun testAndroidxCompiler() = testProject( - TestProjects.customCompiler, defaultTestEnvironment.copy( - kotlinVersion = "1.8.0", - composeCompilerPlugin = "\"androidx.compose.compiler:compiler:1.4.0\"" - ) - ).checkCustomComposeCompiler() - - @Test - fun testSettingLatestCompiler() = testProject( - TestProjects.customCompiler, defaultTestEnvironment.copy( - kotlinVersion = "1.8.20", - composeCompilerPlugin = "dependencies.compiler.forKotlin(\"1.8.20\")", - ) - ).checkCustomComposeCompiler() - - @Test - fun testSettingAutoCompiler() = testProject( - TestProjects.customCompiler, defaultTestEnvironment.copy( - kotlinVersion = "1.8.10", - composeCompilerPlugin = "dependencies.compiler.auto", - ) - ).checkCustomComposeCompiler() - - @Test - fun testKotlinCheckDisabled() = testProject( - TestProjects.customCompilerArgs, defaultTestEnvironment.copy( - kotlinVersion = "1.9.21", - composeCompilerPlugin = "dependencies.compiler.forKotlin(\"1.9.20\")", - composeCompilerArgs = "\"suppressKotlinVersionCompatibilityCheck=1.9.21\"" - ) - ).checkCustomComposeCompiler(checkKJS = true) - - private fun TestProject.checkCustomComposeCompiler(checkKJS: Boolean = false) { - gradle(":runDistributable").checks { - val actualMainImage = file("main-image.actual.png") - val expectedMainImage = file("main-image.expected.png") - assert(actualMainImage.readBytes().contentEquals(expectedMainImage.readBytes())) { - "The actual image '$actualMainImage' does not match the expected image '$expectedMainImage'" - } - } - if (checkKJS) { - gradle(":jsBrowserProductionWebpack").checks { - check.taskSuccessful(":jsBrowserProductionWebpack") - } - } - } - @Test - fun kotlinDsl(): Unit = with(testProject(TestProjects.jvmKotlinDsl)) { + fun kotlinDsl(): Unit = with(testProject("application/jvmKotlinDsl")) { gradle(":packageDistributionForCurrentOS", "--dry-run") gradle(":packageReleaseDistributionForCurrentOS", "--dry-run") } @@ -145,7 +104,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { @Test fun proguard(): Unit = with( testProject( - TestProjects.proguard, + "application/proguard", testEnvironment = defaultTestEnvironment.copy(composeVerbose = false)) ) { val enableObfuscation = """ @@ -188,12 +147,12 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun joinOutputJarsJvm() = with(testProject(TestProjects.jvm)) { + fun joinOutputJarsJvm() = with(testProject("application/jvm")) { joinOutputJars() } @Test - fun joinOutputJarsMpp() = with(testProject(TestProjects.mpp)) { + fun joinOutputJarsMpp() = with(testProject("application/mpp")) { joinOutputJars() } @@ -220,7 +179,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun gradleBuildCache() = with(testProject(TestProjects.jvm)) { + fun gradleBuildCache() = with(testProject("application/jvm")) { modifyGradleProperties { setProperty("org.gradle.caching", "true") } @@ -246,12 +205,12 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun packageJvm() = with(testProject(TestProjects.jvm)) { + fun packageJvm() = with(testProject("application/jvm")) { testPackageJvmDistributions() } @Test - fun packageMpp() = with(testProject(TestProjects.mpp)) { + fun packageMpp() = with(testProject("application/mpp")) { testPackageJvmDistributions() } @@ -305,7 +264,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } private fun customJdkProject(javaVersion: Int): TestProject = - testProject(TestProjects.jvm).apply { + testProject("application/jvm").apply { appendText("build.gradle") { """ compose.desktop.application { @@ -318,22 +277,22 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun packageUberJarForCurrentOSJvm() = with(testProject(TestProjects.jvm)) { + fun packageUberJarForCurrentOSJvm() = with(testProject("application/jvm")) { testPackageUberJarForCurrentOS(false) } @Test - fun packageUberJarForCurrentOSMpp() = with(testProject(TestProjects.mpp)) { + fun packageUberJarForCurrentOSMpp() = with(testProject("application/mpp")) { testPackageUberJarForCurrentOS(false) } @Test - fun packageReleaseUberJarForCurrentOSJvm() = with(testProject(TestProjects.jvm)) { + fun packageReleaseUberJarForCurrentOSJvm() = with(testProject("application/jvm")) { testPackageUberJarForCurrentOS(true) } @Test - fun packageReleaseUberJarForCurrentOSMpp() = with(testProject(TestProjects.mpp)) { + fun packageReleaseUberJarForCurrentOSMpp() = with(testProject("application/mpp")) { testPackageUberJarForCurrentOS(true) } @@ -366,7 +325,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun testModuleClash() = with(testProject(TestProjects.moduleClashCli)) { + fun testModuleClash() = with(testProject("application/moduleClashCli")) { gradle(":app:runDistributable").checks { check.taskSuccessful(":app:createDistributable") check.taskSuccessful(":app:runDistributable") @@ -376,7 +335,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun testJavaLogger() = with(testProject(TestProjects.javaLogger)) { + fun testJavaLogger() = with(testProject("application/javaLogger")) { gradle(":runDistributable").checks { check.taskSuccessful(":runDistributable") check.logContains("Compose Gradle plugin test log warning!") @@ -393,7 +352,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { Assumptions.assumeTrue(currentOS == OS.MacOS) - with(testProject(TestProjects.macOptions)) { + with(testProject("application/macOptions")) { gradle(":runDistributable").checks { check.taskSuccessful(":runDistributable") check.logContains("Hello, from Mac OS!") @@ -411,7 +370,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { fun testMacSignConfiguration() { Assumptions.assumeTrue(currentOS == OS.MacOS) - with(testProject(TestProjects.macSign)) { + with(testProject("application/macSign")) { gradle("--dry-run", ":createDistributable") } } @@ -444,7 +403,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } } - with(testProject(TestProjects.macSign)) { + with(testProject("application/macSign")) { val keychain = file("compose.test.keychain") val password = "compose.test" @@ -474,7 +433,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { @Test fun testOptionsWithSpaces() { - with(testProject(TestProjects.optionsWithSpaces)) { + with(testProject("application/optionsWithSpaces")) { fun testRunTask(runTask: String) { gradle(runTask).checks { check.taskSuccessful(runTask) @@ -496,7 +455,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { @Test fun testDefaultArgs() { - with(testProject(TestProjects.defaultArgs)) { + with(testProject("application/defaultArgs")) { fun testRunTask(runTask: String) { gradle(runTask).checks { check.taskSuccessful(runTask) @@ -515,7 +474,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { @Test fun testDefaultArgsOverride() { - with(testProject(TestProjects.defaultArgsOverride)) { + with(testProject("application/defaultArgsOverride")) { fun testRunTask(runTask: String) { gradle(runTask).checks { check.taskSuccessful(runTask) @@ -534,7 +493,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { @Test fun testSuggestModules() { - with(testProject(TestProjects.jvm)) { + with(testProject("application/jvm")) { gradle(":suggestRuntimeModules").checks { check.taskSuccessful(":suggestRuntimeModules") check.logContains("Suggested runtime modules to include:") @@ -544,12 +503,12 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun testUnpackSkiko() = with(testProject(TestProjects.unpackSkiko)) { + fun testUnpackSkiko() = with(testProject("application/unpackSkiko")) { testUnpackSkiko(":runDistributable") } @Test - fun testUnpackSkikoFromUberJar() = with(testProject(TestProjects.unpackSkiko)) { + fun testUnpackSkikoFromUberJar() = with(testProject("application/unpackSkiko")) { enableJoinOutputJars() testUnpackSkiko(":runReleaseDistributable") } @@ -576,7 +535,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { } @Test - fun resources() = with(testProject(TestProjects.resources)) { + fun resources() = with(testProject("application/resources")) { gradle(":run").checks { check.taskSuccessful(":run") } @@ -590,7 +549,7 @@ class DesktopApplicationTest : GradlePluginTestBase() { fun testWixUnzip() { Assumptions.assumeTrue(currentOS == OS.Windows) { "The test is only relevant for Windows" } - with(testProject(TestProjects.jvm)) { + with(testProject("application/jvm")) { gradle(":unzipWix").checks { check.taskSuccessful(":unzipWix") diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt index 959135780e..261b32054c 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt @@ -5,124 +5,32 @@ package org.jetbrains.compose.test.tests.integration +import org.gradle.internal.impldep.junit.framework.TestCase.assertEquals +import org.gradle.internal.impldep.junit.framework.TestCase.assertTrue import org.gradle.util.GradleVersion import org.jetbrains.compose.desktop.ui.tooling.preview.rpc.PreviewLogger import org.jetbrains.compose.desktop.ui.tooling.preview.rpc.RemoteConnection import org.jetbrains.compose.desktop.ui.tooling.preview.rpc.receiveConfigFromGradle -import org.jetbrains.compose.experimental.internal.kotlinVersionNumbers -import org.jetbrains.compose.internal.utils.Arch -import org.jetbrains.compose.internal.utils.OS -import org.jetbrains.compose.internal.utils.currentArch -import org.jetbrains.compose.internal.utils.currentOS -import org.jetbrains.compose.test.utils.* +import org.jetbrains.compose.test.utils.GradlePluginTestBase +import org.jetbrains.compose.test.utils.checkExists +import org.jetbrains.compose.test.utils.checks import org.junit.jupiter.api.Assumptions - +import org.junit.jupiter.api.Test import java.net.ServerSocket import java.net.Socket import java.net.SocketTimeoutException import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.thread -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import java.io.File +import kotlin.test.assertFalse class GradlePluginTest : GradlePluginTestBase() { - - @Test - fun nativeCacheKind() { - Assumptions.assumeTrue(currentOS == OS.MacOS) - val task = if (currentArch == Arch.X64) { - ":subproject:linkDebugFrameworkIosX64" - } else { - ":subproject:linkDebugFrameworkIosArm64" - } - // Note: we used to test with kotlin version 1.9.0 and 1.9.10 too, - // but since we now use Compose core libs (1.6.0-dev-1340 and newer) built using kotlin 1.9.21, - // the compiler crashed (older k/native doesn't support libs built using newer k/native): - // e: kotlin.NotImplementedError: Generation of stubs for class org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterPublicSymbolImpl is not supported yet - - if (kotlinVersionNumbers(defaultTestEnvironment.kotlinVersion) >= KotlinVersion(1, 9, 20)) { - testWorkDir.deleteRecursively() - testWorkDir.mkdirs() - val project = TestProject( - TestProjects.nativeCacheKind, - defaultTestEnvironment.copy(useGradleConfigurationCache = false) - ) - with(project) { - gradle(task, "--info").checks { - check.taskSuccessful(task) - check.logContains("-Xauto-cache-from=") - } - } - } - } - - @Test - fun nativeCacheKindError() { - Assumptions.assumeTrue(currentOS == OS.MacOS) - fun withNativeCacheKindErrorProject(kotlinVersion: String, fn: TestProject.() -> Unit) { - with(testProject( - TestProjects.nativeCacheKindError, - defaultTestEnvironment.copy(kotlinVersion = kotlinVersion) - )) { - fn() - testWorkDir.deleteRecursively() - testWorkDir.mkdirs() - } - } - - fun testKotlinVersion(kotlinVersion: String) { - val args = arrayOf("help") - val commonPartOfWarning = "Compose Multiplatform Gradle plugin manages this property automatically" - withNativeCacheKindErrorProject(kotlinVersion = kotlinVersion) { - gradle(*args).checks { - check.logDoesntContain("Error: 'kotlin.native.cacheKind") - check.logDoesntContain(commonPartOfWarning) - } - } - withNativeCacheKindErrorProject(kotlinVersion = kotlinVersion) { - gradleFailure(*args, "-Pkotlin.native.cacheKind=none").checks { - check.logContains("Error: 'kotlin.native.cacheKind' is explicitly set to 'none'") - check.logContains(commonPartOfWarning) - } - - gradleFailure(*args, "-Pkotlin.native.cacheKind=none").checks { - check.logContains("Error: 'kotlin.native.cacheKind' is explicitly set to 'none'") - check.logContains(commonPartOfWarning) - } - } - withNativeCacheKindErrorProject(kotlinVersion = kotlinVersion) { - gradleFailure(*args, "-Pkotlin.native.cacheKind=static").checks { - check.logContains("Error: 'kotlin.native.cacheKind' is explicitly set to 'static'") - check.logContains(commonPartOfWarning) - } - } - withNativeCacheKindErrorProject(kotlinVersion = kotlinVersion) { - gradleFailure(*args, "-Pkotlin.native.cacheKind.iosX64=none").checks { - check.logContains("Error: 'kotlin.native.cacheKind.iosX64' is explicitly set to 'none'") - check.logContains(commonPartOfWarning) - } - } - withNativeCacheKindErrorProject(kotlinVersion = kotlinVersion) { - gradleFailure(*args, "-Pkotlin.native.cacheKind.iosX64=static").checks { - check.logContains("Error: 'kotlin.native.cacheKind.iosX64' is explicitly set to 'static'") - check.logContains(commonPartOfWarning) - } - } - } - - testKotlinVersion("1.9.21") - } - @Test fun skikoWasm() = with( testProject( - TestProjects.skikoWasm, - // configuration cache is disabled as a temporary workaround for KT-58057 - // todo: enable once KT-58057 is fixed - testEnvironment = defaultTestEnvironment.copy(useGradleConfigurationCache = false) + "misc/skikoWasm", + // TODO: enable the configuration cache after moving all test projects to kotlin 2.0 or newer + defaultTestEnvironment.copy(useGradleConfigurationCache = false) ) ) { fun jsCanvasEnabled(value: Boolean) { @@ -137,15 +45,29 @@ class GradlePluginTest : GradlePluginTestBase() { jsCanvasEnabled(true) gradle(":build").checks { - check.taskSuccessful(":unpackSkikoWasmRuntimeJs") + check.taskSuccessful(":unpackSkikoWasmRuntime") check.taskSuccessful(":compileKotlinJs") + check.taskSuccessful(":compileKotlinWasmJs") + check.taskSuccessful(":wasmJsBrowserDistribution") + + file("./build/dist/wasmJs/productionExecutable").apply { + checkExists() + assertTrue(isDirectory) + val distributionFiles = listFiles()!!.map { it.name }.toList() + assertFalse( + distributionFiles.contains("skiko.wasm"), + "skiko.wasm is probably a duplicate" + ) + // one file is the app wasm file and another one is skiko wasm file with a mangled name + assertEquals(2, distributionFiles.filter { it.endsWith(".wasm") }.size) + } } } @Test fun newAndroidTarget() { Assumptions.assumeTrue(defaultTestEnvironment.parsedGradleVersion >= GradleVersion.version("8.0.0")) - with(testProject(TestProjects.newAndroidTarget)) { + with(testProject("application/newAndroidTarget")) { gradle("build", "--dry-run").checks { } } @@ -154,12 +76,7 @@ class GradlePluginTest : GradlePluginTestBase() { @Test fun jsMppIsNotBroken() = with( - testProject( - TestProjects.jsMpp, - testEnvironment = defaultTestEnvironment.copy( - kotlinVersion = TestProperties.composeJsCompilerCompatibleKotlinVersion - ) - ) + testProject("misc/jsMpp") ) { gradle(":compileKotlinJs").checks { check.taskSuccessful(":compileKotlinJs") @@ -224,7 +141,7 @@ class GradlePluginTest : GradlePluginTestBase() { private fun testConfigureDesktopPreviewImpl(port: Int) { check(port > 0) { "Invalid port: $port" } - with(testProject(TestProjects.jvmPreview)) { + with(testProject("misc/jvmPreview")) { val portProperty = "-Pcompose.desktop.preview.ide.port=$port" val previewTargetProperty = "-Pcompose.desktop.preview.target=PreviewKt.ExamplePreview" val jvmTask = ":jvm:configureDesktopPreview" diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/KotlinCompatibilityTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/KotlinCompatibilityTest.kt index a790c56bd8..0a452fd67c 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/KotlinCompatibilityTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/KotlinCompatibilityTest.kt @@ -5,10 +5,9 @@ package org.jetbrains.compose.test.tests.integration -import org.jetbrains.compose.newCompilerIsAvailableVersion import org.jetbrains.compose.newComposeCompilerError import org.jetbrains.compose.test.utils.GradlePluginTestBase -import org.jetbrains.compose.test.utils.TestProjects +import org.jetbrains.compose.test.utils.TestProject import org.jetbrains.compose.test.utils.checks import org.junit.jupiter.api.Test @@ -27,7 +26,7 @@ class KotlinCompatibilityTest : GradlePluginTestBase() { private fun testMpp(kotlinVersion: String) = with( testProject( - TestProjects.mpp, + "beforeKotlin2/mpp", testEnvironment = defaultTestEnvironment.copy(kotlinVersion = kotlinVersion) ) ) { @@ -40,7 +39,7 @@ class KotlinCompatibilityTest : GradlePluginTestBase() { private fun testJsMpp(kotlinVersion: String) = with( testProject( - TestProjects.jsMpp, + "beforeKotlin2/jsMpp", testEnvironment = defaultTestEnvironment.copy(kotlinVersion = kotlinVersion) ) ) { @@ -51,14 +50,64 @@ class KotlinCompatibilityTest : GradlePluginTestBase() { @Test fun testNewCompilerPluginError() { - // TODO replace by this after Kotlin 2.0 release - // testEnvironment = defaultTestEnvironment.copy(kotlinVersion = "2.0") val testProject = testProject( - TestProjects.mpp, - testEnvironment = defaultTestEnvironment.copy(kotlinVersion = newCompilerIsAvailableVersion) + "beforeKotlin2/mpp", + testEnvironment = defaultTestEnvironment.copy(kotlinVersion = "2.0.0") ) testProject.gradleFailure("tasks").checks { check.logContains(newComposeCompilerError) } } + + /** + * Test the version of Compose Compiler published by Google. + * See https://developer.android.com/jetpack/androidx/releases/compose-kotlin + */ + @Test + fun testAndroidxCompiler() = testProject( + "beforeKotlin2/custom-compiler", defaultTestEnvironment.copy( + kotlinVersion = "1.8.0", + composeCompilerPlugin = "\"androidx.compose.compiler:compiler:1.4.0\"" + ) + ).checkCustomComposeCompiler() + + @Test + fun testSettingLatestCompiler() = testProject( + "beforeKotlin2/custom-compiler", defaultTestEnvironment.copy( + kotlinVersion = "1.8.20", + composeCompilerPlugin = "dependencies.compiler.forKotlin(\"1.8.20\")", + ) + ).checkCustomComposeCompiler() + + @Test + fun testSettingAutoCompiler() = testProject( + "beforeKotlin2/custom-compiler", defaultTestEnvironment.copy( + kotlinVersion = "1.8.10", + composeCompilerPlugin = "dependencies.compiler.auto", + ) + ).checkCustomComposeCompiler() + + @Test + fun testKotlinCheckDisabled() = testProject( + "beforeKotlin2/custom-compiler-args", defaultTestEnvironment.copy( + kotlinVersion = "1.9.21", + composeCompilerPlugin = "dependencies.compiler.forKotlin(\"1.9.20\")", + composeCompilerArgs = "\"suppressKotlinVersionCompatibilityCheck=1.9.21\"" + ) + ).checkCustomComposeCompiler(checkKJS = true) + + private fun TestProject.checkCustomComposeCompiler(checkKJS: Boolean = false) { + gradle(":runDistributable").checks { + val actualMainImage = file("main-image.actual.png") + val expectedMainImage = file("main-image.expected.png") + assert(actualMainImage.readBytes().contentEquals(expectedMainImage.readBytes())) { + "The actual image '$actualMainImage' does not match the expected image '$expectedMainImage'" + } + } + if (checkKJS) { + gradle(":jsBrowserProductionWebpack").checks { + check.taskSuccessful(":jsBrowserProductionWebpack") + } + } + } } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt index 3a3da032cf..95b599bfcb 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt @@ -2,15 +2,30 @@ package org.jetbrains.compose.test.tests.integration import org.gradle.util.GradleVersion import org.jetbrains.compose.desktop.application.internal.ComposeProperties -import org.jetbrains.compose.internal.utils.* +import org.jetbrains.compose.internal.utils.Arch +import org.jetbrains.compose.internal.utils.OS +import org.jetbrains.compose.internal.utils.currentArch +import org.jetbrains.compose.internal.utils.currentOS import org.jetbrains.compose.resources.XmlValuesConverterTask -import org.jetbrains.compose.test.utils.* +import org.jetbrains.compose.test.utils.GradlePluginTestBase +import org.jetbrains.compose.test.utils.TestProject +import org.jetbrains.compose.test.utils.assertEqualTextFiles +import org.jetbrains.compose.test.utils.assertNotEqualTextFiles +import org.jetbrains.compose.test.utils.checkExists +import org.jetbrains.compose.test.utils.checks +import org.jetbrains.compose.test.utils.modify import org.junit.jupiter.api.Assumptions import org.junit.jupiter.api.Test import java.io.File import java.util.zip.ZipFile +import kotlin.io.path.Path +import kotlin.io.path.invariantSeparatorsPathString import kotlin.io.path.relativeTo -import kotlin.test.* +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNotNull +import kotlin.test.assertNull +import kotlin.test.assertTrue class ResourcesTest : GradlePluginTestBase() { @Test @@ -227,9 +242,7 @@ class ResourcesTest : GradlePluginTestBase() { @Test fun testMultiModuleResources() { - val environment = defaultTestEnvironment.copy( - kotlinVersion = "2.0.0-RC2" - ) + val environment = defaultTestEnvironment.copy(kotlinVersion = "2.0.0") with( testProject("misc/kmpResourcePublication", environment) ) { @@ -246,57 +259,31 @@ class ResourcesTest : GradlePluginTestBase() { val resDir = file("cmplib/src/commonMain/composeResources") val resourcesFiles = resDir.walkTopDown() .filter { !it.isDirectory && !it.isHidden } - .getConvertedResources(resDir) - val subdir = "me.sample.library.resources" + .getConvertedResources(resDir, "composeResources/me.sample.library.resources") fun libpath(target: String, ext: String) = "my-mvn/me/sample/library/cmplib-$target/1.0/cmplib-$target-1.0$ext" val aar = file(libpath("android", ".aar")) - val innerClassesJar = aar.parentFile.resolve("aar-inner-classes.jar") - assertTrue(aar.exists(), "File not found: " + aar.path) - ZipFile(aar).use { zip -> - resourcesFiles - .filter { it.startsWith("font") } - .forEach { fontRes -> - assertNotNull( - zip.getEntry("assets/composeResources/$subdir/$fontRes"), - "Resource not found: '$fontRes' in aar '${aar.path}'" - ) - } - - innerClassesJar.writeBytes( - zip.getInputStream(zip.getEntry("classes.jar")).readBytes() - ) - } - ZipFile(innerClassesJar).use { zip -> - resourcesFiles - .filterNot { it.startsWith("font") } - .forEach { res -> - assertNotNull( - zip.getEntry("composeResources/$subdir/$res"), - "Resource not found: '$res' in aar/classes.jar '${aar.path}'" - ) - } - } + checkResourcesZip(aar, resourcesFiles, true) val jar = file(libpath("jvm", ".jar")) - checkResourcesZip(jar, resourcesFiles, subdir) + checkResourcesZip(jar, resourcesFiles, false) if (currentOS == OS.MacOS) { val iosx64ResZip = file(libpath("iosx64", "-kotlin_resources.kotlin_resources.zip")) - checkResourcesZip(iosx64ResZip, resourcesFiles, subdir) + checkResourcesZip(iosx64ResZip, resourcesFiles, false) val iosarm64ResZip = file(libpath("iosarm64", "-kotlin_resources.kotlin_resources.zip")) - checkResourcesZip(iosarm64ResZip, resourcesFiles, subdir) + checkResourcesZip(iosarm64ResZip, resourcesFiles, false) val iossimulatorarm64ResZip = file( libpath("iossimulatorarm64", "-kotlin_resources.kotlin_resources.zip") ) - checkResourcesZip(iossimulatorarm64ResZip, resourcesFiles, subdir) + checkResourcesZip(iossimulatorarm64ResZip, resourcesFiles, false) } val jsResZip = file(libpath("js", "-kotlin_resources.kotlin_resources.zip")) - checkResourcesZip(jsResZip, resourcesFiles, subdir) + checkResourcesZip(jsResZip, resourcesFiles, false) val wasmjsResZip = file(libpath("wasm-js", "-kotlin_resources.kotlin_resources.zip")) - checkResourcesZip(wasmjsResZip, resourcesFiles, subdir) + checkResourcesZip(wasmjsResZip, resourcesFiles, false) } file("settings.gradle.kts").modify { content -> @@ -344,14 +331,19 @@ class ResourcesTest : GradlePluginTestBase() { } } - private fun checkResourcesZip(zipFile: File, resourcesFiles: Sequence, subdir: String) { + private fun checkResourcesZip(zipFile: File, resourcesFiles: Sequence, isAndroid: Boolean) { + println("check ZIP: '${zipFile.path}'") assertTrue(zipFile.exists(), "File not found: " + zipFile.path) ZipFile(zipFile).use { zip -> resourcesFiles.forEach { res -> - assertNotNull( - zip.getEntry("composeResources/$subdir/$res"), - "Resource not found: '$res' in zip '${zipFile.path}'" - ) + println("check '$res' file") + if (isAndroid) { + //android resources should be only in assets + assertNull(zip.getEntry(res), "file = '$res'") + assertNotNull(zip.getEntry("assets/$res"), "file = 'assets/$res'") + } else { + assertNotNull(zip.getEntry(res), "file = '$res'") + } } } } @@ -390,50 +382,51 @@ class ResourcesTest : GradlePluginTestBase() { file("src/jsMain/composeResources/files/platform.txt").writeNewFile("js") val commonResourcesDir = file("src/commonMain/composeResources") + val repackDir = "composeResources/app.group.resources_test.generated.resources" val commonResourcesFiles = commonResourcesDir.walkTopDown() .filter { !it.isDirectory && !it.isHidden } - .getConvertedResources(commonResourcesDir) + .getConvertedResources(commonResourcesDir, repackDir) gradle("build").checks { - check.taskSuccessful(":copyDemoDebugFontsToAndroidAssets") - check.taskSuccessful(":copyDemoReleaseFontsToAndroidAssets") - check.taskSuccessful(":copyFullDebugFontsToAndroidAssets") - check.taskSuccessful(":copyFullReleaseFontsToAndroidAssets") + check.taskSuccessful(":demoDebugAssetsCopyForAGP") + check.taskSuccessful(":demoReleaseAssetsCopyForAGP") + check.taskSuccessful(":fullDebugAssetsCopyForAGP") + check.taskSuccessful(":fullReleaseAssetsCopyForAGP") getAndroidApk("demo", "debug", "Resources-Test").let { apk -> - checkResourcesInZip(apk, commonResourcesFiles, true) + checkResourcesZip(apk, commonResourcesFiles, true) assertEquals( "android demo-debug", - readFileInZip(apk, "files/platform.txt").decodeToString() + readFileInZip(apk, "assets/$repackDir/files/platform.txt").decodeToString() ) } getAndroidApk("demo", "release", "Resources-Test").let { apk -> - checkResourcesInZip(apk, commonResourcesFiles, true) + checkResourcesZip(apk, commonResourcesFiles, true) assertEquals( "android demo-release", - readFileInZip(apk, "files/platform.txt").decodeToString() + readFileInZip(apk, "assets/$repackDir/files/platform.txt").decodeToString() ) } getAndroidApk("full", "debug", "Resources-Test").let { apk -> - checkResourcesInZip(apk, commonResourcesFiles, true) + checkResourcesZip(apk, commonResourcesFiles, true) assertEquals( "android full-debug", - readFileInZip(apk, "files/platform.txt").decodeToString() + readFileInZip(apk, "assets/$repackDir/files/platform.txt").decodeToString() ) } getAndroidApk("full", "release", "Resources-Test").let { apk -> - checkResourcesInZip(apk, commonResourcesFiles, true) + checkResourcesZip(apk, commonResourcesFiles, true) assertEquals( "android full-release", - readFileInZip(apk, "files/platform.txt").decodeToString() + readFileInZip(apk, "assets/$repackDir/files/platform.txt").decodeToString() ) } file("build/libs/Resources-Test-desktop.jar").let { jar -> - checkResourcesInZip(jar, commonResourcesFiles, false) + checkResourcesZip(jar, commonResourcesFiles, false) assertEquals( "desktop", - readFileInZip(jar, "files/platform.txt").decodeToString() + readFileInZip(jar, "$repackDir/files/platform.txt").decodeToString() ) } @@ -441,41 +434,11 @@ class ResourcesTest : GradlePluginTestBase() { commonResourcesFiles.forEach { res -> assertTrue(jsBuildDir.resolve(res).exists()) } - assertEquals("js", jsBuildDir.resolve("files/platform.txt").readText()) - } - } - - @Test - fun testAndroidFonts(): Unit = with(testProject("misc/commonResources")) { - val commonResourcesDir = file("src/commonMain/composeResources") - val commonResourcesFiles = commonResourcesDir.walkTopDown() - .filter { !it.isDirectory && !it.isHidden } - .getConvertedResources(commonResourcesDir) - - gradle("assembleDebug").checks { - check.taskSuccessful(":copyDebugFontsToAndroidAssets") - - getAndroidApk("", "debug", "Resources-Test").let { apk -> - checkResourcesInZip(apk, commonResourcesFiles, true) - } - } - - file("src/commonMain/composeResources/font-en").renameTo( - file("src/commonMain/composeResources/font-mdpi") - ) - val newCommonResourcesFiles = commonResourcesDir.walkTopDown() - .filter { !it.isDirectory && !it.isHidden } - .getConvertedResources(commonResourcesDir) - gradle("assembleDebug").checks { - check.taskSuccessful(":copyDebugFontsToAndroidAssets") - - getAndroidApk("", "debug", "Resources-Test").let { apk -> - checkResourcesInZip(apk, newCommonResourcesFiles, true) - } + assertEquals("js", jsBuildDir.resolve("$repackDir/files/platform.txt").readText()) } } - private fun Sequence.getConvertedResources(baseDir: File) = map { file -> + private fun Sequence.getConvertedResources(baseDir: File, repackDir: String) = map { file -> val newFile = if ( file.parentFile.name.startsWith("value") && file.extension.equals("xml", true) @@ -485,10 +448,9 @@ class ResourcesTest : GradlePluginTestBase() { } else { file } - newFile.relativeTo(baseDir).invariantSeparatorsPath + Path(repackDir, newFile.relativeTo(baseDir).path).invariantSeparatorsPathString } - private fun File.writeNewFile(text: String) { parentFile.mkdirs() createNewFile() @@ -503,23 +465,6 @@ class ResourcesTest : GradlePluginTestBase() { } } - private fun checkResourcesInZip(file: File, commonResourcesFiles: Sequence, isAndroid: Boolean) { - println("check ZIP: '${file.path}'") - assertTrue(file.exists()) - ZipFile(file).use { zip -> - commonResourcesFiles.forEach { res -> - println("check '$res' file") - if (isAndroid && res.startsWith("font")) { - //android fonts should be only in assets - assertNull(zip.getEntry(res), "file = '$res'") - assertNotNull(zip.getEntry("assets/$res"), "file = 'assets/$res'") - } else { - assertNotNull(zip.getEntry(res), "file = '$res'") - } - } - } - } - private fun readFileInZip(file: File, path: String): ByteArray = ZipFile(file).use { zip -> val platformTxt = zip.getEntry(path) assertNotNull(platformTxt, "file = '$path'") @@ -543,8 +488,7 @@ class ResourcesTest : GradlePluginTestBase() { ) } gradle("prepareKotlinIdeaImport").checks { - check.taskSuccessful(":generateComposeResClass") - assertFalse(file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/resources_test/generated/resources/Res.kt").exists()) + check.taskSkipped(":generateComposeResClass") } modifyText("build.gradle.kts") { str -> @@ -568,9 +512,9 @@ class ResourcesTest : GradlePluginTestBase() { @Test fun testEmptyResClass(): Unit = with(testProject("misc/emptyResources")) { - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { assertDirectoriesContentEquals( - file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/empty_res/generated/resources"), + file("build/generated/compose/resourceGenerator/kotlin"), file("expected") ) } @@ -626,8 +570,14 @@ class ResourcesTest : GradlePluginTestBase() { } """.trimIndent() ) - gradle("generateComposeResClass").checks { - check.logContains("Generation Res class is disabled") + gradle("prepareKotlinIdeaImport").checks { + check.taskSkipped(":generateComposeResClass") + check.taskSkipped(":generateResourceAccessorsForCommonMain") + check.taskSkipped(":generateResourceAccessorsForDesktopMain") + check.taskSkipped(":generateResourceAccessorsForAndroidMain") + check.taskSkipped(":generateExpectResourceCollectorsForCommonMain") + check.taskSkipped(":generateActualResourceCollectorsForDesktopMain") + check.taskSkipped(":generateActualResourceCollectorsForAndroidMain") } } @@ -706,8 +656,8 @@ class ResourcesTest : GradlePluginTestBase() { check.taskNoSource(":prepareComposeResourcesTaskForIosX64Main") check.taskSkipped(":generateResourceAccessorsForIosX64Main") - file("build/compose/cocoapods/compose-resources/drawable/compose-multiplatform.xml").checkExists() - file("build/compose/cocoapods/compose-resources/drawable/icon.xml").checkExists() + file("build/compose/cocoapods/compose-resources/composeResources/iosresources.generated.resources/drawable/compose-multiplatform.xml").checkExists() + file("build/compose/cocoapods/compose-resources/composeResources/iosresources.generated.resources/drawable/icon.xml").checkExists() } gradle(":podspec", "-Pkotlin.native.cocoapods.generate.wrapper=true").checks { @@ -728,8 +678,8 @@ class ResourcesTest : GradlePluginTestBase() { check.taskSkipped(":linkDebugTestIosX64") } gradle(":copyTestComposeResourcesForIosX64").checks { - file("build/bin/iosX64/debugTest/compose-resources/drawable/compose-multiplatform.xml").checkExists() - file("build/bin/iosX64/debugTest/compose-resources/drawable/icon.xml").checkExists() + file("build/bin/iosX64/debugTest/compose-resources/composeResources/iosresources.generated.resources/drawable/compose-multiplatform.xml").checkExists() + file("build/bin/iosX64/debugTest/compose-resources/composeResources/iosresources.generated.resources/drawable/icon.xml").checkExists() } } } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/UnsupportedCompilerPluginWarningTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/UnsupportedCompilerPluginWarningTest.kt deleted file mode 100644 index 36ee19a06a..0000000000 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/UnsupportedCompilerPluginWarningTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -package org.jetbrains.compose.test.tests.integration - -import org.jetbrains.compose.createWarningAboutNonCompatibleCompiler -import org.jetbrains.compose.test.utils.GradlePluginTestBase -import org.jetbrains.compose.test.utils.TestProjects -import org.jetbrains.compose.test.utils.checks -import org.junit.jupiter.api.Test - -class UnsupportedCompilerPluginWarningTest : GradlePluginTestBase() { - - private val androidxComposeCompilerGroupId = "androidx.compose.compiler" - private val androidxComposeCompilerPlugin = "$androidxComposeCompilerGroupId:compiler:1.4.8" - - private fun testCustomCompilerUnsupportedPlatformsWarning( - platforms: String, - warningIsExpected: Boolean - ) { - testProject( - TestProjects.customCompilerUnsupportedPlatformsWarning, defaultTestEnvironment.copy( - kotlinVersion = "1.8.22", - composeCompilerPlugin = "\"$androidxComposeCompilerPlugin\"", - ) - ).apply { - // repeat twice to check that configuration cache hit does not affect the result - repeat(2) { - gradle("-Pplatforms=$platforms").checks { - val warning = createWarningAboutNonCompatibleCompiler(androidxComposeCompilerGroupId) - if (warningIsExpected) { - check.logContainsOnce(warning) - } else { - check.logDoesntContain(warning) - } - } - } - } - } - - @Test - fun testJs() { - testCustomCompilerUnsupportedPlatformsWarning("js", warningIsExpected = true) - } - - @Test - fun testIos() { - testCustomCompilerUnsupportedPlatformsWarning("ios", warningIsExpected = true) - } - - @Test - fun testJvm() { - testCustomCompilerUnsupportedPlatformsWarning("jvm", warningIsExpected = false) - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/unit/ComposeCompilerArtifactProviderTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/unit/ComposeCompilerArtifactProviderTest.kt index eb9e2e7879..d6d93797ff 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/unit/ComposeCompilerArtifactProviderTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/unit/ComposeCompilerArtifactProviderTest.kt @@ -7,12 +7,10 @@ package org.jetbrains.compose.test.tests.unit import org.jetbrains.compose.internal.ComposeCompilerArtifactProvider import org.jetbrains.compose.internal.copy -import org.jetbrains.compose.test.utils.TestProperties import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.Assertions.* - internal class ComposeCompilerArtifactProviderTest { @Test fun customVersion() { @@ -69,12 +67,9 @@ internal class ComposeCompilerArtifactProviderTest { get() = SubpluginArtifact( groupId = "org.jetbrains.compose.compiler", artifactId = "compiler", - version = TestProperties.composeCompilerVersion + version = "1.9.20" ) - val jbCompilerHosted: SubpluginArtifact - get() = jbCompiler.copy(artifactId = "compiler-hosted") - val googleCompiler: SubpluginArtifact get() = jbCompiler.copy(groupId = "androidx.compose.compiler") } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/GradleTestNameGenerator.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/GradleTestNameGenerator.kt index cfb9b0984a..760db9d166 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/GradleTestNameGenerator.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/GradleTestNameGenerator.kt @@ -13,7 +13,7 @@ class GradleTestNameGenerator : DisplayNameGenerator.Standard() { override fun generateDisplayNameForMethod(testClass: Class<*>, testMethod: Method) = testMethod.name + with(TestProperties) { mutableListOf().apply { - muteException { add("kotlin=$composeCompilerCompatibleKotlinVersion") } + muteException { add("kotlin=$kotlinVersion") } muteException { add("gradle=$gradleVersion") } muteException { add("agp=$agpVersion") } }.joinToString(prefix = "(", separator = ", ", postfix = ")") diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt index a48097a094..c8db18f955 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt @@ -9,14 +9,12 @@ import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.util.GradleVersion import org.jetbrains.compose.desktop.application.internal.ComposeProperties -import org.junit.jupiter.params.provider.Arguments import java.io.File -import java.util.Properties -import java.util.stream.Stream +import java.util.* data class TestEnvironment( val workingDir: File, - val kotlinVersion: String = TestProperties.composeCompilerCompatibleKotlinVersion, + val kotlinVersion: String = TestProperties.kotlinVersion, val gradleVersion: String = TestProperties.gradleVersion, val agpVersion: String = TestProperties.agpVersion, val composeGradlePluginVersion: String = TestProperties.composeGradlePluginVersion, diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProjects.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProjects.kt deleted file mode 100644 index 24f59310ed..0000000000 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProjects.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.test.utils - -object TestProjects { - const val jvm = "application/jvm" - const val mpp = "application/mpp" - const val newAndroidTarget = "application/newAndroidTarget" - const val proguard = "application/proguard" - const val customCompiler = "application/custom-compiler" - const val customCompilerArgs = "application/custom-compiler-args" - const val customCompilerUnsupportedPlatformsWarning = "application/customCompilerUnsupportedPlatformsWarning" - const val jvmKotlinDsl = "application/jvmKotlinDsl" - const val moduleClashCli = "application/moduleClashCli" - const val javaLogger = "application/javaLogger" - const val macOptions = "application/macOptions" - const val macSign = "application/macSign" - const val optionsWithSpaces = "application/optionsWithSpaces" - const val defaultArgs = "application/defaultArgs" - const val defaultArgsOverride = "application/defaultArgsOverride" - const val unpackSkiko = "application/unpackSkiko" - const val resources = "application/resources" - const val jsMpp = "misc/jsMpp" - const val skikoWasm = "misc/skikoWasm" - const val jvmPreview = "misc/jvmPreview" - const val iosResources = "misc/iosResources" - const val iosMokoResources = "misc/iosMokoResources" - const val nativeCacheKind = "misc/nativeCacheKind" - const val nativeCacheKindError = "misc/nativeCacheKindError" -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt index 11caa75036..3f4be6cbb8 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt @@ -8,14 +8,8 @@ package org.jetbrains.compose.test.utils import java.io.File object TestProperties { - val composeCompilerVersion: String - get() = notNullSystemProperty("compose.tests.compiler.version") - - val composeCompilerCompatibleKotlinVersion: String - get() = notNullSystemProperty("compose.tests.compiler.compatible.kotlin.version") - - val composeJsCompilerCompatibleKotlinVersion: String - get() = notNullSystemProperty("compose.tests.js.compiler.compatible.kotlin.version") + val kotlinVersion: String + get() = notNullSystemProperty("compose.tests.kotlin.version") val composeGradlePluginVersion: String get() = notNullSystemProperty("compose.tests.compose.gradle.plugin.version") diff --git a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/build.gradle deleted file mode 100644 index 04c2be309b..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.multiplatform" - id "org.jetbrains.compose" -} - -kotlin { - def platforms = project.property("platforms").split(",") - if (platforms.contains("jvm")) { - jvm() - } - if (platforms.contains("js")) { - js(IR) { - browser() - binaries.executable() - } - } - if (platforms.contains("ios")) { - ios() - } - - sourceSets { - commonMain { - dependencies { - implementation compose.runtime - implementation compose.material - implementation compose.foundation - } - } - } -} - -compose { - kotlinCompilerPlugin.set(COMPOSE_COMPILER_PLUGIN_PLACEHOLDER) -} diff --git a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/gradle.properties b/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/gradle.properties deleted file mode 100644 index e209558321..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.jetbrains.compose.experimental.jscanvas.enabled=true -org.jetbrains.compose.experimental.uikit.enabled=true \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/settings.gradle deleted file mode 100644 index fe85d46d01..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/settings.gradle +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - plugins { - id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' - id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' - } - repositories { - mavenLocal() - gradlePluginPortal() - mavenCentral() - google() - maven { - url 'https://maven.pkg.jetbrains.space/public/p/compose/dev' - } - } -} -dependencyResolutionManagement { - repositories { - mavenLocal() - mavenCentral() - google() - maven { - url 'https://maven.pkg.jetbrains.space/public/p/compose/dev' - } - } -} -rootProject.name = "customCompilerUnsupportedPlatformsWarning" diff --git a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/src/commonMain/kotlin/App.kt b/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/src/commonMain/kotlin/App.kt deleted file mode 100644 index 79dcb39588..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/application/customCompilerUnsupportedPlatformsWarning/src/commonMain/kotlin/App.kt +++ /dev/null @@ -1,19 +0,0 @@ -import androidx.compose.material.Button -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember - -@Composable -fun App() { - MaterialTheme { - var message by remember { mutableStateOf("Press the button!") } - - Button( - onClick = { message = "Welcome to Compose Multiplatform!" } - ) { - Text(message) - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/build.gradle index 9d1d21d1cd..0cd904a78f 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/settings.gradle index 1531cffa13..f87e919ea2 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/defaultArgs/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/build.gradle index 427b63b1ad..af907c4297 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/settings.gradle index 1531cffa13..f87e919ea2 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/defaultArgsOverride/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/javaLogger/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/javaLogger/build.gradle index 87fbb5d4de..28b9e0c623 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/javaLogger/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/javaLogger/build.gradle @@ -1,5 +1,6 @@ plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/javaLogger/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/javaLogger/settings.gradle index de29cd8544..78832dc01a 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/javaLogger/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/javaLogger/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/jvm/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/jvm/build.gradle index 4ac0b9f8b2..6b93854d0c 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/jvm/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/jvm/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/jvm/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/jvm/settings.gradle index 9df72a09ce..6d72c98406 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/jvm/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/jvm/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/build.gradle.kts index c8f6ac82b5..3a3c5aa20f 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/build.gradle.kts @@ -3,6 +3,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.compose") } diff --git a/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/settings.gradle index 9df72a09ce..6d72c98406 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/jvmKotlinDsl/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/Expected-Info.plist b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Expected-Info.plist index a54a6e2a56..9f703cf88c 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/macOptions/Expected-Info.plist +++ b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Expected-Info.plist @@ -1,48 +1,123 @@ - - LSMinimumSystemVersion - 12.0 - CFBundleDevelopmentRegion - English - CFBundleAllowMixedLocalizations - true - CFBundleExecutable - TestPackage - CFBundleIconFile - TestPackage.icns - CFBundleIdentifier - MainKt - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - TestPackage - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0.0 - LSApplicationCategoryType - Unknown - CFBundleVersion - 1.0.0 - NSHumanReadableCopyright - Copyright (C) CURRENT_YEAR - NSSupportsAutomaticGraphicsSwitching - true - NSHighResolutionCapable - true + + LSMinimumSystemVersion + 12.0 + CFBundleDevelopmentRegion + English + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + TestPackage + CFBundleIconFile + TestPackage.icns + CFBundleIdentifier + MainKt + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + TestPackage + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + LSApplicationCategoryType + Unknown + CFBundleVersion + 1.0.0 + NSHumanReadableCopyright + Copyright (C) CURRENT_YEAR + NSSupportsAutomaticGraphicsSwitching + true + NSHighResolutionCapable + true + CFBundleDocumentTypes + + + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + kot + + CFBundleTypeIconFile + Kotlin_icon_big.icns + CFBundleTypeMIMETypes + text/kotlin + CFBundleTypeName + Kotlin Source File0 + CFBundleTypeOSTypes + + **** + + + + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + kot1 + + CFBundleTypeIconFile + TestPackage.icns + CFBundleTypeMIMETypes + text/kotlin + CFBundleTypeName + Kotlin Source File1 + CFBundleTypeOSTypes + + **** + + + + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + kott + + CFBundleTypeIconFile + Kotlin_icon_big (1).icns + CFBundleTypeMIMETypes + text/kotlin + CFBundleTypeName + Kotlin Source File2 + CFBundleTypeOSTypes + + **** + + + + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + kott1 + + CFBundleTypeIconFile + TestPackage.icns + CFBundleTypeMIMETypes + text/kotlin + CFBundleTypeName + Kotlin Source File3 + CFBundleTypeOSTypes + + **** + + + - CFBundleURLTypes - - - CFBundleURLName - Exameple URL - CFBundleURLSchemes - - exampleUrl - - - - + CFBundleURLTypes + + + CFBundleURLName + Example URL + CFBundleURLSchemes + + exampleUrl + + + + diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.icns b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.icns new file mode 100644 index 0000000000..fedf6a3f2f Binary files /dev/null and b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.icns differ diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.ico b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.ico new file mode 100644 index 0000000000..3e9c11bb6d Binary files /dev/null and b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.ico differ diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.png b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.png new file mode 100644 index 0000000000..1f93755e75 Binary files /dev/null and b/gradle-plugins/compose/src/test/test-projects/application/macOptions/Kotlin_icon_big.png differ diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/macOptions/build.gradle index 122189c034..754636aa75 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/macOptions/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/macOptions/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } @@ -11,29 +10,53 @@ dependencies { } def extraInfoPlistKeys = """ - CFBundleURLTypes - - - CFBundleURLName - Exameple URL - CFBundleURLSchemes - - exampleUrl - - - """ + CFBundleURLTypes + + + CFBundleURLName + Example URL + CFBundleURLSchemes + + exampleUrl + + + """ compose.desktop { application { mainClass = "MainKt" nativeDistributions { packageName = "TestPackage" + fileAssociation( + "text/kotlin", + "kot", + "Kotlin Source File0", + project.file("Kotlin_icon_big.png"), + project.file("Kotlin_icon_big.ico"), + project.file("Kotlin_icon_big.icns"), + ) + fileAssociation( + "text/kotlin", + "kot1", + "Kotlin Source File1", + ) macOS { dockName = "CustomDockName" minimumSystemVersion = "12.0" infoPlist { extraKeysRawXml = extraInfoPlistKeys } + fileAssociation( + "text/kotlin", + "kott", + "Kotlin Source File2", + project.file("subdir/Kotlin_icon_big.icns"), + ) + fileAssociation( + "text/kotlin", + "kott1", + "Kotlin Source File3", + ) } } } diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/macOptions/settings.gradle index 1531cffa13..f87e919ea2 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/macOptions/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/macOptions/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/macOptions/subdir/Kotlin_icon_big.icns b/gradle-plugins/compose/src/test/test-projects/application/macOptions/subdir/Kotlin_icon_big.icns new file mode 100644 index 0000000000..fedf6a3f2f Binary files /dev/null and b/gradle-plugins/compose/src/test/test-projects/application/macOptions/subdir/Kotlin_icon_big.icns differ diff --git a/gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle index 25af20375d..0f1ab82832 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle index 1531cffa13..f87e919ea2 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/app/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/app/build.gradle index 6791935473..7265e9830d 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/app/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/app/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/settings.gradle index 89f91ba82f..4e3e135f88 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/moduleClashCli/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle index 33fc77b284..b4a447b868 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle @@ -3,6 +3,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "com.android.application" id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } @@ -21,6 +22,9 @@ kotlin { } } } + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } } android { @@ -33,14 +37,6 @@ android { } } -kotlin { - jvm { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(11)) - } - } -} - compose.desktop { application { mainClass = "MainKt" diff --git a/gradle-plugins/compose/src/test/test-projects/application/mpp/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/mpp/settings.gradle index 0276bf4c39..96b75d539d 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/mpp/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/mpp/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' id 'com.android.application' version 'AGP_VERSION_PLACEHOLDER' } diff --git a/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/build.gradle index 33188819c9..ef45b4a99e 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.compose" id "com.android.kotlin.multiplatform.library" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/settings.gradle index 142c0d28b4..86985a3b8e 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/newAndroidTarget/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' id 'com.android.kotlin.multiplatform.library' version '8.2.0-alpha13' } diff --git a/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/build.gradle index f0df53799f..2451e05bed 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/settings.gradle index 1531cffa13..f87e919ea2 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/optionsWithSpaces/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/proguard/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/proguard/build.gradle index 7fe038689d..4b3f792180 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/proguard/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/proguard/build.gradle @@ -3,6 +3,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/proguard/main-methods.expected.txt b/gradle-plugins/compose/src/test/test-projects/application/proguard/main-methods.expected.txt index 3fc7a4f8c7..2932270c74 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/proguard/main-methods.expected.txt +++ b/gradle-plugins/compose/src/test/test-projects/application/proguard/main-methods.expected.txt @@ -1,3 +1,5 @@ keptByKeepRule +keptByKeepRule$lambda$5 main -mainShape \ No newline at end of file +mainShape +mainShape$lambda$2 \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/application/proguard/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/proguard/settings.gradle index 9df72a09ce..6d72c98406 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/proguard/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/proguard/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/resources/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/resources/build.gradle index 9db2a01e22..616c3825c7 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/resources/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/resources/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/resources/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/resources/settings.gradle index 9df72a09ce..6d72c98406 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/resources/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/resources/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/build.gradle index d49191985c..2ccc034b0f 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/build.gradle @@ -2,6 +2,7 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/settings.gradle b/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/settings.gradle index 9df72a09ce..6d72c98406 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/unpackSkiko/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/build.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/build.gradle similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/build.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/build.gradle diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/main-image.expected.png b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/main-image.expected.png similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/main-image.expected.png rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/main-image.expected.png diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/settings.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/settings.gradle similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/settings.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/settings.gradle diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/src/desktopMain/kotlin/Main.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/src/desktopMain/kotlin/Main.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/src/desktopMain/kotlin/Main.kt rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/src/desktopMain/kotlin/Main.kt diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/src/jsMain/kotlin/Main.js.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/src/jsMain/kotlin/Main.js.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler-args/src/jsMain/kotlin/Main.js.kt rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler-args/src/jsMain/kotlin/Main.js.kt diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler/build.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/build.gradle similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler/build.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/build.gradle diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler/main-image.expected.png b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/main-image.expected.png similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler/main-image.expected.png rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/main-image.expected.png diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler/settings.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/settings.gradle similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler/settings.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/settings.gradle diff --git a/gradle-plugins/compose/src/test/test-projects/application/custom-compiler/src/main/kotlin/Main.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/src/main/kotlin/Main.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/custom-compiler/src/main/kotlin/Main.kt rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/custom-compiler/src/main/kotlin/Main.kt diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/build.gradle new file mode 100644 index 0000000000..348b3a4b80 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/build.gradle @@ -0,0 +1,27 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.compose" +} + +kotlin { + js(IR) { + browser() + } + jvm {} + + sourceSets { + named("commonMain") { + } + named("jsMain") { + dependencies { + implementation(compose.html.core) + implementation(compose.runtime) + } + } + named("jvmMain") { + dependencies { + implementation(compose.desktop.currentOs) + } + } + } +} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/settings.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/settings.gradle similarity index 91% rename from gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/settings.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/settings.gradle index 5a99487916..afca8638e9 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/settings.gradle @@ -15,13 +15,12 @@ pluginManagement { } dependencyResolutionManagement { repositories { - mavenCentral() mavenLocal() + mavenCentral() google() maven { url 'https://maven.pkg.jetbrains.space/public/p/compose/dev' } } } -rootProject.name = "nativeCacheKind" -include(":subproject") \ No newline at end of file +rootProject.name = "jsMpp" \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/commonMain/kotlin/platform.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/commonMain/kotlin/platform.kt new file mode 100644 index 0000000000..f60eab5ff6 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/commonMain/kotlin/platform.kt @@ -0,0 +1 @@ +expect fun getPlatformName(): String \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jsMain/kotlin/platform.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jsMain/kotlin/platform.kt new file mode 100644 index 0000000000..b6d4a07a09 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jsMain/kotlin/platform.kt @@ -0,0 +1 @@ +actual fun getPlatformName(): String = "js" \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jvmMain/kotlin/platform.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jvmMain/kotlin/platform.kt new file mode 100644 index 0000000000..144ba29291 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/jsMpp/src/jvmMain/kotlin/platform.kt @@ -0,0 +1 @@ +actual fun getPlatformName(): String = "jvm" \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/build.gradle new file mode 100644 index 0000000000..33fc77b284 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/build.gradle @@ -0,0 +1,73 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + id "com.android.application" + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.compose" +} + +kotlin { + // empty stub (no actual android app) to detect configuration conflicts + // like https://github.com/JetBrains/compose-jb/issues/2345 + android() + + jvm() + sourceSets { + jvmMain { + dependsOn(commonMain) + + dependencies { + implementation(compose.desktop.currentOs) + } + } + } +} + +android { + namespace = "org.jetbrains.compose.testapp" + compileSdk = 31 + + defaultConfig { + minSdk = 21 + targetSdk = 31 + } +} + +kotlin { + jvm { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } + } +} + +compose.desktop { + application { + mainClass = "MainKt" + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + + packageVersion = "1.0.0" + packageName = "TestPackage" + description = "Test description" + copyright = "Test Copyright Holder" + vendor = "Test Vendor" + + linux { + shortcut = true + packageName = "test-package" + debMaintainer = "example@example.com" + menuGroup = "menu-group" + } + windows { + console = true + dirChooser = true + perUserInstall = true + shortcut = true + menu = true + menuGroup = "compose" + upgradeUuid = "2d6ff464-75be-40ad-a256-56420b9cc374" + } + } + } +} diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/gradle.properties b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/gradle.properties new file mode 100644 index 0000000000..2d8d1e4dd1 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX=true \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/settings.gradle b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/settings.gradle similarity index 68% rename from gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/settings.gradle rename to gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/settings.gradle index 5717a21c96..0276bf4c39 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/settings.gradle @@ -2,6 +2,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' + id 'com.android.application' version 'AGP_VERSION_PLACEHOLDER' } repositories { mavenLocal() @@ -11,6 +12,9 @@ pluginManagement { maven { url 'https://maven.pkg.jetbrains.space/public/p/compose/dev' } + maven { + url 'https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/' + } } } dependencyResolutionManagement { @@ -21,7 +25,9 @@ dependencyResolutionManagement { maven { url 'https://maven.pkg.jetbrains.space/public/p/compose/dev' } + maven { + url 'https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/' + } } } -rootProject.name = "nativeCacheKind" -include(":subproject") \ No newline at end of file +rootProject.name = "mpp" \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/src/jvmMain/kotlin/main.kt b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/src/jvmMain/kotlin/main.kt new file mode 100644 index 0000000000..4d7210e2be --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/beforeKotlin2/mpp/src/jvmMain/kotlin/main.kt @@ -0,0 +1,3 @@ +fun main() { + println("Kotlin MPP app is running!") +} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/app/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/app/build.gradle.kts index 5e0fd3e9fa..c139eff8a7 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/app/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/app/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("multiplatform") + kotlin("plugin.compose") id("org.jetbrains.compose") id("com.github.gmazzo.buildconfig") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/build.gradle.kts index 53f913fce7..f31c0a79f5 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/build.gradle.kts @@ -1,4 +1,5 @@ plugins { kotlin("multiplatform").apply(false) + kotlin("plugin.compose").apply(false) id("org.jetbrains.compose").apply(false) } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/settings.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/settings.gradle.kts index af0c57f19b..30b8363492 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/settings.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/bundledKotlinPoet/settings.gradle.kts @@ -9,6 +9,7 @@ pluginManagement { } plugins { id("org.jetbrains.kotlin.multiplatform").version("KOTLIN_VERSION_PLACEHOLDER") + id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") id("com.github.gmazzo.buildconfig").version("5.3.5") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts index beda4225bf..5629e0ad3e 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("multiplatform") + kotlin("plugin.compose") id("com.android.application") id("org.jetbrains.compose") } @@ -9,8 +10,10 @@ group = "app.group" kotlin { androidTarget { compilations.all { - kotlinOptions { - jvmTarget = "11" + compileTaskProvider { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) + } } } } @@ -62,3 +65,31 @@ android { targetCompatibility = JavaVersion.VERSION_11 } } + +abstract class GenerateAndroidRes : DefaultTask() { + @get:Inject + abstract val layout: ProjectLayout + + @get:OutputDirectory + val outputDir = layout.buildDirectory.dir("generatedAndroidResources") + + @TaskAction + fun run() { + val dir = outputDir.get().asFile + dir.deleteRecursively() + File(dir, "values/strings.xml").apply { + parentFile.mkdirs() + writeText( + """ + + Android string + + """.trimIndent() + ) + } + } +} +compose.resources.customDirectory( + sourceSetName = "androidMain", + directoryProvider = tasks.register("generateAndroidRes").map { it.outputDir.get() } +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt index 4c07207da0..9d1d0e7a42 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt @@ -3,20 +3,28 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object AndroidMainString0 { - public val android_str: StringResource by - lazy { init_android_str() } + public val android_str: StringResource by + lazy { init_android_str() } +} + +@InternalResourceApi +internal fun _collectAndroidMainString0Resources(map: MutableMap) { + map.put("android_str", AndroidMainString0.android_str) } public val Res.string.android_str: StringResource - get() = AndroidMainString0.android_str + get() = AndroidMainString0.android_str private fun init_android_str(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:android_str", "android_str", + "string:android_str", "android_str", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.androidMain.cvr", 10, - 39), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.androidMain.cvr", 10, 39), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt new file mode 100644 index 0000000000..9f91d73840 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt @@ -0,0 +1,53 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package my.lib.res + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +public actual val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainDrawable0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + _collectAndroidMainString0Resources(map) + _collectCommonMainString0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainPlurals0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainFont0Resources(map) + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt index 408e508f37..060e66ad48 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt @@ -3,65 +3,95 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.InternalResourceApi private object CommonMainDrawable0 { - public val _3_strange_name: DrawableResource by - lazy { init__3_strange_name() } + public val _3_strange_name: DrawableResource by + lazy { init__3_strange_name() } - public val camelCaseName: DrawableResource by - lazy { init_camelCaseName() } + public val camelCaseName: DrawableResource by + lazy { init_camelCaseName() } - public val vector: DrawableResource by - lazy { init_vector() } + public val `is`: DrawableResource by + lazy { init_is() } - public val vector_2: DrawableResource by - lazy { init_vector_2() } + public val vector: DrawableResource by + lazy { init_vector() } + + public val vector_2: DrawableResource by + lazy { init_vector_2() } +} + +@InternalResourceApi +internal fun _collectCommonMainDrawable0Resources(map: MutableMap) { + map.put("_3_strange_name", CommonMainDrawable0._3_strange_name) + map.put("camelCaseName", CommonMainDrawable0.camelCaseName) + map.put("is", CommonMainDrawable0.`is`) + map.put("vector", CommonMainDrawable0.vector) + map.put("vector_2", CommonMainDrawable0.vector_2) } public val Res.drawable._3_strange_name: DrawableResource get() = CommonMainDrawable0._3_strange_name private fun init__3_strange_name(): DrawableResource = - org.jetbrains.compose.resources.DrawableResource( - "drawable:_3_strange_name", + org.jetbrains.compose.resources.DrawableResource( + "drawable:_3_strange_name", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/3-strange-name.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/drawable/3-strange-name.xml", -1, -1), ) - ) +) public val Res.drawable.camelCaseName: DrawableResource get() = CommonMainDrawable0.camelCaseName private fun init_camelCaseName(): DrawableResource = - org.jetbrains.compose.resources.DrawableResource( - "drawable:camelCaseName", + org.jetbrains.compose.resources.DrawableResource( + "drawable:camelCaseName", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/drawable/camelCaseName.xml", -1, -1), + ) +) + +public val Res.drawable.`is`: DrawableResource + get() = CommonMainDrawable0.`is` + +private fun init_is(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( + "drawable:is", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/camelCaseName.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/drawable/is.xml", -1, -1), ) - ) +) public val Res.drawable.vector: DrawableResource get() = CommonMainDrawable0.vector private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( "drawable:vector", - setOf( - + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("ast"), - ), "drawable-ast/vector.xml", -1, -1), - + ), "composeResources/my.lib.res/drawable-ast/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("au"), - org.jetbrains.compose.resources.RegionQualifier("US"), ), "drawable-au-rUS/vector.xml", -1, -1), - + org.jetbrains.compose.resources.RegionQualifier("US"), ), + "composeResources/my.lib.res/drawable-au-rUS/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.ThemeQualifier.DARK, - org.jetbrains.compose.resources.LanguageQualifier("ge"), ), - "drawable-dark-ge/vector.xml", -1, -1), - + org.jetbrains.compose.resources.LanguageQualifier("ge"), ), + "composeResources/my.lib.res/drawable-dark-ge/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("en"), - ), "drawable-en/vector.xml", -1, -1), - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector.xml", -1, -1), - ) + ), "composeResources/my.lib.res/drawable-en/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/drawable/vector.xml", -1, -1), + ) ) public val Res.drawable.vector_2: DrawableResource @@ -69,7 +99,8 @@ public val Res.drawable.vector_2: DrawableResource private fun init_vector_2(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( "drawable:vector_2", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector_2.xml", -1, -1), - ) -) \ No newline at end of file + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/drawable/vector_2.xml", -1, -1), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt index 1d69a111bb..f6e1193540 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt @@ -3,11 +3,19 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.InternalResourceApi private object CommonMainFont0 { - public val emptyFont: FontResource by - lazy { init_emptyFont() } + public val emptyFont: FontResource by + lazy { init_emptyFont() } +} + +@InternalResourceApi +internal fun _collectCommonMainFont0Resources(map: MutableMap) { + map.put("emptyFont", CommonMainFont0.emptyFont) } public val Res.font.emptyFont: FontResource @@ -15,10 +23,11 @@ public val Res.font.emptyFont: FontResource private fun init_emptyFont(): FontResource = org.jetbrains.compose.resources.FontResource( "font:emptyFont", - setOf( - + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("en"), - ), "font-en/emptyFont.otf", -1, -1), - org.jetbrains.compose.resources.ResourceItem(setOf(), "font/emptyFont.otf", -1, -1), - ) -) \ No newline at end of file + ), "composeResources/my.lib.res/font-en/emptyFont.otf", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/font/emptyFont.otf", -1, -1), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt index 95ecbbca59..7a397b4235 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt @@ -3,21 +3,29 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.PluralStringResource private object CommonMainPlurals0 { - public val numberOfSongsAvailable: PluralStringResource by - lazy { init_numberOfSongsAvailable() } + public val numberOfSongsAvailable: PluralStringResource by + lazy { init_numberOfSongsAvailable() } +} + +@InternalResourceApi +internal fun _collectCommonMainPlurals0Resources(map: MutableMap) { + map.put("numberOfSongsAvailable", CommonMainPlurals0.numberOfSongsAvailable) } public val Res.plurals.numberOfSongsAvailable: PluralStringResource - get() = CommonMainPlurals0.numberOfSongsAvailable + get() = CommonMainPlurals0.numberOfSongsAvailable private fun init_numberOfSongsAvailable(): PluralStringResource = org.jetbrains.compose.resources.PluralStringResource( - "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 10, - 124), - ) - ) \ No newline at end of file + "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 10, 124), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt index d3a70bb1f2..49fa3f8a39 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt @@ -3,29 +3,47 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object CommonMainString0 { - public val PascalCase: StringResource by - lazy { init_PascalCase() } + public val PascalCase: StringResource by + lazy { init_PascalCase() } - public val _1_kebab_case: StringResource by - lazy { init__1_kebab_case() } + public val _1_kebab_case: StringResource by + lazy { init__1_kebab_case() } - public val app_name: StringResource by - lazy { init_app_name() } + public val app_name: StringResource by + lazy { init_app_name() } - public val camelCase: StringResource by - lazy { init_camelCase() } + public val camelCase: StringResource by + lazy { init_camelCase() } - public val hello: StringResource by - lazy { init_hello() } + public val hello: StringResource by + lazy { init_hello() } - public val multi_line: StringResource by - lazy { init_multi_line() } + public val `info_using_release_$x`: StringResource by + lazy { `init_info_using_release_$x`() } - public val str_template: StringResource by - lazy { init_str_template() } + public val multi_line: StringResource by + lazy { init_multi_line() } + + public val str_template: StringResource by + lazy { init_str_template() } +} + +@InternalResourceApi +internal fun _collectCommonMainString0Resources(map: MutableMap) { + map.put("PascalCase", CommonMainString0.PascalCase) + map.put("_1_kebab_case", CommonMainString0._1_kebab_case) + map.put("app_name", CommonMainString0.app_name) + map.put("camelCase", CommonMainString0.camelCase) + map.put("hello", CommonMainString0.hello) + map.put("info_using_release_${'$'}x", CommonMainString0.`info_using_release_$x`) + map.put("multi_line", CommonMainString0.multi_line) + map.put("str_template", CommonMainString0.str_template) } public val Res.string.PascalCase: StringResource @@ -33,10 +51,10 @@ public val Res.string.PascalCase: StringResource private fun init_PascalCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:PascalCase", "PascalCase", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 172, - 34), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 172, 34), + ) ) public val Res.string._1_kebab_case: StringResource @@ -44,10 +62,10 @@ public val Res.string._1_kebab_case: StringResource private fun init__1_kebab_case(): StringResource = org.jetbrains.compose.resources.StringResource( "string:_1_kebab_case", "_1_kebab_case", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 135, - 36), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 135, 36), + ) ) public val Res.string.app_name: StringResource @@ -55,10 +73,10 @@ public val Res.string.app_name: StringResource private fun init_app_name(): StringResource = org.jetbrains.compose.resources.StringResource( "string:app_name", "app_name", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 207, - 44), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 207, 44), + ) ) public val Res.string.camelCase: StringResource @@ -66,10 +84,10 @@ public val Res.string.camelCase: StringResource private fun init_camelCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:camelCase", "camelCase", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 252, - 29), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 252, 29), + ) ) public val Res.string.hello: StringResource @@ -77,10 +95,22 @@ public val Res.string.hello: StringResource private fun init_hello(): StringResource = org.jetbrains.compose.resources.StringResource( "string:hello", "hello", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 282, - 37), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 282, 37), + ) +) + +public val Res.string.`info_using_release_$x`: StringResource + get() = CommonMainString0.`info_using_release_$x` + +private fun `init_info_using_release_$x`(): StringResource = + org.jetbrains.compose.resources.StringResource( + "string:info_using_release_${'$'}x", "info_using_release_${'$'}x", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 320, 57), + ) ) public val Res.string.multi_line: StringResource @@ -88,10 +118,10 @@ public val Res.string.multi_line: StringResource private fun init_multi_line(): StringResource = org.jetbrains.compose.resources.StringResource( "string:multi_line", "multi_line", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 320, - 178), - ) + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 378, 178), + ) ) public val Res.string.str_template: StringResource @@ -99,8 +129,8 @@ public val Res.string.str_template: StringResource private fun init_str_template(): StringResource = org.jetbrains.compose.resources.StringResource( "string:str_template", "str_template", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 499, - 76), - ) -) \ No newline at end of file + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/strings.commonMain.cvr", 557, 76), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceCollectors/my/lib/res/ExpectResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceCollectors/my/lib/res/ExpectResourceCollectors.kt new file mode 100644 index 0000000000..6ea528da50 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceCollectors/my/lib/res/ExpectResourceCollectors.kt @@ -0,0 +1,25 @@ +package my.lib.res + +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +public expect val Res.allDrawableResources: Map + +@ExperimentalResourceApi +public expect val Res.allStringResources: Map + +@ExperimentalResourceApi +public expect val Res.allStringArrayResources: Map + +@ExperimentalResourceApi +public expect val Res.allPluralStringResources: Map + +@ExperimentalResourceApi +public expect val Res.allFontResources: Map diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt index e5a1409634..1cfbcd76e6 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt @@ -22,7 +22,8 @@ public object Res { * @return The content of the file as a byte array. */ @ExperimentalResourceApi - public suspend fun readBytes(path: String): ByteArray = readResourceBytes("" + path) + public suspend fun readBytes(path: String): ByteArray = + readResourceBytes("composeResources/my.lib.res/" + path) /** * Returns the URI string of the resource file at the specified path. @@ -33,7 +34,7 @@ public object Res { * @return The URI string of the file. */ @ExperimentalResourceApi - public fun getUri(path: String): String = getResourceUri("" + path) + public fun getUri(path: String): String = getResourceUri("composeResources/my.lib.res/" + path) public object drawable @@ -44,4 +45,4 @@ public object Res { public object plurals public object font -} \ No newline at end of file +} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt index 4fcecd75b6..f3e28a5b40 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt @@ -3,20 +3,28 @@ package my.lib.res import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object DesktopMainString0 { - public val desktop_str: StringResource by - lazy { init_desktop_str() } + public val desktop_str: StringResource by + lazy { init_desktop_str() } +} + +@InternalResourceApi +internal fun _collectDesktopMainString0Resources(map: MutableMap) { + map.put("desktop_str", DesktopMainString0.desktop_str) } public val Res.string.desktop_str: StringResource - get() = DesktopMainString0.desktop_str + get() = DesktopMainString0.desktop_str private fun init_desktop_str(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:desktop_str", "desktop_str", + "string:desktop_str", "desktop_str", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), - "values/desktop_strings.desktopMain.cvr", 10, 39), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/my.lib.res/values/desktop_strings.desktopMain.cvr", 10, 39), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt new file mode 100644 index 0000000000..5b8690a54a --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceCollectors/my/lib/res/ActualResourceCollectors.kt @@ -0,0 +1,53 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package my.lib.res + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +public actual val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainDrawable0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + _collectDesktopMainString0Resources(map) + _collectCommonMainString0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainPlurals0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +public actual val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainFont0Resources(map) + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt index 98e0355454..020c0d9dce 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt @@ -3,20 +3,29 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object AndroidMainString0 { - public val android_str: StringResource by - lazy { init_android_str() } + public val android_str: StringResource by + lazy { init_android_str() } +} + +@InternalResourceApi +internal fun _collectAndroidMainString0Resources(map: MutableMap) { + map.put("android_str", AndroidMainString0.android_str) } internal val Res.string.android_str: StringResource - get() = AndroidMainString0.android_str + get() = AndroidMainString0.android_str private fun init_android_str(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:android_str", "android_str", + "string:android_str", "android_str", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.androidMain.cvr", 10, - 39), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.androidMain.cvr", + 10, 39), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt new file mode 100644 index 0000000000..b747b87218 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt @@ -0,0 +1,53 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package app.group.resources_test.generated.resources + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal actual val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainDrawable0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + _collectAndroidMainString0Resources(map) + _collectCommonMainString0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainPlurals0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainFont0Resources(map) + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt index 5e7a25ac0e..b648204784 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt @@ -3,65 +3,97 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.InternalResourceApi private object CommonMainDrawable0 { - public val _3_strange_name: DrawableResource by - lazy { init__3_strange_name() } + public val _3_strange_name: DrawableResource by + lazy { init__3_strange_name() } - public val camelCaseName: DrawableResource by - lazy { init_camelCaseName() } + public val camelCaseName: DrawableResource by + lazy { init_camelCaseName() } - public val vector: DrawableResource by - lazy { init_vector() } + public val `is`: DrawableResource by + lazy { init_is() } - public val vector_2: DrawableResource by - lazy { init_vector_2() } + public val vector: DrawableResource by + lazy { init_vector() } + + public val vector_2: DrawableResource by + lazy { init_vector_2() } +} + +@InternalResourceApi +internal fun _collectCommonMainDrawable0Resources(map: MutableMap) { + map.put("_3_strange_name", CommonMainDrawable0._3_strange_name) + map.put("camelCaseName", CommonMainDrawable0.camelCaseName) + map.put("is", CommonMainDrawable0.`is`) + map.put("vector", CommonMainDrawable0.vector) + map.put("vector_2", CommonMainDrawable0.vector_2) } internal val Res.drawable._3_strange_name: DrawableResource get() = CommonMainDrawable0._3_strange_name private fun init__3_strange_name(): DrawableResource = - org.jetbrains.compose.resources.DrawableResource( - "drawable:_3_strange_name", + org.jetbrains.compose.resources.DrawableResource( + "drawable:_3_strange_name", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/3-strange-name.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/drawable/3-strange-name.xml", -1, -1), ) - ) +) internal val Res.drawable.camelCaseName: DrawableResource get() = CommonMainDrawable0.camelCaseName private fun init_camelCaseName(): DrawableResource = - org.jetbrains.compose.resources.DrawableResource( - "drawable:camelCaseName", + org.jetbrains.compose.resources.DrawableResource( + "drawable:camelCaseName", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/drawable/camelCaseName.xml", -1, -1), + ) +) + +internal val Res.drawable.`is`: DrawableResource + get() = CommonMainDrawable0.`is` + +private fun init_is(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( + "drawable:is", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/camelCaseName.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/drawable/is.xml", -1, -1), ) - ) +) internal val Res.drawable.vector: DrawableResource get() = CommonMainDrawable0.vector private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( "drawable:vector", - setOf( - + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("ast"), - ), "drawable-ast/vector.xml", -1, -1), - + ), + "composeResources/app.group.resources_test.generated.resources/drawable-ast/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("au"), - org.jetbrains.compose.resources.RegionQualifier("US"), ), "drawable-au-rUS/vector.xml", -1, -1), - + org.jetbrains.compose.resources.RegionQualifier("US"), ), + "composeResources/app.group.resources_test.generated.resources/drawable-au-rUS/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.ThemeQualifier.DARK, - org.jetbrains.compose.resources.LanguageQualifier("ge"), ), - "drawable-dark-ge/vector.xml", -1, -1), - + org.jetbrains.compose.resources.LanguageQualifier("ge"), ), + "composeResources/app.group.resources_test.generated.resources/drawable-dark-ge/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("en"), - ), "drawable-en/vector.xml", -1, -1), - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector.xml", -1, -1), - ) + ), + "composeResources/app.group.resources_test.generated.resources/drawable-en/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/drawable/vector.xml", -1, -1), + ) ) internal val Res.drawable.vector_2: DrawableResource @@ -69,7 +101,8 @@ internal val Res.drawable.vector_2: DrawableResource private fun init_vector_2(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( "drawable:vector_2", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector_2.xml", -1, -1), - ) -) \ No newline at end of file + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/drawable/vector_2.xml", -1, -1), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt index 89ff6eb7b8..6f89aaafa0 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt @@ -3,11 +3,19 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.InternalResourceApi private object CommonMainFont0 { - public val emptyFont: FontResource by - lazy { init_emptyFont() } + public val emptyFont: FontResource by + lazy { init_emptyFont() } +} + +@InternalResourceApi +internal fun _collectCommonMainFont0Resources(map: MutableMap) { + map.put("emptyFont", CommonMainFont0.emptyFont) } internal val Res.font.emptyFont: FontResource @@ -15,10 +23,12 @@ internal val Res.font.emptyFont: FontResource private fun init_emptyFont(): FontResource = org.jetbrains.compose.resources.FontResource( "font:emptyFont", - setOf( - + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("en"), - ), "font-en/emptyFont.otf", -1, -1), - org.jetbrains.compose.resources.ResourceItem(setOf(), "font/emptyFont.otf", -1, -1), - ) -) \ No newline at end of file + ), + "composeResources/app.group.resources_test.generated.resources/font-en/emptyFont.otf", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/font/emptyFont.otf", -1, -1), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt index 9674a83744..c4c172ec20 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt @@ -3,21 +3,30 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.PluralStringResource private object CommonMainPlurals0 { - public val numberOfSongsAvailable: PluralStringResource by - lazy { init_numberOfSongsAvailable() } + public val numberOfSongsAvailable: PluralStringResource by + lazy { init_numberOfSongsAvailable() } +} + +@InternalResourceApi +internal fun _collectCommonMainPlurals0Resources(map: MutableMap) { + map.put("numberOfSongsAvailable", CommonMainPlurals0.numberOfSongsAvailable) } internal val Res.plurals.numberOfSongsAvailable: PluralStringResource - get() = CommonMainPlurals0.numberOfSongsAvailable + get() = CommonMainPlurals0.numberOfSongsAvailable private fun init_numberOfSongsAvailable(): PluralStringResource = org.jetbrains.compose.resources.PluralStringResource( - "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", - setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 10, - 124), - ) - ) \ No newline at end of file + "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 10, 124), + ) +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt index c57944b003..50ab7a156f 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt @@ -3,104 +3,142 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object CommonMainString0 { - public val PascalCase: StringResource by - lazy { init_PascalCase() } + public val PascalCase: StringResource by + lazy { init_PascalCase() } - public val _1_kebab_case: StringResource by - lazy { init__1_kebab_case() } + public val _1_kebab_case: StringResource by + lazy { init__1_kebab_case() } - public val app_name: StringResource by - lazy { init_app_name() } + public val app_name: StringResource by + lazy { init_app_name() } - public val camelCase: StringResource by - lazy { init_camelCase() } + public val camelCase: StringResource by + lazy { init_camelCase() } - public val hello: StringResource by - lazy { init_hello() } + public val hello: StringResource by + lazy { init_hello() } - public val multi_line: StringResource by - lazy { init_multi_line() } + public val `info_using_release_$x`: StringResource by + lazy { `init_info_using_release_$x`() } - public val str_template: StringResource by - lazy { init_str_template() } + public val multi_line: StringResource by + lazy { init_multi_line() } + + public val str_template: StringResource by + lazy { init_str_template() } +} + +@InternalResourceApi +internal fun _collectCommonMainString0Resources(map: MutableMap) { + map.put("PascalCase", CommonMainString0.PascalCase) + map.put("_1_kebab_case", CommonMainString0._1_kebab_case) + map.put("app_name", CommonMainString0.app_name) + map.put("camelCase", CommonMainString0.camelCase) + map.put("hello", CommonMainString0.hello) + map.put("info_using_release_${'$'}x", CommonMainString0.`info_using_release_$x`) + map.put("multi_line", CommonMainString0.multi_line) + map.put("str_template", CommonMainString0.str_template) } internal val Res.string.PascalCase: StringResource - get() = CommonMainString0.PascalCase + get() = CommonMainString0.PascalCase private fun init_PascalCase(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:PascalCase", "PascalCase", + "string:PascalCase", "PascalCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 172, - 34), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 172, 34), ) ) internal val Res.string._1_kebab_case: StringResource - get() = CommonMainString0._1_kebab_case + get() = CommonMainString0._1_kebab_case private fun init__1_kebab_case(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:_1_kebab_case", "_1_kebab_case", + "string:_1_kebab_case", "_1_kebab_case", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 135, - 36), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 135, 36), ) ) internal val Res.string.app_name: StringResource - get() = CommonMainString0.app_name + get() = CommonMainString0.app_name private fun init_app_name(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:app_name", "app_name", + "string:app_name", "app_name", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 207, - 44), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 207, 44), ) ) internal val Res.string.camelCase: StringResource - get() = CommonMainString0.camelCase + get() = CommonMainString0.camelCase private fun init_camelCase(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:camelCase", "camelCase", + "string:camelCase", "camelCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 252, - 29), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 252, 29), ) ) internal val Res.string.hello: StringResource - get() = CommonMainString0.hello + get() = CommonMainString0.hello private fun init_hello(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:hello", "hello", + "string:hello", "hello", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 282, - 37), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 282, 37), + ) +) + +internal val Res.string.`info_using_release_$x`: StringResource + get() = CommonMainString0.`info_using_release_$x` + +private fun `init_info_using_release_$x`(): StringResource = + org.jetbrains.compose.resources.StringResource( + "string:info_using_release_${'$'}x", "info_using_release_${'$'}x", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 320, 57), ) ) internal val Res.string.multi_line: StringResource - get() = CommonMainString0.multi_line + get() = CommonMainString0.multi_line private fun init_multi_line(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:multi_line", "multi_line", + "string:multi_line", "multi_line", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 320, - 178), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 378, 178), ) ) internal val Res.string.str_template: StringResource - get() = CommonMainString0.str_template + get() = CommonMainString0.str_template private fun init_str_template(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:str_template", "str_template", + "string:str_template", "str_template", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 499, - 76), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/strings.commonMain.cvr", + 557, 76), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceCollectors/app/group/resources_test/generated/resources/ExpectResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceCollectors/app/group/resources_test/generated/resources/ExpectResourceCollectors.kt new file mode 100644 index 0000000000..e287403867 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceCollectors/app/group/resources_test/generated/resources/ExpectResourceCollectors.kt @@ -0,0 +1,25 @@ +package app.group.resources_test.generated.resources + +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal expect val Res.allDrawableResources: Map + +@ExperimentalResourceApi +internal expect val Res.allStringResources: Map + +@ExperimentalResourceApi +internal expect val Res.allStringArrayResources: Map + +@ExperimentalResourceApi +internal expect val Res.allPluralStringResources: Map + +@ExperimentalResourceApi +internal expect val Res.allFontResources: Map diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt index 9b19cafa4c..73506c4d6d 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt @@ -22,7 +22,8 @@ internal object Res { * @return The content of the file as a byte array. */ @ExperimentalResourceApi - public suspend fun readBytes(path: String): ByteArray = readResourceBytes("" + path) + public suspend fun readBytes(path: String): ByteArray = + readResourceBytes("composeResources/app.group.resources_test.generated.resources/" + path) /** * Returns the URI string of the resource file at the specified path. @@ -33,7 +34,8 @@ internal object Res { * @return The URI string of the file. */ @ExperimentalResourceApi - public fun getUri(path: String): String = getResourceUri("" + path) + public fun getUri(path: String): String = + getResourceUri("composeResources/app.group.resources_test.generated.resources/" + path) public object drawable @@ -44,4 +46,4 @@ internal object Res { public object plurals public object font -} \ No newline at end of file +} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt index badfa7b5b2..2948107939 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt @@ -3,20 +3,29 @@ package app.group.resources_test.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap +import org.jetbrains.compose.resources.InternalResourceApi import org.jetbrains.compose.resources.StringResource private object DesktopMainString0 { - public val desktop_str: StringResource by - lazy { init_desktop_str() } + public val desktop_str: StringResource by + lazy { init_desktop_str() } +} + +@InternalResourceApi +internal fun _collectDesktopMainString0Resources(map: MutableMap) { + map.put("desktop_str", DesktopMainString0.desktop_str) } internal val Res.string.desktop_str: StringResource - get() = DesktopMainString0.desktop_str + get() = DesktopMainString0.desktop_str private fun init_desktop_str(): StringResource = org.jetbrains.compose.resources.StringResource( - "string:desktop_str", "desktop_str", + "string:desktop_str", "desktop_str", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), - "values/desktop_strings.desktopMain.cvr", 10, 39), + org.jetbrains.compose.resources.ResourceItem(setOf(), + "composeResources/app.group.resources_test.generated.resources/values/desktop_strings.desktopMain.cvr", + 10, 39), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt new file mode 100644 index 0000000000..d349d941b4 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceCollectors/app/group/resources_test/generated/resources/ActualResourceCollectors.kt @@ -0,0 +1,53 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package app.group.resources_test.generated.resources + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal actual val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainDrawable0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + _collectDesktopMainString0Resources(map) + _collectCommonMainString0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainPlurals0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + _collectCommonMainFont0Resources(map) + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/settings.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/settings.gradle.kts index 19b673273f..30b9d60bc6 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/settings.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/settings.gradle.kts @@ -9,6 +9,7 @@ pluginManagement { plugins { id("com.android.application").version("AGP_VERSION_PLACEHOLDER") id("org.jetbrains.kotlin.multiplatform").version("KOTLIN_VERSION_PLACEHOLDER") + id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") } } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml deleted file mode 100644 index 4855fd3e03..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Android string - \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/drawable/is.xml b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/drawable/is.xml new file mode 100644 index 0000000000..d7bf7955f4 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/drawable/is.xml @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/values/strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/values/strings.xml index 2afea688cf..06e9e90654 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/values/strings.xml +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/values/strings.xml @@ -8,6 +8,7 @@ PascalCase 1-kebab-case camelCase + info_using_release_$x %d zero diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/build.gradle.kts index 699c9aa0f2..f321450f7c 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("multiplatform") + kotlin("plugin.compose") id("org.jetbrains.compose") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/Res.kt deleted file mode 100644 index b6fbefa22e..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/Res.kt +++ /dev/null @@ -1,47 +0,0 @@ -@file:OptIn( - org.jetbrains.compose.resources.InternalResourceApi::class, - org.jetbrains.compose.resources.ExperimentalResourceApi::class, -) - -package app.group.empty_res.generated.resources - -import kotlin.ByteArray -import kotlin.OptIn -import kotlin.String -import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.getResourceUri -import org.jetbrains.compose.resources.readResourceBytes - -internal object Res { - /** - * Reads the content of the resource file at the specified path and returns it as a byte array. - * - * Example: `val bytes = Res.readBytes("files/key.bin")` - * - * @param path The path of the file to read in the compose resource's directory. - * @return The content of the file as a byte array. - */ - @ExperimentalResourceApi - public suspend fun readBytes(path: String): ByteArray = readResourceBytes("" + path) - - /** - * Returns the URI string of the resource file at the specified path. - * - * Example: `val uri = Res.getUri("files/key.bin")` - * - * @param path The path of the file in the compose resource's directory. - * @return The URI string of the file. - */ - @ExperimentalResourceApi - public fun getUri(path: String): String = getResourceUri("" + path) - - public object drawable - - public object string - - public object array - - public object plurals - - public object font -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonMainResourceCollectors/app/group/empty_res/generated/resources/ExpectResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonMainResourceCollectors/app/group/empty_res/generated/resources/ExpectResourceCollectors.kt new file mode 100644 index 0000000000..ff58b70797 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonMainResourceCollectors/app/group/empty_res/generated/resources/ExpectResourceCollectors.kt @@ -0,0 +1,25 @@ +package app.group.empty_res.generated.resources + +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal expect val Res.allDrawableResources: Map + +@ExperimentalResourceApi +internal expect val Res.allStringResources: Map + +@ExperimentalResourceApi +internal expect val Res.allStringArrayResources: Map + +@ExperimentalResourceApi +internal expect val Res.allPluralStringResources: Map + +@ExperimentalResourceApi +internal expect val Res.allFontResources: Map diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonResClass/app/group/empty_res/generated/resources/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonResClass/app/group/empty_res/generated/resources/Res.kt new file mode 100644 index 0000000000..32518fbda7 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/commonResClass/app/group/empty_res/generated/resources/Res.kt @@ -0,0 +1,49 @@ +@file:OptIn( + org.jetbrains.compose.resources.InternalResourceApi::class, + org.jetbrains.compose.resources.ExperimentalResourceApi::class, +) + +package app.group.empty_res.generated.resources + +import kotlin.ByteArray +import kotlin.OptIn +import kotlin.String +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.getResourceUri +import org.jetbrains.compose.resources.readResourceBytes + +internal object Res { + /** + * Reads the content of the resource file at the specified path and returns it as a byte array. + * + * Example: `val bytes = Res.readBytes("files/key.bin")` + * + * @param path The path of the file to read in the compose resource's directory. + * @return The content of the file as a byte array. + */ + @ExperimentalResourceApi + public suspend fun readBytes(path: String): ByteArray = + readResourceBytes("composeResources/app.group.empty_res.generated.resources/" + path) + + /** + * Returns the URI string of the resource file at the specified path. + * + * Example: `val uri = Res.getUri("files/key.bin")` + * + * @param path The path of the file in the compose resource's directory. + * @return The URI string of the file. + */ + @ExperimentalResourceApi + public fun getUri(path: String): String = + getResourceUri("composeResources/app.group.empty_res.generated.resources/" + path) + + public object drawable + + public object string + + public object array + + public object plurals + + public object font +} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/desktopMainResourceCollectors/app/group/empty_res/generated/resources/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/desktopMainResourceCollectors/app/group/empty_res/generated/resources/ActualResourceCollectors.kt new file mode 100644 index 0000000000..be6a2f9dae --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/expected/desktopMainResourceCollectors/app/group/empty_res/generated/resources/ActualResourceCollectors.kt @@ -0,0 +1,48 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package app.group.empty_res.generated.resources + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal actual val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal actual val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/settings.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/settings.gradle.kts index 38898d0d94..65030c40e7 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/settings.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/emptyResources/settings.gradle.kts @@ -8,6 +8,7 @@ pluginManagement { } plugins { id("org.jetbrains.kotlin.multiplatform").version("KOTLIN_VERSION_PLACEHOLDER") + id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") } } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/build.gradle.kts index daeacab621..e8f759c1b8 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("multiplatform") + kotlin("plugin.compose") kotlin("native.cocoapods") id("org.jetbrains.compose") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/expected/iosResources.podspec b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/expected/iosResources.podspec index f08c84b958..aad9ba4363 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/expected/iosResources.podspec +++ b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/expected/iosResources.podspec @@ -22,6 +22,10 @@ Pod::Spec.new do |spec| Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)" end + spec.xcconfig = { + 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO', + } + spec.pod_target_xcconfig = { 'KOTLIN_PROJECT_PATH' => '', 'PRODUCT_MODULE_NAME' => 'shared', diff --git a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/settings.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/settings.gradle.kts index 5efe902b20..af172cd475 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/iosResources/settings.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/iosResources/settings.gradle.kts @@ -8,6 +8,7 @@ pluginManagement { } plugins { id("org.jetbrains.kotlin.multiplatform").version("KOTLIN_VERSION_PLACEHOLDER") + id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.kotlin.native.cocoapods").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/build.gradle index e409ff5ffc..53e1c74582 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/settings.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/settings.gradle index afca8638e9..a7062f47ee 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jsMpp/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/build.gradle.kts index 269826d575..57abbb99b6 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("org.jetbrains.compose") + kotlin("plugin.compose") kotlin("jvm") } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt index 7004b885d8..b532771763 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt @@ -1,6 +1,6 @@ @file:OptIn( - org.jetbrains.compose.resources.InternalResourceApi::class, - org.jetbrains.compose.resources.ExperimentalResourceApi::class, + org.jetbrains.compose.resources.InternalResourceApi::class, + org.jetbrains.compose.resources.ExperimentalResourceApi::class, ) package me.app.jvmonlyresources.generated.resources @@ -13,35 +13,35 @@ import org.jetbrains.compose.resources.getResourceUri import org.jetbrains.compose.resources.readResourceBytes internal object Res { - /** - * Reads the content of the resource file at the specified path and returns it as a byte array. - * - * Example: `val bytes = Res.readBytes("files/key.bin")` - * - * @param path The path of the file to read in the compose resource's directory. - * @return The content of the file as a byte array. - */ - @ExperimentalResourceApi - public suspend fun readBytes(path: String): ByteArray = readResourceBytes("" + path) - - /** - * Returns the URI string of the resource file at the specified path. - * - * Example: `val uri = Res.getUri("files/key.bin")` - * - * @param path The path of the file in the compose resource's directory. - * @return The URI string of the file. - */ - @ExperimentalResourceApi - public fun getUri(path: String): String = getResourceUri("" + path) - - public object drawable - - public object string - - public object array - - public object plurals - - public object font -} \ No newline at end of file + /** + * Reads the content of the resource file at the specified path and returns it as a byte array. + * + * Example: `val bytes = Res.readBytes("files/key.bin")` + * + * @param path The path of the file to read in the compose resource's directory. + * @return The content of the file as a byte array. + */ + @ExperimentalResourceApi + public suspend fun readBytes(path: String): ByteArray = readResourceBytes("" + path) + + /** + * Returns the URI string of the resource file at the specified path. + * + * Example: `val uri = Res.getUri("files/key.bin")` + * + * @param path The path of the file in the compose resource's directory. + * @return The URI string of the file. + */ + @ExperimentalResourceApi + public fun getUri(path: String): String = getResourceUri("" + path) + + public object drawable + + public object string + + public object array + + public object plurals + + public object font +} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt index 98f4998f2b..21c01fd922 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt @@ -3,19 +3,27 @@ package me.app.jvmonlyresources.generated.resources import kotlin.OptIn +import kotlin.String +import kotlin.collections.MutableMap import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.InternalResourceApi private object MainDrawable0 { - public val vector: DrawableResource by - lazy { init_vector() } + public val vector: DrawableResource by + lazy { init_vector() } +} + +@InternalResourceApi +internal fun _collectMainDrawable0Resources(map: MutableMap) { + map.put("vector", MainDrawable0.vector) } internal val Res.drawable.vector: DrawableResource - get() = MainDrawable0.vector + get() = MainDrawable0.vector private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( - "drawable:vector", + "drawable:vector", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector.xml", -1, -1), + org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/vector.xml", -1, -1), ) -) \ No newline at end of file +) diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceCollectors/me/app/jvmonlyresources/generated/resources/ActualResourceCollectors.kt b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceCollectors/me/app/jvmonlyresources/generated/resources/ActualResourceCollectors.kt new file mode 100644 index 0000000000..1a915e8926 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceCollectors/me/app/jvmonlyresources/generated/resources/ActualResourceCollectors.kt @@ -0,0 +1,49 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package me.app.jvmonlyresources.generated.resources + +import kotlin.OptIn +import kotlin.String +import kotlin.collections.Map +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.FontResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringArrayResource +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +internal val Res.allDrawableResources: Map by lazy { + val map = mutableMapOf() + _collectMainDrawable0Resources(map) + return@lazy map +} + + +@ExperimentalResourceApi +internal val Res.allStringResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal val Res.allStringArrayResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal val Res.allPluralStringResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + + +@ExperimentalResourceApi +internal val Res.allFontResources: Map by lazy { + val map = mutableMapOf() + return@lazy map +} + diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/settings.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/settings.gradle.kts index db2097cc90..379274b6cc 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/settings.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/settings.gradle.kts @@ -8,6 +8,7 @@ pluginManagement { } plugins { id("org.jetbrains.kotlin.jvm").version("KOTLIN_VERSION_PLACEHOLDER") + id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") } } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/common/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/common/build.gradle index af37d00512..420faf2b99 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/common/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/common/build.gradle @@ -1,5 +1,6 @@ plugins { id 'org.jetbrains.kotlin.multiplatform' + id 'org.jetbrains.kotlin.plugin.compose' id 'org.jetbrains.compose' } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/jvm/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/jvm/build.gradle index 75721fd9c7..80b5af1c9c 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/jvm/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/jvm/build.gradle @@ -1,5 +1,6 @@ plugins { id 'org.jetbrains.kotlin.jvm' + id 'org.jetbrains.kotlin.plugin.compose' id 'org.jetbrains.compose' } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/mpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/mpp/build.gradle index 884f35288f..a567a308bb 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/mpp/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/mpp/build.gradle @@ -1,5 +1,6 @@ plugins { id 'org.jetbrains.kotlin.multiplatform' + id 'org.jetbrains.kotlin.plugin.compose' id 'org.jetbrains.compose' } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/settings.gradle b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/settings.gradle index 11b571ba96..ceb7bfdecf 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmPreview/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/build.gradle deleted file mode 100644 index 1e43a147b8..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.multiplatform" - id "org.jetbrains.compose" -} - -kotlin { - iosX64 { - binaries.framework { - isStatic = true - baseName = "shared" - } - } - iosArm64 { - binaries.framework { - isStatic = true - baseName = "shared" - } - } - - sourceSets { - commonMain { - dependencies { - implementation(compose.runtime) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/gradle.properties b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/gradle.properties deleted file mode 100644 index 695204ddbf..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx8096M -org.jetbrains.compose.experimental.uikit.enabled=true \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/src/commonMain/kotlin/App.kt b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/src/commonMain/kotlin/App.kt deleted file mode 100644 index 2fe6d0719f..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/src/commonMain/kotlin/App.kt +++ /dev/null @@ -1,10 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue - -@Composable -fun App() { - var text by remember { mutableStateOf("Hello, World!") } -} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/build.gradle deleted file mode 100644 index 1e43a147b8..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.multiplatform" - id "org.jetbrains.compose" -} - -kotlin { - iosX64 { - binaries.framework { - isStatic = true - baseName = "shared" - } - } - iosArm64 { - binaries.framework { - isStatic = true - baseName = "shared" - } - } - - sourceSets { - commonMain { - dependencies { - implementation(compose.runtime) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/src/commonMain/kotlin/App.kt b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/src/commonMain/kotlin/App.kt deleted file mode 100644 index 2fe6d0719f..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKind/subproject/src/commonMain/kotlin/App.kt +++ /dev/null @@ -1,10 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue - -@Composable -fun App() { - var text by remember { mutableStateOf("Hello, World!") } -} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/build.gradle deleted file mode 100644 index 40170b68cb..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/build.gradle +++ /dev/null @@ -1,20 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.multiplatform" - id "org.jetbrains.compose" -} - -kotlin { - iosX64() - iosArm64() - iosSimulatorArm64() - macosX64() - macosArm64() - - sourceSets { - commonMain { - dependencies { - implementation(compose.runtime) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/gradle.properties b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/gradle.properties deleted file mode 100644 index 689880ee3f..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.compose.experimental.uikit.enabled=true \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/src/commonMain/kotlin/App.kt b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/src/commonMain/kotlin/App.kt deleted file mode 100644 index 2fe6d0719f..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/src/commonMain/kotlin/App.kt +++ /dev/null @@ -1,10 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue - -@Composable -fun App() { - var text by remember { mutableStateOf("Hello, World!") } -} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/build.gradle deleted file mode 100644 index 40170b68cb..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/build.gradle +++ /dev/null @@ -1,20 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.multiplatform" - id "org.jetbrains.compose" -} - -kotlin { - iosX64() - iosArm64() - iosSimulatorArm64() - macosX64() - macosArm64() - - sourceSets { - commonMain { - dependencies { - implementation(compose.runtime) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/src/commonMain/kotlin/App.kt b/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/src/commonMain/kotlin/App.kt deleted file mode 100644 index 2fe6d0719f..0000000000 --- a/gradle-plugins/compose/src/test/test-projects/misc/nativeCacheKindError/subproject/src/commonMain/kotlin/App.kt +++ /dev/null @@ -1,10 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue - -@Composable -fun App() { - var text by remember { mutableStateOf("Hello, World!") } -} diff --git a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/build.gradle b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/build.gradle index c6583d3c0a..f9dc490179 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/build.gradle @@ -1,7 +1,6 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat - plugins { id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.compose" } @@ -10,6 +9,10 @@ kotlin { browser() binaries.executable() } + wasm { + browser() + binaries.executable() + } sourceSets { commonMain { dependencies { @@ -22,10 +25,6 @@ kotlin { } } -compose.experimental { - web.application {} -} - // test for https://github.com/JetBrains/compose-multiplatform/issues/3169 afterEvaluate { afterEvaluate { diff --git a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/gradle.properties b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/gradle.properties index 9c8f6b37b5..4fae7bbeff 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/gradle.properties +++ b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/gradle.properties @@ -1 +1,2 @@ +org.gradle.jvmargs=-Xmx8096M org.jetbrains.compose.experimental.jscanvas.enabled=true diff --git a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/settings.gradle b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/settings.gradle index 3e41d3e3e9..56a55d1288 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/settings.gradle +++ b/gradle-plugins/compose/src/test/test-projects/misc/skikoWasm/settings.gradle @@ -1,6 +1,7 @@ pluginManagement { plugins { id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' + id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER' id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' } repositories { diff --git a/gradle-plugins/gradle.properties b/gradle-plugins/gradle.properties index 43681791fc..7f087451cd 100644 --- a/gradle-plugins/gradle.properties +++ b/gradle-plugins/gradle.properties @@ -8,19 +8,15 @@ kotlin.code.style=official dev.junit.parallel=false # Default version of Compose Libraries used by Gradle plugin -compose.version=1.6.10 -# The latest version of Compose Compiler used by Gradle plugin. Used only in tests/CI. -compose.tests.compiler.version=1.5.14 +compose.version=1.7.0-alpha01 # The latest version of Kotlin compatible with compose.tests.compiler.version. Used only in tests/CI. -compose.tests.compiler.compatible.kotlin.version=1.9.24 -# The latest version of Kotlin compatible with compose.tests.compiler.version for JS target. Used only on CI. -compose.tests.js.compiler.compatible.kotlin.version=1.9.24 +compose.tests.kotlin.version=2.0.0 # __SUPPORTED_GRADLE_VERSIONS__ # Don't forget to edit versions in .github/workflows/gradle-plugin.yml as well # and Publish.Subtasks.buildTypes.gradle.GradlePluginTestKt#gradleVersions in the TC config # minimal and current gradle version -compose.tests.gradle.versions=7.4, 8.7 -compose.tests.agp.versions=8.1.0, 8.4.0 +compose.tests.gradle.versions=7.4, 8.8 +compose.tests.agp.versions=8.1.0, 8.5.0 # A version of Gradle plugin, that will be published, # unless overridden by COMPOSE_GRADLE_PLUGIN_VERSION env var. diff --git a/gradle-plugins/gradle/libs.versions.toml b/gradle-plugins/gradle/libs.versions.toml index 5a2fc3056a..b8f8f04a8c 100644 --- a/gradle-plugins/gradle/libs.versions.toml +++ b/gradle-plugins/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "1.9.0" +kotlin = "2.0.0" gradle-download-plugin = "5.5.0" kotlin-poet = "1.16.0" plugin-android = "7.3.0" diff --git a/gradle-plugins/gradle/wrapper/gradle-wrapper.jar b/gradle-plugins/gradle/wrapper/gradle-wrapper.jar index 62d4c05355..e6441136f3 100644 Binary files a/gradle-plugins/gradle/wrapper/gradle-wrapper.jar and b/gradle-plugins/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle-plugins/gradle/wrapper/gradle-wrapper.properties b/gradle-plugins/gradle/wrapper/gradle-wrapper.properties index 48c0a02ca4..a4413138c9 100644 --- a/gradle-plugins/gradle/wrapper/gradle-wrapper.properties +++ b/gradle-plugins/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradle-plugins/gradlew b/gradle-plugins/gradlew index fbd7c51583..1aa94a4269 100755 --- a/gradle-plugins/gradlew +++ b/gradle-plugins/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,99 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradle-plugins/gradlew.bat b/gradle-plugins/gradlew.bat index a9f778a7a9..7101f8e467 100644 --- a/gradle-plugins/gradlew.bat +++ b/gradle-plugins/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -54,31 +55,16 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,17 +72,19 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/tutorials/HTML/Building_UI/README.md b/tutorials/HTML/Building_UI/README.md index 1670b1779d..2de5c7a2b5 100644 --- a/tutorials/HTML/Building_UI/README.md +++ b/tutorials/HTML/Building_UI/README.md @@ -1,4 +1,4 @@ -# Building the UI with with the Compose HTML library +# Building the UI with the Compose HTML library In this tutorial we will look at several examples that use the Composable HTML/CSS DSL to describe the user interface for your web application. diff --git a/tutorials/README.md b/tutorials/README.md index af299b64ce..1e5681c774 100644 --- a/tutorials/README.md +++ b/tutorials/README.md @@ -17,7 +17,7 @@ * [Navigation](Navigation) * [Accessibility](Accessibility) * [Building a native distribution](Native_distributions_and_local_execution) -* [UI testing](UI_Testing) +* [UI testing](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-test.html) ## Web (based on Wasm) * [Getting started](https://kotl.in/wasm-compose-example) diff --git a/tutorials/UI_Testing/README.md b/tutorials/UI_Testing/README.md deleted file mode 100644 index 51daf01e06..0000000000 --- a/tutorials/UI_Testing/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# UI Testing -The API for unit testing in Compose for Desktop is nearly identical to the [Jetpack Compose Android testing API](https://developer.android.com/jetpack/compose/testing). We highly recommended reading that first before moving on to this tutorial. - -## Setting up -To start using the testing API, you will need to add the dependency on `compose.uiTestJUnit4` to your `build.gradle` file and create the directory for your tests. - -If the module is desktop-only (`kotlin("jvm")` is applied), add the dependency via: -``` kotlin -dependencies { - testImplementation(compose.desktop.uiTestJUnit4) - testImplementation(compose.desktop.currentOs) -} -``` - -and the directory for tests will be `src/test/kotlin` - -If the module is multiplatform (`kotlin(“multiplatform”)` is applied), add it via: - -``` kotlin -kotlin { - sourceSets { - val desktopTest by getting { - dependencies { - implementation(compose.desktop.uiTestJUnit4) - implementation(compose.desktop.currentOs) - } - } - } -} -``` - -And the directory for tests will be `src/desktopTest/kotlin` - -## Creating your first test -In the tests directory, create a file named `ExampleTest.kt` and paste this code into it: - -```kotlin -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.test.* -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.test.junit4.createComposeRule -import org.junit.Rule -import org.junit.Test - -class ExampleTest { - @get:Rule - val rule = createComposeRule() - - @Test - fun myTest(){ - rule.setContent { - var text by remember { mutableStateOf("Hello") } - Text( - text = text, - modifier = Modifier.testTag("text") - ) - Button( - onClick = { text = "Compose" }, - modifier = Modifier.testTag("button") - ){ - Text("Click me") - } - } - - rule.onNodeWithTag("text").assertTextEquals("Hello") - rule.onNodeWithTag("button").performClick() - rule.onNodeWithTag("text").assertTextEquals("Compose") - } -} -``` - -Now you can run the test by either clicking ![run](https://github.com/JetBrains/compose-multiplatform/assets/5963351/2eac4041-757e-48b0-9dc2-baef82f21a7b) button in your IDE, or from the command line with -``` -./gradlew test -``` -