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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// No `package` line on purpose (issue #319): a root-package declaration cannot be named from the
// generated fragments, so the processor skips it with a warning instead of breaking this build.

fun rootPackageProbe(): Int = 7

class RootPackageThing
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fixture.app

import python.multiplatform.generated.FunctionTable
import kotlin.test.Test
import kotlin.test.assertTrue

/**
* Issue #319: `RootPackageDeclarations.kt` has no package. Before the fix the processor emitted an
* unqualified `rootPackageProbe()` call inside `python.multiplatform.generated.fragments`, and this
* module did not compile. Now the root-package declarations are skipped (with a KSP warning), the
* module compiles, and neither appears in the generated table.
*/
class RootPackageSkipTest {

@Test
fun rootPackageDeclarationsAreNotInTheTable() {
val names = FunctionTable.fragments.flatMap { fragment -> fragment.entries().map { it.name } + fragment.classes().map { it.toString() } }
assertTrue(names.isNotEmpty(), "the table is empty, so this asserts nothing")
val leaked = names.filter { it == "rootPackageProbe" || it.startsWith("RootPackageThing") || it.endsWith(".rootPackageProbe") }
assertTrue(leaked.isEmpty(), "root-package declarations reached the table: $leaked")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@ class FragmentScanner(private val excludePackages: List<String>, private val log
val classes = mutableListOf<ClassModel>()

files.flatMap { it.declarations }.forEach { declaration ->
// Issue #319: Kotlin cannot name a root-package declaration from a named package, and
// every generated fragment and table lives in one, so a binding could only ever be an
// unresolved reference. Skipped with a warning instead of breaking the consumer's build.
if (declaration.packageName.asString().isEmpty()) {
if (declaration is KSFunctionDeclaration || declaration is KSPropertyDeclaration || declaration is KSClassDeclaration) {
logger.warn(
"python-multiplatform-ksp: ${declaration.simpleName.asString()} is in the root package " +
"and is not exposed to Python (generated code in a named package cannot refer to it); " +
"give its file a `package` declaration to expose it.",
declaration,
)
}
return@forEach
}
when (declaration) {
is KSFunctionDeclaration ->
if (BindingPolicy.isExposedTopLevelFunction(declaration, excludePackages) &&
Expand Down