Browse Source

Web/add compose plugin integration cases for kotlinjs (#870)

* web: Add integration cases for compose plugin targeting kotlin/js

* web: Add integration cases for compose plugin targeting kotlin/js

* Report cases to TeamCity

* Update README.md

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
pull/905/head
Oleksandr Karpovich 3 years ago committed by GitHub
parent
commit
8c01295e8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      web/compose-compiler-integration/README.md
  2. 165
      web/compose-compiler-integration/build.gradle.kts
  3. 27
      web/compose-compiler-integration/main-template/build.gradle.kts
  4. BIN
      web/compose-compiler-integration/main-template/gradle/wrapper/gradle-wrapper.jar
  5. 5
      web/compose-compiler-integration/main-template/gradle/wrapper/gradle-wrapper.properties
  6. 185
      web/compose-compiler-integration/main-template/gradlew
  7. 104
      web/compose-compiler-integration/main-template/gradlew.bat
  8. 26
      web/compose-compiler-integration/main-template/lib/build.gradle.kts
  9. 0
      web/compose-compiler-integration/main-template/lib/src/commonMain/kotlin/Lib.kt
  10. 24
      web/compose-compiler-integration/main-template/settings.gradle.kts
  11. 1
      web/compose-compiler-integration/main-template/src/commonMain/kotlin/Main.kt
  12. 25
      web/compose-compiler-integration/testcases/failing/CompanionGetValueOperatorComposable.kt
  13. 23
      web/compose-compiler-integration/testcases/failing/InstanceGetValueOperatorComposable.kt
  14. 30
      web/compose-compiler-integration/testcases/failing/WithComposableBlockUsingTypeParameterAndDefaultValue.kt
  15. 67
      web/compose-compiler-integration/testcases/passing/ComposableWithParamsWithDefaultValues.kt
  16. 36
      web/compose-compiler-integration/testcases/passing/ComposableWithTypeParams.kt
  17. 45
      web/compose-compiler-integration/testcases/passing/PassingComposableToConstructor.kt
  18. 1
      web/settings.gradle.kts

9
web/compose-compiler-integration/README.md

@ -0,0 +1,9 @@
RUN from project root directory:
`./gradlew :compose-compiler-integration:checkComposeCases`
To use specific version (the default is 0.0.0-SNASPHOT):
`./gradlew :compose-compiler-integration:checkComposeCases -PCOMPOSE_CORE_VERSION=0.5.0-build243`
To fun only filtered cases (check for contained in file path):
`./gradlew :compose-compiler-integration:checkComposeCases -PFILTER_CASES=CaseName`

165
web/compose-compiler-integration/build.gradle.kts

@ -0,0 +1,165 @@
fun cloneTemplate(templateName: String, contentMain: String, contentLib: String): File {
val tempDir = file("${project.buildDir.absolutePath}/temp/cloned-$templateName")
tempDir.deleteRecursively()
tempDir.mkdirs()
file("${projectDir.absolutePath}/main-template").copyRecursively(tempDir)
// tempDir.deleteOnExit()
File("$tempDir/src/commonMain/kotlin/Main.kt").printWriter().use { out ->
out.println(contentMain)
}
File("$tempDir/lib/src/commonMain/kotlin/Lib.kt").printWriter().use { out ->
out.println(contentLib)
}
return tempDir
}
fun build(
caseName: String,
directory: File,
failureExpected: Boolean = false,
composeVersion: String,
vararg buildCmd: String = arrayOf("build", "jsNodeRun")
) {
val isWin = System.getProperty("os.name").startsWith("Win")
val arguments = buildCmd.toMutableList().also {
it.add("-PCOMPOSE_CORE_VERSION=$composeVersion")
}.toTypedArray()
val procBuilder = if (isWin) {
ProcessBuilder("gradlew.bat", *arguments)
} else {
ProcessBuilder("bash", "./gradlew", *arguments)
}
val proc = procBuilder
.directory(directory)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
proc.waitFor(5, TimeUnit.MINUTES)
"(COMPOSE_INTEGRATION_VERSION=\\[.*\\])".toRegex().find(
proc.inputStream.bufferedReader().readText()
)?.also {
println(it.groupValues[1])
}
println(proc.errorStream.bufferedReader().readText())
if (proc.exitValue() != 0 && !failureExpected) {
throw GradleException("Error compiling $caseName")
}
if (failureExpected && proc.exitValue() == 0) {
throw AssertionError("$caseName compilation did not fail!!!")
}
}
data class RunChecksResult(
val cases: Map<String, Throwable?>
) {
val totalCount = cases.size
val failedCount = cases.filter { it.value != null }.size
val hasFailed = failedCount > 0
fun printResults() {
cases.forEach { (name, throwable) ->
println(name + " : " + (throwable ?: "OK"))
}
}
fun reportToTeamCity() {
cases.forEach { (caseName, error) ->
println("##teamcity[testStarted name='compileTestCase_$caseName']")
if (error != null) {
println("##teamcity[testFailed name='compileTestCase_$caseName']")
}
println("##teamcity[testFinished name='compileTestCase_$caseName']")
}
}
}
fun runCasesInDirectory(
dir: File,
filterPath: String,
expectCompilationError: Boolean,
composeVersion: String
): RunChecksResult {
return dir.listFiles()!!.filter { it.absolutePath.contains(filterPath) }.mapIndexed { _, file ->
println("Running check for ${file.name}, expectCompilationError = $expectCompilationError, composeVersion = $composeVersion")
val contentLines = file.readLines()
val startMainLineIx = contentLines.indexOf("// @Module:Main").let { ix ->
if (ix == -1) 0 else ix + 1
}
val startLibLineIx = contentLines.indexOf("// @Module:Lib").let { ix ->
if (ix == -1) contentLines.size else ix - 1
}
require(startMainLineIx < startLibLineIx) {
"The convention is that @Module:Lib should go after @Module:Main"
}
val mainContent = contentLines.let { lines ->
val endLineIx = if (startLibLineIx < lines.size) startLibLineIx - 1 else lines.lastIndex
lines.slice(startMainLineIx..endLineIx).joinToString(separator = "\n")
}
val libContent = contentLines.let { lines ->
if (startLibLineIx < lines.size) {
lines.slice(startLibLineIx..lines.lastIndex)
} else {
emptyList()
}.joinToString(separator = "\n")
}
val caseName = file.name
val tmpDir = cloneTemplate(caseName, contentMain = mainContent, contentLib = libContent)
caseName to kotlin.runCatching {
build(
caseName = caseName,
directory = tmpDir,
failureExpected = expectCompilationError,
composeVersion = composeVersion
)
}.exceptionOrNull()
}.let {
RunChecksResult(it.toMap())
}
}
tasks.register("checkComposeCases") {
doLast {
val filterCases = project.findProperty("FILTER_CASES")?.toString() ?: ""
val composeVersion = project.findProperty("COMPOSE_CORE_VERSION")?.toString() ?: "0.0.0-SNASPHOT"
val expectedFailingCasesDir = File("${projectDir.absolutePath}/testcases/failing")
val expectedFailingResult = runCasesInDirectory(
dir = expectedFailingCasesDir,
expectCompilationError = true,
filterPath = filterCases,
composeVersion = composeVersion
)
val passingCasesDir = File("${projectDir.absolutePath}/testcases/passing")
val passingResult = runCasesInDirectory(
dir = passingCasesDir,
expectCompilationError = false,
filterPath = filterCases,
composeVersion = composeVersion
)
expectedFailingResult.printResults()
expectedFailingResult.reportToTeamCity()
passingResult.printResults()
passingResult.reportToTeamCity()
if (expectedFailingResult.hasFailed || passingResult.hasFailed) {
error("There were failed cases. Check the logs above")
}
}
}

27
web/compose-compiler-integration/main-template/build.gradle.kts

@ -0,0 +1,27 @@
plugins {
kotlin("multiplatform") version "1.5.10"
id("org.jetbrains.compose")
}
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
kotlin {
js(IR) {
nodejs {}
browser() {}
binaries.executable()
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
implementation(compose.runtime)
implementation(project(":lib"))
}
}
}
}

BIN
web/compose-compiler-integration/main-template/gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

5
web/compose-compiler-integration/main-template/gradle/wrapper/gradle-wrapper.properties vendored

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
web/compose-compiler-integration/main-template/gradlew vendored

@ -0,0 +1,185 @@
#!/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" "$@"

104
web/compose-compiler-integration/main-template/gradlew.bat vendored

@ -0,0 +1,104 @@
@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 init
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 init
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
: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
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%
: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

26
web/compose-compiler-integration/main-template/lib/build.gradle.kts

@ -0,0 +1,26 @@
plugins {
kotlin("multiplatform")// version "1.5.10"
id("org.jetbrains.compose")// version (System.getenv("COMPOSE_INTEGRATION_VERSION") ?: "0.0.0-SNASPHOT")
}
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
kotlin {
js(IR) {
nodejs {}
browser() {}
binaries.executable()
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
implementation(compose.runtime)
}
}
}
}

0
web/compose-compiler-integration/main-template/lib/src/commonMain/kotlin/Lib.kt

24
web/compose-compiler-integration/main-template/settings.gradle.kts

@ -0,0 +1,24 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven {
url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.jetbrains.compose") {
val useVersion = if (extra.has("COMPOSE_CORE_VERSION")) {
extra["COMPOSE_CORE_VERSION"].toString()
} else {
"0.0.0-SNASPHOT"
}
println("COMPOSE_INTEGRATION_VERSION=[$useVersion]")
useVersion(useVersion)
}
}
}
}
include(":lib")

1
web/compose-compiler-integration/main-template/src/commonMain/kotlin/Main.kt

@ -0,0 +1 @@
// Empty file. It's used as a template project.

25
web/compose-compiler-integration/testcases/failing/CompanionGetValueOperatorComposable.kt

@ -0,0 +1,25 @@
// @Module:Main
// https://github.com/JetBrains/compose-jb/issues/827
import kotlin.reflect.KProperty
import androidx.compose.runtime.Composable
interface Router {
companion object {
@Composable
operator fun getValue(ref: Any?, property: KProperty<*>): Router {
return object : Router {}
}
}
}
fun main() {
callComposable {
val router by Router
}
}
fun callComposable(content: @Composable () -> Unit) {
// does nothing
}

23
web/compose-compiler-integration/testcases/failing/InstanceGetValueOperatorComposable.kt

@ -0,0 +1,23 @@
// @Module:Main
// https://github.com/JetBrains/compose-jb/issues/827
import kotlin.reflect.KProperty
import androidx.compose.runtime.Composable
class Router {
@Composable
operator fun getValue(ref: Any?, property: KProperty<*>): Router {
return Router()
}
}
fun main() {
callComposable {
val router by Router()
}
}
fun callComposable(content: @Composable () -> Unit) {
// does nothing
}

30
web/compose-compiler-integration/testcases/failing/WithComposableBlockUsingTypeParameterAndDefaultValue.kt

@ -0,0 +1,30 @@
// https://github.com/JetBrains/compose-jb/issues/774
import androidx.compose.runtime.Composable
fun main() {
callComposable {
Foo<String> { }
FooTakesTypedComposableLambda2("T")
FooTakesTypedComposableLambda3("T")
}
}
fun callComposable(content: @Composable () -> Unit) {
// does nothing
}
class RouterState<C>
@Composable
fun <C : Any> Foo(block: @Composable (RouterState<C>) -> Unit = {}) {}
@Composable
fun <T> FooTakesTypedComposableLambda2(t: T, composable: @Composable (T) -> T = { t }) {
composable(t)
}
@Composable
fun <T> FooTakesTypedComposableLambda3(t: T, composable: @Composable () -> T = { t }) {
composable()
}

67
web/compose-compiler-integration/testcases/passing/ComposableWithParamsWithDefaultValues.kt

@ -0,0 +1,67 @@
// @Module:Main
import androidx.compose.runtime.Composable
import androidx.compose.runtime.currentComposer
import androidx.compose.runtime.Composer
fun main() {
callComposable {
FooTakesLambda()
InlineFooTakesLambda()
FooTakesComposableLambda()
InlineFooTakesComposableLambda()
FooTakesTypedExtesionComposableLambdaWithExplicitTypesAndDefaultLambda("4", 5)
ComposableWithDifferentDefaultValuesForParameters(a = Any())
ComposableWithReturnAndWithDefaultLambda().invoke()
}
}
fun callComposable(content: @Composable () -> Unit) {
val c = content
}
// @Module:Lib
import androidx.compose.runtime.Composable
@Composable
fun FooTakesLambda(block: () -> Unit = {}) {
block()
}
@Composable
inline fun InlineFooTakesLambda(block: () -> Unit = {}) {
block()
}
@Composable
fun FooTakesComposableLambda(composable: @Composable () -> Unit = {}) {
composable()
}
@Composable
inline fun InlineFooTakesComposableLambda(composable: @Composable () -> Unit = {}) {
composable()
}
@Composable
fun FooTakesTypedExtesionComposableLambdaWithExplicitTypesAndDefaultLambda(
t: String, k: Int, composable: @Composable String.(Int) -> Double = { (this + ". $it").toDouble() }
) {
t.composable(k)
}
@Composable
fun ComposableWithDifferentDefaultValuesForParameters(
a: Any, i: Int = 1, b: Boolean = false, s: String = "s",
u: Unit = Unit, a2: Any = Any(), l: List<Any> = listOf("1")
) {
a.toString() + "$i $b $s $u $a2 $l"
}
@Composable
fun ComposableWithReturnAndWithDefaultLambda(
l: @Composable () -> (@Composable () -> Unit) = { { } }
): @Composable () -> Unit {
return { l() }
}

36
web/compose-compiler-integration/testcases/passing/ComposableWithTypeParams.kt

@ -0,0 +1,36 @@
// @Module:Main
import androidx.compose.runtime.Composable
import androidx.compose.runtime.currentComposer
import androidx.compose.runtime.Composer
fun main() {
callComposable {
FooTakesTypedComposableLambda { "text" }
FooTakesTypedComposableLambda2(10) { it + 100 }
FooTakesTypedExtesionComposableLambda<String, Any, Unit>("text", Any()) { }
}
}
fun callComposable(content: @Composable () -> Unit) {
val c = content
}
// @Module:Lib
import androidx.compose.runtime.Composable
@Composable
fun <T> FooTakesTypedComposableLambda(composable: @Composable () -> T) {
composable()
}
@Composable
fun <T> FooTakesTypedComposableLambda2(t: T, composable: @Composable (T) -> T) {
composable(t)
}
@Composable
fun <T, K, R> FooTakesTypedExtesionComposableLambda(t: T, k: K, composable: @Composable T.(K) -> R) {
t.composable(k)
}

45
web/compose-compiler-integration/testcases/passing/PassingComposableToConstructor.kt

@ -0,0 +1,45 @@
// @Module:Main
// https://youtrack.jetbrains.com/issue/KT-46880
import androidx.compose.runtime.Composable
fun main() {
val instance = testCase { }
val instance2 = TestCase2()
callComposable {
instance.composable()
instance2.composable()
}
}
fun callComposable(content: @Composable () -> Unit) {
// does nothing
}
// @Module:Lib
import androidx.compose.runtime.Composable
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class TestCase(val composable: @Composable () -> Unit) {
operator fun provideDelegate(
thisRef: Any,
property: KProperty<*>
): ReadOnlyProperty<Any?, String> {
return ReadOnlyProperty { _, _ -> property.name }
}
}
class TestCase2(val composable: @Composable () -> Unit = {}) {
operator fun provideDelegate(
thisRef: Any,
property: KProperty<*>
): ReadOnlyProperty<Any?, String> {
return ReadOnlyProperty { _, _ -> property.name }
}
}
fun testCase(composable: @Composable () -> Unit): TestCase {
return TestCase(composable)
}

1
web/settings.gradle.kts

@ -32,6 +32,7 @@ module(":web-widgets", "$rootDir/widgets")
module(":web-integration-core", "$rootDir/integration-core") module(":web-integration-core", "$rootDir/integration-core")
module(":web-integration-widgets", "$rootDir/integration-widgets") module(":web-integration-widgets", "$rootDir/integration-widgets")
module(":web-benchmark-core", "$rootDir/benchmark-core") module(":web-benchmark-core", "$rootDir/benchmark-core")
module(":compose-compiler-integration", "$rootDir/compose-compiler-integration")
if (extra["COMPOSE_WEB_BUILD_WITH_EXAMPLES"]!!.toString().toBoolean() == true) { if (extra["COMPOSE_WEB_BUILD_WITH_EXAMPLES"]!!.toString().toBoolean() == true) {
println("building with examples") println("building with examples")

Loading…
Cancel
Save