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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions desloppify/languages/kotlin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from desloppify.languages._framework.generic_support.core import generic_lang
from desloppify.languages._framework.treesitter import KOTLIN_SPEC
from desloppify.languages.kotlin._zones import KOTLIN_ZONE_RULES

generic_lang(
name="kotlin",
Expand All @@ -20,9 +21,11 @@
depth="shallow",
detect_markers=["build.gradle.kts", "build.gradle"],
treesitter_spec=KOTLIN_SPEC,
zone_rules=KOTLIN_ZONE_RULES,
)

__all__ = [
"generic_lang",
"KOTLIN_SPEC",
"KOTLIN_ZONE_RULES",
]
44 changes: 44 additions & 0 deletions desloppify/languages/kotlin/_zones.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Zone/path classification rules for Kotlin.

Kotlin projects are laid out by Gradle source sets, not by a top-level ``test/``
directory. Kotlin Multiplatform in particular names every test source set
``<target>Test`` — ``src/commonTest/kotlin``, ``src/jvmTest/kotlin``,
``src/iosTest/kotlin``, ``src/androidUnitTest/kotlin`` — none of which contain the
``/test/`` path segment the common rules look for. Without these rules every test
file is scored as production code.
"""

from __future__ import annotations

from desloppify.engine.policy.zones import COMMON_ZONE_RULES, Zone, ZoneRule

KOTLIN_ZONE_RULES = [
# Gradle/KMP test source sets: src/test/, src/androidTest/, src/commonTest/,
# src/jvmTest/, src/iosTest/, src/androidUnitTest/, src/nativeTest/, ...
# The pattern has no leading "." / trailing "_" so it matches as a path substring.
ZoneRule(
Zone.TEST,
[
"/src/test/",
"/src/androidTest/",
"/src/testFixtures/",
"Test/kotlin/",
"Test/java/",
"Test/resources/",
],
),
ZoneRule(Zone.GENERATED, ["/generated/", "/build/generated/"]),
ZoneRule(
Zone.CONFIG,
[
"build.gradle.kts",
"settings.gradle.kts",
"build.gradle",
"settings.gradle",
"gradle.properties",
"gradle/libs.versions.toml",
],
),
] + COMMON_ZONE_RULES

__all__ = ["KOTLIN_ZONE_RULES"]
67 changes: 67 additions & 0 deletions desloppify/tests/lang/common/test_kotlin_zones.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Regression tests for Kotlin/Gradle zone classification.

Kotlin projects are organised by Gradle source sets rather than a top-level
``test/`` directory, so the common rules classify every test file as production.
"""

from __future__ import annotations

import pytest

from desloppify.engine.policy.zones import Zone, classify_file
from desloppify.languages.kotlin._zones import KOTLIN_ZONE_RULES


def _zone(rel_path: str) -> Zone:
return classify_file(rel_path, KOTLIN_ZONE_RULES)


@pytest.mark.parametrize(
"rel_path",
[
# Kotlin Multiplatform source sets
"shared/src/commonTest/kotlin/com/example/FormEngineTest.kt",
"sync/src/jvmTest/kotlin/com/example/SubmissionStoreTest.kt",
"sync/src/iosTest/kotlin/com/example/DeviceCryptoTest.kt",
"composeApp/src/androidUnitTest/kotlin/com/example/RendererTest.kt",
"shared/src/nativeTest/kotlin/com/example/ParserTest.kt",
# Plain Gradle JVM / Android layouts
"app/src/test/java/com/example/HelperTest.kt",
"app/src/androidTest/java/com/example/LoginFlowTest.kt",
"lib/src/testFixtures/kotlin/com/example/Fixtures.kt",
],
)
def test_gradle_test_source_sets_are_test_zone(rel_path):
assert _zone(rel_path) == Zone.TEST


@pytest.mark.parametrize(
"rel_path",
[
"shared/src/commonMain/kotlin/com/example/FormEngine.kt",
"sync/src/jvmMain/kotlin/com/example/SubmissionStore.kt",
"composeApp/src/androidMain/kotlin/com/example/Renderer.kt",
"composeApp/src/iosMain/kotlin/com/example/MapSeam.ios.kt",
],
)
def test_main_source_sets_stay_production(rel_path):
assert _zone(rel_path) == Zone.PRODUCTION


@pytest.mark.parametrize(
"rel_path",
[
"build.gradle.kts",
"settings.gradle.kts",
"androidApp/build.gradle.kts",
"gradle.properties",
"gradle/libs.versions.toml",
],
)
def test_gradle_build_files_are_config_zone(rel_path):
assert _zone(rel_path) == Zone.CONFIG


def test_latest_is_not_mistaken_for_a_test_source_set():
"""A directory merely ending in 'Test' must still need the source-set suffix."""
assert _zone("shared/src/commonMain/kotlin/com/example/LatestKotlinThing.kt") == Zone.PRODUCTION