diff --git a/build.gradle.kts b/build.gradle.kts index 77769f836e..79bfa0ee6a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,10 +45,13 @@ allprojects { apply(plugin = "io.github.yairm210.purity-plugin") configure{ - wellKnownPureFunctions = setOf("kotlin.internal.ir.CHECK_NOT_NULL") + wellKnownPureFunctions = setOf() wellKnownReadonlyFunctions = setOf( "kotlin.collections.any", - "kotlin.collections.Iterator.hasNext" + "kotlin.collections.all", + "kotlin.ranges.coerceAtLeast", + // Looks like the Collection.contains is not considered overridden :thunk: + "java.util.AbstractCollection.contains", ) } diff --git a/core/src/com/unciv/logic/MultiFilter.kt b/core/src/com/unciv/logic/MultiFilter.kt index be611f4c1a..7cafca10f3 100644 --- a/core/src/com/unciv/logic/MultiFilter.kt +++ b/core/src/com/unciv/logic/MultiFilter.kt @@ -1,5 +1,7 @@ package com.unciv.logic +import org.jetbrains.annotations.Contract + object MultiFilter { private const val andPrefix = "{" private const val andSeparator = "} {" @@ -17,6 +19,7 @@ object MultiFilter { * @param filterFunction The single filter implementation * @param forUniqueValidityTests Inverts the `non-[filter]` test because Unique validity doesn't check for actual matching */ + @Contract("readonly") @Suppress("purity") fun multiFilter( input: String, filterFunction: (String) -> Boolean, @@ -33,6 +36,7 @@ object MultiFilter { return filterFunction(input) } + @Contract("readonly") fun getAllSingleFilters(input: String): Sequence = when { input.hasSurrounding(andPrefix, andSuffix) && input.contains(andSeparator) -> // Resolve "AND" filters @@ -45,6 +49,7 @@ object MultiFilter { else -> sequenceOf(input) } + @Contract("readonly") fun String.hasSurrounding(prefix: String, suffix: String) = startsWith(prefix) && endsWith(suffix) } diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index 33db1172d1..9185308628 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -28,6 +28,7 @@ import com.unciv.models.stats.GameResource import com.unciv.models.stats.INamed import com.unciv.models.stats.Stat import com.unciv.models.stats.SubStat +import org.jetbrains.annotations.Contract import java.util.UUID import kotlin.math.roundToInt @@ -169,6 +170,7 @@ class City : IsPartOfGameInfoSerialization, INamed { fun getCenterTileOrNull(): Tile? = if (::centerTile.isInitialized) centerTile else null fun getTiles(): Sequence = tiles.asSequence().map { tileMap[it] } fun getWorkableTiles() = tilesInRange.asSequence().filter { it.getOwner() == civ } + @Contract("readonly") fun isWorked(tile: Tile) = workedTiles.contains(tile.position) fun isCapital(): Boolean = cityConstructions.builtBuildingUniqueMap.hasUnique(UniqueType.IndicatesCapital, state) diff --git a/core/src/com/unciv/logic/map/tile/Tile.kt b/core/src/com/unciv/logic/map/tile/Tile.kt index 8c0d29f21c..feae190ece 100644 --- a/core/src/com/unciv/logic/map/tile/Tile.kt +++ b/core/src/com/unciv/logic/map/tile/Tile.kt @@ -34,6 +34,7 @@ import com.unciv.utils.DebugUtils import com.unciv.utils.Log import com.unciv.utils.withItem import com.unciv.utils.withoutItem +import org.jetbrains.annotations.Contract import kotlin.collections.ArrayList import kotlin.collections.HashSet import kotlin.math.abs @@ -257,6 +258,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { return null } + @Contract("readonly") fun getCity(): City? = owningCity internal fun getNaturalWonder(): Terrain = @@ -351,6 +353,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { fun getBaseTerrain(): Terrain = baseTerrainObject + @Contract("readonly") fun getOwner(): Civilization? = getCity()?.civ fun getRoadOwner(): Civilization? { @@ -401,6 +404,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { return uniques } + @Contract("readonly") fun getWorkingCity(): City? { val civInfo = getOwner() ?: return null if (owningCity?.isWorked(this) == true) return owningCity // common case @@ -433,6 +437,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { return false } + @Contract("readonly") fun isWorked(): Boolean = getWorkingCity() != null fun providesYield(): Boolean { if (getCity() == null) return false @@ -481,10 +486,12 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { } /** Implements [UniqueParameterType.TileFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TileFilter] */ + @Contract("readonly") fun matchesFilter(filter: String, civInfo: Civilization? = null): Boolean { return MultiFilter.multiFilter(filter, { matchesSingleFilter(it, civInfo) }) } + @Contract("readonly") @Suppress("purity") private fun matchesSingleFilter(filter: String, civInfo: Civilization? = null): Boolean { if (matchesSingleTerrainFilter(filter, civInfo)) return true if ((improvement == null || improvementIsPillaged) && filter == "unimproved") return true diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index 803d3b0dc7..e90bc195ef 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -96,7 +96,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s return true } - @Contract("readonly") @Suppress("purity") + @Contract("readonly") private fun getUniqueMultiplier(stateForConditionals: StateForConditionals): Int { if (stateForConditionals == StateForConditionals.IgnoreMultiplicationForCaching) return 1