Kapt: Gradle integration tests for the new kapt

This commit is contained in:
Yan Zhulanow
2016-08-12 19:03:38 +03:00
parent bb370f1732
commit 467d0fd10f
94 changed files with 1810 additions and 8 deletions

View File

@@ -26,7 +26,6 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@@ -45,7 +45,7 @@ class ExampleAnnotationProcessor : AbstractProcessor() {
val simpleName = element.simpleName.toString()
val generatedJavaClassName = generatedFilePrefix.capitalize() + simpleName.capitalize() + generatedFileSuffix
filer.createSourceFile(generatedJavaClassName).openWriter().use { with(it) {
filer.createSourceFile(packageName + '.' + generatedJavaClassName).openWriter().use { with(it) {
appendln("package $packageName;")
appendln("public final class $generatedJavaClassName {}")
}}

View File

@@ -72,8 +72,14 @@ abstract class BaseGradleIT {
val androidHome: File? = null,
val androidGradlePluginVersion: String? = null)
open inner class Project(val projectName: String, val wrapperVersion: String, val minLogLevel: LogLevel = LogLevel.DEBUG) {
open val resourcesRoot = File(resourcesRootFile, "testProject/$projectName")
open inner class Project(
val projectName: String,
val wrapperVersion: String,
directoryPrefix: String? = null,
val minLogLevel: LogLevel = LogLevel.DEBUG
) {
val resourceDirName = if (directoryPrefix != null) "$directoryPrefix/$projectName" else projectName
open val resourcesRoot = File(resourcesRootFile, "testProject/$resourceDirName")
val projectDir = File(workingDir.canonicalFile, projectName)
open fun setupWorkingDir() {

View File

@@ -10,7 +10,7 @@ import kotlin.test.assertEquals
abstract class BaseIncrementalGradleIT : BaseGradleIT() {
inner class JpsTestProject(val buildLogFinder: BuildLogFinder, val resourcesBase: File, val relPath: String, wrapperVersion: String = "2.10", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(File(relPath).name, wrapperVersion, minLogLevel) {
inner class JpsTestProject(val buildLogFinder: BuildLogFinder, val resourcesBase: File, val relPath: String, wrapperVersion: String = "2.10", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(File(relPath).name, wrapperVersion, null, minLogLevel) {
override val resourcesRoot = File(resourcesBase, relPath)
val mapWorkingToOriginalFile = hashMapOf<File, File>()

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle
import org.junit.Test
import java.io.File
import java.io.FileFilter
class Kapt2IT: BaseGradleIT() {
companion object {
private const val GRADLE_VERSION = "2.10"
private const val ANDROID_GRADLE_PLUGIN_VERSION = "1.5.+"
}
private fun androidBuildOptions() =
BuildOptions(withDaemon = true,
androidHome = File("../../../dependencies/android-sdk-for-tests"),
androidGradlePluginVersion = ANDROID_GRADLE_PLUGIN_VERSION)
override fun defaultBuildOptions(): BuildOptions =
super.defaultBuildOptions().copy(withDaemon = true)
private fun CompiledProject.assertKaptSuccessful() {
assertContains("Kapt: Annotation processing complete, 0 errors, 0 warnings")
}
@Test
fun testSimple() {
val project = Project("simple", GRADLE_VERSION, directoryPrefix = "kapt2")
project.build("build") {
assertSuccessful()
assertKaptSuccessful()
assertContains(":compileKotlin")
assertContains(":compileJava")
assertFileExists("build/generated/source/kapt2/main/example/TestClassGenerated.java")
assertFileExists("build/classes/main/example/TestClass.class")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/SourceAnnotatedTestClassGenerated.class")
assertFileExists("build/classes/main/example/BinaryAnnotatedTestClassGenerated.class")
assertFileExists("build/classes/main/example/RuntimeAnnotatedTestClassGenerated.class")
assertContains("example.JavaTest PASSED")
}
project.build("build") {
assertSuccessful()
assertContains(":compileKotlin UP-TO-DATE")
assertContains(":compileJava UP-TO-DATE")
}
}
@Test
fun testInheritedAnnotations() {
Project("inheritedAnnotations", GRADLE_VERSION, directoryPrefix = "kapt2").build("build") {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("build/generated/source/kapt2/main/example/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt2/main/example/AncestorClassGenerated.java")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/AncestorClassGenerated.class")
}
}
@Test
fun testButterKnife() {
val project = Project("android-butterknife", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.java")
assertFileExists("app/build/intermediates/classes/release/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.class")
assertFileExists("app/build/intermediates/classes/release/org/example/kotlin/butterknife/SimpleAdapter\$ViewHolder.class")
}
project.build("assembleRelease", options = options) {
assertSuccessful()
assertContains(":compileReleaseKotlin UP-TO-DATE")
assertContains(":compileReleaseJavaWithJavac UP-TO-DATE")
}
}
@Test
fun testDagger() {
val project = Project("android-dagger", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/com/example/dagger/kotlin/DaggerApplicationComponent.java")
assertFileExists("app/build/generated/source/kapt2/release/com/example/dagger/kotlin/ui/HomeActivity_MembersInjector.java")
assertFileExists("app/build/intermediates/classes/release/com/example/dagger/kotlin/DaggerApplicationComponent.class")
assertFileExists("app/build/intermediates/classes/release/com/example/dagger/kotlin/AndroidModule.class")
}
}
@Test
fun testDbFlow() {
val project = Project("android-dbflow", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/com/raizlabs/android/dbflow/config/GeneratedDatabaseHolder.java")
assertFileExists("app/build/generated/source/kapt2/release/com/raizlabs/android/dbflow/config/AppDatabaseapp_Database.java")
assertFileExists("app/build/generated/source/kapt2/release/mobi/porquenao/poc/kotlin/core/Item_Table.java")
assertFileExists("app/build/generated/source/kapt2/release/mobi/porquenao/poc/kotlin/core/Item_Adapter.java")
}
}
@Test
fun testRealm() {
val project = Project("android-realm", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("build/generated/source/kapt2/release/io/realm/CatRealmProxy.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/CatRealmProxyInterface.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/DefaultRealmModule.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/DefaultRealmModuleMediator.java")
}
}
}

View File

@@ -24,7 +24,7 @@ class KaptIT: BaseGradleIT() {
assertContains(":compileKotlin")
assertContains(":compileJava")
assertFileExists("build/tmp/kapt/main/wrappers/annotations.main.txt")
assertFileExists("build/generated/source/kapt/main/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/TestClassGenerated.java")
assertFileExists("build/classes/main/example/TestClass.class")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertNoSuchFile("build/classes/main/example/SourceAnnotatedTestClassGenerated.class")
@@ -160,8 +160,8 @@ class KaptIT: BaseGradleIT() {
fun testInheritedAnnotations() {
Project("kaptInheritedAnnotations", GRADLE_VERSION).build("build") {
assertSuccessful()
assertFileExists("build/generated/source/kapt/main/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/AncestorClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/AncestorClassGenerated.java")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/AncestorClassGenerated.class")
}

View File

@@ -0,0 +1,37 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "org.example.kotlin.butterknife"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.jakewharton:butterknife:8.0.1'
kapt 'com.jakewharton:butterknife-compiler:8.0.1'
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
}

View File

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/yan/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.kotlin.butterknife">
<application
android:label="@string/app_name"
android:name=".SimpleApp">
<activity
android:label="@string/app_name"
android:name=".SimpleActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,84 @@
package org.example.kotlin.butterknife
import android.app.Activity
import android.os.Bundle
import android.view.View
import android.view.animation.AlphaAnimation
import android.widget.Button
import android.widget.ListView
import android.widget.TextView
import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT
import butterknife.*
class SimpleActivity : Activity() {
@BindView(R.id.title)
lateinit var title: TextView
@BindView(R.id.subtitle)
lateinit var subtitle: TextView
@BindView(R.id.hello)
lateinit var hello: Button
@BindView(R.id.list_of_things)
lateinit var listOfThings: ListView
@BindView(R.id.footer)
lateinit var footer: TextView
@BindViews(R.id.title, R.id.subtitle, R.id.hello)
lateinit var headerViews: MutableList<View>
@JvmField
@BindColor(R.color.blue)
var titleTextColor: Int = 0
private lateinit var adapter: SimpleAdapter
@OnClick(R.id.hello)
fun sayHello() {
Toast.makeText(this, "Hello, views!", LENGTH_SHORT).show()
ButterKnife.apply(headerViews.toList(), ALPHA_FADE)
}
@OnLongClick(R.id.hello)
fun sayGetOffMe(): Boolean {
Toast.makeText(this, "Let go of me!", LENGTH_SHORT).show()
return true
}
@OnItemClick(R.id.list_of_things)
fun onItemClick(position: Int) {
Toast.makeText(this, "You clicked: " + adapter.getItem(position), LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.simple_activity)
ButterKnife.bind(this)
title.text = "Butter Knife"
subtitle.text = "Field and method binding for Android views."
footer.text = "by Jake Wharton"
hello.text = "Say Hello"
title.setTextColor(titleTextColor)
adapter = SimpleAdapter(this)
listOfThings.adapter = adapter
}
companion object {
private val ALPHA_FADE = ButterKnife.Action<View> { view, index ->
with (AlphaAnimation(0f, 1f)) {
fillBefore = true
duration = 500
startOffset = (index * 100).toLong()
view.startAnimation(this)
}
}
}
}

View File

@@ -0,0 +1,57 @@
package org.example.kotlin.butterknife
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import butterknife.ButterKnife
import butterknife.BindView
class SimpleAdapter(context: Context) : BaseAdapter() {
private val inflater = LayoutInflater.from(context)
override fun getCount() = CONTENTS.size
override fun getItem(position: Int) = CONTENTS[position]
override fun getItemId(position: Int) = position.toLong()
override fun getView(position: Int, v: View?, parent: ViewGroup): View {
var view = v
val holder: ViewHolder
if (view != null) {
holder = view.tag as ViewHolder
} else {
view = inflater.inflate(R.layout.simple_list_item, parent, false)
holder = ViewHolder(view)
view!!.tag = holder
}
val word = getItem(position)
holder.word.text = "Word: $word"
holder.length.text = "Length: ${word.length}"
holder.position.text = "Position: $position"
return view
}
class ViewHolder(view: View) {
@BindView(R.id.word)
lateinit var word: TextView
@BindView(R.id.length)
lateinit var length: TextView
@BindView(R.id.position)
lateinit var position: TextView
init {
ButterKnife.bind(this, view)
}
}
companion object {
private val CONTENTS = "The quick brown fox jumps over the lazy dog".split(" ")
}
}

View File

@@ -0,0 +1,11 @@
package org.example.kotlin.butterknife
import android.app.Application
import butterknife.ButterKnife
class SimpleApp : Application() {
override fun onCreate() {
super.onCreate()
ButterKnife.setDebug(BuildConfig.DEBUG)
}
}

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="50sp"
/>
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
/>
<Button
android:id="@+id/hello"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="10dp"
/>
<ListView
android:id="@+id/list_of_things"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="10dp"
/>
<TextView
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
android:textStyle="italic"
/>
</LinearLayout>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/length"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/position"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="blue">#3366ee</color>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Butter Knife</string>
</resources>

View File

@@ -0,0 +1,24 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
}

View File

@@ -0,0 +1,37 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.dagger.kotlin"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.3.0'
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile 'com.google.dagger:dagger:2.2'
kapt 'com.google.dagger:dagger-compiler:2.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
}

View File

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/yan/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dagger.kotlin">
<application
android:allowBackup="true"
android:label="app_name"
android:name=".DemoApplication">
<activity
android:label="app_name"
android:name=".ui.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.kotlin
import android.content.Context
import android.content.Context.LOCATION_SERVICE
import android.location.LocationManager
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
/**
* A module for Android-specific dependencies which require a [Context] or
* [android.app.Application] to create.
*/
@Module class AndroidModule(private val application: BaseApplication) {
/**
* Allow the application context to be injected but require that it be annotated with
* [@Annotation][ForApplication] to explicitly differentiate it from an activity context.
*/
@Provides @Singleton @ForApplication
fun provideApplicationContext(): Context {
return application
}
@Provides @Singleton
fun provideLocationManager(): LocationManager {
return application.getSystemService(LOCATION_SERVICE) as LocationManager
}
}

View File

@@ -0,0 +1,13 @@
package com.example.dagger.kotlin
import com.example.dagger.kotlin.ui.HomeActivity
import dagger.Component
import javax.inject.Singleton
@Singleton
@Component(modules = arrayOf(AndroidModule::class))
interface ApplicationComponent {
fun inject(application: BaseApplication)
fun inject(homeActivity: HomeActivity)
fun inject(demoActivity: DemoActivity)
}

View File

@@ -0,0 +1,11 @@
package com.example.dagger.kotlin
import android.app.Application
abstract class BaseApplication : Application() {
protected fun initDaggerComponent(): ApplicationComponent {
return DaggerApplicationComponent.builder().androidModule(AndroidModule(this)).build()
}
}

View File

@@ -0,0 +1,12 @@
package com.example.dagger.kotlin
import android.app.Activity
import android.os.Bundle
abstract class DemoActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Perform injection so that when this call returns all dependencies will be available for use.
(application as DemoApplication).component.inject(this)
}
}

View File

@@ -0,0 +1,13 @@
package com.example.dagger.kotlin
class DemoApplication : BaseApplication() {
lateinit var component: ApplicationComponent
override fun onCreate() {
super.onCreate()
val component = initDaggerComponent()
component.inject(this) // As of now, LocationManager should be injected into this.
this.component = component
}
}

View File

@@ -0,0 +1,6 @@
package com.example.dagger.kotlin
import javax.inject.Qualifier
@Qualifier
annotation class ForApplication

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.kotlin.ui
import android.location.LocationManager
import android.os.Bundle
import com.example.dagger.kotlin.DemoActivity
import com.example.dagger.kotlin.DemoApplication
import com.example.dagger.kotlin.R
import kotlinx.android.synthetic.main.activity_main.locationInfo
import javax.inject.Inject
class HomeActivity : DemoActivity() {
@Inject
lateinit var locationManager: LocationManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(application as DemoApplication).component.inject(this)
// TODO do something with the injected dependencies here!
locationInfo.text = "Injected LocationManager:\n$locationManager"
}
}

View File

@@ -0,0 +1,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".ui.HomeActivity">
<TextView android:id="@+id/locationInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp" />
</RelativeLayout>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">kotlin</string>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,24 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
}

View File

@@ -0,0 +1,39 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
def dbflow_version = "3.1.1"
dependencies {
// Android Support Libraries
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:cardview-v7:23.3.0'
compile 'com.android.support:recyclerview-v7:23.3.0'
// DBFlow
kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${dbflow_version}"
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="mobi.porquenao.poc.kotlin"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".DatabaseApplication"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,18 @@
package mobi.porquenao.poc.kotlin
import android.app.Application
import com.raizlabs.android.dbflow.config.FlowConfig
import com.raizlabs.android.dbflow.config.FlowManager
class DatabaseApplication : Application() {
override fun onCreate() {
super.onCreate()
FlowManager.init(FlowConfig.Builder(this).build())
}
override fun onTerminate() {
super.onTerminate()
FlowManager.destroy()
}
}

View File

@@ -0,0 +1,9 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.annotation.Database
@Database(name = AppDatabase.NAME, version = AppDatabase.VERSION, generatedClassSeparator = "_")
object AppDatabase {
const val NAME: String = "app"
const val VERSION: Int = 1
}

View File

@@ -0,0 +1,20 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.converter.TypeConverter
import java.util.*
import com.raizlabs.android.dbflow.annotation.TypeConverter as TypeConverterAnnotation
@TypeConverterAnnotation
class CalendarConverter : TypeConverter<Long, Calendar>() {
override fun getDBValue(model: Calendar): Long? {
return model.timeInMillis
}
override fun getModelValue(data: Long?): Calendar {
val calendar = Calendar.getInstance()
calendar.timeInMillis = data!!
return calendar
}
}

View File

@@ -0,0 +1,19 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.annotation.Column
import com.raizlabs.android.dbflow.annotation.PrimaryKey
import com.raizlabs.android.dbflow.annotation.Table
import com.raizlabs.android.dbflow.structure.BaseModel
import java.util.*
@Table(name = "items", database = AppDatabase::class)
class Item : BaseModel() {
@PrimaryKey(autoincrement = true)
@Column(name = "id")
var id: Long = 0
@Column(name = "updated_at", typeConverter = CalendarConverter::class)
var updatedAt: Calendar = Calendar.getInstance()
}

View File

@@ -0,0 +1,15 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.sql.language.Select
object ItemRepository {
fun getAll(): MutableList<Item> {
return Select()
.from(Item::class.java)
.where()
.orderBy(Item_Table.updated_at, false)
.queryList()
}
}

View File

@@ -0,0 +1,38 @@
package mobi.porquenao.poc.kotlin.ui
import android.app.ActivityManager
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import mobi.porquenao.poc.kotlin.R
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
prepareTaskDescription()
}
override fun setContentView(layoutResID: Int) {
super.setContentView(layoutResID)
setSupportActionBar(toolbar)
}
private fun prepareTaskDescription() {
if (Build.VERSION.SDK_INT >= 21) {
if (sTaskDescription == null) {
val label = getString(R.string.app_name)
val icon = BitmapFactory.decodeResource(resources, R.drawable.ic_task)
val colorPrimary = resources.getColor(R.color.app_primary_500)
sTaskDescription = ActivityManager.TaskDescription(label, icon, colorPrimary)
}
setTaskDescription(sTaskDescription)
}
}
companion object {
private var sTaskDescription: ActivityManager.TaskDescription? = null
}
}

View File

@@ -0,0 +1,36 @@
package mobi.porquenao.poc.kotlin.ui
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import kotlinx.android.synthetic.main.activity_main.*
import mobi.porquenao.poc.kotlin.R
class MainActivity : BaseActivity() {
lateinit var listAdapter: MainAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
with (list) {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(this@MainActivity)
listAdapter = MainAdapter()
adapter = listAdapter
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
listAdapter.add()
list.smoothScrollToPosition(0)
return true
}
}

View File

@@ -0,0 +1,67 @@
package mobi.porquenao.poc.kotlin.ui
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.main_item.view.*
import mobi.porquenao.poc.kotlin.R
import mobi.porquenao.poc.kotlin.core.Item
import mobi.porquenao.poc.kotlin.core.ItemRepository
import java.util.*
class MainAdapter : RecyclerView.Adapter<MainAdapter.ViewHolder>() {
private val mItems: MutableList<Item>
private val mOnClickListener: View.OnClickListener
init {
mItems = ItemRepository.getAll()
mOnClickListener = View.OnClickListener { v ->
val item = v.tag as Item
item.updatedAt = Calendar.getInstance()
item.save()
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return ViewHolder(layoutInflater.inflate(R.layout.main_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = mItems[position]
val date = item.updatedAt.timeInMillis
val color = "#" + date.toString().substring(7)
holder.card.setCardBackgroundColor(Color.parseColor(color))
holder.title.text = color
holder.date.text = DateFormat.format("hh:mm:ss", Date(date))
with (holder.container) {
tag = item
setOnClickListener(mOnClickListener)
}
}
override fun getItemCount(): Int {
return mItems.size
}
fun add() {
val item = Item()
mItems.add(0, item)
item.save()
notifyItemInserted(0)
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val card = view.card
val container = view.container
val title = view.title
val date = view.date
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:attr/selectableItemBackground" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/AppToolbar"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:scrollbars="vertical"/>
</LinearLayout>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
android:id="@+id/card"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
app:cardBackgroundColor="@color/app_primary_500"
app:cardCornerRadius="2dp"
tools:ignore="RtlHardcoded,RtlSymmetry">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:padding="16dip"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="30sp"
tools:text="#2196F3"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:text="01:23:45"
tools:ignore="HardcodedText" />
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_event"
android:icon="@drawable/abc_ic_menu_copy_mtrl_am_alpha"
android:title="@string/menu_add"
app:showAsAction="always"/>
</menu>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="app_primary_500">#2196F3</color>
<color name="app_primary_700">#0087e9</color>
<color name="app_accent_200">#FF3D00</color>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">POC Kotlin</string>
<string name="menu_add">Add</string>
</resources>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">@color/app_accent_200</item>
<item name="colorPrimary">@color/app_primary_500</item>
<item name="colorPrimaryDark">@color/app_primary_700</item>
</style>
<style name="AppToolbar" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">?attr/colorPrimary</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>
</resources>

View File

@@ -0,0 +1,25 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
maven { url "https://jitpack.io" }
}
}

View File

@@ -0,0 +1,63 @@
buildscript {
ext.realm_version = '1.1.1'
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath("io.realm:realm-gradle-plugin:$realm_version") {
exclude group: 'com.android.tools.build', module: 'gradle'
}
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId 'io.realm.examples.kotlin'
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
}
}
dexOptions {
incremental false
}
}
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
maven {
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:kotlin-reflect:0.1-SNAPSHOT"
compile 'org.jetbrains.anko:anko-common:0.9'
}

View File

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/22.6.2/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -0,0 +1,20 @@
<manifest package="io.realm.examples.kotlin"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".KotlinExampleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,219 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
import android.widget.TextView
import io.realm.Realm
import io.realm.Sort
import io.realm.RealmConfiguration
import io.realm.examples.kotlin.model.Cat
import io.realm.examples.kotlin.model.Dog
import io.realm.examples.kotlin.model.Person
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import kotlin.properties.Delegates
class KotlinExampleActivity : Activity() {
companion object {
val TAG: String = KotlinExampleActivity::class.qualifiedName as String
}
private var rootLayout: LinearLayout by Delegates.notNull()
private var realm: Realm by Delegates.notNull()
private var realmConfig: RealmConfiguration by Delegates.notNull()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_realm_basic_example)
rootLayout = findViewById(R.id.container) as LinearLayout
rootLayout.removeAllViews()
// These operations are small enough that
// we can generally safely run them on the UI thread.
// Create configuration and reset Realm.
realmConfig = RealmConfiguration.Builder(this).build()
Realm.deleteRealm(realmConfig)
// Open the realm for the UI thread.
realm = Realm.getInstance(realmConfig)
basicCRUD(realm)
basicQuery(realm)
basicLinkQuery(realm)
// Delete all persons
// Using executeTransaction with a lambda reduces code size and makes it impossible
// to forget to commit the transaction.
realm.executeTransaction {
realm.delete(Person::class.java)
}
// More complex operations can be executed on another thread, for example using
// Anko's async extension method.
doAsync() {
var info: String
info = complexReadWrite()
info += complexQuery()
uiThread {
showStatus(info)
}
}
}
override fun onDestroy() {
super.onDestroy()
realm.close() // Remember to close Realm when done.
}
private fun showStatus(txt: String) {
Log.i(TAG, txt)
val tv = TextView(this)
tv.text = txt
rootLayout.addView(tv)
}
private fun basicCRUD(realm: Realm) {
showStatus("Perform basic Create/Read/Update/Delete (CRUD) operations...")
// All writes must be wrapped in a transaction to facilitate safe multi threading
realm.executeTransaction {
// Add a person
var person = realm.createObject(Person::class.java)
person.id = 1
person.name = "Young Person"
person.age = 14
}
// Find the first person (no query conditions) and read a field
var person = realm.where(Person::class.java).findFirst()
showStatus(person.name + ": " + person.age)
// Update person in a transaction
realm.executeTransaction {
person.name = "Senior Person"
person.age = 99
showStatus(person.name + " got older: " + person.age)
}
}
private fun basicQuery(realm: Realm) {
showStatus("\nPerforming basic Query operation...")
showStatus("Number of persons: ${realm.where(Person::class.java).count()}")
val results = realm.where(Person::class.java).equalTo("age", 99).findAll()
showStatus("Size of result set: " + results.size)
}
private fun basicLinkQuery(realm: Realm) {
showStatus("\nPerforming basic Link Query operation...")
showStatus("Number of persons: ${realm.where(Person::class.java).count()}")
val results = realm.where(Person::class.java).equalTo("cats.name", "Tiger").findAll()
showStatus("Size of result set: ${results.size}")
}
private fun complexReadWrite(): String {
var status = "\nPerforming complex Read/Write operation..."
// Open the default realm. All threads must use it's own reference to the realm.
// Those can not be transferred across threads.
val realm = Realm.getInstance(realmConfig)
// Add ten persons in one transaction
realm.executeTransaction {
val fido = realm.createObject(Dog::class.java)
fido.name = "fido"
for (i in 0..9) {
val person = realm.createObject(Person::class.java)
person.id = i.toLong()
person.name = "Person no. $i"
person.age = i
person.dog = fido
// The field tempReference is annotated with @Ignore.
// This means setTempReference sets the Person tempReference
// field directly. The tempReference is NOT saved as part of
// the RealmObject:
person.tempReference = 42
for (j in 0..i - 1) {
val cat = realm.createObject(Cat::class.java)
cat.name = "Cat_$j"
person.cats.add(cat)
}
}
}
// Implicit read transactions allow you to access your objects
status += "\nNumber of persons: ${realm.where(Person::class.java).count()}"
// Iterate over all objects
for (person in realm.where(Person::class.java).findAll()) {
val dogName: String = person?.dog?.name ?: "None"
status += "\n${person.name}: ${person.age} : $dogName : ${person.cats.size}"
// The field tempReference is annotated with @Ignore
// Though we initially set its value to 42, it has
// not been saved as part of the Person RealmObject:
check(person.tempReference == 0)
}
// Sorting
val sortedPersons = realm.where(Person::class.java).findAllSorted("age", Sort.DESCENDING);
check(realm.where(Person::class.java).findAll().last().name == sortedPersons.first().name)
status += "\nSorting ${sortedPersons.last().name} == ${realm.where(Person::class.java).findAll().first().name}"
realm.close()
return status
}
private fun complexQuery(): String {
var status = "\n\nPerforming complex Query operation..."
// Realm implements the Closable interface, therefore we can make use of Kotlin's built-in
// extension method 'use' (pun intended).
Realm.getInstance(realmConfig).use {
// 'it' is the implicit lambda parameter of type Realm
status += "\nNumber of persons: ${it.where(Person::class.java).count()}"
// Find all persons where age between 7 and 9 and name begins with "Person".
val results = it
.where(Person::class.java)
.between("age", 7, 9) // Notice implicit "and" operation
.beginsWith("name", "Person")
.findAll()
status += "\nSize of result set: ${results.size}"
}
return status
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmObject
open class Cat : RealmObject() {
open var name: String? = null
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmObject
open class Dog : RealmObject() {
open var name: String? = null
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
// Your model has to extend RealmObject. Furthermore, the class and all of the
// properties must be annotated with open (Kotlin classes and methods are final
// by default).
open class Person(
// You can put properties in the constructor as long as all of them are initialized with
// default values. This ensures that an empty constructor is generated.
// All properties are by default persisted.
// Properties can be annotated with PrimaryKey or Index.
// If you use non-nullable types, properties must be initialized with non-null values.
@PrimaryKey open var name: String = "",
open var age: Int = 0,
// Other objects in a one-to-one relation must also subclass RealmObject
open var dog: Dog? = null,
// One-to-many relations is simply a RealmList of the objects which also subclass RealmObject
open var cats: RealmList<Cat> = RealmList(),
// You can instruct Realm to ignore a field and not persist it.
@Ignore open var tempReference: Int = 0,
open var id: Long = 0
) : RealmObject() {
// The Kotlin compiler generates standard getters and setters.
// Realm will overload them and code inside them is ignored.
// So if you prefer you can also just have empty abstract methods.
}

View File

@@ -0,0 +1,30 @@
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:keep="@layout/activity_realm_basic_example">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:gravity="center_horizontal"
android:text="@string/status_output"
android:textStyle="bold"
android:textSize="18sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10sp"
android:orientation="vertical"
tools:context=".RealmIntroExample"/>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Kotlin example</string>
<string name="status_output">Status Output…</string>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,36 @@
buildscript {
repositories {
mavenCentral()
maven {
url 'file://' + pathToKotlinPlugin
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
}
}
apply plugin: "java"
apply plugin: "kotlin"
apply plugin: "kotlin-kapt"
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
kapt "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
}
task show << {
buildscript.configurations.classpath.each { println it }
}
kapt {
generateStubs = true
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example
@example.ExampleAnnotation
open class TestClass
class AncestorClass : TestClass()

View File

@@ -0,0 +1,33 @@
buildscript {
repositories {
mavenCentral()
maven {
url 'file://' + pathToKotlinPlugin
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
}
}
apply plugin: "java"
apply plugin: "kotlin"
apply plugin: "kotlin-kapt"
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
kapt "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
testCompile 'junit:junit:4.12'
}
task show << {
buildscript.configurations.classpath.each { println it }
}

View File

@@ -0,0 +1,5 @@
package foo
internal class InternalDummy {
internal val x = "InternalDummy.x"
}

View File

@@ -0,0 +1,7 @@
package foo
internal class InternalDummyUser {
internal fun use(dummy: InternalDummy) {
if (dummy.x != "InternalDummy.x") throw AssertionError("dummy.x = ${dummy.x}")
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javaPackage;
public class JavaClass {
public void test() {
System.out.println(example.TestClassGenerated.class.getName());
System.out.println(example.SourceAnnotatedTestClassGenerated.class.getName());
System.out.println(example.BinaryAnnotatedTestClassGenerated.class.getName());
System.out.println(example.RuntimeAnnotatedTestClassGenerated.class.getName());
}
}

View File

@@ -0,0 +1,15 @@
package example
@example.ExampleAnnotation
@example.ExampleSourceAnnotation
@example.ExampleBinaryAnnotation
@example.ExampleRuntimeAnnotation
public class TestClass {
@example.ExampleAnnotation
public val testVal: String = "text"
@example.ExampleAnnotation
public fun testFunction(): TestClassGenerated = TestClassGenerated()
}

View File

@@ -0,0 +1,12 @@
package example;
import org.junit.Assert;
import org.junit.Test;
public class JavaTest {
@Test
public void test() {
TestClass testClass = new TestClass();
Assert.assertEquals("text", testClass.getTestVal());
}
}

View File

@@ -0,0 +1,12 @@
package foo
import org.junit.Test
class InternalDummyTest {
@Test
fun testDummy() {
val dummy = InternalDummy()
val dummyUser = InternalDummyUser()
dummyUser.use(dummy)
}
}