Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Adopt PublishedApi #36

Merged
merged 11 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/**.gradle', '**/**.gradle.kts', '**/gradle/wrapper/gradle-wrapper.properties', '**/buildSrc/src/main/kotlin/**.kt') }}
- name: Unit tests
run: ./gradlew testDebugUnitTest
run: ./gradlew test

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test events were not received

instrumentation-tests:
name: Instrumentation tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import okhttp3.OkHttpClient
import retrofit2.Converter
import retrofit2.Retrofit

@Suppress("unused")
abstract class BaseRetrofitHelper {

private val retrofit by lazy {
@PublishedApi
internal val retrofit by lazy {
Retrofit.Builder()
.baseUrl(baseUrl)
.client(buildOkHttpClient())
Expand All @@ -32,9 +32,7 @@ abstract class BaseRetrofitHelper {
}
}

fun <T : Any> create(service: Class<T>): T = retrofit.create(service)

inline fun <reified T : Any> create(): T = create(T::class.java)
inline fun <reified T : Any> create(): T = retrofit.create(T::class.java)

protected abstract fun OkHttpClient.Builder.addInterceptors(): OkHttpClient.Builder

Expand Down
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ fun DependencyHandler.androidTestImplementations(vararg names: Any): Array<Depen
fun DependencyHandler.testImplementations(vararg names: Any): Array<Dependency?> =
config("testImplementation", *names)

fun DependencyHandler.kaptTests(vararg names: Any): Array<Dependency?> =
config("kaptTest", *names)

fun PluginAware.applyPlugins(vararg names: String) {
apply { names.forEach(::plugin) }
}
Expand Down
2 changes: 2 additions & 0 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ dependencies {
implementations(*Libs.coil)
debugImplementations(Libs.chuckerDebug)
releaseImplementations(Libs.chuckerRelease)

kaptTests(Libs.moshiCompiler)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

java.lang.RuntimeException: Failed to find the generated JsonAdapter class for class io.goooler.demoapp.common.JsonUtilTest$Repo
	at com.squareup.moshi.internal.Util.generatedAdapter(Util.java:590)
	at com.squareup.moshi.StandardJsonAdapters$1.create(StandardJsonAdapters.java:61)
	at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
	at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
	at com.squareup.moshi.Moshi.adapter(Moshi.java:80)
	at io.goooler.demoapp.common.JsonUtilTest.JsonUtil fromJson(String)(JsonUtilTest.kt:95)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.ClassNotFoundException: io.goooler.demoapp.common.JsonUtilTest_RepoJsonAdapter
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:467)
	at com.squareup.moshi.internal.Util.generatedAdapter(Util.java:564)
	... 48 more

}
34 changes: 15 additions & 19 deletions common/src/main/kotlin/io/goooler/demoapp/common/util/JsonUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,43 @@ package io.goooler.demoapp.common.util

import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import java.lang.reflect.Type
import org.intellij.lang.annotations.Language

object JsonUtil {
@PublishedApi
internal val moshi: Moshi = Moshi.Builder().build()

fun <T> fromJson(json: String, clazz: Class<T>): T? = try {
moshi.adapter(clazz).fromJson(json)
inline fun <reified T> fromJson(@Language("JSON") string: String): T? = try {
moshi.adapter(T::class.java).fromJson(string)
} catch (e: Exception) {
e.printStackTrace()
null
}

fun <T> fromJson(json: String, typeOfT: Type): T? = try {
moshi.adapter<T>(typeOfT).fromJson(json)
inline fun <reified T> fromJson(
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is reified there really needed?

@Language("JSON") string: String,
rawType: Class<*>,
vararg typeArguments: Class<*>
): T? = try {
moshi.adapter<T>(Types.newParameterizedType(rawType, *typeArguments)).fromJson(string)
} catch (e: Exception) {
e.printStackTrace()
null
}

fun <T> fromJson(json: String, rawType: Class<*>, vararg typeArguments: Class<*>): T? = try {
fromJson(json, Types.newParameterizedType(rawType, *typeArguments))
@Language("JSON")
inline fun <reified T> toJson(value: T?): String? = try {
moshi.adapter(T::class.java).toJson(value)
} catch (e: Exception) {
e.printStackTrace()
null
}

fun <T> toJson(o: T?, clazz: Class<T>): String? = try {
moshi.adapter(clazz).toJson(o)
} catch (e: Exception) {
e.printStackTrace()
null
}

inline fun <reified T> toJson(o: T?): String? = toJson(o, T::class.java)
}

inline fun <reified T> String.fromJson(): T? = JsonUtil.fromJson(this, T::class.java)

inline fun <reified T> String.fromJson(typeOfT: Type): T? = JsonUtil.fromJson(this, typeOfT)
inline fun <reified T> String.fromJson(): T? = JsonUtil.fromJson(this)

inline fun <reified T> String.fromJson(rawType: Class<*>, vararg typeArguments: Class<*>): T? =
JsonUtil.fromJson(this, rawType, *typeArguments)

@Language("JSON")
fun Any?.toJson(): String? = JsonUtil.toJson(this)
85 changes: 85 additions & 0 deletions common/src/test/kotlin/io/goooler/demoapp/common/JsonUtilTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.goooler.demoapp.common

import com.squareup.moshi.JsonClass
import io.goooler.demoapp.base.util.secondOrNull
import io.goooler.demoapp.common.util.JsonUtil
import io.goooler.demoapp.common.util.fromJson
import io.goooler.demoapp.common.util.toJson
import org.intellij.lang.annotations.Language
import org.junit.Assert.assertTrue
import org.junit.Test

class JsonUtilTest {
@Test
fun `JsonUtil fromJson(String)`() {
assertTrue(JsonUtil.fromJson<Repo>(firstStr) == firstBean)
assertTrue(JsonUtil.fromJson<Repo>(secondStr) == secondBean)
}

@Test
fun `JsonUtil fromJson(String, Class, Class)`() {
val list: List<Repo> = JsonUtil.fromJson(strArray, List::class.java, Repo::class.java)
?: throw Exception("Parse json error")
assertTrue(list.firstOrNull() == firstBean)
assertTrue(list.secondOrNull() == secondBean)
}

@Test
fun `JsonUtil toJson(T)`() {
assertTrue(JsonUtil.toJson(firstBean) == firstStr)
assertTrue(JsonUtil.toJson(secondBean) == secondStr)
}

@Test
fun `String fromJson()`() {
assertTrue(firstStr.fromJson<Repo>() == firstBean)
assertTrue(secondStr.fromJson<Repo>() == secondBean)
}

@Test
fun `String fromJson(Class, Class)`() {
val list: List<Repo> = strArray.fromJson(List::class.java, Repo::class.java)
?: throw Exception("Parse json error")
assertTrue(list.first() == firstBean)
assertTrue(list[1] == secondBean)
}

@Test
fun `Any toJson(T)`() {
assertTrue(firstBean.toJson() == firstStr)
assertTrue(secondBean.toJson() == secondStr)
}

@JsonClass(generateAdapter = true)
internal data class Repo(val id: Long, val name: String, val owner: Owner) {
@JsonClass(generateAdapter = true)
data class Owner(val login: String)

override fun equals(other: Any?): Boolean = if (other is Repo) {
this.id == other.id && this.name == other.name && this.owner.login == other.owner.login
} else {
false
}

override fun hashCode(): Int = id.hashCode()
}

companion object {
@Language("JSON")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private val firstStr = """
{"id":126987864,"name":"1024_hosts","owner":{"login":"Goooler"}}
""".trimIndent()

@Language("JSON")
private val secondStr = """
{"id":374913489,"name":"AndroidUiDemo","owner":{"login":"Goooler"}}
""".trimIndent()

// https://api.github.com/users/goooler/repos?&page=1&per_page=2
@Language("JSON")
private val strArray = "[$firstStr,$secondStr]"

private val firstBean = Repo(126987864, "1024_hosts", Repo.Owner("Goooler"))
private val secondBean = Repo(374913489, "AndroidUiDemo", Repo.Owner("Goooler"))
}
}