diff --git a/build.gradle.kts b/build.gradle.kts index 9356046..5c33a67 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,15 +3,15 @@ import java.net.URL plugins { - kotlin("jvm") version "1.5.20" + kotlin("jvm") version "1.5.30" `maven-publish` signing id("io.github.gradle-nexus.publish-plugin") version "1.1.0" id("net.nemerosa.versioning") version "2.14.0" - id("org.jetbrains.dokka") version "1.4.32" - id("io.gitlab.arturbosch.detekt") version "1.17.0" + id("org.jetbrains.dokka") version "1.5.0" + id("io.gitlab.arturbosch.detekt") version "1.18.0" } group = "pw.forst" @@ -23,7 +23,7 @@ repositories { } dependencies { - val jacksonVersion = "2.12.3" + val jacksonVersion = "2.12.4" compileOnly("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion) compileOnly("com.fasterxml.jackson.module", "jackson-module-kotlin", jacksonVersion) compileOnly("org.jetbrains.kotlin", "kotlin-reflect", "1.5.20") @@ -49,9 +49,15 @@ detekt { } tasks { + compileJava { + targetCompatibility = "1.8" + } compileKotlin { kotlinOptions.jvmTarget = "1.8" } + compileTestJava { + targetCompatibility = "1.8" + } compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } diff --git a/detekt-config.yml b/detekt-config.yml index 55453ee..a0f611e 100644 --- a/detekt-config.yml +++ b/detekt-config.yml @@ -9,6 +9,7 @@ build: config: validation: true + warningsAsErrors: true # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' excludes: '' @@ -16,11 +17,18 @@ processors: active: true exclude: - 'DetektProgressListener' + # - 'KtFileCountProcessor' + # - 'PackageCountProcessor' + # - 'ClassCountProcessor' # - 'FunctionCountProcessor' # - 'PropertyCountProcessor' - # - 'ClassCountProcessor' - # - 'PackageCountProcessor' - # - 'KtFileCountProcessor' + # - 'ProjectComplexityProcessor' + # - 'ProjectCognitiveComplexityProcessor' + # - 'ProjectLLOCProcessor' + # - 'ProjectCLOCProcessor' + # - 'ProjectLOCProcessor' + # - 'ProjectSLOCProcessor' + # - 'LicenseHeaderLoaderExtension' console-reports: active: true @@ -40,27 +48,30 @@ output-reports: comments: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] AbsentOrWrongFileLicense: active: false licenseTemplateFile: 'license.template' + licenseTemplateIsRegex: false CommentOverPrivateFunction: active: false CommentOverPrivateProperty: active: false EndOfSentenceFormat: - active: false + active: true endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' UndocumentedPublicClass: - active: true + active: false searchInNestedClass: true searchInInnerClass: true searchInInnerObject: true searchInInnerInterface: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] UndocumentedPublicFunction: active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] UndocumentedPublicProperty: active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] complexity: active: true @@ -78,13 +89,13 @@ complexity: ignoreSingleWhenExpression: false ignoreSimpleWhenEntries: false ignoreNestingFunctions: false - nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull] + nestingFunctions: [ run, let, apply, with, also, use, forEach, isNotNull, ifNull ] LabeledExpression: active: false - ignoredLabels: [] + ignoredLabels: [ ] LargeClass: active: true - threshold: 600 + threshold: 400 LongMethod: active: true threshold: 60 @@ -94,16 +105,21 @@ complexity: constructorThreshold: 7 ignoreDefaultParameters: false ignoreDataClasses: true - ignoreAnnotated: [] + ignoreAnnotated: [ ] MethodOverloading: active: false threshold: 6 + NamedArguments: + active: true + threshold: 3 NestedBlockDepth: active: true threshold: 4 + ReplaceSafeCallChainWithRun: + active: true StringLiteralDuplication: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] threshold: 3 ignoreAnnotation: true excludeStringsWithLessThan5Characters: true @@ -111,21 +127,25 @@ complexity: TooManyFunctions: # because we don't use classes, this is acceptable active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - thresholdInFiles: 11 - thresholdInClasses: 11 - thresholdInInterfaces: 11 - thresholdInObjects: 11 - thresholdInEnums: 11 - ignoreDeprecated: false - ignorePrivate: false + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] + thresholdInFiles: 20 + thresholdInClasses: 13 + thresholdInInterfaces: 13 + thresholdInObjects: 13 + thresholdInEnums: 13 + ignoreDeprecated: true + ignorePrivate: true ignoreOverridden: false coroutines: active: true GlobalCoroutineUsage: - active: false + active: true RedundantSuspendModifier: + active: true + SleepInsteadOfDelay: + active: true + SuspendFunWithFlowReturnType: active: false empty-blocks: @@ -167,21 +187,23 @@ exceptions: active: true ExceptionRaisedInUnexpectedLocation: active: true - methodNames: [toString, hashCode, equals, finalize] + methodNames: [ toString, hashCode, equals, finalize ] InstanceOfCheckForException: active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] NotImplementedDeclaration: active: false - PrintStackTrace: + ObjectExtendsThrowable: active: false + PrintStackTrace: + active: true RethrowCaughtException: - active: false + active: true ReturnFromFinally: - active: false + active: true ignoreLabeled: false SwallowedException: - active: false + active: true ignoredExceptionTypes: - InterruptedException - NumberFormatException @@ -189,21 +211,21 @@ exceptions: - MalformedURLException allowedExceptionNameRegex: '_|(ignore|expected).*' ThrowingExceptionFromFinally: - active: false + active: true ThrowingExceptionInMain: - active: false + active: true ThrowingExceptionsWithoutMessageOrCause: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] exceptions: - IllegalArgumentException - IllegalStateException - IOException ThrowingNewInstanceOfSameException: - active: false + active: true TooGenericExceptionCaught: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] exceptionNames: - ArrayIndexOutOfBoundsException - Error @@ -227,7 +249,13 @@ formatting: android: false autoCorrect: true AnnotationOnSeparateLine: - active: false + active: true + autoCorrect: true + AnnotationSpacing: + active: true + autoCorrect: true + ArgumentListWrapping: + active: true autoCorrect: true ChainWrapping: active: true @@ -236,7 +264,7 @@ formatting: active: true autoCorrect: true EnumEntryNameCase: - active: false + active: true autoCorrect: true Filename: active: true @@ -272,7 +300,7 @@ formatting: active: true autoCorrect: true NoEmptyFirstLineInMethodBlock: - active: false + active: true autoCorrect: true NoLineBreakAfterElse: active: true @@ -304,6 +332,9 @@ formatting: active: true autoCorrect: true indentSize: 4 + SpacingAroundAngleBrackets: + active: true + autoCorrect: true SpacingAroundColon: active: true autoCorrect: true @@ -331,6 +362,9 @@ formatting: SpacingAroundRangeOperator: active: true autoCorrect: true + SpacingAroundUnaryOperator: + active: true + autoCorrect: true SpacingBetweenDeclarationsWithAnnotations: active: true autoCorrect: true @@ -345,46 +379,47 @@ naming: active: true ClassNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] classPattern: '[A-Z][a-zA-Z0-9]*' ConstructorParameterNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] parameterPattern: '[a-z][A-Za-z0-9]*' privateParameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' ignoreOverridden: true EnumNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' ForbiddenClassName: active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - forbiddenName: [] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] + forbiddenName: [ ] FunctionMaxLength: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] maximumFunctionNameLength: 30 FunctionMinLength: active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] minimumFunctionNameLength: 3 FunctionNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)' excludeClassPattern: '$^' ignoreOverridden: true - ignoreAnnotated: ['Composable'] + ignoreAnnotated: [ 'Composable' ] FunctionParameterNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] parameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' ignoreOverridden: true InvalidPackageDeclaration: - active: false + active: true + excludes: [ '*.kts' ] rootPackage: '' MatchingDeclarationName: active: true @@ -392,33 +427,38 @@ naming: MemberNameEqualsClassName: active: true ignoreOverridden: true + NoNameShadowing: + active: true + NonBooleanPropertyPrefixedWithIs: + active: false + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] ObjectPropertyNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] constantPattern: '[A-Za-z][_A-Za-z0-9]*' propertyPattern: '[A-Za-z][_A-Za-z0-9]*' privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' PackageNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' TopLevelPropertyNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] constantPattern: '[A-Z][_A-Z0-9]*' propertyPattern: '[A-Za-z][_A-Za-z0-9]*' privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' VariableMaxLength: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] maximumVariableNameLength: 64 VariableMinLength: active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] minimumVariableNameLength: 1 VariableNaming: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] variablePattern: '[a-z][A-Za-z0-9]*' privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' @@ -430,33 +470,39 @@ performance: active: true ForEachOnRange: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] SpreadOperator: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] UnnecessaryTemporaryInstantiation: active: true potential-bugs: active: true + CastToNullableType: + active: true Deprecation: - active: false + active: true + DontDowncastCollectionTypes: + active: true DuplicateCaseInWhenExpression: active: true EqualsAlwaysReturnsTrueOrFalse: active: true EqualsWithHashCodeExist: active: true + ExitOutsideMain: + active: false ExplicitGarbageCollectionCall: active: true HasPlatformType: - active: false + active: true IgnoredReturnValue: active: false restrictToAnnotatedMethods: true - returnValueAnnotations: ['*.CheckReturnValue', '*.CheckResult'] + returnValueAnnotations: [ '*.CheckReturnValue', '*.CheckResult' ] ImplicitDefaultLocale: - active: false + active: true ImplicitUnitReturnType: active: false allowExplicitReturnType: true @@ -467,35 +513,44 @@ potential-bugs: IteratorNotThrowingNoSuchElementException: active: true LateinitUsage: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - excludeAnnotatedProperties: [] + active: true + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] + excludeAnnotatedProperties: [ ] ignoreOnClassesPattern: '' MapGetWithNotNullAssertionOperator: - active: false + active: true MissingWhenCase: active: true + allowElseExpression: true + NullableToStringCall: + active: true RedundantElseInWhen: active: true UnconditionalJumpStatementInLoop: - active: false + active: true UnnecessaryNotNullOperator: - active: false + active: true UnnecessarySafeCall: - active: false + active: true + UnreachableCatchBlock: + active: true UnreachableCode: active: true UnsafeCallOnNullableType: active: true UnsafeCast: - active: false + active: true + UnusedUnaryOperator: + active: true UselessPostfixExpression: - active: false + active: true WrongEqualsTypeParameter: active: true style: active: true + ClassOrdering: + active: false CollapsibleIfStatements: active: true DataClassContainsFunctions: @@ -503,10 +558,13 @@ style: conversionFunctionPrefix: 'to' DataClassShouldBeImmutable: active: true + DestructuringDeclarationWithTooManyEntries: + active: true + maxDestructuringEntries: 3 EqualsNullCall: active: true EqualsOnSignatureLine: - active: false + active: true ExplicitCollectionElementAccessMethod: active: false ExplicitItLambdaParameter: @@ -516,52 +574,59 @@ style: includeLineWrapping: false ForbiddenComment: active: true - values: ['TODO:', 'FIXME:', 'STOPSHIP:'] - allowedPatterns: '' + values: [ 'TODO', 'FIXME:', 'STOPSHIP:' ] + allowedPatterns: 'TODO #' ForbiddenImport: active: false - imports: [] + imports: [ ] forbiddenPatterns: '' ForbiddenMethodCall: - active: true - methods: ['kotlin.io.println', 'kotlin.io.print'] - ForbiddenPublicDataClass: active: false - ignorePackages: ['*.internal', '*.internal.*'] + methods: [ 'kotlin.io.println', 'kotlin.io.print' ] + ForbiddenPublicDataClass: + active: true + excludes: [ '**' ] + ignorePackages: [ '*.internal', '*.internal.*' ] ForbiddenVoid: - active: false + active: true ignoreOverridden: false ignoreUsageInGenerics: false FunctionOnlyReturningConstant: active: true ignoreOverridableFunction: true + ignoreActualFunction: true excludedFunctions: 'describeContents' - excludeAnnotatedFunction: ['dagger.Provides'] + excludeAnnotatedFunction: [ 'dagger.Provides' ] LibraryCodeMustSpecifyReturnType: active: true + excludes: [ '**' ] + LibraryEntitiesShouldNotBePublic: + active: true + excludes: [ '**' ] LoopWithTooManyJumpStatements: active: true maxJumpCount: 1 MagicNumber: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - ignoreNumbers: ['-1', '0', '1', '2'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] + ignoreNumbers: [ '-1', '0', '1', '2' ] ignoreHashCodeFunction: true - ignorePropertyDeclaration: false + ignorePropertyDeclaration: true ignoreLocalVariableDeclaration: false ignoreConstantDeclaration: true ignoreCompanionObjectPropertyDeclaration: true - ignoreAnnotation: false + ignoreAnnotation: true ignoreNamedArgument: true - ignoreEnums: false + ignoreEnums: true ignoreRanges: false + ignoreExtensionFunctions: true MandatoryBracesIfStatements: - active: false + active: true MandatoryBracesLoops: - active: false + active: true MaxLineLength: active: true - maxLineLength: 160 + maxLineLength: 140 excludePackageStatements: true excludeImportStatements: true excludeCommentStatements: false @@ -569,8 +634,10 @@ style: active: true ModifierOrder: active: true - NestedClassesVisibility: + MultilineLambdaItParameter: active: false + NestedClassesVisibility: + active: true NewLineAtEndOfFile: active: true NoTabs: @@ -582,13 +649,15 @@ style: OptionalWhenBraces: active: false PreferToOverPairSyntax: - active: false + active: true ProtectedMemberInFinalClass: active: true RedundantExplicitType: active: false - RedundantVisibilityModifierRule: + RedundantHigherOrderMapUsage: active: false + RedundantVisibilityModifierRule: + active: true ReturnCount: active: true max: 2 @@ -599,60 +668,72 @@ style: SafeCast: active: true SerialVersionUIDInSerializableClass: - active: false + active: true SpacingBetweenPackageAndImports: - active: false + active: true ThrowsCount: active: true max: 2 TrailingWhitespace: - active: false + active: true UnderscoresInNumericLiterals: - active: false + active: true acceptableDecimalLength: 5 UnnecessaryAbstractClass: active: true - excludeAnnotatedClasses: ['dagger.Module'] + excludeAnnotatedClasses: [ 'dagger.Module' ] UnnecessaryAnnotationUseSiteTarget: active: false UnnecessaryApply: - active: false + active: true + UnnecessaryFilter: + active: true UnnecessaryInheritance: active: true UnnecessaryLet: - active: false + active: true UnnecessaryParentheses: - active: false + active: true UntilInsteadOfRangeTo: active: false UnusedImports: - active: false + active: true UnusedPrivateClass: active: true UnusedPrivateMember: - active: false + active: true allowedNames: '(_|ignored|expected|serialVersionUID)' UseArrayLiteralsInAnnotations: - active: false + active: true + UseCheckNotNull: + active: true UseCheckOrError: - active: false + active: true UseDataClass: - active: false - excludeAnnotatedClasses: [] + active: true + excludeAnnotatedClasses: [ ] allowVars: false UseEmptyCounterpart: active: false + UseIfEmptyOrIfBlank: + active: true UseIfInsteadOfWhen: active: false + UseIsNullOrEmpty: + active: true + UseOrEmpty: + active: true UseRequire: - active: false + active: true + UseRequireNotNull: + active: true UselessCallOnNotNull: active: true UtilityClassWithPublicConstructor: active: true VarCouldBeVal: - active: false + active: true WildcardImport: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - excludeImports: ['java.util.*', 'kotlinx.android.synthetic.*'] + excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ] + excludeImports: [ 'java.util.*', 'kotlinx.android.synthetic.*' ] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..ffed3a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 43369d7..4f906e0 100755 --- a/gradlew +++ b/gradlew @@ -26,22 +26,22 @@ # 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 +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 || true -APP_HOME="$(pwd -P)" +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" -APP_BASE_NAME=$(basename "$0") +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"' @@ -49,15 +49,15 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn() { - echo "$*" +warn () { + echo "$*" } -die() { - echo - echo "$*" - echo - exit 1 +die () { + echo + echo "$*" + echo + exit 1 } # OS specific support (must be 'true' or 'false'). @@ -65,118 +65,119 @@ 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 + ;; + 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 +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 + 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" + 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" +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 - 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\"" + 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\"" +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 - 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 + # 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 " " +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -APP_ARGS=$(save "$@") +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" diff --git a/src/main/kotlin/pw/forst/katlib/IterableExtensions.kt b/src/main/kotlin/pw/forst/katlib/IterableExtensions.kt index baeed0b..158f1ef 100644 --- a/src/main/kotlin/pw/forst/katlib/IterableExtensions.kt +++ b/src/main/kotlin/pw/forst/katlib/IterableExtensions.kt @@ -70,8 +70,8 @@ fun Iterable>.sumByIndexes(): List { } /** - * Sums all Lists of integers into single one by indexes (i.e. all the numbers with the same index are always summed together). If the lists have different - * lengths, the final list has length corresponding to the shortest list in [this] iterable. + * Sums all Lists of integers into single one by indexes (i.e. all the numbers with the same index are always summed together). + * If the lists have different lengths, the final list has length corresponding to the shortest list in [this] iterable. */ fun Iterable>.sumDoublesByIndexes(): List { val minSize = requireNotNull(this.minValueBy { it.size }) { "Only nonempty collections are supported." } @@ -140,7 +140,8 @@ inline fun Iterable.dominantValueBy(crossinline selector: (T) -> R): R this.groupingBy(selector).eachCount().maxByOrNull { it.value }?.key /** - * Creates cartesian product between all the elements from [this] and [other] iterable. E.g. when [this] contains [1,2,3] and [other] contains ['a', 'b'], the + * Creates cartesian product between all the elements from [this] and [other] iterable. + * E.g. when [this] contains [1,2,3] and [other] contains ['a', 'b'], the * result will be {Pair(1,'a'), Pair(1,'b'), Pair(2,'a'), Pair(2,'b'), Pair(3,'a'), Pair(3,'b')}. */ fun Iterable.cartesianProduct(other: Iterable): Set> { @@ -326,7 +327,7 @@ inline fun > Iterable.assocTo(destination * Returns a [Map] containing the elements from the given collection indexed by the key * returned from [keySelector] function applied to each element. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. * * The returned map preserves the entry iteration order of the original collection. */ @@ -339,7 +340,7 @@ inline fun Iterable.assocBy(keySelector: (T) -> K): Map { * where key is provided by the [keySelector] function applied to each element of the given collection * and value is the element itself. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. */ inline fun > Iterable.assocByTo(destination: M, keySelector: (T) -> K): M { var size = 0 @@ -352,9 +353,10 @@ inline fun > Iterable.assocByTo(destination: } /** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given collection. + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] + * functions applied to elements of the given collection. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. * * The returned map preserves the entry iteration order of the original collection. */ @@ -364,12 +366,15 @@ inline fun Iterable.assocBy(keySelector: (T) -> K, valueTransform: /** * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and + * where key is provided by the [keySelector] function * and value is provided by the [valueTransform] function applied to elements of the given collection. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. */ -inline fun > Iterable.assocByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { +inline fun > Iterable.assocByTo( + destination: M, keySelector: (T) -> K, + valueTransform: (T) -> V +): M { var size = 0 for (element in this) { destination.put(keySelector(element), valueTransform(element)) @@ -473,7 +478,8 @@ internal val iterableLogger = Logger.getLogger("pw.forst.katlib.IterableExtensio internal const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 /** - * Checks that [this] map has [expectedSize] and if it is not the case (because value for some key was overwritten), warning with affected keys is generated. + * Checks that [this] map has [expectedSize] and if it is not the case (because value for some key was overwritten), + * warning with affected keys is generated. */ @PublishedApi internal inline fun > M.checkUniqueness(expectedSize: Int, grouping: () -> Map>) { @@ -528,7 +534,8 @@ inline fun Iterable.flatMapIndexedNotNull(transform: (index: Int, T) - } /** - * Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination]. + * Appends all elements yielded from results of [transform] function being invoked on each element of original collection, + * to the given [destination]. */ inline fun > Iterable.flatMapIndexedTo( destination: C, @@ -544,7 +551,7 @@ inline fun > Iterable.flatMapIndexedTo( } /** - * Validates the relationship between every element of an Iterable. + * Validates the relationship between every element of Iterable. * * Iterates through the elements invoking the validationFunction on each one. * Returns false on the first element that does not pass the validation function, otherwise true. diff --git a/src/main/kotlin/pw/forst/katlib/JacksonExtensions.kt b/src/main/kotlin/pw/forst/katlib/JacksonExtensions.kt index c872680..9829b14 100644 --- a/src/main/kotlin/pw/forst/katlib/JacksonExtensions.kt +++ b/src/main/kotlin/pw/forst/katlib/JacksonExtensions.kt @@ -38,8 +38,11 @@ inline fun parseJson(json: ByteArray, logParserException: Boolean = @PublishedApi internal fun Result.getOrLog(json: String, logParserException: Boolean) = - onFailure { if (logParserException) jsonLogger.warning("Exception raised during JSON parsing:$newLine${it.message}$newLine$json$newLine") } - .getOrNull() + onFailure { + if (logParserException) { + jsonLogger.warning("Exception raised during JSON parsing:$newLine${it.message}$newLine$json$newLine") + } + }.getOrNull() /** * Serializes given object to string. diff --git a/src/main/kotlin/pw/forst/katlib/MapExtensions.kt b/src/main/kotlin/pw/forst/katlib/MapExtensions.kt index 6422f74..880deac 100644 --- a/src/main/kotlin/pw/forst/katlib/MapExtensions.kt +++ b/src/main/kotlin/pw/forst/katlib/MapExtensions.kt @@ -30,7 +30,8 @@ fun Map.getWeightedRandom(rand: Random): T { /** - * Randomly sorts the items with respect to the current weight distribution. [normalizer] is used to normalize the random value obtained from [rand] to control + * Randomly sorts the items with respect to the current weight distribution. + * [normalizer] is used to normalize the random value obtained from [rand] to control * how important the original weights are. With higher [normalizer] the importance of the random factor decreases. */ fun Map.getKeysInWeightedRandomOrder(normalizer: Double, rand: Random): List { @@ -38,14 +39,16 @@ fun Map.getKeysInWeightedRandomOrder(normalizer: Double, rand: Ra } /** - * Merges two maps together using the given [reduce] function. By default, the reduce function keeps the value from [this] map. + * Merges two maps together using the given [reduce] function. + * By default, the reduce function keeps the value from [this] map. */ inline fun Map.mergeReduce(other: Map, reduce: (V, V) -> V = { a, _ -> a }): Map { return mergeReduceTo(LinkedHashMap(this.size + other.size), other, reduce) } /** - * Merges two maps together using the given [reduce] function into the given [destination]. By default, the reduce function keeps the value from [this] map. + * Merges two maps together using the given [reduce] function into the given [destination]. + * By default, the reduce function keeps the value from [this] map. */ inline fun > Map.mergeReduceTo(destination: M, other: Map, reduce: (V, V) -> V = { a, _ -> a }): M { destination.putAll(this) @@ -74,14 +77,15 @@ inline fun > Map.joinTo(destination: } /** - * Swaps dimensions in two dimensional map. The returned map has keys from the second dimension as primary keys and primary keys are used in the second - * dimension. + * Swaps dimensions in two dimensional map. The returned map has keys from the second dimension as primary keys + * and primary keys are used in the second dimension. */ fun Map>.swapKeys(): Map> = swapKeysTo(LinkedHashMap()) { LinkedHashMap() } /** - * Swaps dimensions in two dimensional map. The returned map has keys from the second dimension as primary keys and primary keys are stored in the second - * dimension. [topDestination] specifies which map should be used to store the new primary keys and [bottomDestination] is used to store the new secondary keys. + * Swaps dimensions in two dimensional map. The returned map has keys from the second dimension as primary keys + * and primary keys are stored in the second dimension. [topDestination] specifies which map should be used to store the new primary keys + * and [bottomDestination] is used to store the new secondary keys. */ inline fun , M1 : MutableMap> Map>.swapKeysTo( topDestination: M1, @@ -96,7 +100,8 @@ inline fun , M1 : MutableMap> Map Map>>.swapKeys(transform: (K1, K2, K3) -> Triple): @@ -104,11 +109,14 @@ inline fun Map>>.swapKeys( this.swapKeysTo(LinkedHashMap(), { LinkedHashMap>() }, { LinkedHashMap() }, transform) /** - * Works similarly as [swapKeys] but the final map has three levels. [transform] specifies how the keys should be swapped (or modified) in the newly created - * map. [topDestination] specifies which map should be used to store the new primary keys, [middleDestination] is used to store the new secondary keys and + * Works similarly as [swapKeys] but the final map has three levels. + * [transform] specifies how the keys should be swapped (or modified) in the newly created + * map. [topDestination] specifies which map should be used to store the new primary keys, + * [middleDestination] is used to store the new secondary keys and * [bottomDestination] is used to store the new tertiary keys. */ -inline fun , M2 : MutableMap, M1 : MutableMap> Map>>.swapKeysTo( +inline fun , M2 : MutableMap, M1 : MutableMap> + Map>>.swapKeysTo( topDestination: M1, middleDestination: () -> M2, bottomDestination: () -> M3, @@ -126,14 +134,15 @@ inline fun , M2 : MutableM } /** - * Transforms map of pairs as a keys into two dimensional map where the first elements in the pair are used as primary keys and second elements as secondary - * keys. + * Transforms map of pairs as a keys into two-dimensional map where the first elements in the pair are used as primary keys + * and second elements as secondary keys. */ fun Map, V>.toTwoLevelMap(): Map> = toTwoLevelMap(LinkedHashMap()) { LinkedHashMap() } /** - * Transforms map of pairs as a keys into two dimensional map where the first elements in the pair are used as primary keys and second elements as secondary - * keys. [topDestination] specifies which map should be used to store the new primary keys and [bottomDestination] is used to store the new secondary keys. + * Transforms map of pairs as a keys into two-dimensional map where the first elements in the pair are used as primary keys + * and second elements as secondary keys. [topDestination] specifies which map should be used to store the new primary keys and + * [bottomDestination] is used to store the new secondary keys. */ inline fun , M1 : MutableMap> Map, V>.toTwoLevelMap( topDestination: M1, @@ -147,15 +156,16 @@ inline fun , M1 : MutableMap> Map List, V>>.toTwoLevelMap(): Map> = toTwoLevelMap(LinkedHashMap()) { LinkedHashMap() } /** - * Transforms list of pairs, where the first element consists of pairs into two dimensional map where the first elements from the inner pair are used as - * primary keys and second elements as secondary keys. [topDestination] specifies which map should be used to store the new primary keys and - * [bottomDestination] is used to store the new secondary keys. + * Transforms list of pairs, where the first element consists of pairs into two-dimensional map where the first elements + * from the inner pair are used as primary keys and second elements as secondary keys. + * [topDestination] specifies which map should be used to store the new primary keys and [bottomDestination] is used to store the new + * secondary keys. */ inline fun , M1 : MutableMap> List, V>>.toTwoLevelMap( topDestination: M1, @@ -175,10 +185,12 @@ fun Map, V>.toThreeLevelMap(): Map>() }, { LinkedHashMap() }) /** - * Works similarly as [toTwoLevelMap] but the final map has three levels. [topDestination] specifies which map should be used to store the new primary keys, + * Works similarly as [toTwoLevelMap] but the final map has three levels. + * [topDestination] specifies which map should be used to store the new primary keys, * [middleDestination] is used to store the new secondary keys and [bottomDestination] is used to store the new tertiary keys. */ -inline fun , M2 : MutableMap, M1 : MutableMap> Map, V>.toThreeLevelMap( +inline fun , M2 : MutableMap, M1 : MutableMap> + Map, V>.toThreeLevelMap( topDestination: M1, middleDestination: () -> M2, bottomDestination: () -> M3 diff --git a/src/main/kotlin/pw/forst/katlib/SequenceExtensions.kt b/src/main/kotlin/pw/forst/katlib/SequenceExtensions.kt index bc9d72e..ccbbea3 100644 --- a/src/main/kotlin/pw/forst/katlib/SequenceExtensions.kt +++ b/src/main/kotlin/pw/forst/katlib/SequenceExtensions.kt @@ -51,7 +51,7 @@ inline fun Sequence.assoc(transform: (T) -> Pair): Map * Returns a [Map] containing the elements from the given collection indexed by the key * returned from [keySelector] function applied to each element. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. * * The returned map preserves the entry iteration order of the original collection. */ @@ -59,9 +59,10 @@ inline fun Sequence.assocBy(keySelector: (T) -> K): Map = assocByTo(LinkedHashMap(defaultMapCapacity()), keySelector) /** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given collection. + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] + * functions applied to elements of the given collection. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. * * The returned map preserves the entry iteration order of the original collection. */ @@ -73,7 +74,7 @@ inline fun Sequence.assocBy(keySelector: (T) -> K, valueTransform: * where key is provided by the [keySelector] function applied to each element of the given collection * and value is the element itself. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. */ inline fun > Sequence.assocByTo(destination: M, keySelector: (T) -> K): M { var size = 0 @@ -87,12 +88,16 @@ inline fun > Sequence.assocByTo(destination: /** * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and + * where key is provided by the [keySelector] function * and value is provided by the [valueTransform] function applied to elements of the given collection. * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. + * If any two elements had the same key returned by [keySelector] the last one gets added to the map and the method creates a warning. */ -inline fun > Sequence.assocByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { +inline fun > Sequence.assocByTo( + destination: M, + keySelector: (T) -> K, + valueTransform: (T) -> V +): M { var size = 0 for (element in this) { destination.put(keySelector(element), valueTransform(element)) diff --git a/src/main/kotlin/pw/forst/katlib/StringExtensions.kt b/src/main/kotlin/pw/forst/katlib/StringExtensions.kt index 03397e3..66bd5ce 100644 --- a/src/main/kotlin/pw/forst/katlib/StringExtensions.kt +++ b/src/main/kotlin/pw/forst/katlib/StringExtensions.kt @@ -10,13 +10,16 @@ import java.util.regex.Pattern * For example, returns "ABCD…" when called for "ABCDEFHG".(5, "…") */ fun String.restrictLengthWithEllipsis(maxLength: Int, ellipsis: String = "…"): String = - if (this.length <= maxLength) this - else this.substring(0, maxLength - ellipsis.length) + ellipsis + if (this.length <= maxLength) { + this + } else { + this.substring(0, maxLength - ellipsis.length) + ellipsis + } private val regexStartsWithLetter = "^[a-zA-Z]".toRegex() /** - * Returns true if the string starts with a latin letter a-z or A-Z + * Returns true if the string starts with a latin letter a-z or A-Z. */ fun String.startsWithLetter() = this.contains(regexStartsWithLetter) diff --git a/src/test/kotlin/pw/forst/katlib/MapExtensionsTest.kt b/src/test/kotlin/pw/forst/katlib/MapExtensionsTest.kt index 896d1f3..3368311 100644 --- a/src/test/kotlin/pw/forst/katlib/MapExtensionsTest.kt +++ b/src/test/kotlin/pw/forst/katlib/MapExtensionsTest.kt @@ -219,7 +219,9 @@ internal class MapExtensionsTest { val map1 = mapOf(1 to listOf("a", "b"), 2 to listOf("b"), 3 to listOf("c")) val map2 = mapOf(2 to listOf("d"), 3 to listOf("c", "d", "e"), 4 to listOf("f")) val map3 = mapOf(2 to listOf("x"), 3 to listOf("y"), 4 to listOf("z", "k")) - val expected = mapOf(1 to listOf("a", "b"), 2 to listOf("b", "d", "x"), 3 to listOf("c", "c", "d", "e", "y"), 4 to listOf("f", "z", "k")) + val expected = mapOf( + 1 to listOf("a", "b"), 2 to listOf("b", "d", "x"), 3 to listOf("c", "c", "d", "e", "y"), 4 to listOf("f", "z", "k") + ) assertEquals(expected, listOf(map1, map2, map3).flatMerge()) } } diff --git a/src/test/kotlin/pw/forst/katlib/OtherExtensionsTest.kt b/src/test/kotlin/pw/forst/katlib/OtherExtensionsTest.kt index f402801..1dd4d71 100644 --- a/src/test/kotlin/pw/forst/katlib/OtherExtensionsTest.kt +++ b/src/test/kotlin/pw/forst/katlib/OtherExtensionsTest.kt @@ -180,7 +180,7 @@ internal class OtherExtensionsTest { @Test fun `test isURL valid urls`() { val inputs = (0..5).map { "http://hello.com/$it" } + listOf("https://gooo.pw/a#b", "https://sm.ai:90") - inputs.forEach { isUrl(it).whenFalse { org.junit.jupiter.api.fail("Method did not recognize correctly $it! This is valid URL") } } + inputs.forEach { isUrl(it).whenFalse { fail("Method did not recognize correctly $it! This is valid URL") } } } /** @@ -189,25 +189,29 @@ internal class OtherExtensionsTest { @Test fun isUrlFalsePositives() { val inputs = listOf("https://sm.ai,", "https://,", "https:/sm.ai/sd", "https:sm.ai/sd") - inputs.forEach { isUrl(it).whenFalse { org.junit.jupiter.api.fail("Method did recognize correctly $it, however it is expected to fail") } } + inputs.forEach { + isUrl(it).whenFalse { + fail("Method did recognize correctly $it, however it is expected to fail") + } + } } @Test fun `test isURL invalid urls`() { val inputs = (0..5).map { it.toString() } + listOf("gooo.pw", "ht://", "https//:sm.ai/sd", UUID.randomUUID().toString()) - inputs.forEach { isUrl(it).whenTrue { org.junit.jupiter.api.fail("Method did not recognize correctly $it. This is not valid URL.") } } + inputs.forEach { isUrl(it).whenTrue { fail("Method did not recognize correctly $it. This is not valid URL.") } } } @Test fun `test isUUID with valid inputs`() { val inputs = (0..5).map { UUID.randomUUID() } + UUID(0L, 0L) - inputs.forEach { isUuid(it.toString()).whenFalse { org.junit.jupiter.api.fail("Method did recognize correctly $it, it is valid UUID.") } } + inputs.forEach { isUuid(it.toString()).whenFalse { fail("Method did recognize correctly $it, it is valid UUID.") } } } @Test fun `test isUUID with invalid inputs`() { val inputs = (0..5).map { it.toString() } + listOf("ajksdjkfjkgf", "", "sdfghfg", Long.toString()) - inputs.forEach { isUuid(it).whenTrue { org.junit.jupiter.api.fail("Method did recognize correctly $it, it is not valid UUID.") } } + inputs.forEach { isUuid(it).whenTrue { fail("Method did recognize correctly $it, it is not valid UUID.") } } } @Test diff --git a/src/test/kotlin/pw/forst/katlib/ServicesTest.kt b/src/test/kotlin/pw/forst/katlib/ServicesTest.kt index ba24e4f..248eb2e 100644 --- a/src/test/kotlin/pw/forst/katlib/ServicesTest.kt +++ b/src/test/kotlin/pw/forst/katlib/ServicesTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue class ServicesTest { @Test fun `test mock TimeProvider`() { - val time = Instant.ofEpochSecond(1000000L) + val time = Instant.ofEpochSecond(1_000_000L) val timeProviderMock = mockk>() every { timeProviderMock.now() } returns time