├── .gitattributes
├── subprojects
├── kotlin-for-java-devs
│ ├── src
│ │ ├── main
│ │ │ ├── resources
│ │ │ │ └── hello.txt
│ │ │ ├── kotlin
│ │ │ │ └── org
│ │ │ │ │ └── sdkotlin
│ │ │ │ │ ├── intro
│ │ │ │ │ └── kotlin
│ │ │ │ │ │ ├── _04_imports
│ │ │ │ │ │ ├── otherpackage
│ │ │ │ │ │ │ └── Thing1.kt
│ │ │ │ │ │ └── ImportsInKotlin.kt
│ │ │ │ │ │ ├── _23_generics
│ │ │ │ │ │ └── util
│ │ │ │ │ │ │ └── Utilities.kt
│ │ │ │ │ │ ├── _XX_tdd
│ │ │ │ │ │ └── TddInKotlin.kt
│ │ │ │ │ │ ├── _XX_reflection
│ │ │ │ │ │ └── ReflectionInKotlin.kt
│ │ │ │ │ │ ├── _XX_scopingfunctions
│ │ │ │ │ │ └── ScopingFunctionsInKotlin.kt
│ │ │ │ │ │ ├── _02_helloworld
│ │ │ │ │ │ ├── HelloKotlin.kt
│ │ │ │ │ │ └── withargs
│ │ │ │ │ │ │ └── HelloWithArgs.kt
│ │ │ │ │ │ ├── _01_packages
│ │ │ │ │ │ └── PackagesInKotlin.kt
│ │ │ │ │ │ ├── _30_sealedtypes
│ │ │ │ │ │ ├── UnknownPlayer.kt
│ │ │ │ │ │ ├── otherpackage
│ │ │ │ │ │ │ ├── OtherPackagePlayer.kt
│ │ │ │ │ │ │ └── AiNPC.kt
│ │ │ │ │ │ └── SealedTypesInKotlin.kt
│ │ │ │ │ │ ├── _00_classes
│ │ │ │ │ │ └── ClassesInKotlin.kt
│ │ │ │ │ │ ├── _03_toplevel
│ │ │ │ │ │ ├── TopLevelInKotlin.kt
│ │ │ │ │ │ └── usage
│ │ │ │ │ │ │ └── TopLevelUsageInKotlin.kt
│ │ │ │ │ │ ├── _07_equality
│ │ │ │ │ │ └── EqualityInKotlin.kt
│ │ │ │ │ │ ├── _08_3_extensionfunctions
│ │ │ │ │ │ ├── otherpackage
│ │ │ │ │ │ │ └── ExtensionFunctionScopingInKotlin.kt
│ │ │ │ │ │ └── ExtensionFunctionsInKotlin.kt
│ │ │ │ │ │ ├── _08_2_tailrecursivefunctions
│ │ │ │ │ │ ├── TailRecursionDebugging.kt
│ │ │ │ │ │ └── TailRecursionInKotlin.kt
│ │ │ │ │ │ ├── _05_1_unsigned_types
│ │ │ │ │ │ └── UnsignedTypesInKotlin.kt
│ │ │ │ │ │ ├── _XX_try_w_resources
│ │ │ │ │ │ └── TryWithResourcesInKotlin.kt
│ │ │ │ │ │ ├── _16_static
│ │ │ │ │ │ └── StaticInKotlin.kt
│ │ │ │ │ │ ├── _08_5_infixfunctions
│ │ │ │ │ │ └── InfixFunctionsInKotlin.kt
│ │ │ │ │ │ ├── _32_delegation
│ │ │ │ │ │ └── LateInit.kt
│ │ │ │ │ │ ├── _15_singletons
│ │ │ │ │ │ └── SingletonInKotlin.kt
│ │ │ │ │ │ ├── _06_strings
│ │ │ │ │ │ └── StringsInKotlin.kt
│ │ │ │ │ │ ├── _18_inheritance
│ │ │ │ │ │ └── InheritanceInKotlin.kt
│ │ │ │ │ │ ├── _19_abstractclasses
│ │ │ │ │ │ └── AbstractClassesInKotlin.kt
│ │ │ │ │ │ ├── _12_properties
│ │ │ │ │ │ └── PropertiesInKotlin.kt
│ │ │ │ │ │ ├── _08_4_operatorfunctions
│ │ │ │ │ │ └── OperatorOverloadingInKotlin.kt
│ │ │ │ │ │ ├── _05_0_variables_and_types
│ │ │ │ │ │ └── VariablesAndTypesInKotlin.kt
│ │ │ │ │ │ ├── _17_constants
│ │ │ │ │ │ └── ConstantsInKotlin.kt
│ │ │ │ │ │ ├── _11_iteration
│ │ │ │ │ │ └── IterationInKotlin.kt
│ │ │ │ │ │ ├── _13_constructors
│ │ │ │ │ │ └── ConstructorsAndInitializersInKotlin.kt
│ │ │ │ │ │ ├── _25_varargfunctions
│ │ │ │ │ │ └── VarargsInKotlin.kt
│ │ │ │ │ │ ├── _21_smartcasts
│ │ │ │ │ │ └── SmartCastsInKotlin.kt
│ │ │ │ │ │ ├── _XX_coroutines
│ │ │ │ │ │ └── CoroutinesInKotlin.kt
│ │ │ │ │ │ ├── _10_selection
│ │ │ │ │ │ └── SelectionInKotlin.kt
│ │ │ │ │ │ ├── _20_interfaces
│ │ │ │ │ │ └── InterfacesInKotlin.kt
│ │ │ │ │ │ ├── _08_0_functions
│ │ │ │ │ │ └── FunctionsInKotlin.kt
│ │ │ │ │ │ ├── _29_enums
│ │ │ │ │ │ └── EnumsInKotlin.kt
│ │ │ │ │ │ ├── _31_annotations
│ │ │ │ │ │ └── AnnotationsInKotlin.kt
│ │ │ │ │ │ └── _26_collections
│ │ │ │ │ │ └── CollectionsInKotlin.kt
│ │ │ │ │ ├── javainterop
│ │ │ │ │ └── _XX_constants
│ │ │ │ │ │ ├── ConstantsInKotlinObject.kt
│ │ │ │ │ │ ├── ConstantsInKotlin.kt
│ │ │ │ │ │ └── ConstantsInKotlinCompanion.kt
│ │ │ │ │ └── meetup
│ │ │ │ │ └── firstwednesday
│ │ │ │ │ └── SDKotlin.kt
│ │ │ └── java
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── intro
│ │ │ │ └── java
│ │ │ │ ├── _01_packages
│ │ │ │ └── PackagesInJava.java
│ │ │ │ ├── _06_strings
│ │ │ │ └── StringsInJava.java
│ │ │ │ ├── _13_constructors
│ │ │ │ └── ConstructorsAndInitializersInJava.java
│ │ │ │ ├── _02_helloworld
│ │ │ │ ├── HelloJava.java
│ │ │ │ └── HelloJava21.java
│ │ │ │ ├── _17_constants
│ │ │ │ └── ConstantsInJava.java
│ │ │ │ ├── _00_classes
│ │ │ │ └── ClassesInJava.java
│ │ │ │ ├── _16_static
│ │ │ │ └── StaticInJava.java
│ │ │ │ ├── _22_nullsafety
│ │ │ │ └── NullSafetyInJava.java
│ │ │ │ ├── _24_arrays
│ │ │ │ └── ArraysInJava.java
│ │ │ │ ├── _10_selection
│ │ │ │ └── SelectionInJava.java
│ │ │ │ ├── _XX_try_w_resources
│ │ │ │ └── TryWithResourcesInJava.java
│ │ │ │ ├── _11_iteration
│ │ │ │ └── IterationInJava.java
│ │ │ │ ├── _06_equality
│ │ │ │ └── EqualityInJava.java
│ │ │ │ ├── _05_variables
│ │ │ │ └── VariablesAndTypesInJava.java
│ │ │ │ ├── _14_dataclasses
│ │ │ │ └── DataClassesInJava.java
│ │ │ │ ├── _28_variance
│ │ │ │ └── VarianceInJava.java
│ │ │ │ └── _15_singletons
│ │ │ │ └── SingletonsInJava.java
│ │ └── test
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── intro
│ │ │ └── kotlin
│ │ │ ├── _XX_tdd
│ │ │ └── TddInKotlinTest.kt
│ │ │ └── _14_0_dataclasses
│ │ │ └── PolyglotPersonTest.kt
│ ├── README.md
│ └── build.gradle.kts
├── tdd-in-kotlin
│ ├── src
│ │ ├── test
│ │ │ ├── resources
│ │ │ │ └── io
│ │ │ │ │ └── mockk
│ │ │ │ │ └── settings.properties
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── tdd
│ │ │ │ ├── fizzbuzz
│ │ │ │ ├── TestPrinter.kt
│ │ │ │ ├── FizzBuzzMockKTest.kt
│ │ │ │ ├── FizzBuzzMockitoKotlinTest.kt
│ │ │ │ └── FizzBuzzTest.kt
│ │ │ │ ├── assertj
│ │ │ │ └── FloatingPointAssertionsTest.kt
│ │ │ │ ├── testfixtures
│ │ │ │ └── InternalComponentTest.kt
│ │ │ │ ├── mockk
│ │ │ │ └── MockKValueClassParameterTest.kt
│ │ │ │ └── sorting
│ │ │ │ ├── KotestSortTest.kt
│ │ │ │ ├── JUnit5LoopingSortTest.kt
│ │ │ │ ├── JUnit5DynamicTestSortTest.kt
│ │ │ │ ├── JUnit5ParameterizedSortTest.kt
│ │ │ │ └── JUnit5SortTest.kt
│ │ ├── main
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── tdd
│ │ │ │ ├── fizzbuzz
│ │ │ │ ├── Printer.kt
│ │ │ │ ├── ConsolePrinter.kt
│ │ │ │ └── FizzBuzz.kt
│ │ │ │ ├── sorting
│ │ │ │ └── Sorting.kt
│ │ │ │ └── testfixtures
│ │ │ │ └── InternalComponent.kt
│ │ └── testFixtures
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── tdd
│ │ │ └── testfixtures
│ │ │ └── InternalComponentTestDouble.kt
│ └── build.gradle.kts
├── constant-dependencies
│ ├── constant-producer
│ │ ├── build.gradle.kts
│ │ └── src
│ │ │ └── main
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── constants
│ │ │ └── producer
│ │ │ └── CompanionConstants.kt
│ └── constant-consumer
│ │ ├── build.gradle.kts
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── constants
│ │ └── consumer
│ │ └── CompanionConstantConsumer.kt
├── sorting-in-kotlin
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkoltin
│ │ │ └── sort
│ │ │ ├── BubbleSort.kt
│ │ │ └── Swap.kt
│ │ └── test
│ │ └── kotlin
│ │ └── org
│ │ └── sdkoltin
│ │ └── sort
│ │ ├── SortTestCases.kt
│ │ ├── BubbleSortKtTest.kt
│ │ └── SwapKtTest.kt
├── testing-with-mokkery
│ ├── src
│ │ ├── main
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── testing
│ │ │ │ └── mokkery
│ │ │ │ ├── ValueClassSuperType.kt
│ │ │ │ ├── DataClassSuperType.kt
│ │ │ │ ├── ValueClass.kt
│ │ │ │ └── DataClass.kt
│ │ └── test
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── testing
│ │ │ └── mokkery
│ │ │ └── MokkeryValueClassParameterTest.kt
│ └── build.gradle.kts
├── ksp-builder-generator
│ ├── api
│ │ ├── builder
│ │ │ ├── build.gradle.kts
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── buildergen
│ │ │ │ └── api
│ │ │ │ └── builder
│ │ │ │ └── Builder.kt
│ │ └── annotations
│ │ │ ├── build.gradle.kts
│ │ │ └── src
│ │ │ ├── main
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── buildergen
│ │ │ │ └── api
│ │ │ │ └── annotations
│ │ │ │ └── GeneratedBuilder.kt
│ │ │ └── test
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── buildergen
│ │ │ └── api
│ │ │ └── annotations
│ │ │ └── GeneratedBuilderTest.kt
│ └── processor
│ │ ├── src
│ │ └── main
│ │ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── services
│ │ │ │ └── com.google.devtools.ksp.processing.SymbolProcessorProvider
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── buildergen
│ │ │ └── processor
│ │ │ ├── BuilderGenSymbolProcessorProvider.kt
│ │ │ └── BuilderGenSymbolProcessor.kt
│ │ ├── test-project
│ │ ├── src
│ │ │ ├── main
│ │ │ │ └── kotlin
│ │ │ │ │ └── org
│ │ │ │ │ └── sdkotlin
│ │ │ │ │ └── buildergen
│ │ │ │ │ └── processor
│ │ │ │ │ └── it
│ │ │ │ │ └── TestEntity.kt
│ │ │ └── test
│ │ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── buildergen
│ │ │ │ └── processor
│ │ │ │ └── it
│ │ │ │ └── TestEntityBuilderTest.kt
│ │ └── build.gradle.kts
│ │ └── build.gradle.kts
├── di-with-koin
│ ├── src
│ │ ├── main
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── koin
│ │ │ │ └── hello
│ │ │ │ ├── ExternalComponent.kt
│ │ │ │ ├── GreetingService.kt
│ │ │ │ ├── HelloController.kt
│ │ │ │ ├── ExternalComponentContainer.kt
│ │ │ │ ├── HelloKoin.kt
│ │ │ │ ├── SimpleHelloController.kt
│ │ │ │ ├── EnglishGreetingService.kt
│ │ │ │ ├── HelloApp.kt
│ │ │ │ ├── RandomGreetingService.kt
│ │ │ │ └── helloModule.kt
│ │ ├── it
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── koin
│ │ │ │ └── it
│ │ │ │ └── hello
│ │ │ │ ├── test
│ │ │ │ ├── testHelloModule.kt
│ │ │ │ └── TestGreetingService.kt
│ │ │ │ ├── HelloControllerIT.kt
│ │ │ │ └── HelloModuleIT.kt
│ │ └── test
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── koin
│ │ │ └── hello
│ │ │ ├── RandomGreetingServiceTest.kt
│ │ │ ├── EnglishGreetingServiceTest.kt
│ │ │ └── SimpleHelloControllerTest.kt
│ └── build.gradle.kts
├── kotlin-reflect
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── kotlin
│ │ └── reflect
│ │ └── SealedSubclasses.kt
├── effective-kotlin
│ ├── build.gradle.kts
│ ├── README.md
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── meetup
│ │ ├── effectivejava
│ │ ├── item62
│ │ │ └── AvoidStrings.kt
│ │ ├── item58
│ │ │ └── PreferForEach.kt
│ │ ├── item3and4
│ │ │ └── Singletons.kt
│ │ ├── item17
│ │ │ └── MinimizeMutability.kt
│ │ ├── item2
│ │ │ └── ConsiderBuilders.kt
│ │ ├── item10through13
│ │ │ └── CommonMethods.kt
│ │ ├── item16
│ │ │ └── AccessorsOverFields.kt
│ │ ├── item50
│ │ │ └── MakeDefensiveCopies.kt
│ │ ├── item18and19
│ │ │ └── FavorComposition.kt
│ │ └── item1
│ │ │ └── ConsiderStaticFactoryMethods.kt
│ │ └── idioms
│ │ ├── Destructuring.kt
│ │ ├── Nulls.kt
│ │ └── ControlStructuresAsExpressions.kt
├── user-defined-integrals-in-kotlin
│ ├── src
│ │ ├── main
│ │ │ └── kotlin
│ │ │ │ └── org
│ │ │ │ └── sdkotlin
│ │ │ │ └── integral
│ │ │ │ ├── Progression.kt
│ │ │ │ ├── Integral.kt
│ │ │ │ ├── IntegralRange.kt
│ │ │ │ ├── Octal.kt
│ │ │ │ ├── UOctal.kt
│ │ │ │ └── IntegralProgression.kt
│ │ └── test
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── integral
│ │ │ ├── IntegralProgressionTest.kt
│ │ │ ├── IntegralRangeTest.kt
│ │ │ └── SignedIntegral.kt
│ └── build.gradle.kts
├── kotlin-for-java-devs-client
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── intro
│ │ └── kotlin
│ │ └── _30_sealedtypes
│ │ ├── OtherModulePlayer.kt
│ │ ├── SealedTypeSmartCastFromOtherModule.kt
│ │ └── otherpackage
│ │ └── OtherModuleAndPackageNPC.kt
├── typed-errors-in-kotlin
│ ├── src
│ │ └── main
│ │ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── typederrors
│ │ │ ├── FruitBasket.kt
│ │ │ ├── Fruit.kt
│ │ │ ├── TypedError.kt
│ │ │ ├── union
│ │ │ └── ConvertersWithUnionTypes.kt
│ │ │ ├── raise
│ │ │ ├── ConvertersWithRaise.kt
│ │ │ └── TypedErrorsWithRaise.kt
│ │ │ └── either
│ │ │ └── ConvertersWithEither.kt
│ └── build.gradle.kts
├── kotlin-dl
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── kotlindl
│ │ └── FashionMnist.kt
└── equalsverifier-with-kotlin
│ ├── src
│ ├── test
│ │ └── kotlin
│ │ │ └── org
│ │ │ └── sdkotlin
│ │ │ └── equalsverifier
│ │ │ ├── delegation
│ │ │ ├── BarImplTest.kt
│ │ │ ├── BazImplTest.kt
│ │ │ ├── LazyEqualsImplTest.kt
│ │ │ └── FooBarImplTest.kt
│ │ │ └── recursive
│ │ │ └── DataClassWithSealedTypePropertyTest.kt
│ └── main
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── equalsverifier
│ │ ├── delegation
│ │ ├── LazyEquals.kt
│ │ └── DelegatedEquals.kt
│ │ └── recursive
│ │ └── DataClassWithSealedTypeProperty.kt
│ └── build.gradle.kts
├── detekt-rules
├── src
│ └── main
│ │ ├── resources
│ │ ├── config
│ │ │ └── config.yml
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── io.gitlab.arturbosch.detekt.api.RuleSetProvider
│ │ └── kotlin
│ │ └── org
│ │ └── sdkotlin
│ │ └── detekt
│ │ └── junit
│ │ ├── JUnitRuleSetProvider.kt
│ │ └── InvalidTestFactoryReturnType.kt
├── settings.gradle.kts
└── build.gradle.kts
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── codeStyles
│ └── codeStyleConfig.xml
├── encodings.xml
└── inspectionProfiles
│ └── Project_Default.xml
├── platforms
├── plugins-platform
│ └── build.gradle.kts
├── app-platform
│ └── build.gradle.kts
├── settings.gradle.kts
└── test-platform
│ └── build.gradle.kts
├── .editorconfig
├── .gitignore
├── gradle.properties
├── config
└── detekt
│ └── detekt.yml
├── README.md
├── .github
└── workflows
│ └── gradle.yml
├── settings.gradle.kts
├── gradlew.bat
└── .junie
└── guidelines.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.jar filter=lfs diff=lfs merge=lfs -text
2 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/resources/hello.txt:
--------------------------------------------------------------------------------
1 | Hello, World!
2 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/resources/io/mockk/settings.properties:
--------------------------------------------------------------------------------
1 | relaxed=true
2 |
--------------------------------------------------------------------------------
/detekt-rules/src/main/resources/config/config.yml:
--------------------------------------------------------------------------------
1 | junit:
2 | InvalidTestFactoryReturnType:
3 | active: true
4 |
--------------------------------------------------------------------------------
/subprojects/constant-dependencies/constant-producer/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | }
4 |
--------------------------------------------------------------------------------
/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider:
--------------------------------------------------------------------------------
1 | org.sdkotlin.detekt.junit.JUnitRuleSetProvider
2 |
--------------------------------------------------------------------------------
/subprojects/sorting-in-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | }
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:423cb469ccc0ecc31f0e4e1c309976198ccb734cdcbb7029d4bda0f18f57e8d9
3 | size 45633
4 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/src/main/kotlin/org/sdkotlin/testing/mokkery/ValueClassSuperType.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.testing.mokkery
2 |
3 | interface ValueClassSuperType
4 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/api/builder/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | }
5 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/api/annotations/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | }
5 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/main/kotlin/org/sdkotlin/tdd/fizzbuzz/Printer.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | fun interface Printer {
4 |
5 | fun print(fizzBuzz: String)
6 | }
7 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/ExternalComponent.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | @JvmInline
4 | value class ExternalComponent(val value: String)
5 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/GreetingService.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | interface GreetingService {
4 |
5 | fun getGreeting(): String
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/HelloController.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | interface HelloController {
4 |
5 | fun sayHello(): String
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_04_imports/otherpackage/Thing1.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._04_imports.otherpackage
2 |
3 | class Thing1
4 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_23_generics/util/Utilities.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._23_generics.util
2 |
3 | internal fun itsYourBirthday() = true
4 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_XX_tdd/TddInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._XX_tdd
2 |
3 | class TddInKotlin {
4 |
5 | fun weCanDoIt() = true
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider:
--------------------------------------------------------------------------------
1 | org.sdkotlin.buildergen.processor.BuilderGenSymbolProcessorProvider
2 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_01_packages/PackagesInJava.java:
--------------------------------------------------------------------------------
1 | // Package names must match the source folder in Java.
2 |
3 | package org.sdkotlin.intro.java._01_packages;
4 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_XX_reflection/ReflectionInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._XX_reflection
2 |
3 | // TODO: Add reflection example for Kotlin.
4 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/main/kotlin/org/sdkotlin/tdd/sorting/Sorting.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.sorting
2 |
3 | fun > sort(array: Array): Array =
4 | array.copyOf().sortedArray()
5 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/src/main/kotlin/org/sdkotlin/testing/mokkery/DataClassSuperType.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.testing.mokkery
2 |
3 | interface DataClassSuperType {
4 | val v: ValueClassSuperType
5 | }
6 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/src/main/kotlin/org/sdkotlin/testing/mokkery/ValueClass.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.testing.mokkery
2 |
3 | @JvmInline
4 | value class ValueClass(val s: String) : ValueClassSuperType
5 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/ExternalComponentContainer.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | data class ExternalComponentContainer(val externalComponent: ExternalComponent)
4 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/api/annotations/src/main/kotlin/org/sdkotlin/buildergen/api/annotations/GeneratedBuilder.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.api.annotations
2 |
3 | annotation class GeneratedBuilder
4 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/api/builder/src/main/kotlin/org/sdkotlin/buildergen/api/builder/Builder.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.api.builder
2 |
3 | fun interface Builder {
4 |
5 | fun build(): T
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_XX_scopingfunctions/ScopingFunctionsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._XX_scopingfunctions
2 |
3 | // TODO: Add scoping functions example for Kotlin.
4 |
--------------------------------------------------------------------------------
/subprojects/constant-dependencies/constant-consumer/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | }
4 |
5 | dependencies {
6 |
7 | implementation(projects.subprojects.constantDependencies.constantProducer)
8 | }
9 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_06_strings/StringsInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._06_strings;
2 |
3 | public class StringsInJava {
4 |
5 | public static final String STRING = "string";
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/kotlin-reflect/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | }
5 |
6 | dependencies {
7 |
8 | implementation(kotlin("reflect"))
9 | }
10 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/main/kotlin/org/sdkotlin/tdd/testfixtures/InternalComponent.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.testfixtures
2 |
3 | internal interface InternalComponent {
4 |
5 | fun getInt(): Int
6 |
7 | fun getString(): String
8 | }
9 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/main/kotlin/org/sdkotlin/tdd/fizzbuzz/ConsolePrinter.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | internal class ConsolePrinter : Printer {
4 |
5 | override fun print(fizzBuzz: String) {
6 | println(fizzBuzz)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | }
4 |
5 | dependencies {
6 |
7 | implementation(platform("org.sdkotlin.platforms:app-platform"))
8 |
9 | implementation(libs.org.json)
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_02_helloworld/HelloKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._02_helloworld
2 |
3 | // "Hello, World" is pretty simple in Kotlin.
4 |
5 | fun main() {
6 | println("Hello, SD Kotlin!")
7 | }
8 |
--------------------------------------------------------------------------------
/subprojects/kotlin-reflect/src/main/kotlin/org/sdkotlin/kotlin/reflect/SealedSubclasses.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.kotlin.reflect
2 |
3 | sealed class SealedClass
4 | class SubClass : SealedClass()
5 |
6 | fun main() {
7 | println(SealedClass::class.sealedSubclasses)
8 | }
9 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/HelloKoin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import org.koin.core.context.startKoin
4 |
5 | fun main() {
6 |
7 | startKoin {
8 | modules(helloModule)
9 | }
10 |
11 | HelloApp().run()
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/main/kotlin/org/sdkotlin/integral/Progression.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | interface Progression : Iterable {
4 | val first: I
5 | val last: I
6 | val step: I
7 |
8 | fun isEmpty(): Boolean
9 | }
10 |
--------------------------------------------------------------------------------
/subprojects/constant-dependencies/constant-producer/src/main/kotlin/org/sdkotlin/constants/producer/CompanionConstants.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.constants.producer
2 |
3 | class CompanionConstants {
4 |
5 | companion object {
6 |
7 | const val TESTING: String = "testing"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/src/main/kotlin/org/sdkotlin/testing/mokkery/DataClass.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.testing.mokkery
2 |
3 | @Suppress("unused") // Not mockable by Mokkery unless all-opened.
4 | data class DataClass(
5 | override val v: ValueClassSuperType,
6 | ) : DataClassSuperType
7 |
--------------------------------------------------------------------------------
/subprojects/constant-dependencies/constant-consumer/src/main/kotlin/org/sdkotlin/constants/consumer/CompanionConstantConsumer.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.constants.consumer
2 |
3 | import org.sdkotlin.constants.producer.CompanionConstants.Companion.TESTING
4 |
5 | fun main() {
6 | println(TESTING)
7 | }
8 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/SimpleHelloController.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | class SimpleHelloController(private val greetingService: GreetingService) :
4 | HelloController {
5 |
6 | override fun sayHello() = greetingService.getGreeting()
7 | }
8 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_01_packages/PackagesInKotlin.kt:
--------------------------------------------------------------------------------
1 | // Package names in Kotlin don't have to match the source folder.
2 |
3 | package somewhere.over.the.rainbow // Also, no semicolon.
4 |
5 | // Semicolons are optional in Kotlin, and rarely used.
6 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_02_helloworld/withargs/HelloWithArgs.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._02_helloworld.withargs
2 |
3 | // Args are optional.
4 |
5 | fun main(args: Array) {
6 |
7 | println("args: ${args.contentToString()}")
8 | }
9 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_13_constructors/ConstructorsAndInitializersInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._13_constructors;
2 |
3 | public class ConstructorsAndInitializersInJava {
4 |
5 | // TODO: Add constructors and initializers example for Java
6 | }
7 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/fizzbuzz/TestPrinter.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | internal class TestPrinter : Printer {
4 |
5 | val prints = mutableListOf()
6 |
7 | override fun print(fizzBuzz: String) {
8 | prints.add(fizzBuzz)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/EnglishGreetingService.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | class EnglishGreetingService : GreetingService {
4 |
5 | companion object {
6 | const val GREETING = "Hi, World!"
7 | }
8 |
9 | override fun getGreeting() = GREETING
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.global-exec")
3 | id("org.sdkotlin.buildlogic.kotlin-project")
4 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
5 | }
6 |
7 | dependencies {
8 |
9 | api(projects.subprojects.kotlinForJavaDevs)
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/typed-errors-in-kotlin/src/main/kotlin/org/sdkotlin/typederrors/FruitBasket.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.typederrors
2 |
3 | interface FruitBasket {
4 |
5 | val fruit: List
6 | }
7 |
8 | internal data class FruitBasketImpl(
9 | override val fruit: List = emptyList(),
10 | ) : FruitBasket
11 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction to Kotlin for Java Developers
2 |
3 | Code examples from
4 | the [San Diego Kotlin User Group](https://www.meetup.com/sd-kotlin/events/nlxltpyxjbjb/)'
5 | s meetings on introducing the [Kotlin](http://kotlinlang.org/) programming
6 | language to Java developers (and friends).
7 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/it/kotlin/org/sdkotlin/koin/it/hello/test/testHelloModule.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.it.hello.test
2 |
3 | import org.koin.dsl.module
4 | import org.sdkotlin.koin.hello.GreetingService
5 |
6 | internal val testHelloModule = module {
7 |
8 | single { TestGreetingService() }
9 | }
10 |
--------------------------------------------------------------------------------
/subprojects/kotlin-dl/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | }
4 |
5 | dependencies {
6 |
7 | api(platform("org.sdkotlin.platforms:app-platform"))
8 |
9 | implementation(libs.kotlinx.dl.api)
10 | implementation(libs.kotlinx.dl.dataset)
11 | implementation(libs.kotlinx.dl.tensorflow)
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_02_helloworld/HelloJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._02_helloworld;
2 |
3 | import java.util.Arrays;
4 |
5 | public class HelloJava {
6 |
7 | public static void main(final String[] args) {
8 | System.out.println("args: " + Arrays.toString(args));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/typed-errors-in-kotlin/src/main/kotlin/org/sdkotlin/typederrors/Fruit.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.typederrors
2 |
3 | sealed interface Fruit {
4 | data class Apple(val hasWorm: Boolean) : Fruit
5 | data class Banana(val microSieverts: Double) : Fruit
6 | data class Grapes(val moreLikeRaisins: Boolean) : Fruit
7 | data object Orange : Fruit
8 | }
9 |
--------------------------------------------------------------------------------
/platforms/plugins-platform/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("java-platform")
3 | }
4 |
5 | dependencies {
6 | constraints {
7 | api(libs.dependencyAnalysis.gradlePluginDependency)
8 | api(libs.jvmDependencyConflictResolution.gradlePluginDependency)
9 | api(libs.kotlin.gradlePluginDependency)
10 | api(libs.ksp.gradlePluginDependency)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/UnknownPlayer.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._30_sealedtypes
2 |
3 | // Direct subclasses can be in other files so long as they're in the same
4 | // package.
5 |
6 | class UnknownPlayer : Player {
7 | override val name: String = "Unknown"
8 | override val health: Int = 0
9 | }
10 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | id("org.sdkotlin.buildlogic.mokkery-project")
5 | }
6 |
7 | dependencies {
8 |
9 | testImplementation(platform("org.sdkotlin.platforms:test-platform"))
10 |
11 | testImplementation(libs.mokkery.core)
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/HelloApp.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import org.koin.core.component.KoinComponent
4 | import org.koin.core.component.inject
5 |
6 | internal class HelloApp : KoinComponent {
7 |
8 | private val helloController: HelloController by inject()
9 |
10 | fun run() = println(helloController.sayHello())
11 | }
12 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/javainterop/_XX_constants/ConstantsInKotlinObject.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.javainterop._XX_constants
2 |
3 | object ConstantsInKotlinObject {
4 |
5 | @JvmField
6 | val OBJECT_JVM_FIELD_VAL = "Testing @JvmField val in object"
7 |
8 | @JvmStatic
9 | val OBJECT_JVM_STATIC_VAL = "Testing @JvmStatic val in object"
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_17_constants/ConstantsInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._17_constants;
2 |
3 | import java.math.BigInteger;
4 |
5 | public class ConstantsInJava {
6 |
7 | public static final String JAVA_CONST = "Constants in Java";
8 |
9 | public static final BigInteger NON_PRIMITIVE_JAVA_CONST = BigInteger.ONE;
10 | }
11 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/it/kotlin/org/sdkotlin/koin/it/hello/test/TestGreetingService.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.it.hello.test
2 |
3 | import org.sdkotlin.koin.hello.GreetingService
4 |
5 | internal class TestGreetingService : GreetingService {
6 |
7 | companion object {
8 | const val TEST_GREETING = "Howdy, World!"
9 | }
10 |
11 | override fun getGreeting() = TEST_GREETING
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs-client/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/OtherModulePlayer.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._30_sealedtypes
2 |
3 | // Direct subclasses of sealed classes can't be in other modules.
4 |
5 | // Does not compile...
6 | /*
7 | class OtherModulePlayer(
8 | override val name: String,
9 | override val health: Int,
10 | ) : Player
11 | */
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | charset = utf-8
3 | max_line_length = 80
4 | end_of_line = lf
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 | indent_style = tab
8 | tab_width = 4
9 |
10 | [*.{yml,yaml}]
11 | indent_size = 2
12 |
13 | [detekt-baseline.xml]
14 | max_line_length = off
15 |
16 | [{.idea/**/*.xml,*.iml}]
17 | indent_size = 2
18 | max_line_length = off
19 | insert_final_newline = false
20 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/README.md:
--------------------------------------------------------------------------------
1 | # Effective Kotlin
2 |
3 | Code examples from the San Diego Kotlin User
4 | Group's [June 2018 meeting](https://www.meetup.com/sd-kotlin/events/nlxltpyxjbjb/)
5 | on popular Kotlin idioms, and how Kotlin addresses several items from Joshua
6 | Bloch's seminal book,
7 | _[Effective Java](https://www.pearson.com/us/higher-education/program/Bloch-Effective-Java-3rd-Edition/PGM1763855.html)_.
8 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/test/kotlin/org/sdkotlin/equalsverifier/delegation/BarImplTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import org.junit.jupiter.api.Test
5 |
6 | class BarImplTest {
7 |
8 | @Test
9 | fun `test equals, hashCode, and toString`() {
10 |
11 | EqualsVerifier.forClass(BarImpl::class.java).verify()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/test/kotlin/org/sdkotlin/equalsverifier/delegation/BazImplTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import org.junit.jupiter.api.Test
5 |
6 | class BazImplTest {
7 |
8 | @Test
9 | fun `test equals, hashCode, and toString`() {
10 |
11 | EqualsVerifier.forClass(BazImpl::class.java).verify()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/test-project/src/main/kotlin/org/sdkotlin/buildergen/processor/it/TestEntity.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.processor.it
2 |
3 | import org.sdkotlin.buildergen.api.annotations.GeneratedBuilder
4 |
5 | @GeneratedBuilder
6 | data class TestEntity(
7 | val testInt: Int,
8 | val testNullableInt: Int?,
9 | val testString: String,
10 | val testNullableString: String?,
11 | )
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### JetBrains template
2 |
3 | .idea/*
4 | !.idea/codeStyles/
5 | !.idea/inspectionProfiles/
6 | !.idea/encodings.xml
7 |
8 | # Gradle:
9 | *.iml
10 |
11 | # IntelliJ
12 | out/
13 |
14 | ### Gradle template
15 | .gradle
16 | build/
17 |
18 | ### Gradle Profiler
19 | gradle-user-home/
20 | profile-out*/
21 |
22 | ### Kotlin
23 | .kotlin
24 |
25 | ### KotlinTest
26 | .kotlintest/
27 |
28 | ### KotlinDL
29 | cache/
30 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_00_classes/ClassesInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._00_classes;
2 |
3 | // Public class names must match the source file name in Java.
4 |
5 | public class ClassesInJava {
6 | //...
7 | }
8 |
9 | // You can have multiple classes in a file, but only one public class,
10 | // and curly braces are required.
11 |
12 | class Class {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/main/kotlin/org/sdkotlin/integral/Integral.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | interface Integral : Comparable where I : Comparable {
4 |
5 | val minValue: I
6 | val maxValue: I
7 | val zero: I
8 | val one: I
9 |
10 | operator fun plus(other: I): I
11 | operator fun minus(other: I): I
12 | operator fun unaryMinus(): I
13 | operator fun rem(other: I): I
14 | }
15 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_00_classes/ClassesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._00_classes
2 |
3 | // Class name doesn't have to match file name, though doing so is idiomatic.
4 |
5 | class ClassesInKotlinExample {
6 | //...
7 | }
8 |
9 | // Unlike Java, you can have multiple public classes in a source file.
10 |
11 | // Curly braces are optional for empty classes.
12 |
13 | class Class
14 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/otherpackage/OtherPackagePlayer.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnusedImport")
2 |
3 | package org.sdkotlin.intro.kotlin._30_sealedtypes.otherpackage
4 |
5 | // Direct subtypes of sealed types can't be in other packages.
6 |
7 | // Does not compile...
8 | /*
9 | class OtherPackagePlayer(
10 | override val name: String,
11 | override var health: Int,
12 | ) : Player
13 | */
14 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/test/kotlin/org/sdkotlin/intro/kotlin/_XX_tdd/TddInKotlinTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._XX_tdd
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class TddInKotlinTest {
7 |
8 | @Test
9 | fun `test TDD in Kotlin for smoke`() {
10 |
11 | val tddInKotlin = TddInKotlin()
12 |
13 | assertThat(tddInKotlin.weCanDoIt()).isTrue
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/platforms/app-platform/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("java-platform")
3 | }
4 |
5 | javaPlatform {
6 | allowDependencies()
7 | }
8 |
9 | dependencies {
10 |
11 | api(platform(libs.koin.bom))
12 | api(platform(libs.kotlinx.coroutines.bom))
13 |
14 | constraints {
15 | api(libs.bundles.arrow.jvm)
16 | api(libs.jetbrains.annotations)
17 | api(libs.bundles.kotlinx.dl)
18 | api(libs.ksp.api)
19 | api(libs.org.json)
20 | api(libs.slf4j.simple)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.ksp-processor-project")
4 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
5 | }
6 |
7 | dependencies {
8 |
9 | implementation(projects.subprojects.kspBuilderGenerator.api.annotations)
10 | implementation(projects.subprojects.kspBuilderGenerator.api.builder)
11 |
12 | implementation(libs.bundles.kotlinpoet.ksp)
13 | }
14 |
--------------------------------------------------------------------------------
/subprojects/sorting-in-kotlin/src/main/kotlin/org/sdkoltin/sort/BubbleSort.kt:
--------------------------------------------------------------------------------
1 | package org.sdkoltin.sort
2 |
3 | /**
4 | * Sorts the list in-place via a stable, iterative implementation of the Bubble
5 | * Sort algorithm.
6 | */
7 | fun > MutableList.bubbleSort() {
8 |
9 | if (size <= 1) return
10 |
11 | for (i in 0 until size - 1) {
12 | for (j in 0 until size - i - 1) {
13 | if (this[j] > this[j + 1]) this.swap(j, j + 1)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/test-project/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.ksp-processed-project")
4 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
5 | }
6 |
7 | dependencies {
8 |
9 | api(projects.subprojects.kspBuilderGenerator.api.annotations)
10 | api(projects.subprojects.kspBuilderGenerator.api.builder)
11 |
12 | ksp(projects.subprojects.kspBuilderGenerator.processor)
13 | }
14 |
--------------------------------------------------------------------------------
/platforms/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | versionCatalogs {
3 | create("libs") {
4 | from(files("../gradle/libs.versions.toml"))
5 | }
6 | }
7 | }
8 |
9 | rootProject.name = "platforms"
10 |
11 | gradle.beforeProject {
12 | // Set group and version properties for all projects
13 | group = "org.sdkotlin.platforms"
14 | version = "1.0.0-SNAPSHOT"
15 | }
16 |
17 | include("app-platform")
18 | include("test-platform")
19 | include("plugins-platform")
20 |
--------------------------------------------------------------------------------
/platforms/test-platform/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("java-platform")
3 | }
4 |
5 | javaPlatform {
6 | allowDependencies()
7 | }
8 |
9 | dependencies {
10 |
11 | api(platform(libs.junit.bom))
12 | api(platform(libs.koin.bom))
13 | api(platform(libs.kotest.bom))
14 |
15 | constraints {
16 | api(libs.assertj)
17 | api(libs.equalsverifier)
18 | api(libs.mockito)
19 | api(libs.mockito.kotlin)
20 | api(libs.mokkery.core)
21 | api(libs.bundles.mockk.jvm)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs-client/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/SealedTypeSmartCastFromOtherModule.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._30_sealedtypes
2 |
3 | fun main() {
4 |
5 | // Sealed types from other modules can be smart cast by type.
6 |
7 | val output = when (val player = playerFactory()) {
8 | is HumanPlayer -> player.topScore
9 | is NPC -> player.attack()
10 | is UnknownPlayer -> player.name
11 | }
12 |
13 | println(output)
14 | }
15 |
--------------------------------------------------------------------------------
/subprojects/sorting-in-kotlin/src/test/kotlin/org/sdkoltin/sort/SortTestCases.kt:
--------------------------------------------------------------------------------
1 | package org.sdkoltin.sort
2 |
3 | internal object SortTestCases {
4 |
5 | val IN_PLACE_SORT_TEST_CASES: List> = listOf(
6 | mutableListOf(),
7 | mutableListOf(1),
8 | mutableListOf(1, 2),
9 | mutableListOf(2, 1),
10 | mutableListOf(1, 2, 3),
11 | mutableListOf(2, 1, 3),
12 | mutableListOf(1, 3, 2),
13 | mutableListOf(3, 1, 2),
14 | mutableListOf(3, 2, 1),
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/detekt-rules/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | gradlePluginPortal()
5 | }
6 | }
7 |
8 | dependencyResolutionManagement {
9 | @Suppress("UnstableApiUsage")
10 | repositories {
11 | mavenCentral()
12 | gradlePluginPortal()
13 | }
14 | versionCatalogs {
15 | create("libs") {
16 | from(files("../gradle/libs.versions.toml"))
17 | }
18 | }
19 | }
20 |
21 | includeBuild("../platforms")
22 |
23 | rootProject.name = "detekt-rules"
24 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
4 | }
5 |
6 | dependencies {
7 |
8 | testImplementation(platform("org.sdkotlin.platforms:test-platform"))
9 |
10 | testImplementation(libs.equalsverifier)
11 |
12 | testRuntimeOnly(libs.mockito) {
13 | because("Used by EqualsVerifier for prefab value generation.")
14 | }
15 | testRuntimeOnly(kotlin("reflect"))
16 | }
17 |
--------------------------------------------------------------------------------
/subprojects/typed-errors-in-kotlin/src/main/kotlin/org/sdkotlin/typederrors/TypedError.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.typederrors
2 |
3 | sealed interface TypedError {
4 |
5 | sealed interface BadFruitTypedError : TypedError {
6 |
7 | data object BadAppleTypedError : BadFruitTypedError
8 |
9 | data object RadioactiveBananaTypedError : BadFruitTypedError
10 |
11 | data object ShriveledGrapesTypedError : BadFruitTypedError
12 | }
13 |
14 | data object BadBasketTypedError : TypedError
15 | }
16 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/RandomGreetingService.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import kotlin.random.Random
4 |
5 | class RandomGreetingService : GreetingService {
6 |
7 | companion object {
8 | val GREETINGS = listOf(
9 | "Hello, World!",
10 | "¡Hola Mundo!",
11 | "Salamu, Dunia!",
12 | "Aloha nui kāua!"
13 | )
14 | }
15 |
16 | override fun getGreeting(): String {
17 |
18 | return GREETINGS[Random.nextInt(GREETINGS.size)]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_03_toplevel/TopLevelInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._03_toplevel
2 |
3 | // You can define top level properties and functions in Kotlin.
4 |
5 | var sanDiego = true
6 |
7 | // They can be private, in which case they're only visible within the same file.
8 |
9 | private var justHere = true
10 |
11 | fun printWeather() {
12 |
13 | if (sanDiego) {
14 | println("It's sunny!")
15 | }
16 |
17 | println(justHere)
18 | }
19 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_07_equality/EqualityInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._07_equality
2 |
3 | fun main() {
4 |
5 | println(java.lang.String("foo") === java.lang.String("foo"))
6 | println(java.lang.String("foo") == java.lang.String("foo"))
7 |
8 | // Equivalent to "=="
9 | println("foo".equals("foo"))
10 |
11 | // TODO: Research and explain why this prints "true"...
12 | println("fo" + "o" === "foo")
13 |
14 | println("foo" == "foo")
15 | }
16 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_08_3_extensionfunctions/otherpackage/ExtensionFunctionScopingInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._08_3_extensionfunctions.otherpackage
2 |
3 | import org.sdkotlin.intro.kotlin._08_3_extensionfunctions.shuffled
4 |
5 | fun main() {
6 |
7 | // Extension functions aren't really added to the receiver classes. They
8 | // must be imported to be used in a scope other than where they are defined.
9 |
10 | println("Hello".shuffled())
11 | }
12 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/meetup/firstwednesday/SDKotlin.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | package org.sdkotlin.meetup.firstwednesday
9 |
10 | import java.time.DayOfWeek.WEDNESDAY
11 | import java.time.LocalDate.now
12 | import java.time.temporal.TemporalAdjusters.dayOfWeekInMonth
13 |
14 | fun firstWednesday() =
15 | now().equals(now().with(dayOfWeekInMonth(1, WEDNESDAY)))
16 |
17 | fun main() {
18 | when {
19 | firstWednesday() -> println("SD Kotlin time!")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/otherpackage/AiNPC.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._30_sealedtypes.otherpackage
2 |
3 | import org.sdkotlin.intro.kotlin._30_sealedtypes.NPC
4 |
5 | // Indirect subtypes of open types that are sealed subtypes are allowed in
6 | // other packages and modules.
7 |
8 | data class AiNPC(
9 | override val name: String,
10 | override var health: Int = 100,
11 | ) : NPC() {
12 |
13 | override fun attack() = "AI is coming to get ya!"
14 | }
15 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/testFixtures/kotlin/org/sdkotlin/tdd/testfixtures/InternalComponentTestDouble.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.testfixtures
2 |
3 | class InternalComponentTestDouble(
4 | private val testInt: Int = TEST_INT,
5 | private val testString: String = TEST_STRING,
6 | ) : InternalComponent {
7 |
8 | companion object {
9 | const val TEST_INT = 42
10 | const val TEST_STRING = "Testing"
11 | }
12 |
13 | override fun getInt(): Int = testInt
14 |
15 | override fun getString(): String = testString
16 | }
17 |
--------------------------------------------------------------------------------
/subprojects/typed-errors-in-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2 |
3 | plugins {
4 | id("org.sdkotlin.buildlogic.kotlin-project")
5 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
6 | }
7 |
8 | dependencies {
9 |
10 | api(platform("org.sdkotlin.platforms:app-platform"))
11 |
12 | api(libs.bundles.arrow.jvm)
13 | }
14 |
15 | tasks {
16 | withType().configureEach {
17 | compilerOptions {
18 | freeCompilerArgs.add("-Xcontext-receivers")
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/test/kotlin/org/sdkotlin/koin/hello/RandomGreetingServiceTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class RandomGreetingServiceTest {
7 |
8 | @Test
9 | fun `should return a random greeting`() {
10 |
11 | val greetingService: GreetingService = RandomGreetingService()
12 |
13 | val response = greetingService.getGreeting()
14 |
15 | assertThat(response).isIn(RandomGreetingService.GREETINGS)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/javainterop/_XX_constants/ConstantsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.javainterop._XX_constants
2 |
3 | @JvmField
4 | val JVM_FIELD_VAL = "Testing @JvmField val"
5 |
6 | @JvmField
7 | val NON_PRIMITIVE_JVM_FIELD_VAL = intArrayOf(1)
8 |
9 | // Only members in named objects and companion objects can be annotated with '@JvmStatic'
10 |
11 | //@JvmStatic
12 | //val JVM_STATIC_VAL = "Testing @JvmStatic val"
13 |
14 | //@JvmStatic
15 | //const val JVM_STATIC_VAL = "Testing @JvmStatic const val"
16 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.kotlin-project")
3 | id("org.sdkotlin.buildlogic.mockk-project")
4 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
5 | }
6 |
7 | dependencies {
8 |
9 | testImplementation(platform("org.sdkotlin.platforms:test-platform"))
10 |
11 | testImplementation(libs.equalsverifier)
12 |
13 | testRuntimeOnly(libs.mockito) {
14 | because("Used by EqualsVerifier for prefab value generation.")
15 | }
16 | testRuntimeOnly(kotlin("reflect"))
17 | }
18 |
--------------------------------------------------------------------------------
/detekt-rules/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.kotlin.gradlePlugin)
3 | id("jvm-test-suite")
4 | }
5 |
6 | group = "org.sdkotlin.detekt"
7 | version = "1.0.0-SNAPSHOT"
8 |
9 | dependencies {
10 |
11 | compileOnly(libs.detekt.api)
12 |
13 | testImplementation(libs.assertj)
14 | testImplementation(libs.detekt.test)
15 | }
16 |
17 | @Suppress("UnstableApiUsage")
18 | testing {
19 | suites {
20 | configureEach {
21 | if (this is JvmTestSuite) {
22 | useJUnitJupiter(libs.versions.junit.get())
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/test/kotlin/org/sdkotlin/koin/hello/EnglishGreetingServiceTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class EnglishGreetingServiceTest {
7 |
8 | @Test
9 | fun `should return an English greeting`() {
10 |
11 | val greetingService: GreetingService = EnglishGreetingService()
12 |
13 | val response = greetingService.getGreeting()
14 |
15 | assertThat(response).isIn(EnglishGreetingService.GREETING)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/test/kotlin/org/sdkotlin/equalsverifier/delegation/LazyEqualsImplTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import org.junit.jupiter.api.Test
5 |
6 | class LazyEqualsImplTest {
7 |
8 | @Test
9 | fun `test equals, hashCode, and toString`() {
10 |
11 | EqualsVerifier
12 | // Required per https://github.com/jqno/equalsverifier/issues/1097
13 | .forExamples(LazyEqualsImpl(1, "red"), LazyEqualsImpl(2, "blue"))
14 | .verify()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/detekt-rules/src/main/kotlin/org/sdkotlin/detekt/junit/JUnitRuleSetProvider.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.detekt.junit
2 |
3 | import io.gitlab.arturbosch.detekt.api.Config
4 | import io.gitlab.arturbosch.detekt.api.RuleSet
5 | import io.gitlab.arturbosch.detekt.api.RuleSetProvider
6 |
7 | class JUnitRuleSetProvider : RuleSetProvider {
8 |
9 | override val ruleSetId: String = "junit"
10 |
11 | override fun instance(config: Config): RuleSet =
12 | RuleSet(
13 | ruleSetId,
14 | listOf(
15 | InvalidTestFactoryReturnType(config),
16 | ),
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_03_toplevel/usage/TopLevelUsageInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._03_toplevel.usage
2 |
3 | // Top level variables and functions are package scoped...
4 |
5 | import org.sdkotlin.intro.kotlin._03_toplevel.printWeather
6 | import org.sdkotlin.intro.kotlin._03_toplevel.sanDiego
7 |
8 | // Can't access private top-level properties or functions
9 | //import org.sdkotlin.intro.kotlin._03_toplevel.justHere
10 |
11 | fun main() {
12 | println(sanDiego)
13 | printWeather()
14 | }
15 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_08_2_tailrecursivefunctions/TailRecursionDebugging.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._08_2_tailrecursivefunctions
2 |
3 | /**
4 | * Debugger didn't used to show variable changes in tailrec functions per
5 | * [KT-47203](https://youtrack.jetbrains.com/issue/KT-47203), but now it does.
6 | */
7 | tailrec fun tailrecFun(number: Int): Int =
8 | if (number < 10) {
9 | number
10 | } else {
11 | tailrecFun(number - 1) // breakpoint here
12 | }
13 |
14 | fun main() {
15 | tailrecFun(15)
16 | }
17 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/api/annotations/src/test/kotlin/org/sdkotlin/buildergen/api/annotations/GeneratedBuilderTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.api.annotations
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class GeneratedBuilderTest {
7 |
8 | @GeneratedBuilder
9 | data class TestEntity(
10 | val b: Boolean,
11 | )
12 |
13 | @Test
14 | fun `verify GeneratedBuilder target`() {
15 |
16 | assertThat(TestEntity::class.java)
17 | .hasAnnotation(GeneratedBuilder::class.java)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.global-exec")
3 | id("org.sdkotlin.buildlogic.kotlin-project")
4 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
5 | }
6 |
7 | dependencies {
8 |
9 | api(platform("org.sdkotlin.platforms:app-platform"))
10 |
11 | api(libs.bundles.arrow.jvm)
12 |
13 | implementation(libs.bundles.kotlinx.coroutines.jvm)
14 |
15 | compileOnly(libs.jetbrains.annotations)
16 |
17 | testImplementation(platform("org.sdkotlin.platforms:test-platform"))
18 |
19 | testImplementation(libs.equalsverifier)
20 | }
21 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs-client/src/main/kotlin/org/sdkotlin/intro/kotlin/_30_sealedtypes/otherpackage/OtherModuleAndPackageNPC.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._30_sealedtypes.otherpackage
2 |
3 | import org.sdkotlin.intro.kotlin._30_sealedtypes.NPC
4 |
5 | // Indirect subtypes of sealed types can be in other modules.
6 |
7 | class OtherModuleAndPackageNPC : NPC() {
8 |
9 | override val name: String = "Invincible"
10 | override val health: Int = 100
11 |
12 | override fun attack() = "$name attack!"
13 | }
14 |
15 | fun main() {
16 | println(OtherModuleAndPackageNPC().attack())
17 | }
18 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_02_helloworld/HelloJava21.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Java 21+ is previewing "Unnamed Classes and Instance Main Methods":
3 | *
9 | */
10 | void main() {
11 | System.out.println("Hello World");
12 | }
13 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_16_static/StaticInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._16_static;
2 |
3 | import org.sdkotlin.intro.kotlin._16_static.StaticInKotlin;
4 |
5 | public class StaticInJava {
6 |
7 | public static final String CONSTANT = "Death & Taxes";
8 |
9 | public static void saySomething() {
10 | System.out.println(CONSTANT);
11 | }
12 |
13 | public static void main(final String[] args) {
14 | StaticInJava.saySomething();
15 | StaticInKotlin.saySomething();
16 |
17 | new StaticInJava().saySomething();
18 | new StaticInKotlin().saySomething();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/javainterop/_XX_constants/ConstantsInKotlinCompanion.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.javainterop._XX_constants
2 |
3 | class ConstantsInKotlinCompanion {
4 |
5 | companion object {
6 |
7 | @JvmField
8 | val COMPANION_JVM_FIELD_VAL = "Testing @JvmField val in object"
9 |
10 | @JvmStatic
11 | val COMPANION_JVM_STATIC_VAL = "Testing @JvmStatic val in object"
12 |
13 | // '@JvmStatic' annotation is useless for const or '@JvmField' properties
14 |
15 | //@JvmStatic
16 | //const val COMPANION_JVM_STATIC_CONST_VAL = "Testing @JvmStatic const val in object"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_22_nullsafety/NullSafetyInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._22_nullsafety;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | public class NullSafetyInJava {
7 |
8 | public static final String MAYBE_NULL = null;
9 |
10 | @NotNull
11 | public static final String NOT_NULL = "";
12 |
13 | @Nullable
14 | public static final String NULL = null;
15 |
16 | @NotNull
17 | public static final String SURPRISE = null;
18 |
19 | @NotNull
20 | public static String surpriseMethod() {
21 | return null;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/main/kotlin/org/sdkotlin/equalsverifier/delegation/LazyEquals.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | interface LazyEquals {
4 | val foo: Int
5 | val bar: String
6 | }
7 |
8 | class LazyEqualsImpl(foo: Int, bar: String) : LazyEquals {
9 |
10 | override val foo: Int by lazy { foo }
11 | override val bar: String by lazy { bar }
12 |
13 | override fun equals(other: Any?) =
14 | other is LazyEqualsImpl && other.foo == foo && other.bar == bar
15 |
16 | override fun hashCode() = foo.hashCode() + 31 * bar.hashCode()
17 | override fun toString() = "LazyEqualsImpl(foo=$foo, bar=$bar)"
18 | }
19 |
--------------------------------------------------------------------------------
/subprojects/testing-with-mokkery/src/test/kotlin/org/sdkotlin/testing/mokkery/MokkeryValueClassParameterTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.testing.mokkery
2 |
3 | import dev.mokkery.answering.returns
4 | import dev.mokkery.every
5 | import dev.mokkery.mock
6 | import org.assertj.core.api.Assertions.assertThat
7 | import org.junit.jupiter.api.Test
8 |
9 | class MokkeryValueClassParameterTest {
10 |
11 | @Test
12 | fun `test value class parameter`() {
13 |
14 | val testValue = ValueClass("testing")
15 |
16 | val mock = mock {
17 | every { v } returns testValue
18 | }
19 |
20 | assertThat(mock.v).isEqualTo(testValue)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/subprojects/sorting-in-kotlin/src/test/kotlin/org/sdkoltin/sort/BubbleSortKtTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkoltin.sort
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.DynamicTest.dynamicTest
5 | import org.junit.jupiter.api.TestFactory
6 | import org.sdkoltin.sort.SortTestCases.IN_PLACE_SORT_TEST_CASES
7 |
8 | internal class BubbleSortKtTest {
9 |
10 | @TestFactory
11 | fun `test bubble sort`() =
12 | IN_PLACE_SORT_TEST_CASES.map { mutableList ->
13 |
14 | dynamicTest("test bubble sort for $mutableList") {
15 |
16 | mutableList.bubbleSort()
17 |
18 | assertThat(mutableList).isSorted
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/test/kotlin/org/sdkotlin/integral/IntegralProgressionTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | import io.mockk.mockk
4 | import nl.jqno.equalsverifier.EqualsVerifier
5 | import org.junit.jupiter.api.Test
6 |
7 | class IntegralProgressionTest {
8 |
9 | @Test
10 | fun `test equals, hashCode, and toString`() {
11 | EqualsVerifier.forClass(IntegralProgression::class.java)
12 | // Required per https://github.com/jqno/equalsverifier/issues/1082.
13 | .withPrefabValues(
14 | Integral::class.java,
15 | mockk(relaxed = true),
16 | mockk(relaxed = true),
17 | )
18 | .verify()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_05_1_unsigned_types/UnsignedTypesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._05_1_unsigned_types
2 |
3 | // Kotlin 1.5 on supports unsigned types and "u/U"-suffixed literals
4 |
5 | val uByte: UByte = 255u // or uppercase 255U
6 | val hexUByte: UByte = 0x01u
7 | val binUByte: UByte = 0b0000_0001u
8 | val uShort: UShort = UShort.MAX_VALUE
9 | val uInt = 0u // UInt inferred type if literal fits
10 | val uLong = 0xFF_FF_FF_FF_01u // ULong inferred when literal doesn't fit UInt
11 |
12 | // 'lateinit' modifier is not allowed on properties of unsigned types
13 | //lateinit var lateUInt: UInt
14 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/src/main/kotlin/org/sdkotlin/buildergen/processor/BuilderGenSymbolProcessorProvider.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.processor
2 |
3 | import com.google.devtools.ksp.processing.SymbolProcessor
4 | import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
5 | import com.google.devtools.ksp.processing.SymbolProcessorProvider
6 |
7 | class BuilderGenSymbolProcessorProvider : SymbolProcessorProvider {
8 |
9 | override fun create(
10 | environment: SymbolProcessorEnvironment,
11 | ): SymbolProcessor =
12 | BuilderGenSymbolProcessor(
13 | environment.codeGenerator,
14 | environment.logger,
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item62/AvoidStrings.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item62
2 |
3 | /* Effective Java
4 | Item 62: Avoid strings where other types are more appropriate
5 | */
6 |
7 | // Data classes in Kotlin are so easy!
8 |
9 | data class EmailAddress(val address: String, val name: String)
10 |
11 | fun send(emailAddress: String) {
12 | println("Sending to $emailAddress")
13 | }
14 |
15 | // vs.
16 |
17 | fun send(emailAddress: EmailAddress) {
18 | println("Sending to ${emailAddress.address}")
19 | }
20 |
21 | // It's safer and easier to add a "name" property to the data class in the future!
22 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/test/kotlin/org/sdkotlin/equalsverifier/recursive/DataClassWithSealedTypePropertyTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.recursive
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class DataClassWithSealedTypePropertyTest {
7 |
8 | @Test
9 | fun `test equals, hashCode, and toString`() {
10 | EqualsVerifier.forClass(DataClassWithSealedTypeProperty::class.java)
11 | // Required per https://github.com/jqno/equalsverifier/issues/1081.
12 | .withPrefabValues(
13 | Foo::class.java,
14 | FooImpl(1),
15 | FooImpl(2),
16 | )
17 | .verify()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/assertj/FloatingPointAssertionsTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.assertj
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.assertj.core.api.Assertions.within
5 | import org.assertj.core.api.Assertions.withinPercentage
6 | import org.junit.jupiter.api.Test
7 |
8 | private const val OFFSET = 0.00001
9 |
10 | internal class FloatingPointAssertionsTest {
11 |
12 | @Test
13 | fun `test double assertion`() {
14 |
15 | val expected = 0.3
16 | val actual: Double = 0.1 + 0.2
17 |
18 | assertThat(actual)
19 | .isEqualTo(expected, within(OFFSET))
20 | .isCloseTo(expected, withinPercentage(1.0))
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item58/PreferForEach.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item58
2 |
3 | /* Effective Java
4 | Item 58: Prefer for-each loops to traditional for loops
5 | */
6 |
7 | // Kotlin only has for-each loops!
8 |
9 | fun main() {
10 |
11 | val shapes = arrayOf("Circle", "Triangle", "Rectangle")
12 |
13 | /* Doesn't compile...
14 | for (int i; i < shapes.size; i++) {
15 | println("The shape is ${shapes[i]}")
16 | }
17 | */
18 |
19 | for (i: Int in shapes.indices) {
20 | println("The shape is ${shapes[i]}")
21 | }
22 |
23 | for (shape: String in shapes) {
24 | println("Again the shape is $shape")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_24_arrays/ArraysInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._24_arrays;
2 |
3 | public class ArraysInJava {
4 |
5 | public static void main(final String[] args) {
6 |
7 | // Java has array literals.
8 |
9 | final int[] ints = {1, 2, 3};
10 |
11 | // Array literals can be used with local variable type inference if you
12 | // also include the initializer.
13 |
14 | //var nope = {1, 2, 3}; // Does not compile.
15 |
16 | final var inferredInts = new int[]{1, 2, 3};
17 |
18 | // Array literals can be used for multidimensional arrays.
19 |
20 | final var twoDInferredInts = new int[][]{{1, 2, 3}, {4, 5, 6}};
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/testfixtures/InternalComponentTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.testfixtures
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 | import org.sdkotlin.tdd.testfixtures.InternalComponentTestDouble.Companion.TEST_INT
6 | import org.sdkotlin.tdd.testfixtures.InternalComponentTestDouble.Companion.TEST_STRING
7 |
8 | internal class InternalComponentTest {
9 |
10 | @Test
11 | fun testInternalComponent() {
12 |
13 | val internalComponent: InternalComponent = InternalComponentTestDouble()
14 |
15 | assertThat(internalComponent.getInt()).isEqualTo(TEST_INT)
16 |
17 | assertThat(internalComponent.getString()).isEqualTo(TEST_STRING)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_04_imports/ImportsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._04_imports
2 |
3 | // Imports in Kotlin are very similar to Java.
4 |
5 | import java.math.BigDecimal
6 | import kotlin.math.PI
7 |
8 | // If there is a name collision, the 'as' keyword can be used.
9 |
10 | import org.sdkotlin.intro.kotlin._04_imports.otherpackage.Thing1 as Thing2
11 |
12 | class Thing1
13 |
14 | var lawOfLargeNumbers = BigDecimal.TEN
15 |
16 | var thing1 = Thing1()
17 | var thing2 = Thing2()
18 |
19 | fun main() {
20 | println(PI)
21 | println(lawOfLargeNumbers)
22 | println("Thing1 type: " + thing1::class.qualifiedName)
23 | println("Thing2 type: " + thing2::class.qualifiedName)
24 | }
25 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_10_selection/SelectionInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._10_selection;
2 |
3 | public class SelectionInJava {
4 |
5 | public static void main(final String[] args) {
6 |
7 | if (true) {
8 | System.out.println(true);
9 | } else if (false) {
10 | System.out.println(false);
11 | } else {
12 | System.out.println("Huh?");
13 | }
14 |
15 | final var x = (true) ? 1 : 0;
16 |
17 | switch (x) {
18 | case 0:
19 | System.out.println("x == 0");
20 | case 1:
21 | System.out.println("x == 1");
22 | case 2:
23 | System.out.println("x == 1 (Oops, forgot the break!)");
24 | default:
25 | System.out.println("Double oops!");
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/test/kotlin/org/sdkotlin/koin/hello/SimpleHelloControllerTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import com.nhaarman.mockitokotlin2.doReturn
4 | import com.nhaarman.mockitokotlin2.mock
5 | import org.assertj.core.api.Assertions.assertThat
6 | import org.junit.jupiter.api.Test
7 |
8 | internal class SimpleHelloControllerTest {
9 |
10 | @Test
11 | fun `should say hello`() {
12 |
13 | val expectedGreeting = "Hi!"
14 |
15 | val helloService = mock {
16 | on { getGreeting() } doReturn expectedGreeting
17 | }
18 |
19 | val helloController = SimpleHelloController(helloService)
20 |
21 | val greeting = helloController.sayHello()
22 |
23 | assertThat(greeting).isEqualTo(expectedGreeting)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.caching=true
2 | org.gradle.configuration-cache=true
3 | org.gradle.configuration-cache.parallel=true
4 | org.gradle.configureondemand=true
5 | org.gradle.jvmargs=-Xmx4g
6 | org.gradle.kotlin.dsl.skipMetadataVersionCheck=false
7 | org.gradle.parallel=true
8 |
9 | # KSP and Gradle Versions Plugin `dependencyUpdates` task fails with:
10 | #org.gradle.unsafe.isolated-projects=true
11 |
12 | # Explicitly enable filesystem watching so Gradle doesn't go through its
13 | # default of trying to evaluate whether it can be enabled automatically, which
14 | # can be slow on Windows machines with mapped network drives:
15 | # https://github.com/gradle/gradle/issues/17955.
16 | org.gradle.vfs.watch=true
17 |
18 | dependency.analysis.print.build.health=true
19 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item3and4/Singletons.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item3and4
2 |
3 | /* Effective Java
4 | Item 3: Enforce the singleton property with a private constructor or an enum type
5 | Item 4: Enforce noninstantiability with a private constructor
6 | */
7 |
8 | // Kotlin has the singleton pattern built into the language using `object`
9 | // definitions.
10 |
11 | object HelloSingleton {
12 |
13 | const val DEFAULT_MOOD = "fine"
14 |
15 | private var mood = DEFAULT_MOOD
16 |
17 | fun howYouDoin() {
18 | mood = "great"
19 | println("${mood.replaceFirstChar { it.uppercase() }}, thanks for asking!")
20 | }
21 | }
22 |
23 | fun main() {
24 |
25 | HelloSingleton.howYouDoin()
26 | }
27 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_XX_try_w_resources/TryWithResourcesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._XX_try_w_resources
2 |
3 | import java.io.IOException
4 | import java.nio.file.Files
5 | import java.nio.file.Paths
6 | import java.util.stream.Collectors.joining
7 |
8 | fun main() {
9 |
10 | val classLoader = Thread.currentThread().contextClassLoader
11 | val resource = classLoader.getResource("hello.txt")
12 | ?: throw IllegalArgumentException("File not found!")
13 | val path = Paths.get(resource.toURI())
14 |
15 | try {
16 | Files.lines(path).use { lines ->
17 |
18 | val data = lines.collect(joining("\n"))
19 |
20 | println(data)
21 | }
22 | } catch (e: IOException) {
23 | e.printStackTrace()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_16_static/StaticInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._16_static
2 |
3 | import org.sdkotlin.intro.java._16_static.StaticInJava
4 |
5 | class StaticInKotlin {
6 |
7 | companion object {
8 |
9 | const val CONSTANT = "Unchanging"
10 |
11 | @JvmStatic
12 | fun saySomething() {
13 | println(CONSTANT)
14 | }
15 | }
16 |
17 | val instanceProperty = "Hello"
18 | fun instanceFunction() = "World"
19 | }
20 |
21 | fun main() {
22 |
23 | StaticInKotlin.saySomething()
24 | StaticInKotlin.CONSTANT
25 |
26 | StaticInKotlin().instanceFunction()
27 |
28 | StaticInJava.saySomething()
29 |
30 | // StaticInJava().saySomething() // Does not compile
31 | // StaticInKotlin().saySomething() // Does not compile
32 | }
33 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/main/kotlin/org/sdkotlin/tdd/fizzbuzz/FizzBuzz.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | fun main() {
4 |
5 | println("Function-oriented...")
6 | fizzBuzz1to100(::println)
7 |
8 | println("Object-oriented...")
9 | fizzBuzz1to100(ConsolePrinter())
10 | }
11 |
12 | fun fizzBuzz1to100() {
13 | (1..100).forEach { println(fizzBuzzOf(it)) }
14 | }
15 |
16 | fun fizzBuzz1to100(printFunction: (String) -> Unit) {
17 | (1..100).forEach { printFunction(fizzBuzzOf(it)) }
18 | }
19 |
20 | fun fizzBuzz1to100(printer: Printer) {
21 | fizzBuzz1to100 { fizzBuzz -> printer.print(fizzBuzz) }
22 | }
23 |
24 | internal fun fizzBuzzOf(n: Int): String {
25 | if (n % 15 == 0) return "FizzBuzz"
26 | if (n % 5 == 0) return "Buzz"
27 | if (n % 3 == 0) return "Fizz"
28 | return n.toString()
29 | }
30 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/main/kotlin/org/sdkotlin/equalsverifier/delegation/DelegatedEquals.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | interface Foo {
4 | val foo: Int
5 | }
6 |
7 | interface Bar {
8 | val bar: Int
9 | }
10 |
11 | data class BarImpl(override val bar: Int) : Bar
12 |
13 | class FooBarImpl(barValue: Int) : Foo, Bar by BarImpl(barValue) {
14 |
15 | override val foo = -bar
16 |
17 | override fun equals(other: Any?): Boolean {
18 | if (this === other) return true
19 | if (other !is FooBarImpl) return false
20 | return bar == other.bar
21 | }
22 |
23 | override fun hashCode(): Int = bar
24 | override fun toString(): String = "FooBarImpl(foo=$bar)"
25 | }
26 |
27 | interface Baz {
28 | val bar: Bar
29 | }
30 |
31 | data class BazImpl(override val bar: Bar) : Baz
32 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2 |
3 | plugins {
4 | id("org.sdkotlin.buildlogic.kotlin-project")
5 | id("org.sdkotlin.buildlogic.test.integration-test-suite")
6 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
7 | id("org.sdkotlin.buildlogic.mockito-kotlin-project")
8 | }
9 |
10 | dependencies {
11 |
12 | api(platform("org.sdkotlin.platforms:app-platform"))
13 |
14 | implementation(libs.bundles.koin.jvm)
15 |
16 | compileOnly(libs.jetbrains.annotations)
17 |
18 | integrationTestImplementation(platform("org.sdkotlin.platforms:test-platform"))
19 |
20 | integrationTestImplementation(libs.bundles.koin.test.junit5)
21 | }
22 |
23 | tasks {
24 |
25 | withType().configureEach {
26 | compilerOptions {
27 | optIn.add("kotlin.RequiresOptIn")
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/mockk/MockKValueClassParameterTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.mockk
2 |
3 | import io.mockk.every
4 | import io.mockk.mockk
5 | import org.assertj.core.api.Assertions.assertThat
6 | import org.junit.jupiter.api.Disabled
7 | import org.junit.jupiter.api.Test
8 |
9 | interface ValueClassSuperType
10 |
11 | @JvmInline
12 | value class ValueClass(val s: String) : ValueClassSuperType
13 |
14 | data class TestDataClass(val v: ValueClassSuperType)
15 |
16 | class MockKValueClassParameterTest {
17 |
18 | @Test
19 | @Disabled("https://github.com/mockk/mockk/issues/1342")
20 | fun `test value class parameter`() {
21 |
22 | val testValue = ValueClass("testing")
23 |
24 | val mock = mockk {
25 | every { v } returns testValue
26 | }
27 |
28 | assertThat(mock.v).isEqualTo(testValue)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/config/detekt/detekt.yml:
--------------------------------------------------------------------------------
1 | build:
2 | maxIssues: 0
3 | excludeCorrectable: false
4 |
5 | config:
6 | validation: true
7 | warningsAsErrors: true
8 | checkExhaustiveness: false
9 | # when writing own rules with new properties,
10 | # exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
11 | excludes: ''
12 |
13 | processors:
14 | active: true
15 | exclude:
16 | - 'DetektProgressListener'
17 |
18 | console-reports:
19 | active: true
20 | exclude:
21 | - 'ProjectStatisticsReport'
22 | - 'ComplexityReport'
23 | - 'NotificationReport'
24 | #- 'FindingsReport'
25 | - 'FileBasedFindingsReport'
26 |
27 | output-reports:
28 | active: true
29 | exclude:
30 | - 'HtmlOutputReport'
31 | - 'TxtOutputReport'
32 | - 'XmlOutputReport'
33 | - 'SarifOutputReport'
34 | #- 'MdOutputReport'
35 |
36 | junit:
37 | active: true
38 | InvalidTestFactoryReturnType:
39 | active: true
40 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.sdkotlin.buildlogic.global-exec")
3 | id("org.sdkotlin.buildlogic.kotlin-project")
4 | id("org.sdkotlin.buildlogic.test.test-fixtures-project")
5 | id("org.sdkotlin.buildlogic.test.unit-test-suite")
6 | id("org.sdkotlin.buildlogic.mockk-project")
7 | id("org.sdkotlin.buildlogic.mockito-kotlin-project")
8 | }
9 |
10 | dependencies {
11 |
12 | testImplementation(platform("org.sdkotlin.platforms:test-platform"))
13 |
14 | testImplementation(testFixtures(projects.subprojects.tddInKotlin))
15 |
16 | testImplementation(libs.kotest.assertions.core.jvm)
17 | testImplementation(libs.kotest.assertions.table.jvm)
18 | testImplementation(libs.kotest.framework.engine)
19 | testImplementation(libs.kotest.runner.junit5)
20 | testImplementation(libs.mockk)
21 |
22 | testRuntimeOnly(platform("org.sdkotlin.platforms:app-platform"))
23 |
24 | testRuntimeOnly(libs.slf4j.simple)
25 | }
26 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_08_5_infixfunctions/InfixFunctionsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._08_5_infixfunctions
2 |
3 | import kotlin.random.Random
4 |
5 | // Kotlin supports defining member and extension functions that can be called
6 | // using infix notation.
7 |
8 | infix fun Int.plusOrMinus(other: Int) =
9 | if (Random.nextBoolean()) {
10 | this + other
11 | } else {
12 | this - other
13 | }
14 |
15 | // Backticks can be used to escape nonstandard function names. This could be
16 | // combined with infix functions to simulate new operators, but backticks would
17 | // again be required at the call site.
18 |
19 | infix fun Int.`+-`(other: Int) = this.plusOrMinus(other)
20 |
21 | fun main() {
22 |
23 | val result = 1 plusOrMinus 2
24 |
25 | val alternateResult = 1 `+-` 2
26 |
27 | println("1 plusOrMinus 2: $result")
28 | println("1 `+-` 2: $alternateResult")
29 | }
30 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/main/kotlin/org/sdkotlin/equalsverifier/recursive/DataClassWithSealedTypeProperty.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.recursive
2 |
3 | data class DataClassWithSealedTypeProperty(
4 | val foo: Foo,
5 | )
6 |
7 | sealed interface Foo {
8 |
9 | val value: Int
10 |
11 | companion object {
12 | fun get(value: Int): Foo =
13 | FooEnum.INSTANCES[value] ?: UnknownFooImpl(value)
14 | }
15 | }
16 |
17 | enum class FooEnum(
18 | private val delegate: Foo,
19 | ) : Foo by delegate {
20 |
21 | FOO_1(1),
22 | FOO_2(2),
23 | ;
24 |
25 | constructor(
26 | value: Int,
27 | ) : this(FooImpl(value))
28 |
29 | companion object {
30 | val INSTANCES: Map =
31 | entries.associateBy { enum -> enum.value }
32 | }
33 | }
34 |
35 | internal data class FooImpl(
36 | override val value: Int,
37 | ) : Foo
38 |
39 | internal data class UnknownFooImpl(
40 | override val value: Int,
41 | ) : Foo
42 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/idioms/Destructuring.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.idioms
2 |
3 | // Use data classes for "multiple return values".
4 |
5 | data class Point3D(
6 | val x: Double = 0.0,
7 | val y: Double = 0.0,
8 | val z: Double = 0.0,
9 | )
10 |
11 | fun getOrigin() = Point3D()
12 |
13 | fun printOrigin() {
14 | val (x, y, z) = getOrigin()
15 | println("x: $x, y: $y, z: $z")
16 | }
17 |
18 | // Use destructuring with Maps and Arrays.
19 |
20 | val arrayOfMonths = arrayOf("Jan.", "Feb.", "etc.")
21 | val mapOfWeekdays = mapOf(1 to "Sunday", 2 to "Monday", 3 to "etc.")
22 |
23 | fun printMonthsAndWeekdays() {
24 |
25 | for ((index, value) in arrayOfMonths.withIndex()) {
26 | println("Month #${index + 1} is $value")
27 | }
28 |
29 | for ((key, value) in mapOfWeekdays) {
30 | println("Weekday #$key is $value")
31 | }
32 | }
33 |
34 | fun main() {
35 | printOrigin()
36 | printMonthsAndWeekdays()
37 | }
38 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/test/kotlin/org/sdkotlin/intro/kotlin/_14_0_dataclasses/PolyglotPersonTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._14_0_dataclasses
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import org.assertj.core.api.Assertions.assertThat
5 | import org.junit.jupiter.api.Test
6 |
7 | internal class PolyglotPersonTest {
8 |
9 | @Test
10 | fun `test equals, hashCode, and toString`() {
11 | EqualsVerifier.forClass(PolyglotPerson::class.java).verify()
12 | }
13 |
14 | @Test
15 | fun `test data class deep equals for immutable lists`() {
16 | val kotlinJavaPerson = PolyglotPerson(
17 | "Fran", listOf(
18 | ProgrammingLanguage("Kotlin"), ProgrammingLanguage("Java")
19 | )
20 | )
21 |
22 | val javaKotlinPerson = PolyglotPerson(
23 | "Fran", listOf(
24 | ProgrammingLanguage("Java"), ProgrammingLanguage("Kotlin")
25 | )
26 | )
27 |
28 | assertThat(kotlinJavaPerson).isNotEqualTo(javaKotlinPerson)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/subprojects/sorting-in-kotlin/src/main/kotlin/org/sdkoltin/sort/Swap.kt:
--------------------------------------------------------------------------------
1 | package org.sdkoltin.sort
2 |
3 | /**
4 | * In-place swaps the elements at the given indices.
5 | *
6 | * @param i the first index.
7 | * @param j the second index.
8 | * @throws IllegalStateException if the list size is less than 2.
9 | * @throws IllegalArgumentException if a given index is out of bounds, or if
10 | * the given indices are equal.
11 | */
12 | fun MutableList.swap(i: Int, j: Int) {
13 |
14 | check(size >= 2) {
15 | "Can't swap elements for a list with size $size!"
16 | }
17 |
18 | require(i in 0 until size) {
19 | "Index i = $i is out of bounds for list with size $size!"
20 | }
21 |
22 | require(j in 0 until size) {
23 | "Index j = $j is out of bounds for list with size $size!"
24 | }
25 |
26 | require(i != j) {
27 | "Can't swap elements for the same i and j index $i"
28 | }
29 |
30 | val temp = this[j]
31 | this[j] = this[i]
32 | this[i] = temp
33 | }
34 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/main/kotlin/org/sdkotlin/koin/hello/helloModule.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.hello
2 |
3 | import org.koin.core.qualifier.named
4 | import org.koin.dsl.module
5 |
6 | const val DECLARED_COMPONENT = "declared component"
7 | const val DECLARED_COMPONENT_CONTAINER = "declared component container"
8 |
9 | internal val helloModule = module {
10 |
11 | // An unqualified GreetingService
12 | single {
13 | RandomGreetingService()
14 | }
15 |
16 | // A named GreetingService
17 | single(named()) {
18 | EnglishGreetingService()
19 | }
20 |
21 | single {
22 | SimpleHelloController(get())
23 | }
24 |
25 | // Injection will fail if DECLARED_COMPONENT isn't externally declared
26 | // prior, e.g. with getKoin().declare(...)
27 | single(named(DECLARED_COMPONENT_CONTAINER)) {
28 | ExternalComponentContainer(
29 | get(named(DECLARED_COMPONENT))
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/sorting/KotestSortTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.sorting
2 |
3 | import io.kotest.core.spec.style.StringSpec
4 | import io.kotest.data.forAll
5 | import io.kotest.data.headers
6 | import io.kotest.data.row
7 | import io.kotest.data.table
8 | import io.kotest.matchers.shouldBe
9 |
10 | internal class KotestSortTest : StringSpec({
11 |
12 | "should return elements in order for" {
13 | val unsortedArrays = table(
14 | headers("unsortedArray", "expectedArray"),
15 | row(emptyArray(), emptyArray()),
16 | row(arrayOf(1), arrayOf(1)),
17 | row(arrayOf(1, 2), arrayOf(1, 2)),
18 | row(arrayOf(2, 1), arrayOf(1, 2)),
19 | row(arrayOf(1, 2, 3), arrayOf(1, 2, 3)),
20 | row(arrayOf(2, 1, 3), arrayOf(1, 2, 3)),
21 | row(arrayOf(1, 3, 2), arrayOf(1, 2, 3)),
22 | row(arrayOf(3, 2, 1), arrayOf(1, 2, 3))
23 | )
24 | forAll(unsortedArrays) { unsortedArray, sortedArray ->
25 | sort(unsortedArray) shouldBe sortedArray
26 | }
27 | }
28 | })
29 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/sorting/JUnit5LoopingSortTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.sorting
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 |
6 | internal class JUnit5LoopingSortTest {
7 |
8 | @Test
9 | fun `test sort`() {
10 |
11 | // Assemble
12 | val testCases = listOf(
13 | emptyArray() to emptyArray(),
14 | arrayOf(1) to arrayOf(1),
15 | arrayOf(1, 2) to arrayOf(1, 2),
16 | arrayOf(2, 1) to arrayOf(1, 2),
17 | arrayOf(1, 2, 3) to arrayOf(1, 2, 3),
18 | arrayOf(2, 1, 3) to arrayOf(1, 2, 3),
19 | arrayOf(1, 3, 2) to arrayOf(1, 2, 3),
20 | arrayOf(3, 2, 1) to arrayOf(1, 2, 3),
21 | )
22 |
23 | // Avoid: Fails fast (consider `@TestFactory` instead).
24 | for ((unsortedArray, sortedArray) in testCases) {
25 |
26 | // Act
27 | val sortResult = sort(unsortedArray)
28 |
29 | // Assert
30 | assertThat(sortResult)
31 | .isEqualTo(sortedArray)
32 | .isNotSameAs(unsortedArray)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_XX_try_w_resources/TryWithResourcesInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._XX_try_w_resources;
2 |
3 | import java.io.IOException;
4 | import java.net.URISyntaxException;
5 | import java.nio.file.Files;
6 | import java.nio.file.Paths;
7 |
8 | import static java.util.stream.Collectors.joining;
9 |
10 | public class TryWithResourcesInJava {
11 |
12 | public static void main(final String[] args) throws URISyntaxException {
13 |
14 | final var classLoader = Thread.currentThread().getContextClassLoader();
15 | final var resource = classLoader.getResource("hello.txt");
16 | if (resource == null) {
17 | throw new IllegalArgumentException("File not found!");
18 | }
19 | final var path = Paths.get(resource.toURI());
20 |
21 | try (final var lines = Files.lines(path)) {
22 |
23 | final var data = lines.collect(joining("\n"));
24 |
25 | System.out.println(data);
26 | } catch (final IOException e) {
27 | e.printStackTrace();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item17/MinimizeMutability.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item17
2 |
3 | /* Effective Java
4 | Item 17: Minimize mutability
5 | */
6 |
7 | // In Kotlin, immutability is just a `val` away.
8 |
9 | const val FUGGETABOUTIT = "Not gonna do it"
10 |
11 | data class ThreadSafe(val readOnly: String = "Can't touch this") {
12 |
13 | fun immutable(): String {
14 | val value = "Don't even"
15 | // value += "Nope" // Doesn't compile
16 | return value
17 | }
18 | }
19 |
20 | // The base collection APIs are immutable by default in Kotlin.
21 |
22 | val immutableList: List = listOf("Not", "gonna", "do", "it", "!")
23 |
24 | fun main() {
25 |
26 | //FUGGETABOUTIT = "As if" // Doesn't compile
27 | println(FUGGETABOUTIT)
28 |
29 | val threadSafe = ThreadSafe()
30 | // threadSafe.readOnly = "Sorry" // Doesn't compile
31 | println(threadSafe.readOnly)
32 | println(threadSafe.immutable())
33 |
34 | //immutableList[0] = "Are" // Does not compile.
35 |
36 | println(immutableList)
37 | }
38 |
--------------------------------------------------------------------------------
/subprojects/di-with-koin/src/it/kotlin/org/sdkotlin/koin/it/hello/HelloControllerIT.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.koin.it.hello
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 | import org.junit.jupiter.api.extension.RegisterExtension
6 | import org.koin.test.KoinTest
7 | import org.koin.test.inject
8 | import org.koin.test.junit5.KoinTestExtension
9 | import org.sdkotlin.koin.hello.HelloController
10 | import org.sdkotlin.koin.hello.helloModule
11 | import org.sdkotlin.koin.it.hello.test.TestGreetingService
12 | import org.sdkotlin.koin.it.hello.test.testHelloModule
13 |
14 | internal class HelloControllerIT : KoinTest {
15 |
16 | private val helloController: HelloController by inject()
17 |
18 | @JvmField
19 | @RegisterExtension
20 | val koinTestExtension = KoinTestExtension.create {
21 | modules(listOf(helloModule, testHelloModule))
22 | }
23 |
24 | @Test
25 | fun `Integration test the hello controller`() {
26 |
27 | val response = helloController.sayHello()
28 |
29 | assertThat(response).isEqualTo(TestGreetingService.TEST_GREETING)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_11_iteration/IterationInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._11_iteration;
2 |
3 | public class IterationInJava {
4 |
5 | public static void main(final String[] args) {
6 |
7 | for (int i = 1; i <= 5; i++) {
8 | System.out.println("Counting... " + i);
9 | }
10 |
11 | for (int i = 5; i >= 1; i--) {
12 | System.out.println("Down... " + i);
13 | }
14 |
15 | for (int i = 1; i <= 5; i += 2) {
16 | System.out.println("Odds... " + i);
17 | }
18 |
19 | final char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
20 |
21 | for (final char l : alphabet) {
22 | System.out.println("Letters... " + l);
23 | }
24 |
25 | for (int i = 0; i < alphabet.length; i++) {
26 | System.out.println("Letter " + (i + 1) + " of the alphabet is " + alphabet[i]);
27 | }
28 |
29 | var i = 1;
30 |
31 | while (i <= 5) {
32 | System.out.println("Counting between 1 and 5: " + i++);
33 | }
34 |
35 | var j = 1;
36 |
37 | do {
38 | System.out.println("Counting between 1 and 5: " + j++);
39 | } while (j <= 5);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/sorting/JUnit5DynamicTestSortTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.sorting
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.DynamicTest.dynamicTest
5 | import org.junit.jupiter.api.TestFactory
6 |
7 | internal class JUnit5DynamicTestSortTest {
8 |
9 | @TestFactory
10 | fun `test sort`() =
11 | // Assemble
12 | listOf(
13 | emptyArray() to emptyArray(),
14 | arrayOf(1) to arrayOf(1),
15 | arrayOf(1, 2) to arrayOf(1, 2),
16 | arrayOf(2, 1) to arrayOf(1, 2),
17 | arrayOf(1, 2, 3) to arrayOf(1, 2, 3),
18 | arrayOf(2, 1, 3) to arrayOf(1, 2, 3),
19 | arrayOf(1, 3, 2) to arrayOf(1, 2, 3),
20 | arrayOf(3, 2, 1) to arrayOf(1, 2, 3),
21 | ).map { (unsortedArray, expectedArray) ->
22 | dynamicTest(
23 | "sort(${unsortedArray.contentToString()}) is ${expectedArray.contentToString()}"
24 | ) {
25 | // Act
26 | val sortedArray = sort(unsortedArray)
27 |
28 | // Assert
29 | assertThat(sortedArray)
30 | .isEqualTo(expectedArray)
31 | .isNotSameAs(unsortedArray)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/test/kotlin/org/sdkotlin/integral/IntegralRangeTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | import io.mockk.mockk
4 | import nl.jqno.equalsverifier.EqualsVerifier
5 | import org.junit.jupiter.api.Test
6 |
7 | class IntegralRangeTest {
8 |
9 | @Test
10 | fun `test equals, hashCode, and toString`() {
11 |
12 | EqualsVerifier.forClass(IntegralRange::class.java)
13 | .withIgnoredFields("endExclusive", $$$"$$delegate_0")
14 | // Required per https://github.com/jqno/equalsverifier/issues/1082.
15 | .withPrefabValues(
16 | Integral::class.java,
17 | mockk(relaxed = true),
18 | mockk(relaxed = true),
19 | )
20 | .verify()
21 | }
22 |
23 | @Test
24 | fun `test equals, hashCode, and toString with examples`() {
25 |
26 | val zero = SignedIntegral(0)
27 | val one = SignedIntegral(1)
28 | val two = SignedIntegral(2)
29 | val red: ClosedRange = zero..one
30 | val blue: ClosedRange = one..two
31 |
32 | EqualsVerifier.forExamples(red, blue)
33 | .withIgnoredFields("endExclusive", $$$"$$delegate_0")
34 | .verify()
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/subprojects/equalsverifier-with-kotlin/src/test/kotlin/org/sdkotlin/equalsverifier/delegation/FooBarImplTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.equalsverifier.delegation
2 |
3 | import nl.jqno.equalsverifier.EqualsVerifier
4 | import nl.jqno.equalsverifier.Mode
5 | import org.assertj.core.api.Assertions.assertThat
6 | import org.junit.jupiter.api.Test
7 |
8 | class FooBarImplTest {
9 |
10 | @Test
11 | fun `test equals, hashCode, and toString`() {
12 |
13 | EqualsVerifier.forClass(FooBarImpl::class.java)
14 | .withIgnoredFields(Foo::foo.name)
15 | // Mockito skip or prefab values required per
16 | // https://github.com/jqno/equalsverifier/issues/1083.
17 | .set(Mode.skipMockito())
18 | //.withPrefabValues(BarImpl::class.java, BarImpl(1), BarImpl(2))
19 | .verify()
20 | }
21 |
22 | @Test
23 | fun `test equals for equal`() {
24 | val actual = FooBarImpl(1)
25 | val expected = FooBarImpl(1)
26 | assertThat(actual).isEqualTo(expected)
27 | }
28 |
29 | @Test
30 | fun `test equals for not equal`() {
31 | val actual = FooBarImpl(1)
32 | val expected = FooBarImpl(2)
33 | assertThat(actual).isNotEqualTo(expected)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item2/ConsiderBuilders.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item2
2 |
3 | /* Effective Java
4 | Item 2: Consider a builder when faced with many constructor parameters
5 | */
6 |
7 | // Kotlin supports named and default parameters, which make the telescoping
8 | // constructor and method patterns, and in many cases the builder pattern,
9 | // obsolete.
10 |
11 | data class NutritionFacts(
12 | val servingSize: Int,
13 | val servings: Int,
14 | val calories: Int = 0,
15 | val fat: Int = 0,
16 | val sodium: Int = 0,
17 | val carbohydrate: Int = 0,
18 | ) {
19 | init {
20 | require(servingSize > 0) { "servingSize must be greater than 0" }
21 | }
22 | }
23 |
24 | fun main() {
25 |
26 | val sodaNutritionFacts =
27 | NutritionFacts(servingSize = 12, servings = 2, calories = 180)
28 |
29 | val pizzaNutritionFacts =
30 | NutritionFacts(
31 | servingSize = 1,
32 | servings = 12,
33 | calories = 250,
34 | fat = 12,
35 | carbohydrate = 24,
36 | )
37 |
38 | println("Soda facts: $sodaNutritionFacts")
39 | println("Pizza facts: $pizzaNutritionFacts")
40 | }
41 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item10through13/CommonMethods.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item10through13
2 |
3 | /* Effective Java
4 | Item 10: Obey the general contract when overriding equals
5 | Item 11: Always override hashCode when you override equals
6 | Item 12: Always override toString
7 | Item 13: Override clone judiciously
8 | */
9 |
10 | // Data classes do all these things correctly for you out of the box.
11 |
12 | data class Person(val name: String, var age: Int)
13 |
14 | fun `with data classes`() {
15 |
16 | val sally = Person("Sally", 22)
17 | val sandy = Person("Sandy", 32)
18 |
19 | // equals
20 |
21 | println("Sally == Sandy?: ${sally == sandy}")
22 |
23 | // toString
24 |
25 | println("sally: $sally")
26 |
27 | // "clone"
28 |
29 | val suzzy = sally.copy(name = "Suzzy")
30 |
31 | // hashCode
32 |
33 | val people =
34 | mapOf(sally.name to sally, sandy.name to sandy, suzzy.name to suzzy)
35 |
36 | people.forEach { (name, person) ->
37 | println("$name's hash code is: ${person.hashCode()}")
38 | }
39 | }
40 |
41 | fun main() {
42 | `with data classes`()
43 | }
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/sdkotlin/sd-kotlin-talks/actions/workflows/gradle.yml)
2 | [](https://sonarcloud.io/dashboard?id=sdkotlin_sd-kotlin-talks)
3 |
4 | # San Diego Kotlin User Group Talks
5 |
6 | Code examples from
7 | the [San Diego Kotlin User Group](https://www.meetup.com/sd-kotlin/) meetings on
8 | the [Kotlin](http://kotlinlang.org/) programming language.
9 |
10 | ## Building
11 |
12 | The project is built
13 | with [Gradle](https://docs.gradle.org/current/userguide/userguide.html) and uses
14 | the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html#gradle_wrapper_reference),
15 | which can be invoked from the project root once
16 | the [Gradle prerequisites](https://docs.gradle.org/current/userguide/installation.html#sec:prerequisites)
17 | are met.
18 |
19 | The project currently requires Gradle to be invoked with a Java Development
20 | Kit (JDK) version 21 or higher.
21 |
22 | The primary build task is `build`.
23 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item16/AccessorsOverFields.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item16
2 |
3 | /* Effective Java
4 | Item 16: In public classes, use accessor methods, not public fields
5 | */
6 |
7 | // Kotlin doesn't have fields, only properties with their associated accessors
8 | // and private backing fields.
9 |
10 | data class Programmer(val name: String) {
11 | var languages: String = "Kotlin"
12 | set(value) {
13 | when (value) {
14 | "Kotlin", "Java" -> {
15 | println("""DEBUG: Appending "$value" to "$field"""")
16 | field += ", and $value"
17 | }
18 | else -> println("""DEBUG: Ignoring "$value"""")
19 | }
20 | }
21 | get() = "$field!"
22 |
23 | val favoriteIde = "IntelliJ"
24 | get() = "$field. 🙂"
25 | }
26 |
27 | fun main() {
28 |
29 | val programmer = Programmer("Jim")
30 |
31 | // Look, Ma, "field access"
32 | programmer.languages = "Java"
33 | programmer.languages = "Kotlin"
34 | programmer.languages = "Perl"
35 |
36 | println("${programmer.name} knows ${programmer.languages}")
37 | println("Their favorite IDE is ${programmer.favoriteIde}")
38 | }
39 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/test-project/src/test/kotlin/org/sdkotlin/buildergen/processor/it/TestEntityBuilderTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.processor.it
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.api.Test
5 | import org.sdkotlin.buildergen.api.builder.Builder
6 |
7 | internal class TestEntityBuilderTest {
8 |
9 | companion object {
10 | const val TEST_INT = 1
11 | const val TEST_STRING = "Testing"
12 | }
13 |
14 | @Test
15 | fun `test generated builder`() {
16 |
17 | val testEntityBuilder = TestEntityBuilder()
18 |
19 | testEntityBuilder.testInt = TEST_INT
20 | testEntityBuilder.testNullableInt = null
21 | testEntityBuilder.testString = TEST_STRING
22 | testEntityBuilder.testNullableString = null
23 |
24 | assertThat(testEntityBuilder).isInstanceOf(Builder::class.java)
25 |
26 | val testEntity: TestEntity = testEntityBuilder.build()
27 |
28 | assertThat(testEntity.testInt).isEqualTo(TEST_INT)
29 | assertThat(testEntity.testNullableInt).isNull()
30 | assertThat(testEntity.testString).isEqualTo(TEST_STRING)
31 | assertThat(testEntity.testNullableString).isNull()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_32_delegation/LateInit.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._32_delegation
2 |
3 | import kotlin.properties.ReadWriteProperty
4 | import kotlin.reflect.KProperty
5 |
6 | class LateInit(
7 | val createException: (s: String) -> Exception,
8 | ) : ReadWriteProperty {
9 |
10 | private object EMPTY
11 |
12 | private var value: Any? = EMPTY
13 |
14 | override fun getValue(
15 | thisRef: Any,
16 | property: KProperty<*>,
17 | ): T {
18 | if (value == EMPTY) {
19 | throw createException("${property.name} isn't initialized")
20 | } else {
21 | @Suppress("UNCHECKED_CAST") // Must be EMPTY or a T.
22 | return value as T
23 | }
24 | }
25 |
26 | override fun setValue(
27 | thisRef: Any,
28 | property: KProperty<*>,
29 | value: T,
30 | ) {
31 | if (this.value != EMPTY) {
32 | throw createException("${property.name} already initialized")
33 | }
34 | this.value = value
35 | }
36 | }
37 |
38 | inline fun lateInit(
39 | noinline createException: (s: String) -> Exception =
40 | { IllegalStateException(it) },
41 | ): ReadWriteProperty =
42 | LateInit(createException)
43 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/fizzbuzz/FizzBuzzMockKTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | import io.mockk.mockk
4 | import io.mockk.verify
5 | import io.mockk.verifyOrder
6 | import org.junit.jupiter.api.Test
7 |
8 | internal class FizzBuzzMockKTest {
9 |
10 | @Test
11 | fun `test fizzBuzz1To100() prints 100 FizzBuzzes with MockK Printer`() {
12 |
13 | val mockPrinter = mockk()
14 |
15 | fizzBuzz1to100(mockPrinter)
16 |
17 | verify(exactly = 100) {
18 | mockPrinter.print(any())
19 | }
20 |
21 | verifyOrder {
22 | mockPrinter.print("1")
23 | mockPrinter.print("2")
24 | mockPrinter.print("Fizz")
25 | mockPrinter.print("Buzz")
26 | mockPrinter.print("FizzBuzz")
27 | }
28 | }
29 |
30 | @Test
31 | fun `test fizzBuzz1To100() prints 100 FizzBuzzes with MockK function object`() {
32 |
33 | val mockPrintLn = mockk<(String) -> Unit>()
34 |
35 | fizzBuzz1to100(mockPrintLn)
36 |
37 | verify(exactly = 100) {
38 | mockPrintLn(any())
39 | }
40 |
41 | verifyOrder {
42 | mockPrintLn("1")
43 | mockPrintLn("2")
44 | mockPrintLn("Fizz")
45 | mockPrintLn("Buzz")
46 | mockPrintLn("FizzBuzz")
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/main/kotlin/org/sdkotlin/integral/IntegralRange.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | class IntegralRange>(
4 | start: I,
5 | endInclusive: I,
6 | ) : ClosedRange, OpenEndRange,
7 | Progression by IntegralProgression(
8 | start,
9 | endInclusive,
10 | step = start.one
11 | ) {
12 |
13 | override val start: I = first
14 |
15 | override val endInclusive: I = last
16 |
17 | override val endExclusive: I by lazy {
18 | check(endInclusive != endInclusive.maxValue) {
19 | "Cannot return the exclusive upper bound of a range that includes MAX_VALUE."
20 | }
21 | endInclusive + endInclusive.one
22 | }
23 |
24 | override fun contains(value: I): Boolean =
25 | value in start..endInclusive
26 |
27 | override fun isEmpty(): Boolean = start > endInclusive
28 |
29 | override fun equals(other: Any?): Boolean =
30 | other is IntegralRange<*> && (isEmpty() && other.isEmpty() ||
31 | start == other.start && endInclusive == other.endInclusive)
32 |
33 | override fun hashCode(): Int =
34 | if (isEmpty()) -1 else (31 * start.hashCode() + endInclusive.hashCode())
35 |
36 | override fun toString(): String = "$start..$endInclusive"
37 | }
38 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/sorting/JUnit5ParameterizedSortTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.sorting
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.junit.jupiter.params.ParameterizedTest
5 | import org.junit.jupiter.params.provider.Arguments
6 | import org.junit.jupiter.params.provider.Arguments.arguments
7 | import org.junit.jupiter.params.provider.MethodSource
8 |
9 | internal class JUnit5ParameterizedSortTest {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun arrays() = listOf(
14 | Arguments.of(emptyArray(), emptyArray()),
15 | arguments(arrayOf(1), arrayOf(1)),
16 | arguments(arrayOf(1, 2), arrayOf(1, 2)),
17 | arguments(arrayOf(2, 1), arrayOf(1, 2)),
18 | arguments(arrayOf(1, 2, 3), arrayOf(1, 2, 3)),
19 | arguments(arrayOf(2, 1, 3), arrayOf(1, 2, 3)),
20 | arguments(arrayOf(1, 3, 2), arrayOf(1, 2, 3)),
21 | arguments(arrayOf(3, 2, 1), arrayOf(1, 2, 3))
22 | )
23 | }
24 |
25 | @ParameterizedTest(name = "sort({0}) is {1}")
26 | @MethodSource("arrays")
27 | fun `test sort`(unsortedArray: Array, sortedArray: Array) {
28 | assertThat(sort(unsortedArray)).isEqualTo(sortedArray)
29 | .isNotSameAs(unsortedArray)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/idioms/Nulls.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.idioms
2 |
3 | data class Person(val name: String, val address: Address? = null)
4 |
5 | data class Address(
6 | val street1: String, val street2: String? = null,
7 | val city: String,
8 | val state: String, val zipCode: String,
9 | )
10 |
11 | /**
12 | * Handle nulls in chained property accessor and method calls
13 | */
14 | fun whichState(person: Person?): String {
15 | return person?.address?.state ?: "Unknown"
16 | }
17 |
18 | /**
19 | * Handle nulls with a little less conversation, a little more action, using
20 | * Kotlin's Elvis operator
21 | *
22 | * @throws IllegalArgumentException if an address is not available
23 | */
24 | fun sendCard(person: Person) {
25 |
26 | val address = person.address ?: throw IllegalArgumentException(
27 | "Can't send a card to a person if they don't have an address"
28 | )
29 |
30 | println("Sending a card to ${person.name} at $address")
31 | }
32 |
33 | fun main() {
34 |
35 | val sally = Person(name = "Sally")
36 |
37 | println("Sally lives in ${whichState(sally)}")
38 |
39 | try {
40 | sendCard(sally)
41 | } catch (e: IllegalArgumentException) {
42 | println(e.message)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_06_equality/EqualityInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._06_equality;
2 |
3 | import java.util.Objects;
4 |
5 | public class EqualityInJava {
6 |
7 | public static void main(final String[] args) {
8 |
9 | // False.
10 | System.out.println("\"foo\"==new String(\"foo\"): "
11 | + ("foo" == new String("foo")));
12 |
13 | // True only because of the string pool.
14 | System.out.println("\"foo\"==\"foo\": "
15 | + ("foo" == "foo"));
16 |
17 | // True because of the integer pool.
18 | System.out.println("127==127: "
19 | + (Integer.valueOf(Byte.MAX_VALUE) == Integer.valueOf(Byte.MAX_VALUE)));
20 |
21 | // Likely false, but may be true depending on VM and its settings for the integer pool.
22 | System.out.println("128==128: "
23 | + (Integer.valueOf(Byte.MAX_VALUE + 1) == Integer.valueOf(Byte.MAX_VALUE + 1)));
24 |
25 | // Correct logical comparison. Null safe only when the left side is known to not be null.
26 | System.out.println("\"foo\".equals(new String(\"foo\")): "
27 | + "foo".equals(new String("foo")));
28 |
29 | // Null safe.
30 | System.out.println("Objects.equals(null, null): "
31 | + Objects.equals(null, null));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/effectivejava/item50/MakeDefensiveCopies.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.effectivejava.item50
2 |
3 | /* Effective Java
4 | Item 50: Make defensive copies when needed
5 | */
6 |
7 | // Kotlin data classes come with `copy()`.
8 |
9 | data class Person(val name: String, var age: Int)
10 |
11 | object OlympicTriplets {
12 | val leila = Person("Leila", 33)
13 | val liina = leila.copy(name = "Liina")
14 | val lily = liina.copy(name = "Lily")
15 |
16 | override fun toString(): String {
17 | return "{ $leila, $liina, $lily }"
18 | }
19 | }
20 |
21 | fun good(triplets: OlympicTriplets) {
22 |
23 | // Copy Leila so as not to change her age on the passed parameter
24 | val leilaClone = triplets.leila.copy()
25 |
26 | leilaClone.age++
27 |
28 | println("Leila's clone is ${leilaClone.age} years old.")
29 | }
30 |
31 | fun bad(triplets: OlympicTriplets) {
32 |
33 | println("Unless we don't make a defensive copy, in which case...")
34 | triplets.leila.age++
35 | }
36 |
37 | fun main() {
38 |
39 | good(OlympicTriplets)
40 |
41 | println("The original Leila is still ${OlympicTriplets.leila.age}.")
42 |
43 | bad(OlympicTriplets)
44 |
45 | println("The original Leila is now ${OlympicTriplets.leila.age}.")
46 | }
47 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_15_singletons/SingletonInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._15_singletons
2 |
3 | // Kotlin has built-in support for the singleton pattern.
4 |
5 | object KotlinSingleton {
6 |
7 | const val notQuitePi = 3.14
8 |
9 | fun doIt() {
10 | println("The most wonderful thing about tiggers is I'm the only one!")
11 | }
12 | }
13 |
14 | // Kotlin 1.8 will introduce data objects, which override toString().
15 |
16 | data object TooStringy {
17 |
18 | const val cheesy = "String Cheese"
19 |
20 | // Data objects override toString without including any properties, like:
21 | //override fun toString() = "${TooStringy::class.simpleName}"
22 |
23 | // You can still provide your own override to include them:
24 | //override fun toString() = "${TooStringy::class.simpleName}[cheesy=$cheesy]"
25 | }
26 |
27 | fun main() {
28 |
29 | // Singleton instances are available by their type name.
30 |
31 | val singleton = KotlinSingleton
32 |
33 | singleton.doIt()
34 |
35 | // No need to assign them to a var.
36 |
37 | println(KotlinSingleton.notQuitePi)
38 |
39 | // Singletons do not have constructors.
40 |
41 | //KotlinSingleton().doIt()
42 |
43 | // Regular objects don't override toString().
44 |
45 | println(KotlinSingleton)
46 |
47 | // Data objects do.
48 |
49 | println(TooStringy)
50 | }
51 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_06_strings/StringsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._06_strings
2 |
3 | import org.sdkotlin.intro.java._06_strings.StringsInJava.STRING
4 |
5 | fun main() {
6 |
7 | // Kotlin supports string templates.
8 |
9 | val yay = "yay"
10 |
11 | val template = "Kotlin supports String templates, $yay!\n\n"
12 |
13 | println(template)
14 |
15 | val otherTemplate = "You can use arbitrary expressions if you" +
16 | "add curly braces: ${1 + 1}"
17 |
18 | println(otherTemplate)
19 |
20 | val rawString = """
21 | You can use "raw" strings for more substantial bodies of text.
22 | val someString = "That gets you out of "
23 | + "concatenation-wrapping, and lets you use literal whitespace "
24 | + "instead of escape sequences such as \t, \n, etc."
25 | You can still use string templates in raw strings: $STRING
26 | You can still put arbitrary expressions in those string templates with
27 | curly braces. ${"\n".repeat(2)}
28 |
29 | You can trim leading indentation.
30 | """.trimIndent()
31 |
32 | val prefixedRawString = """
33 | > You can also trim to a prefix string,
34 | > as with email-style quotations.
35 | > The default prefix is "|" for `.trimMargin()`.
36 | > > Trimming is not eager.
37 | """.trimMargin("> ")
38 |
39 | println(template + rawString + prefixedRawString)
40 | }
41 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_08_3_extensionfunctions/ExtensionFunctionsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._08_3_extensionfunctions
2 |
3 | // Kotlin allows us to add functions to an existing class by prefixing the
4 | // function name with the type it's extending.
5 |
6 | // You can refer to the instance the extension is called on (the "receiver")
7 | // with the usual 'this' keyword.
8 |
9 | fun String.shuffled() = this.toList().shuffled().joinToString(separator = "")
10 |
11 | // This is handy for adding things to the stdlib or other libraries that you
12 | // feel are missing.
13 |
14 | fun String.bedazzled() = "***$this***"
15 |
16 | fun main() {
17 |
18 | val shuffled = "Alphabet".shuffled()
19 |
20 | println("Alphabet.shuffled(): $shuffled")
21 |
22 | val bedazzled = "Snazzy".bedazzled()
23 |
24 | println("Snazzy.bedazzled(): $bedazzled")
25 |
26 | // Extension functions are resolved statically by the receiver's
27 | // declared or inferred type. In other words, they are not polymorphic.
28 |
29 | abstract class Animal
30 |
31 | class Lion : Animal()
32 |
33 | fun Animal.name() = "Animal"
34 | fun Lion.name() = "Simba"
35 |
36 | val genericLion: Animal = Lion()
37 | val specificLion = Lion()
38 |
39 | println("Lion as Animal's name: ${genericLion.name()}")
40 | println("Lion as Lion's name: ${specificLion.name()}")
41 | }
42 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_18_inheritance/InheritanceInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._18_inheritance
2 |
3 | class Class
4 |
5 | // "Effective Java, 3rd Edition. Item 19: Design and
6 | // Document for Inheritance or Else Prohibit It"
7 |
8 | // Classes are final by default in Kotlin (see bytecode)
9 | //class Subclass : Class()
10 |
11 | // You can "open" them like so...
12 | open class BaseClass(var name: String = "Cliff") {
13 |
14 | constructor(nameAsInt: Int) : this(name = nameAsInt.toString())
15 |
16 | // Functions are final by default in Kotlin as well
17 | fun finalFunction() = println("Can't touch this!")
18 |
19 | // But they can be opened too
20 | open fun openFunction() = println("Base class implementation")
21 | }
22 |
23 | // Subclasses must call a constructor of their superclass.
24 | class Subclass : BaseClass(nameAsInt = 1) {
25 |
26 | // You can't override a final function
27 | //override fun finalFunction() = println("nope!")
28 |
29 | // You can explicitly override open functions
30 | override fun openFunction() = println("Subclass implementation")
31 | }
32 |
33 | fun main() {
34 |
35 | println(Class())
36 |
37 | val baseClass = BaseClass()
38 | baseClass.finalFunction()
39 | baseClass.openFunction()
40 |
41 | val subclass = Subclass()
42 | subclass.finalFunction()
43 | subclass.openFunction()
44 | }
45 |
--------------------------------------------------------------------------------
/subprojects/tdd-in-kotlin/src/test/kotlin/org/sdkotlin/tdd/fizzbuzz/FizzBuzzMockitoKotlinTest.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.tdd.fizzbuzz
2 |
3 | import com.nhaarman.mockitokotlin2.any
4 | import com.nhaarman.mockitokotlin2.inOrder
5 | import com.nhaarman.mockitokotlin2.mock
6 | import com.nhaarman.mockitokotlin2.times
7 | import com.nhaarman.mockitokotlin2.verify
8 | import org.junit.jupiter.api.Test
9 |
10 | internal class FizzBuzzMockitoKotlinTest {
11 |
12 | @Test
13 | fun `test fizzBuzz1To100() prints 100 FizzBuzzes with Mockito mock Printer`() {
14 |
15 | val mockPrinter = mock()
16 |
17 | fizzBuzz1to100(mockPrinter)
18 |
19 | verify(mockPrinter, times(100)).print(any())
20 |
21 | inOrder(mockPrinter) {
22 | mockPrinter.print("1")
23 | mockPrinter.print("2")
24 | mockPrinter.print("Fizz")
25 | mockPrinter.print("Buzz")
26 | mockPrinter.print("FizzBuzz")
27 | }
28 | }
29 |
30 | @Test
31 | fun `test fizzBuzz1To100() prints 100 FizzBuzzes with Mockito mock function object`() {
32 |
33 | val mockPrinter = mock<(String) -> Unit>()
34 |
35 | fizzBuzz1to100(mockPrinter)
36 |
37 | verify(mockPrinter, times(100)).invoke(any())
38 |
39 | // Or...
40 | verify(mockPrinter, times(100))(any())
41 |
42 | inOrder(mockPrinter) {
43 | mockPrinter("1")
44 | mockPrinter("2")
45 | mockPrinter("Fizz")
46 | mockPrinter("Buzz")
47 | mockPrinter("FizzBuzz")
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Gradle and cache/restore any
2 | # dependencies to improve the workflow execution time. For more information see:
3 | # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
4 |
5 | name: Gradle Build
6 |
7 | on:
8 | push:
9 | branches: [ "main" ]
10 | pull_request:
11 | branches: [ "main" ]
12 |
13 | jobs:
14 | build:
15 |
16 | runs-on: ubuntu-latest
17 | permissions:
18 | contents: read
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 | with:
23 | lfs: 'true'
24 | - name: Set up JDK 21
25 | uses: actions/setup-java@v4
26 | with:
27 | java-version: '21'
28 | distribution: 'temurin'
29 |
30 | # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies.
31 | # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
32 | - name: Setup Gradle
33 | uses: gradle/actions/setup-gradle@v3
34 | with:
35 | build-scan-publish: true
36 | build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
37 | build-scan-terms-of-use-agree: "yes"
38 |
39 | # Useful for observing eager configuration
40 | - name: Run Gradle Help
41 | run: ./gradlew help
42 |
43 | - name: Run Gradle Build
44 | run: ./gradlew build
45 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_19_abstractclasses/AbstractClassesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._19_abstractclasses
2 |
3 | // Kotlin supports abstract classes and members.
4 |
5 | // Abstract classes are implicitly open.
6 |
7 | abstract class DinnerTemplate {
8 |
9 | protected open fun cookFood() {
10 | println("It's pasta for dinner")
11 | }
12 |
13 | // Abstract members are implicitly open as well.
14 |
15 | protected abstract fun serve()
16 |
17 | protected abstract fun enjoy()
18 |
19 | fun haveDinner() {
20 | cookFood()
21 | serve()
22 | enjoy()
23 | }
24 | }
25 |
26 | class NiceMeal : DinnerTemplate() {
27 |
28 | override fun serve() {
29 | println("Paper plates and plasticware")
30 | }
31 |
32 | override fun enjoy() {
33 | println("Slrrrp")
34 | }
35 | }
36 |
37 | abstract class NotPastaAgainTemplate : DinnerTemplate() {
38 |
39 | // An open member function can be overridden as abstract.
40 | abstract override fun cookFood()
41 | }
42 |
43 | class FancyMeal : NotPastaAgainTemplate() {
44 |
45 | override fun cookFood() {
46 | println("Chef's special")
47 | }
48 |
49 | override fun serve() {
50 | println("Fine china and silverware")
51 | }
52 |
53 | override fun enjoy() {
54 | println("Bon appetit")
55 | }
56 | }
57 |
58 | fun main() {
59 |
60 | val niceMeal = NiceMeal()
61 | val fancyMeal = FancyMeal()
62 |
63 | niceMeal.haveDinner()
64 | fancyMeal.haveDinner()
65 | }
66 |
--------------------------------------------------------------------------------
/subprojects/ksp-builder-generator/processor/src/main/kotlin/org/sdkotlin/buildergen/processor/BuilderGenSymbolProcessor.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.buildergen.processor
2 |
3 | import com.google.devtools.ksp.processing.CodeGenerator
4 | import com.google.devtools.ksp.processing.KSPLogger
5 | import com.google.devtools.ksp.processing.Resolver
6 | import com.google.devtools.ksp.processing.SymbolProcessor
7 | import com.google.devtools.ksp.symbol.KSAnnotated
8 | import com.google.devtools.ksp.symbol.KSClassDeclaration
9 | import com.google.devtools.ksp.validate
10 | import org.sdkotlin.buildergen.api.annotations.GeneratedBuilder
11 |
12 | internal class BuilderGenSymbolProcessor(
13 | private val codeGenerator: CodeGenerator,
14 | private val logger: KSPLogger,
15 | ) : SymbolProcessor {
16 |
17 | override fun process(resolver: Resolver): List {
18 |
19 | val annotationClass = GeneratedBuilder::class
20 |
21 | val symbols = resolver.getSymbolsWithAnnotation(
22 | annotationClass.qualifiedName
23 | ?: throw IllegalArgumentException(
24 | "Could not get $annotationClass qualified name"
25 | )
26 | )
27 |
28 | val annotatedSymbols: List =
29 | symbols.filter { !it.validate() }.toList()
30 |
31 | symbols
32 | .filter { it is KSClassDeclaration && it.validate() }
33 | .forEach {
34 | it.accept(
35 | visitor = BuilderGenVisitor(codeGenerator, logger),
36 | data = Unit
37 | )
38 | }
39 |
40 | return annotatedSymbols
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/subprojects/kotlin-dl/src/main/kotlin/org/sdkotlin/kotlindl/FashionMnist.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.kotlindl
2 |
3 | import org.jetbrains.kotlinx.dl.api.core.Sequential
4 | import org.jetbrains.kotlinx.dl.api.core.layer.core.Dense
5 | import org.jetbrains.kotlinx.dl.api.core.layer.core.Input
6 | import org.jetbrains.kotlinx.dl.api.core.layer.reshaping.Flatten
7 | import org.jetbrains.kotlinx.dl.api.core.loss.Losses
8 | import org.jetbrains.kotlinx.dl.api.core.metric.Metrics
9 | import org.jetbrains.kotlinx.dl.api.core.optimizer.Adam
10 | import org.jetbrains.kotlinx.dl.dataset.embedded.fashionMnist
11 |
12 | private const val EPOCHS = 5
13 | private const val TRAINING_BATCH_SIZE = 100
14 | private const val TEST_BATCH_SIZE = 1000
15 | private const val NUM_LABELS = 10
16 | private const val NUM_CHANNELS = 1L
17 | private const val IMAGE_SIZE = 28L
18 |
19 | internal val model = Sequential.of(
20 | Input(IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS),
21 | Flatten(),
22 | Dense(300),
23 | Dense(100),
24 | Dense(NUM_LABELS)
25 | )
26 |
27 | fun main() {
28 |
29 | val (train, test) = fashionMnist()
30 |
31 | model.use {
32 |
33 | it.compile(
34 | optimizer = Adam(),
35 | loss = Losses.SOFT_MAX_CROSS_ENTROPY_WITH_LOGITS,
36 | metric = Metrics.ACCURACY
37 | )
38 |
39 | it.fit(
40 | dataset = train,
41 | epochs = EPOCHS,
42 | batchSize = TRAINING_BATCH_SIZE
43 | )
44 |
45 | val accuracy = it.evaluate(
46 | dataset = test,
47 | batchSize = TEST_BATCH_SIZE
48 | ).metrics[Metrics.ACCURACY]
49 |
50 | println("Accuracy: $accuracy")
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_12_properties/PropertiesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._12_properties
2 |
3 | // Top level variables and class fields in Kotlin are really all properties.
4 |
5 | val readOnly = 0
6 | // They have default getters (and for 'var', setters) that can be overridden.
7 | get() {
8 |
9 | // If you later decide you need to add some behavior to the getter,
10 | // you can.
11 |
12 | println("Audit readOnly get.")
13 |
14 | // The underlying field is available in getters and setters using the
15 | // keyword 'field'.
16 |
17 | return field
18 | }
19 |
20 | var readWrite = 1
21 | get() {
22 | println("Audit readWrite get.")
23 | return field
24 | }
25 | set(value) {
26 | println("Audit readWrite set: $value.")
27 | field = value
28 | }
29 |
30 | // You can use access modifiers to restrict the getter or setter, and omit the
31 | // either to use the default.
32 |
33 | var readPrivateWrite = 1
34 | private set(value) {
35 | println("Audit readWrite set: $value.")
36 | field = value
37 | }
38 |
39 | // Getters and setters can be computed.
40 |
41 | var width = 1
42 | var height = 1
43 |
44 | val area: Int
45 | get() = width * height
46 |
47 | fun main() {
48 | println("readOnly is $readOnly")
49 |
50 | println("readWrite is $readWrite")
51 | readWrite++
52 | println("After readWrite++ it's $readWrite")
53 |
54 | println("Only this file can readPrivateWrite++: ${readPrivateWrite++}")
55 |
56 | println("Area: $area")
57 | width++
58 | height++
59 | println("New area: $area")
60 | }
61 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_08_4_operatorfunctions/OperatorOverloadingInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._08_4_operatorfunctions
2 |
3 | // Kotlin supports limited operator overloading via specific member or
4 | // extension functions.
5 |
6 | data class Zebra(var name: String = "Zebra") {
7 |
8 | // Operators are overloaded for a type by way of 'operator' funs that
9 | // have well known names. For '++' it's 'inc()', for '--' it's 'dec()', etc.
10 |
11 | operator fun inc() = Zebra("More $name")
12 |
13 | // See the Kotlin docs for the full list and their contracts:
14 | // https://kotlinlang.org/docs/reference/operator-overloading.html
15 | }
16 |
17 | // Operator overloading is one of the core Kotlin language features that
18 | // can be leveraged for creating internal DSLs. For example, overloading
19 | // 'invoke()' can be used to make a String executable.
20 |
21 | operator fun String.invoke() = println("To the moon, $this!")
22 |
23 | // Note that not all operators are overloadable, e.g. '=', '===', '!=='.
24 |
25 | // There is no mechanism for defining additional first-class operators,
26 | // though this can be simulated with infix functions to be covered next.
27 |
28 | // Like extension functions, operator overloads are scoped and must be
29 | // imported to have any effect.
30 |
31 | // Member operator overloads shadow extension operator overloads, which
32 | // prevents overriding the base operator implementations for common types.
33 |
34 | operator fun Int.minus(other: Int) = this + other
35 |
36 | fun main() {
37 |
38 | var zebra = Zebra()
39 |
40 | println(zebra)
41 |
42 | zebra++
43 |
44 | println(zebra)
45 |
46 | "Alice"()
47 |
48 | println("1 - 1: ${1 - 1}")
49 | }
50 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_05_variables/VariablesAndTypesInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._05_variables;
2 |
3 | public class VariablesAndTypesInJava {
4 |
5 | // Fields get default values in Java
6 |
7 | boolean bool; // = false
8 | Boolean Bool; // = null
9 | byte b; // = 0
10 | Byte B; // = null
11 | char c; // = 'u0000', i.e. NULL
12 | Character C; // = null
13 | short s; // = 0
14 | Short S; // = null
15 | int i; // = 0
16 | Integer I; // = null
17 | long l; // = 0L
18 | Long L; // = null
19 | float f; // = 0.0f
20 | Float F; // = null
21 | double d; // = 0.0d
22 | Double D; // = null
23 |
24 | // They are mutable unless declared 'final'
25 |
26 | final int j = 0;
27 |
28 | void funWithVariables() {
29 | i++;
30 |
31 | // Cannot assign a value to final variable 'j'
32 | //j++;
33 |
34 | // Local variables are not given default values.
35 | int anotherI;
36 |
37 | // It's a compile time error to try to use them before they're initialized
38 | //System.out.println(anotherI);
39 |
40 | anotherI = 1;
41 |
42 | System.out.println(anotherI);
43 |
44 | // You can have late initialized immutable local variables in Java
45 | final int yetAnotherI;
46 |
47 | yetAnotherI = 1;
48 |
49 | // Once initialized they can't be changed
50 | //yetAnotherI++;
51 | }
52 |
53 | void funWithJava11TypeInference() {
54 |
55 | // Java 11 brings type inference for local variables
56 |
57 | var typeInferenceInJava11 = "This is new";
58 |
59 | final var immutable = "Like 'val' in Kotlin";
60 |
61 | // Type inferred variables must be initialized
62 | //var notGonnaDoIt;
63 | }
64 |
65 | // Type inference is not supported for fields in Java
66 | //var notHotDog = 1;
67 | }
68 |
--------------------------------------------------------------------------------
/subprojects/user-defined-integrals-in-kotlin/src/test/kotlin/org/sdkotlin/integral/SignedIntegral.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.integral
2 |
3 | @JvmInline
4 | value class SignedIntegral(private val i: Int) : Integral {
5 |
6 | companion object {
7 |
8 | val MIN_VALUE: SignedIntegral = SignedIntegral(Int.MIN_VALUE)
9 |
10 | val MAX_VALUE: SignedIntegral = SignedIntegral(Int.MAX_VALUE)
11 |
12 | val ZERO: SignedIntegral = SignedIntegral(0)
13 |
14 | val ONE: SignedIntegral = SignedIntegral(1)
15 |
16 | val NEGATIVE_ONE: SignedIntegral = SignedIntegral(-1)
17 | }
18 |
19 | override val minValue: SignedIntegral
20 | get() = MIN_VALUE
21 |
22 | override val maxValue: SignedIntegral
23 | get() = MAX_VALUE
24 |
25 | override val zero: SignedIntegral
26 | get() = ZERO
27 |
28 | override val one: SignedIntegral
29 | get() = ONE
30 |
31 | override fun plus(other: SignedIntegral): SignedIntegral =
32 | SignedIntegral(i + other.i)
33 |
34 | override fun minus(other: SignedIntegral): SignedIntegral =
35 | SignedIntegral(i - other.i)
36 |
37 | override fun unaryMinus(): SignedIntegral =
38 | SignedIntegral(-i)
39 |
40 | override fun rem(other: SignedIntegral): SignedIntegral =
41 | SignedIntegral(i % other.i)
42 |
43 | override fun compareTo(other: SignedIntegral): Int =
44 | i.compareTo(other.i)
45 |
46 | operator fun rangeTo(other: SignedIntegral): ClosedRange =
47 | IntegralRange(this, other)
48 |
49 | operator fun rangeUntil(other: SignedIntegral): OpenEndRange =
50 | IntegralRange(this, other - ONE)
51 |
52 | override fun toString(): String = i.toString()
53 | }
54 |
55 | infix fun SignedIntegral.downTo(to: SignedIntegral): IntegralProgression =
56 | IntegralProgression.fromClosedRange(this, to, SignedIntegral.NEGATIVE_ONE)
57 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | gradlePluginPortal()
5 | }
6 |
7 | includeBuild("build-logic")
8 | }
9 |
10 | plugins {
11 | id("com.gradle.develocity") version "3.18"
12 | }
13 |
14 | dependencyResolutionManagement {
15 | @Suppress("UnstableApiUsage")
16 | repositories {
17 | mavenCentral()
18 | }
19 | }
20 |
21 | enableFeaturePreview("STABLE_CONFIGURATION_CACHE")
22 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
23 |
24 | develocity {
25 | buildScan {
26 | publishing.onlyIf { !System.getenv("CI").isNullOrEmpty() }
27 | termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use")
28 | termsOfUseAgree.set("yes")
29 | }
30 | }
31 |
32 | rootProject.name = "sd-kotlin-talks"
33 |
34 | includeBuild("platforms")
35 |
36 | gradle.beforeProject {
37 | // Set group and version properties for all projects
38 | group = "org.sdkotlin"
39 | version = "1.0.0-SNAPSHOT"
40 | }
41 |
42 | include("subprojects:constant-dependencies:constant-consumer")
43 | include("subprojects:constant-dependencies:constant-producer")
44 | include("subprojects:di-with-koin")
45 | include("subprojects:effective-kotlin")
46 | include("subprojects:equalsverifier-with-kotlin")
47 | include("subprojects:kotlin-dl")
48 | include("subprojects:kotlin-for-java-devs")
49 | include("subprojects:kotlin-for-java-devs-client")
50 | include("subprojects:kotlin-reflect")
51 | include("subprojects:ksp-builder-generator:api:annotations")
52 | include("subprojects:ksp-builder-generator:api:builder")
53 | include("subprojects:ksp-builder-generator:processor")
54 | include("subprojects:ksp-builder-generator:processor:test-project")
55 | include("subprojects:sorting-in-kotlin")
56 | include("subprojects:tdd-in-kotlin")
57 | include("subprojects:testing-with-mokkery")
58 | include("subprojects:typed-errors-in-kotlin")
59 | include("subprojects:user-defined-integrals-in-kotlin")
60 |
--------------------------------------------------------------------------------
/subprojects/effective-kotlin/src/main/kotlin/org/sdkotlin/meetup/idioms/ControlStructuresAsExpressions.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.meetup.idioms
2 |
3 | import org.json.JSONException
4 | import org.json.JSONObject
5 | import java.time.Month
6 | import java.time.Month.APRIL
7 | import java.time.Month.AUGUST
8 | import java.time.Month.DECEMBER
9 | import java.time.Month.FEBRUARY
10 | import java.time.Month.JANUARY
11 | import java.time.Month.JULY
12 | import java.time.Month.JUNE
13 | import java.time.Month.MARCH
14 | import java.time.Month.MAY
15 | import java.time.Month.NOVEMBER
16 | import java.time.Month.OCTOBER
17 | import java.time.Month.SEPTEMBER
18 |
19 | // Use `if` as an expression in place of the absent ternary operator.
20 |
21 | fun toBinary(boolean: Boolean): Byte {
22 | // return (boolean) ? 1 : 0 // Doesn't compile!
23 | return if (boolean) 1 else 0
24 | }
25 |
26 | // Use `when` as an expression for terse transformer functions.
27 |
28 | fun Month.toQuarter() = when (this) {
29 | JANUARY, FEBRUARY, MARCH -> 1
30 | APRIL, MAY, JUNE -> 2
31 | JULY, AUGUST, SEPTEMBER -> 3
32 | OCTOBER, NOVEMBER, DECEMBER -> 4
33 | }
34 |
35 | // Use `try` as an expression for setting values from functions that may throw
36 | // exceptions.
37 |
38 | fun parseJson(json: String): String {
39 | return try {
40 | JSONObject(json).getString("usergroup")
41 | } catch (e: JSONException) {
42 | "Unknown"
43 | }
44 | }
45 |
46 | fun main() {
47 |
48 | val boolean = true
49 | val binary = toBinary(boolean)
50 | println("Binary equivalent of $boolean is $binary")
51 |
52 | val month = JUNE
53 | val quarter = month.toQuarter()
54 | println("$month is in quarter $quarter")
55 |
56 | val partialJson = "'usergroup' : 'SD Kotlin'"
57 | val completeJson = "{ $partialJson }"
58 | println("Correct JSON parses to \"${parseJson(completeJson)}\"")
59 | println("Incorrect JSON parses to \"${parseJson(partialJson)}\"")
60 | }
61 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_05_0_variables_and_types/VariablesAndTypesInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._05_0_variables_and_types
2 |
3 | // var's are mutable, val's are read only
4 |
5 | // Pascal notation is used: name first, then, optionally or as needed, the type
6 | // after a colon (Same as Pascal, Scala, Swift, Go, Rust, etc.)
7 |
8 | // Variables aren't defaulted, and must be initialized
9 |
10 | // Kotlin does its best to abstract away primitives vs. wrapper types
11 |
12 | val aBoolean: Boolean = true // Boolean
13 | val aByte: Byte = 0 // Byte, type required because no literal
14 | val anotherByte = 0.toByte() // Alternatively, as literals are objects
15 | val aLiteralHexByte: Byte = 0xF // Kotlin supports hex literals
16 | val aLiteralBinaryByte: Byte = 0b0000_0000 // Kotlin supports binary literals
17 | val aCharacter = 'c' // Char, can't be treated as a number
18 | val aString = "Go, Kotlin!" // String
19 | val aShort = 0.toShort() // 16-bit Short, no literal
20 | val anInteger = 0 // 32-bit Int
21 | val aLong = 1_000_000L // 64-bit Long, lowercase 'l' not supported
22 | val aFloat = .0f // 32-bit Float, 'F' also supported
23 | val aDouble = 0.0 // 64-bit Double, 'd/D' not supported
24 |
25 | val i = 0
26 | var j = 0
27 |
28 | fun withVariables() {
29 | //i++ // Does not compile
30 | j++
31 | }
32 |
33 | fun main() {
34 | println("Boolean: " + aBoolean)
35 | println("Byte: " + aByte)
36 | println("Other Byte: " + anotherByte)
37 | println("Hex Byte: " + aLiteralHexByte)
38 | println("Binary Byte: " + aLiteralBinaryByte)
39 | println("Char: " + aCharacter)
40 | println("String: " + aString)
41 | println("Short: " + aShort)
42 | println("Int: " + anInteger)
43 | println("Long: " + aLong)
44 | println("Float: " + aFloat)
45 | println("Double: " + aDouble)
46 | println("variable Int j: " + j)
47 | withVariables()
48 | println("variable Int j: " + j)
49 | }
50 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_14_dataclasses/DataClassesInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._14_dataclasses;
2 |
3 | import java.util.Objects;
4 |
5 | public class DataClassesInJava {
6 |
7 | public static void main(final String[] args) {
8 | System.out.println(new Person("Luke"));
9 | }
10 | }
11 |
12 | class Person {
13 |
14 | private String name;
15 | private String favoriteProgrammingLanguage;
16 |
17 | public Person(final String name) {
18 | this(name, "Kotlin");
19 | }
20 |
21 | public Person(final String name, final String favoriteProgrammingLanguage) {
22 | this.name = name;
23 | this.favoriteProgrammingLanguage = favoriteProgrammingLanguage;
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public void setName(final String name) {
31 | this.name = name;
32 | }
33 |
34 | public String getFavoriteProgrammingLanguage() {
35 | return favoriteProgrammingLanguage;
36 | }
37 |
38 | public void setFavoriteProgrammingLanguage(final String favoriteProgrammingLanguage) {
39 | this.favoriteProgrammingLanguage = favoriteProgrammingLanguage;
40 | }
41 |
42 | @Override
43 | public boolean equals(final Object o) {
44 | if (this == o) return true;
45 | if (o == null || getClass() != o.getClass()) return false;
46 | final var person = (Person) o;
47 | return Objects.equals(name, person.name) &&
48 | Objects.equals(favoriteProgrammingLanguage, person.favoriteProgrammingLanguage);
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | return Objects.hash(name, favoriteProgrammingLanguage);
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | final var sb = new StringBuilder("Person{");
59 | sb.append("name='").append(name).append('\'');
60 | sb.append(", favoriteProgrammingLanguage='").append(favoriteProgrammingLanguage).append('\'');
61 | sb.append('}');
62 | return sb.toString();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/kotlin/org/sdkotlin/intro/kotlin/_17_constants/ConstantsInKotlin.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.kotlin._17_constants
2 |
3 | // Kotlin compiles vals to properties, meaning in Java they have a private
4 | // field and a getter.
5 |
6 | val REGULAR_VAL = "val"
7 |
8 | // A private val gets a private getter.
9 |
10 | private val PRIVATE_VAL = "private val"
11 |
12 | // Add 'const' to make a val compile-time constant. It becomes a public static
13 | // final field in Java. It is also inlined at compile time. In a sense,
14 | // 'const' is to 'val' as 'inline' is to 'fun'. Note that if code is compiled
15 | // against a const in a library, and the value changes in the library, the code
16 | // won't reflect the change until it is recompiled.
17 |
18 | const val CONST_VAL = "const val"
19 |
20 | // Only primitive types and String can be const, as it is known they can be
21 | // inlined into expressions at compile-time.
22 |
23 | //const val CONST_NON_PRIMITIVE_VAL = BigInteger.ONE
24 |
25 | // This includes primitive Arrays.
26 |
27 | //const val CONST_PRIMITIVE_ARRAY_VAL = intArrayOf(1)
28 |
29 | // The unsigned types are now considered primitives.
30 |
31 | const val U_CONST = 1u
32 |
33 | class ConstantsInKotlinCompanion {
34 |
35 | // Const vals must be either top level, in a companion object, or in an
36 | // object.
37 |
38 | //const val NOPE = false
39 |
40 | companion object {
41 |
42 | // Unlike regular vals, const vals can be used in annotations.
43 |
44 | @Deprecated(CONST_VAL)
45 | val COMPANION_VAL = "val in companion object"
46 |
47 | //@Deprecated(REGULAR_VAL)
48 | const val COMPANION_CONST_VAL = "const val in companion object"
49 | }
50 | }
51 |
52 | object ConstantsInKotlinObject {
53 |
54 | val OBJECT_VAL = "val in object"
55 |
56 | const val OBJECT_CONST_VAL = "const val in object"
57 | }
58 |
59 | fun main() {
60 | println("Regular val: $REGULAR_VAL")
61 | println("Const val: $CONST_VAL")
62 | }
63 |
--------------------------------------------------------------------------------
/subprojects/typed-errors-in-kotlin/src/main/kotlin/org/sdkotlin/typederrors/union/ConvertersWithUnionTypes.kt:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.typederrors.union
2 |
3 | data class ConverterError(
4 | val e: Exception,
5 | )
6 |
7 | fun interface Converter {
8 | operator fun invoke(input: I): O
9 | }
10 |
11 | // If Kotlin had union types (https://youtrack.jetbrains.com/issue/KT-13108/)...
12 |
13 | /*
14 | object StringToIntConverter : Converter {
15 |
16 | override fun invoke(input: String): ConverterError | Int =
17 | try {
18 | input.toInt()
19 | } catch (e: NumberFormatException) {
20 | ConverterError(e)
21 | }
22 | }
23 |
24 | object IntToStringConverter : Converter {
25 | override fun invoke(input: Int): String =
26 | input.toString()
27 | }
28 |
29 | // We can generalize over the `EitherConverter` supertype
30 | fun withUnionConverter(
31 | input: I,
32 | converter: Converter,
33 | ): E | O =
34 | converter(input)
35 |
36 | fun main() {
37 |
38 | val stringToIntSuccess =
39 | withUnionConverter("1", StringToIntConverter)
40 |
41 | println(
42 | // Would be an Int
43 | "withUnionConverter(\"1\", StringToIntConverter): $stringToIntSuccess"
44 | )
45 |
46 | val stringToIntFailure =
47 | withUnionConverter("Nope", StringToIntConverter)
48 |
49 | println(
50 | // Would be a ConverterError
51 | "withUnionConverter(\"Nope\", StringToIntConverter): $stringToIntFailure"
52 | )
53 |
54 | val intToStringSuccess =
55 | // The `Converter` subtype is substitutable...
56 | withUnionConverter(1, IntToStringConverter)
57 |
58 | println(
59 | // Would be a String
60 | "withUnionConverter(1, IntToStringConverter): $intToStringSuccess"
61 | )
62 |
63 | // We can call the union `Converter` directly
64 | val intToStringDirect = IntToStringConverter(1)
65 |
66 | println(
67 | // Would be a String
68 | "direct IntToStringConverter(1): $intToStringDirect"
69 | )
70 | }
71 | */
72 |
--------------------------------------------------------------------------------
/subprojects/kotlin-for-java-devs/src/main/java/org/sdkotlin/intro/java/_28_variance/VarianceInJava.java:
--------------------------------------------------------------------------------
1 | package org.sdkotlin.intro.java._28_variance;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class VarianceInJava {
7 |
8 | public static void main(final String[] args) {
9 |
10 | // Arrays are covariant in Java
11 |
12 | final String[] strings = new String[]{"Hello", "World"};
13 |
14 | final Object[] objects = strings;
15 |
16 | // However, as they are both producers and consumers, that means
17 | // type-safety is not ensured by the compiler.
18 |
19 | try {
20 | objects[0] = 1;
21 | } catch (final ArrayStoreException e) {
22 | System.out.println(e);
23 | }
24 |
25 | // Item 28 in the third edition of "Effective Java" is "Prefer Lists to
26 | // Arrays" for this very reason. Collections are invariant in Java.
27 |
28 | final List listOfStrings = new ArrayList<>();
29 | listOfStrings.add("Hello");
30 |
31 | //final List