/*
 * Copyright 2020 Google LLC
 *
 * 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
 *
 *     https://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.google.android.ground.persistence.remote.firestore.schema

import com.google.android.ground.model.task.MultipleChoice
import com.google.android.ground.model.task.Option
import com.google.android.ground.util.Enums.toEnum
import com.google.android.ground.util.toImmutableList

internal object MultipleChoiceConverter {

    @JvmStatic
    fun toMultipleChoice(em: TaskNestedObject): MultipleChoice {
        var options: List<Option> = listOf()
        if (em.options != null) {
            options = em.options.entries.sortedBy { it.value.index }
                .map { (key, value): Map.Entry<String, OptionNestedObject> ->
                    OptionConverter.toOption(
                        key, value
                    )
                }.toImmutableList()
        }
        return MultipleChoice(
            options,
            toEnum(MultipleChoice.Cardinality::class.java, em.cardinality!!)
        )
    }
}

Fix incorrect list type passed to MultipleChoice

/*
 * Copyright 2020 Google LLC
 *
 * 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
 *
 *     https://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.google.android.ground.persistence.remote.firestore.schema

import com.google.android.ground.model.task.MultipleChoice
import com.google.android.ground.model.task.Option
import com.google.android.ground.util.Enums.toEnum
import com.google.android.ground.util.toImmutableList

internal object MultipleChoiceConverter {

    @JvmStatic
    fun toMultipleChoice(em: TaskNestedObject): MultipleChoice {
        var options: List<Option> = listOf()
        if (em.options != null) {
            options = em.options.entries.sortedBy { it.value.index }
                .map { (key, value): Map.Entry<String, OptionNestedObject> ->
                    OptionConverter.toOption(
                        key, value
                    )
                }.toImmutableList()
        }
        return MultipleChoice(
            options.toImmutableList(),
            toEnum(MultipleChoice.Cardinality::class.java, em.cardinality!!)
        )
    }
}


import org.gradle.plugins.ide.eclipse.model.Classpath
import org.gradle.plugins.ide.eclipse.model.ProjectDependency

description = "JUnit Jupiter API"

dependencies {
	api("org.opentest4j:opentest4j:${Versions.ota4j}")
	api(project(":junit-platform-commons"))
	compileOnly("org.jetbrains.kotlin:kotlin-stdlib")
	runtimeOnly(project(":junit-jupiter-engine"))
}

tasks.jar {
	manifest {
		attributes(
			"Automatic-Module-Name" to "org.junit.jupiter.api"
		)
	}
}

// Remove runtimeOnly dependency on junit-jupiter-engine and junit-platform-engine.
// See https://github.com/junit-team/junit5/issues/1669
eclipse.classpath.file.whenMerged(Action<Classpath> {
	entries.removeAll {
		it is ProjectDependency &&
				(it.path.contains("junit-jupiter-engine") || it.path.contains("junit-platform-engine"))
	}
})

Remove runtime dependency from Jupiter API to its Engine

description = "JUnit Jupiter API"

dependencies {
	api("org.opentest4j:opentest4j:${Versions.ota4j}")
	api(project(":junit-platform-commons"))
	compileOnly("org.jetbrains.kotlin:kotlin-stdlib")
}

tasks.jar {
	manifest {
		attributes(
			"Automatic-Module-Name" to "org.junit.jupiter.api"
		)
	}
}


/*
 * Copyright 2019 Louis Cognault Ayeva Derman. Use of this source code is governed by the Apache 2.0 license.
 */

@file:Suppress("PackageDirectoryMismatch")

import org.gradle.api.Project
import org.gradle.kotlin.dsl.extra
import java.util.Properties

object ProjectVersions {
    const val androidSdk = 29
}

val Project.thisLibraryVersion: String
    get() {
        val key = "splitties.version"
        return rootProject.extra.properties.getOrPut(key) {
            rootProject.file("libraries_version.txt").readLines().first()
        } as String
    }

val Project.isDevVersion get() = thisLibraryVersion.contains("-dev-")

Remove no longer needed isDevVersion extension property

/*
 * Copyright 2019-2021 Louis Cognault Ayeva Derman. Use of this source code is governed by the Apache 2.0 license.
 */

@file:Suppress("PackageDirectoryMismatch")

import org.gradle.api.Project
import org.gradle.kotlin.dsl.extra
import java.util.Properties

object ProjectVersions {
    const val androidSdk = 29
}

val Project.thisLibraryVersion: String
    get() {
        val key = "splitties.version"
        return rootProject.extra.properties.getOrPut(key) {
            rootProject.file("libraries_version.txt").readLines().first()
        } as String
    }


package org.wordpress.aztec.glideloader

import android.content.Context
import android.graphics.drawable.Drawable

import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.GlideDrawable
import com.bumptech.glide.request.Request
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SizeReadyCallback
import com.bumptech.glide.request.target.Target

import org.wordpress.aztec.Html

class GlideImageLoader(private val context: Context) : Html.ImageGetter {

    override fun loadImage(source: String, callbacks: Html.ImageGetter.Callbacks, maxWidth: Int) {
        Glide.with(context).load(source).fitCenter().into(object : Target<GlideDrawable> {
            override fun onLoadStarted(placeholder: Drawable) {
                val r = context.resources
            }

            override fun onLoadFailed(e: Exception, errorDrawable: Drawable) {
                callbacks.onImageLoadingFailed()
            }

            override fun onResourceReady(resource: GlideDrawable, glideAnimation: GlideAnimation<in GlideDrawable>) {
                callbacks.onImageLoaded(resource)
            }

            override fun onLoadCleared(placeholder: Drawable) {}

            override fun getSize(cb: SizeReadyCallback) {
                cb.onSizeReady(maxWidth, Target.SIZE_ORIGINAL)
            }

            override fun setRequest(request: Request) {

            }

            override fun getRequest(): Request? {
                return null
            }

            override fun onStart() {

            }

            override fun onStop() {

            }

            override fun onDestroy() {

            }
        })
    }
}

Fix for a possible crash in GlideLoader

package org.wordpress.aztec.glideloader

import android.content.Context
import android.graphics.drawable.Drawable

import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.GlideDrawable
import com.bumptech.glide.request.Request
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SizeReadyCallback
import com.bumptech.glide.request.target.Target

import org.wordpress.aztec.Html

class GlideImageLoader(private val context: Context) : Html.ImageGetter {

    override fun loadImage(source: String, callbacks: Html.ImageGetter.Callbacks, maxWidth: Int) {
        Glide.with(context).load(source).fitCenter().into(object : Target<GlideDrawable> {
            override fun onLoadStarted(placeholder: Drawable?) {
                val r = context.resources
            }

            override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
                callbacks.onImageLoadingFailed()
            }

            override fun onResourceReady(resource: GlideDrawable?, glideAnimation: GlideAnimation<in GlideDrawable>?) {
                callbacks.onImageLoaded(resource)
            }

            override fun onLoadCleared(placeholder: Drawable?) {}

            override fun getSize(cb: SizeReadyCallback?) {
                cb?.onSizeReady(maxWidth, Target.SIZE_ORIGINAL)
            }

            override fun setRequest(request: Request?) {

            }

            override fun getRequest(): Request? {
                return null
            }

            override fun onStart() {

            }

            override fun onStop() {

            }

            override fun onDestroy() {

            }
        })
    }
}


import nu.studer.gradle.rocker.RockerConfig

plugins {
    id("nu.studer.rocker") version "2.1"
    id("java")
}

repositories {
    jcenter()
}

val rockerVersion by extra("1.3.0")

rocker {
    create("main") {
        templateDir = file("src/rocker")
        outputDir = file("src/generated/rocker")
        isOptimize = true // optional
    }
}

Clean up Kotlin DSL example

import nu.studer.gradle.rocker.RockerConfig

plugins {
    id("nu.studer.rocker") version "2.1.1"
    id("java")
}

repositories {
    jcenter()
}

val rockerVersion by extra("1.3.0")

rocker {
    create("main") {
        templateDir.set(file("src/rocker"))
        outputDir.set(file("src/generated/rocker"))
        optimize.set(true) // optional
    }
}


package venus.simulator

class History {
    private val diffs = ArrayList<List<Diff>>()

    fun add(pre: List<Diff>) = diffs.add(pre.toList())
    fun pop() = diffs.removeAt(diffs.size - 1)
    fun isEmpty() = diffs.isEmpty()
}

Add a TODO about deque

package venus.simulator

/* TODO: add a way to have a limit (maybe a deque?) */
class History {
    private val diffs = ArrayList<List<Diff>>()

    fun add(pre: List<Diff>) = diffs.add(pre.toList())
    fun pop() = diffs.removeAt(diffs.size - 1)
    fun isEmpty() = diffs.isEmpty()
}


plugins {
    id("gradlebuild.distribution.api-java")
}

dependencies {
    implementation(project(":base-services"))
    implementation(project(":messaging"))
    implementation(project(":logging"))
    implementation(project(":core-api"))
    implementation(project(":model-core"))
    implementation(project(":core"))
    implementation(project(":dependency-management"))
    implementation(project(":plugin-use"))

    implementation(libs.slf4jApi)
    implementation(libs.guava)

    testImplementation(testFixtures(project(":dependency-management")))

    integTestImplementation(project(":build-option"))
    integTestImplementation(project(":launcher"))

    integTestDistributionRuntimeOnly(project(":distributions-basics")) {
        because("Requires test-kit: 'java-gradle-plugin' is used in some integration tests which always adds the test-kit dependency.")
    }
}

testFilesCleanup.reportOnly.set(true)

Add missing test implementation dependency

plugins {
    id("gradlebuild.distribution.api-java")
}

dependencies {
    implementation(project(":base-services"))
    implementation(project(":messaging"))
    implementation(project(":logging"))
    implementation(project(":core-api"))
    implementation(project(":model-core"))
    implementation(project(":core"))
    implementation(project(":dependency-management"))
    implementation(project(":plugin-use"))

    implementation(libs.slf4jApi)
    implementation(libs.guava)

    testImplementation(project(":file-watching"))
    testImplementation(testFixtures(project(":dependency-management")))

    integTestImplementation(project(":build-option"))
    integTestImplementation(project(":launcher"))

    integTestDistributionRuntimeOnly(project(":distributions-basics")) {
        because("Requires test-kit: 'java-gradle-plugin' is used in some integration tests which always adds the test-kit dependency.")
    }
}

testFilesCleanup.reportOnly.set(true)


plugins {
    id("gradlebuild.internal.java")
}

dependencies {
    implementation(project(":base-services"))
    implementation(project(":native"))

    implementation(libs.groovy)
    implementation(libs.slf4jApi)
    implementation(libs.guava)
    implementation(libs.commonsLang)
    implementation(libs.commonsIo)
    implementation(libs.ant)
    implementation(libs.asm)
    implementation(libs.asmTree)
    implementation(libs.junit)
    implementation(libs.spock)
    implementation(libs.spockJUnit4)
    implementation(libs.jsoup)
    implementation(libs.testcontainersSpock)

    runtimeOnly(libs.bytebuddy)
}

Upgrade 'internal-testing' to Groovy 3

plugins {
    id("gradlebuild.internal.java")
}

dependencies {
    implementation(project(":base-services"))
    implementation(project(":native"))

    implementation(libs.groovy)
    implementation(libs.groovyJson)
    implementation(libs.groovyXml)
    implementation(libs.slf4jApi)
    implementation(libs.guava)
    implementation(libs.commonsLang)
    implementation(libs.commonsIo)
    implementation(libs.ant)
    implementation(libs.asm)
    implementation(libs.asmTree)
    implementation(libs.junit)
    implementation(libs.spock)
    implementation(libs.spockJUnit4)
    implementation(libs.jsoup)
    implementation(libs.testcontainersSpock)

    runtimeOnly(libs.bytebuddy)
}


plugins {
    kotlin("jvm")
    id("com.gradle.plugin-publish") version "0.10.0"
    `java-gradle-plugin`
}

dependencies {
    compile(project(":apina-core"))

    testImplementation(kotlin("test"))
    testImplementation("org.junit.jupiter:junit-jupiter-api")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

pluginBundle {
    website = "https://github.com/EvidentSolutions/apina"
    vcsUrl = "https://github.com/EvidentSolutions/apina"
    description = "Gradle plugin for creating TypeScript client code from Spring controllers and Jackson classes"
    tags = listOf("typescript", "angular", "jackson", "spring")
}

gradlePlugin {
    plugins {
        create("apinaPlugin") {
            id = "fi.evident.apina"
            displayName = "Gradle Apina plugin"
            implementationClass = "fi.evident.apina.gradle.ApinaPlugin"
        }
    }
}

Use supported version of publishing plugin

plugins {
    kotlin("jvm")
    id("com.gradle.plugin-publish") version "0.11.0"
    `java-gradle-plugin`
}

dependencies {
    compile(project(":apina-core"))

    testImplementation(kotlin("test"))
    testImplementation("org.junit.jupiter:junit-jupiter-api")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

pluginBundle {
    website = "https://github.com/EvidentSolutions/apina"
    vcsUrl = "https://github.com/EvidentSolutions/apina"
    description = "Gradle plugin for creating TypeScript client code from Spring controllers and Jackson classes"
    tags = listOf("typescript", "angular", "jackson", "spring")
}

gradlePlugin {
    plugins {
        create("apinaPlugin") {
            id = "fi.evident.apina"
            displayName = "Gradle Apina plugin"
            implementationClass = "fi.evident.apina.gradle.ApinaPlugin"
        }
    }
}


package org.jetbrains.dokka

public class JekyllFormatService(locationService: LocationService, signatureGenerator: SignatureGenerator)
: MarkdownFormatService(locationService, signatureGenerator) {
    override val extension: String = "html"
    override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
        to.appendln("---")
        to.appendln("layout: post")
        to.appendln("title: ${nodes.first().name}")
        to.appendln("---")
        super<MarkdownFormatService>.format(nodes, to)
    }
}

Revert to md for now.

package org.jetbrains.dokka

public class JekyllFormatService(locationService: LocationService, signatureGenerator: SignatureGenerator)
: MarkdownFormatService(locationService, signatureGenerator) {
    override val extension: String = "md"
    override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
        to.appendln("---")
        to.appendln("layout: post")
        to.appendln("title: ${nodes.first().name}")
        to.appendln("---")
        super<MarkdownFormatService>.format(nodes, to)
    }
}


package venus.riscv

fun userStringToInt(s: String): Int {
    if (isCharacterLiteral(s)) {
        return s[1].toInt()
    }
    val radix = when (s.take(2)) {
        "0x" -> 16
        "0b" -> 2
        else -> return s.toLong().toInt()
    }
    return s.drop(2).toLong(radix).toInt()
}

private fun isCharacterLiteral(s: String) =
        s.length == 3 && s[0] == '\'' && s[2] == '\''

Improve support for parsing character literals

package venus.riscv

fun userStringToInt(s: String): Int {
    if (isCharacterLiteral(s)) {
        return characterLiteralToInt(s)
    }
    val radix = when (s.take(2)) {
        "0x" -> 16
        "0b" -> 2
        else -> return s.toLong().toInt()
    }
    return s.drop(2).toLong(radix).toInt()
}

private fun isCharacterLiteral(s: String) =
        s.first() == '\'' && s.last() == '\''

private fun characterLiteralToInt(s: String): Int {
    val stripSingleQuotes = s.drop(1).dropLast(1)
    val jsonString = "\"$stripSingleQuotes\""
    try {
        val parsed = JSON.parse<String>(jsonString)
        if (parsed.isEmpty()) throw NumberFormatException("charater literal $s is empty")
        if (parsed.length > 1) throw NumberFormatException("charater literal $s too long")
        return parsed[0].toInt()
    } catch (e: Throwable) {
        throw NumberFormatException("could not parse character literal $s")
    }
}


package to.etc.domui.component2.conditionpanel

import to.etc.domui.databinding.observables.ObservableList
import to.etc.domui.dom.html.Div
import to.etc.webapp.query.QOperation

interface IConditionModel<T, F> {
	fun getFields(): List<F>

	fun fieldName(field: F): String

	fun allowedOperations(field: F): Set<QOperation>
}

class ConditionPanel<T, F>(val model: IConditionModel<T, F>) : Div("ui-copa") {

}

open class CondUiBase<T, F>(val panel: ConditionPanel<T, F>, css: String) : Div(css) {

}

/**
 * UI for a simple condition in the form FIELD OPERATION VALUE.
 */
open class CondUiSimple<T, F>(panel: ConditionPanel<T, F>) : CondUiBase<T, F>(panel, "ui-copa-cmp") {

}

/**
 * UI for a list of conditions, contained of both compounds and comparisons.
 */
open class CondUiCompound<T, F>(panel: ConditionPanel<T, F>) : CondUiBase<T, F>(panel, "ui-copa-list") {

}

sealed internal class CoNode<T, F>(val parent: CoNode<T, F>?) {}

internal class CoCompound<T, F>(val parent: CoCompound<T, F>?) {
	val conditions = ObservableList<CoNode<T, F>>()
}

internal class CoSimple<T, F>(var parent: CoCompound<T, F>) {
	var operation: QOperation? = null
	var field: F? = null
	var value: Any? = null
}


dependencies {
    implementation("me.champeau.gradle:jmh-gradle-plugin:0.4.7")
    implementation("org.jsoup:jsoup:1.11.3")
    implementation("com.gradle:build-scan-plugin:2.1")
    implementation(project(":configuration"))
    implementation(project(":kotlinDsl"))
    implementation(project(":plugins"))
    implementation(project(":build"))
}

gradlePlugin {
    plugins {
        register("buildscan") {
            id = "gradlebuild.buildscan"
            implementationClass = "org.gradle.gradlebuild.profiling.buildscan.BuildScanPlugin"
        }
    }
}

Upgrade to JMH plugin 0.4.8

dependencies {
    implementation("me.champeau.gradle:jmh-gradle-plugin:0.4.8")
    implementation("org.jsoup:jsoup:1.11.3")
    implementation("com.gradle:build-scan-plugin:2.1")
    implementation(project(":configuration"))
    implementation(project(":kotlinDsl"))
    implementation(project(":plugins"))
    implementation(project(":build"))
}

gradlePlugin {
    plugins {
        register("buildscan") {
            id = "gradlebuild.buildscan"
            implementationClass = "org.gradle.gradlebuild.profiling.buildscan.BuildScanPlugin"
        }
    }
}


package iii_conventions.multiAssignemnt

import util.TODO
import util.doc30

fun todoTask30(): Nothing = TODO(
    """
        Task 30.
        Read about destructuring declarations and make the following code compile by adding one word (after uncommenting it).
    """,
    documentation = doc30()
)

class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)

operator fun MyDate.component1() = year
operator fun MyDate.component2() = month
operator fun MyDate.component3() = dayOfMonth

fun isLeapDay(date: MyDate): Boolean {
    val (year, month, dayOfMonth) = date

    // 29 February of a leap year
    return year % 4 == 0 && month == 2 && dayOfMonth == 29
}

Complete koan 30, take 2 (Destructuring Declarations). Instructions say to only add one word, in this case "data" to class

package iii_conventions.multiAssignemnt

import util.TODO
import util.doc30

fun todoTask30(): Nothing = TODO(
    """
        Task 30.
        Read about destructuring declarations and make the following code compile by adding one word (after uncommenting it).
    """,
    documentation = doc30()
)

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)

//operator fun MyDate.component1() = year
//operator fun MyDate.component2() = month
//operator fun MyDate.component3() = dayOfMonth

fun isLeapDay(date: MyDate): Boolean {
    val (year, month, dayOfMonth) = date

    // 29 February of a leap year
    return year % 4 == 0 && month == 2 && dayOfMonth == 29
}


package com.barista_v.debug_artist.utils.extensions

import com.barista_v.debug_artist.utils.RetryAfterTimeoutWithDelay
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers

/**
 * Shorthand to set [subscribeOn], [observeOn] and retry policy for observables
 */
fun <T> Observable<T>.composeForIoTasks(): Observable<T> = compose<T>(Observable.Transformer {
  it.subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .retryWhen(RetryAfterTimeoutWithDelay(3, 500))
})

Use 10 retries for timeout (pivotal have a lot of them)

package com.barista_v.debug_artist.utils.extensions

import com.barista_v.debug_artist.utils.RetryAfterTimeoutWithDelay
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers

/**
 * Shorthand to set [subscribeOn], [observeOn] and retry policy for observables
 */
fun <T> Observable<T>.composeForIoTasks(): Observable<T> = compose<T>(Observable.Transformer {
  it.subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .retryWhen(RetryAfterTimeoutWithDelay(10, 1000))
})


Add tests for import quick fix for expression constructors

package org.purescript.psi.expression

import com.intellij.testFramework.fixtures.BasePlatformTestCase
import org.purescript.getImportDeclaration
import org.purescript.getImportDeclarations
import org.purescript.ide.inspections.PSUnresolvedReferenceInspection

class ImportExpressionConstructorQuickFixTest : BasePlatformTestCase() {

    fun `test imports module`() {
        myFixture.configureByText(
            "Maybe.purs",
            """
                module Data.Maybe where
                data Maybe a
                    = Just a
                    | Nothing
            """.trimIndent()
        )
        val file = myFixture.configureByText(
            "Foo.purs",
            """
                module Foo where
                f = Just 3
            """.trimIndent()
        )
        myFixture.enableInspections(PSUnresolvedReferenceInspection())
        val action = myFixture.getAllQuickFixes("Foo.purs").single()
        myFixture.launchAction(action)
        val importDeclaration = file.getImportDeclaration()

        assertEquals("Import", action.familyName)
        assertEquals("Data.Maybe", importDeclaration.name)
    }

    fun `test imports module with other imports`() {
        myFixture.configureByText(
            "Maybe.purs",
            """
                module Data.Maybe where
                newtype Just = Just Int
            """.trimIndent()
        )
        myFixture.configureByText("Prelude.purs", "module Prelude where")
        val file = myFixture.configureByText(
            "Foo.purs",
            """
                module Foo where
                import Prelude
                f = Just 3
            """.trimIndent()
        )
        myFixture.enableInspections(PSUnresolvedReferenceInspection())
        val action = myFixture.getAllQuickFixes("Foo.purs").single()
        myFixture.launchAction(action)

        val importDeclarations = file.getImportDeclarations()
        assertSize(2, importDeclarations)
        assertContainsElements(importDeclarations.map { it.name }, "Prelude", "Data.Maybe")
    }

    fun `test doesn't import non-existing module`() {
        val file = myFixture.configureByText(
            "Foo.purs",
            """
                module Foo where
                f = Just 3
            """.trimIndent()
        )
        myFixture.enableInspections(PSUnresolvedReferenceInspection())
        val action = myFixture.getAllQuickFixes("Foo.purs").single()
        myFixture.launchAction(action)

        assertEmpty(file.getImportDeclarations())
    }
}


/*
 * Copyright (C) 2020 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 app.cash.turbine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.suspendCancellableCoroutine

/** A flow that never emits anything. */
fun neverFlow(): Flow<Nothing> = flow {
  suspendCancellableCoroutine {
    // Do nothing!
  }
}

expect fun suspendTest(body: suspend CoroutineScope.() -> Unit)

inline fun <reified T : Throwable> assertThrows(body: () -> Unit): T {
  try {
    body()
  } catch (t: Throwable) {
    if (t is T) {
      return t
    }
    throw t
  }
  throw AssertionError(
    "Expected body to throw ${T::class.simpleName} but it completed successfully"
  )
}

Use awaitCancellation instead of suspendCancellableCoroutine

/*
 * Copyright (C) 2020 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 app.cash.turbine

import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

/** A flow that never emits anything. */
fun neverFlow(): Flow<Nothing> = flow { awaitCancellation() }

expect fun suspendTest(body: suspend CoroutineScope.() -> Unit)

inline fun <reified T : Throwable> assertThrows(body: () -> Unit): T {
  try {
    body()
  } catch (t: Throwable) {
    if (t is T) {
      return t
    }
    throw t
  }
  throw AssertionError(
    "Expected body to throw ${T::class.simpleName} but it completed successfully"
  )
}


plugins {
  id("adventure.parent-build-logic")
}

group = "net.kyori"
version = "4.8.1"
description = "A user-interface library for Minecraft: Java Edition."

Return to development on 4.9.0

plugins {
  id("adventure.parent-build-logic")
}

group = "net.kyori"
version = "4.9.0-SNAPSHOT"
description = "A user-interface library for Minecraft: Java Edition."


package br.com.bloder.migration

import br.com.bloder.migration.internal.detail.MigrationDetail
import io.realm.DynamicRealm
import io.realm.RealmMigration

/**
 * Abstract better migration actions to transform in
 * a realm migration
 */
class BetterMigration(private val migration: MigrationDetail) : RealmMigration {

    /**
     * Realm Migration main function
     */
    override fun migrate(realm: DynamicRealm?, oldVersion: Long, newVersion: Long) {
        if (newVersion < oldVersion && newVersion == migration.version) {
            migration.migration?.down()
        }
        if (newVersion == migration.version) {
            migration.migration?.up()
        }
    }
}

Fix wrong param in better migration class

package br.com.bloder.migration

import br.com.bloder.migration.internal.detail.MigrationDetail
import io.realm.DynamicRealm
import io.realm.RealmMigration

/**
 * Abstract better migration actions to transform in
 * a realm migration
 */
class BetterMigration(private val migration: MigrationDetail) : RealmMigration {

    /**
     * Realm Migration main function
     */
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        if (migration.version > newVersion) {
            migration.migration?.down(realm)
        }
        if (newVersion == migration.version) {
            migration.migration?.up(realm)
        }
    }
}


object Versions {
    const val LORITTA = "2021-SNAPSHOT"
    const val KOTLIN = "1.5.0"
    const val KTOR = "1.5.2"
    const val JDA = "4.3.0_324"
    const val KOTLIN_SERIALIZATION = "1.1.0"
    const val KOTLIN_COROUTINES = "1.5.0"
    const val EXPOSED = "0.36.1"
}

Update Kotlin, Ktor and Kotlin Coroutines

object Versions {
    const val LORITTA = "2021-SNAPSHOT"
    const val KOTLIN = "1.5.31"
    const val KTOR = "1.6.5"
    const val JDA = "4.3.0_324"
    const val KOTLIN_SERIALIZATION = "1.1.0"
    const val KOTLIN_COROUTINES = "1.5.2"
    const val EXPOSED = "0.36.1"
}


package org.javacs.kt

import org.javacs.kt.j2k.convertJavaToKotlin
import org.junit.Test
import org.junit.Assert.assertThat
import org.hamcrest.Matchers.equalTo
import java.nio.file.Paths

class JavaToKotlinTest : LanguageServerTestFixture("j2k") {
    @Test fun `test j2k conversion`() {
        val javaCode = workspaceRoot
            .resolve("JavaJSONConverter.java")
            .toFile()
            .readText()
            .trim()
        val expectedKotlinCode = workspaceRoot
            .resolve("JavaJSONConverter.kt")
            .toFile()
            .readText()
            .trim()
        val compiler = languageServer.classPath.compiler
        val convertedKotlinCode = convertJavaToKotlin(javaCode, compiler)
        assertThat(convertedKotlinCode, equalTo(expectedKotlinCode))
    }
}

Update J2K test to always use linefeeds

package org.javacs.kt

import org.javacs.kt.j2k.convertJavaToKotlin
import org.junit.Test
import org.junit.Assert.assertThat
import org.hamcrest.Matchers.equalTo
import java.nio.file.Paths

class JavaToKotlinTest : LanguageServerTestFixture("j2k") {
    @Test fun `test j2k conversion`() {
        val javaCode = workspaceRoot
            .resolve("JavaJSONConverter.java")
            .toFile()
            .readText()
            .trim()
        val expectedKotlinCode = workspaceRoot
            .resolve("JavaJSONConverter.kt")
            .toFile()
            .readText()
            .trim()
            .replace("\r\n", "\n")
        val compiler = languageServer.classPath.compiler
        val convertedKotlinCode = convertJavaToKotlin(javaCode, compiler).replace("\r\n", "\n")
        assertThat(convertedKotlinCode, equalTo(expectedKotlinCode))
    }
}


package io.ktor.util

/**
 * API marked with this annotation is ktor internal and it is not intended to be used outside.
 * It could be modified or removed without any notice. Using it outside of ktor could cause undefined behaviour and/or
 * any strange effects.
 *
 * We are strongly recommend to not use such API.
 */
@Experimental(level = Experimental.Level.ERROR)
@Target(
    AnnotationTarget.CLASS,
    AnnotationTarget.TYPEALIAS,
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY,
    AnnotationTarget.FIELD,
    AnnotationTarget.CONSTRUCTOR
)
annotation class InternalAPI

/**
 * API marked with this annotation is experimental and is not guaranteed to be stable.
 */
@Experimental(level = Experimental.Level.WARNING)
annotation class KtorExperimentalAPI

Make KtorExperimentalAPI applicable to all suitable targets

package io.ktor.util

/**
 * API marked with this annotation is ktor internal and it is not intended to be used outside.
 * It could be modified or removed without any notice. Using it outside of ktor could cause undefined behaviour and/or
 * any strange effects.
 *
 * We are strongly recommend to not use such API.
 */
@Experimental(level = Experimental.Level.ERROR)
@Target(
    AnnotationTarget.CLASS,
    AnnotationTarget.TYPEALIAS,
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY,
    AnnotationTarget.FIELD,
    AnnotationTarget.CONSTRUCTOR
)
annotation class InternalAPI

/**
 * API marked with this annotation is experimental and is not guaranteed to be stable.
 */
@Experimental(level = Experimental.Level.WARNING)
@Target(
    AnnotationTarget.CLASS,
    AnnotationTarget.TYPEALIAS,
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY,
    AnnotationTarget.FIELD,
    AnnotationTarget.CONSTRUCTOR
)
annotation class KtorExperimentalAPI


package configurations

import jetbrains.buildServer.configs.kotlin.v10.BuildType
import model.CIBuildModel
import model.OS
import model.TestCoverage
import model.TestType

class FunctionalTest(testCoverage : TestCoverage, bucket: Int = 0) : BuildType({
    uuid = "${testCoverage.asId()}_$bucket"
    extId = uuid
    name = testCoverage.asName() + if (bucket > 0) " ($bucket)" else ""
    if (bucket > 0) {
        description = CIBuildModel.testBuckets[bucket - 1].joinToString()
    }
    val testTask = testCoverage.testType.name + "Test" + if (bucket > 0) bucket.toString() else ""
    val quickTest = testCoverage.testType == TestType.quick
    applyDefaults(this, testTask, requiresDistribution = !quickTest,
            runsOnWindows = testCoverage.os == OS.windows, timeout = if (quickTest) 60 else 180)

    params {
        param("env.JAVA_HOME", "%${testCoverage.os}.${testCoverage.version}.${testCoverage.vendor}.64bit%")
    }
})

Set Android home for soak tests

package configurations

import jetbrains.buildServer.configs.kotlin.v10.BuildType
import model.CIBuildModel
import model.OS
import model.TestCoverage
import model.TestType

class FunctionalTest(testCoverage : TestCoverage, bucket: Int = 0) : BuildType({
    uuid = "${testCoverage.asId()}_$bucket"
    extId = uuid
    name = testCoverage.asName() + if (bucket > 0) " ($bucket)" else ""
    if (bucket > 0) {
        description = CIBuildModel.testBuckets[bucket - 1].joinToString()
    }
    val testTask = testCoverage.testType.name + "Test" + if (bucket > 0) bucket.toString() else ""
    val quickTest = testCoverage.testType == TestType.quick
    applyDefaults(this, testTask, requiresDistribution = !quickTest,
            runsOnWindows = testCoverage.os == OS.windows, timeout = if (quickTest) 60 else 180)

    params {
        param("env.JAVA_HOME", "%${testCoverage.os}.${testCoverage.version}.${testCoverage.vendor}.64bit%")
        param("env.ANDROID_HOME", "/opt/android/sdk")
    }
})


Add basic page queue storage implementation

package org.mozilla.mobilefino.tabqueue.storage

import android.content.Context
import org.json.JSONArray
import java.lang.ref.WeakReference

val SHAREDPREFERENCES_NAME = "pagequeue"

val KEY_QUEUE = "key_sitequeue"

/**
 * List of pages that have been queued for reading.
 */
class PageQueue {
    val mPageList: JSONArray

    val mContext: WeakReference<Context>

    constructor(context: Context) {
        mContext = WeakReference<Context>(context.applicationContext)

        val preferences = context.getSharedPreferences(SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE)

        if (preferences.contains(KEY_QUEUE)) {
            val jsonString = preferences.getString(KEY_QUEUE, "");

            mPageList = JSONArray(jsonString)
        } else {
            mPageList = JSONArray()
        }
    }

    private fun commit() {
        synchronized(mPageList) {
            val context = mContext.get() ?: return

            val jsonString = mPageList.toString()

            context.getSharedPreferences(SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE)
                    .edit()
                    .putString(KEY_QUEUE, jsonString)
                    .apply()
        }
    }

    fun add(url: String) {
        synchronized(mPageList) {
            mPageList.put(url)
        }

        commit()
    }
}

val sPageQueueLock = Object()
var sPageQueue: PageQueue? = null

fun getPageQueue(context: Context): PageQueue {
    synchronized(sPageQueueLock) {
        if (sPageQueue == null) {
            sPageQueue = PageQueue(context)
        }

        // sPageQueue cannot be null at this point (but the IDE / compiler aren't able to deduce that)
        return sPageQueue!!
    }
}


package io.github.malteseduck.springframework.data.marklogic.core.query

import com.fasterxml.jackson.databind.JsonNode
import io.github.malteseduck.springframework.data.marklogic.repository.query.CombinedQueryDefinition

abstract class QueryCriteria<T> {
    // Allow support of passing a query string
    var qtext: String? = null

    // Allow support of passing a QBE node
    var query: JsonNode? = null

    // Allow specification of which fields to return in the results.  Specify using dot notation, i.e.
    // "name" for a property at the root and "friends.name" for a property "name" nested under a "friends" property
    var fields: List<String> = emptyList()

    // Allow specifying of specific persisted query options to use when executing the query.  Set the
    // options to the name of the options you have specified in your src/main/resources/db/options directory.
    var options: String? = null

    // Override to do customization of the created CombinedQueryDefinition
    fun configure(query: CombinedQueryDefinition): CombinedQueryDefinition = query
}

Allow override of configure function

package io.github.malteseduck.springframework.data.marklogic.core.query

import com.fasterxml.jackson.databind.JsonNode
import io.github.malteseduck.springframework.data.marklogic.repository.query.CombinedQueryDefinition

abstract class QueryCriteria<T> {
    // Allow support of passing a query string
    var qtext: String? = null

    // Allow support of passing a QBE node
    var query: JsonNode? = null

    // Allow specification of which fields to return in the results.  Specify using dot notation, i.e.
    // "name" for a property at the root and "friends.name" for a property "name" nested under a "friends" property
    var fields: List<String> = emptyList()

    // Allow specifying of specific persisted query options to use when executing the query.  Set the
    // options to the name of the options you have specified in your src/main/resources/db/options directory.
    var options: String? = null

    // Override to do customization of the created CombinedQueryDefinition
    open fun configure(query: CombinedQueryDefinition): CombinedQueryDefinition = query
}


package org.ccci.gto.android.common.picasso.widget

import android.graphics.drawable.Drawable
import android.widget.TextView
import org.ccci.gto.android.common.picasso.BaseViewTarget
import org.ccci.gto.android.common.picasso.R

class TextViewDrawableEndTarget(view: TextView) : BaseViewTarget<TextView>(view) {
    init {
        view.setTag(R.id.picasso_textViewDrawableEndTarget, this)
    }

    companion object {
        fun of(view: TextView) = view.getTag(R.id.picasso_textViewDrawableEndTarget) as? TextViewDrawableEndTarget
                ?: TextViewDrawableEndTarget(view)
    }

    public override fun updateDrawable(drawable: Drawable?) {
        val current = view.compoundDrawablesRelative
        drawable?.apply { setBounds(0, 0, intrinsicWidth, intrinsicHeight) }
        view.setCompoundDrawablesRelative(drawable, current[1], current[2], current[3])
    }
}

Replace end drawable instead of start

package org.ccci.gto.android.common.picasso.widget

import android.graphics.drawable.Drawable
import android.widget.TextView
import org.ccci.gto.android.common.picasso.BaseViewTarget
import org.ccci.gto.android.common.picasso.R

class TextViewDrawableEndTarget(view: TextView) : BaseViewTarget<TextView>(view) {
    init {
        view.setTag(R.id.picasso_textViewDrawableEndTarget, this)
    }

    companion object {
        fun of(view: TextView) = view.getTag(R.id.picasso_textViewDrawableEndTarget) as? TextViewDrawableEndTarget
                ?: TextViewDrawableEndTarget(view)
    }

    public override fun updateDrawable(drawable: Drawable?) {
        val current = view.compoundDrawablesRelative
        drawable?.apply { setBounds(0, 0, intrinsicWidth, intrinsicHeight) }
        view.setCompoundDrawablesRelative(current[0], current[1], drawable, current[3])
    }
}


/*
 * Copyright 2020 the original author or authors.
 *
 * 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 configurations

import common.Branch

val triggerExcludes = """
        -:.idea
        -:.github
        -:.teamcity
        -:.teamcityTest
        -:subprojects/docs/src/docs/release
    """.trimIndent()

fun branchFilter(branch: Branch) = """
    +:$branch
""".trimIndent()

val allBranchesFilter = """
    +:*
    -:<default>
""".trimIndent()

Fix branch name case in triggers

/*
 * Copyright 2020 the original author or authors.
 *
 * 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 configurations

import common.Branch

val triggerExcludes = """
        -:.idea
        -:.github
        -:.teamcity
        -:.teamcityTest
        -:subprojects/docs/src/docs/release
    """.trimIndent()

fun branchFilter(branch: Branch) = """
    +:${branch.name.toLowerCase()}
""".trimIndent()

val allBranchesFilter = """
    +:*
    -:<default>
""".trimIndent()


// When flag is set, use an Kotlin EAP to allow Gradle to be built when instant execution is enabled
// Remove this when upgrading to Kotlin 1.3.70
val useKotlinEap = providers.systemProperty("org.gradle.unsafe.kotlin-eap").map(String::toBoolean).orElse(false)
val kotlinVersion = if (useKotlinEap.get()) {
    println("Using Kotlin EAP version to build Gradle")
    "1.3.70-eap-16"
} else {
    null
}

dependencies {

    implementation(project(":build"))
    implementation(project(":configuration"))

    api(kotlin("gradle-plugin", kotlinVersion))
    api(kotlin("stdlib-jdk8", kotlinVersion))
    api(kotlin("reflect", kotlinVersion))
    api(kotlin("compiler-embeddable", kotlinVersion))

    implementation("org.gradle.kotlin:gradle-kotlin-dsl-conventions:0.4.1")
    implementation("com.gradle.publish:plugin-publish-plugin:0.10.0")

    implementation("com.thoughtworks.qdox:qdox:2.0-M9")
    implementation("org.ow2.asm:asm:7.1")

    testImplementation("junit:junit:4.12")
    testImplementation("com.nhaarman:mockito-kotlin:1.6.0")
}

Upgrade kotlin version to eap-17

// When flag is set, use an Kotlin EAP to allow Gradle to be built when instant execution is enabled
// Remove this when upgrading to Kotlin 1.3.70
val useKotlinEap = providers.systemProperty("org.gradle.unsafe.kotlin-eap").map(String::toBoolean).orElse(false)
val kotlinVersion = if (useKotlinEap.get()) {
    println("Using Kotlin EAP version to build Gradle")
    "1.3.70-eap-17"
} else {
    null
}

dependencies {

    implementation(project(":build"))
    implementation(project(":configuration"))

    api(kotlin("gradle-plugin", kotlinVersion))
    api(kotlin("stdlib-jdk8", kotlinVersion))
    api(kotlin("reflect", kotlinVersion))
    api(kotlin("compiler-embeddable", kotlinVersion))

    implementation("org.gradle.kotlin:gradle-kotlin-dsl-conventions:0.4.1")
    implementation("com.gradle.publish:plugin-publish-plugin:0.10.0")

    implementation("com.thoughtworks.qdox:qdox:2.0-M9")
    implementation("org.ow2.asm:asm:7.1")

    testImplementation("junit:junit:4.12")
    testImplementation("com.nhaarman:mockito-kotlin:1.6.0")
}


/*
 * Minecraft Dev for IntelliJ
 *
 * https://minecraftdev.org
 *
 * Copyright (c) 2017 minecraft-dev
 *
 * MIT License
 */

package com.demonwav.mcdev.i18n.inspections

import com.intellij.codeInspection.BaseJavaLocalInspectionTool
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor

abstract class TranslationInspection : BaseJavaLocalInspectionTool() {
    protected abstract fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor

    override final fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
        return buildVisitor(holder)
    }
}

Check for MCP module type for translation inspections

/*
 * Minecraft Dev for IntelliJ
 *
 * https://minecraftdev.org
 *
 * Copyright (c) 2017 minecraft-dev
 *
 * MIT License
 */

package com.demonwav.mcdev.i18n.inspections

import com.demonwav.mcdev.platform.mcp.McpModuleType
import com.intellij.codeInspection.BaseJavaLocalInspectionTool
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiFile

abstract class TranslationInspection : BaseJavaLocalInspectionTool() {
    protected abstract fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor

    override final fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
        if (McpModuleType.isInModule(holder.file)) {
            return buildVisitor(holder)
        }

        return PsiElementVisitor.EMPTY_VISITOR
    }

    override final fun processFile(file: PsiFile, manager: InspectionManager): List<ProblemDescriptor> {
        return if (McpModuleType.isInModule(file)) {
            super.processFile(file, manager)
        } else {
            listOf()
        }
    }
}


package io.kotlintest.mock

import org.mockito.Mockito
import org.mockito.stubbing.OngoingStubbing

inline fun <reified T> mock(): T {
  val klass = T::class
  val t = Mockito.mock(Class.forName(klass.qualifiedName)) as T
  return t
}

fun <A> `when`(methodCall: A): OngoingStubbing<A> = Mockito.`when`(methodCall)

Add Mockito sugar for creating spies.

package io.kotlintest.mock

import org.mockito.Mockito
import org.mockito.stubbing.OngoingStubbing

inline fun <reified T> mock(): T {
  val klass = T::class
  val t = Mockito.mock(Class.forName(klass.qualifiedName)) as T
  return t
}

fun <T> spy(instance: T) = Mockito.spy(instance)

inline fun <reified T : Any> spy() = Mockito.spy(T::class.java)

fun <A> `when`(methodCall: A): OngoingStubbing<A> = Mockito.`when`(methodCall)


package jp.toastkid.yobidashi.main

import android.support.annotation.IdRes
import android.support.annotation.StringRes
import jp.toastkid.yobidashi.R

/**
 * Start-up view definition.
 *
 * @param titleId
 * @param radioButtonId
 *
 * @author toastkidjp
 */
enum class StartUp(@StringRes val titleId: Int, @IdRes val radioButtonId: Int) {
    START(R.string.title_startup_start, R.id.start_up_start),
    SEARCH(R.string.title_search, R.id.start_up_search),
    BROWSER(R.string.title_browser, R.id.start_up_browser),
    APPS_LAUNCHER(R.string.title_apps_launcher, R.id.start_up_launcher);

    companion object {
        fun find(name: String): StartUp {
            if (name.isEmpty()) {
                return getDefault()
            }
            return valueOf(name)
        }

        private fun getDefault(): StartUp = START

        fun findById(@IdRes checkedRadioButtonId: Int): StartUp =
                values().find { it.radioButtonId == checkedRadioButtonId } ?: START
    }
}

Modify default startup to browser.

package jp.toastkid.yobidashi.main

import android.support.annotation.IdRes
import android.support.annotation.StringRes
import jp.toastkid.yobidashi.R

/**
 * Start-up view definition.
 *
 * @param titleId
 * @param radioButtonId
 *
 * @author toastkidjp
 */
enum class StartUp(@StringRes val titleId: Int, @IdRes val radioButtonId: Int) {
    START(R.string.title_startup_start, R.id.start_up_start),
    SEARCH(R.string.title_search, R.id.start_up_search),
    BROWSER(R.string.title_browser, R.id.start_up_browser),
    APPS_LAUNCHER(R.string.title_apps_launcher, R.id.start_up_launcher);

    companion object {
        fun find(name: String): StartUp {
            if (name.isEmpty()) {
                return getDefault()
            }
            return valueOf(name)
        }

        private fun getDefault(): StartUp = BROWSER

        fun findById(@IdRes checkedRadioButtonId: Int): StartUp =
                values().find { it.radioButtonId == checkedRadioButtonId } ?: getDefault()
    }
}


package org.jetbrains.dokka.tests

import org.jetbrains.dokka.DocumentationNode
import org.jetbrains.dokka.FileGenerator
import org.jetbrains.dokka.FormatService
import org.junit.Before
import org.junit.Rule
import org.junit.rules.TemporaryFolder

abstract class FileGeneratorTestCase {
    abstract val formatService: FormatService

    @get:Rule
    var folder = TemporaryFolder()

    val fileGenerator = FileGenerator(folder.apply { create() }.root)

    @Before
    fun bindGenerator() {
        fileGenerator.formatService = formatService
    }

    fun buildPagesAndReadInto(nodes: List<DocumentationNode>, sb: StringBuilder) = with(fileGenerator) {
        buildPages(nodes)
        nodes.forEach {
            val fileForNode = location(it).file
            sb.append(fileForNode.readText())
        }
    }
}

Check file path in testData, when more then one node

package org.jetbrains.dokka.tests

import org.jetbrains.dokka.DocumentationNode
import org.jetbrains.dokka.FileGenerator
import org.jetbrains.dokka.FormatService
import org.jetbrains.dokka.relativeToRoot
import org.junit.Before
import org.junit.Rule
import org.junit.rules.TemporaryFolder

abstract class FileGeneratorTestCase {
    abstract val formatService: FormatService

    @get:Rule
    var folder = TemporaryFolder()

    val fileGenerator = FileGenerator(folder.apply { create() }.root)

    @Before
    fun bindGenerator() {
        fileGenerator.formatService = formatService
    }

    fun buildPagesAndReadInto(nodes: List<DocumentationNode>, sb: StringBuilder) = with(fileGenerator) {
        buildPages(nodes)
        val byLocations = nodes.groupBy { location(it) }
        byLocations.forEach { (loc, _) ->
            if (byLocations.size > 1) {
                sb.appendln("<!-- File: ${relativeToRoot(loc)} -->")
            }
            sb.append(loc.file.readText())
        }
    }
}


Create a simple test for checking button click for SignInFragment

package com.google.android.ground.ui.signin

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.withId
import com.google.android.ground.BaseHiltTest
import com.google.android.ground.R
import com.google.android.ground.launchFragmentInHiltContainer
import com.google.android.ground.system.auth.SignInState
import com.sharedtest.FakeData
import com.sharedtest.system.auth.FakeAuthenticationManager
import dagger.hilt.android.testing.HiltAndroidTest
import javax.inject.Inject
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@HiltAndroidTest
@RunWith(RobolectricTestRunner::class)
class SignInFragmentTest : BaseHiltTest() {

  @Inject lateinit var fakeAuthenticationManager: FakeAuthenticationManager

  override fun setUp() {
    super.setUp()
    fakeAuthenticationManager.setState(SignInState.signedOut())
  }

  @Test
  fun buttonClick_shouldSignIn() {
    launchFragmentInHiltContainer<SignInFragment>()
    fakeAuthenticationManager.setUser(TEST_USER)

    onView(withId(R.id.sign_in_button)).perform(click())

    fakeAuthenticationManager.signInState
      .test()
      .assertValue(SignInState(SignInState.State.SIGNED_IN, Result.success(TEST_USER)))
  }

  companion object {
    private val TEST_USER = FakeData.USER
  }
}


/*
 * Copyright (c) 2018. Louis Cognault Ayeva Derman
 *
 * 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 splitties.viewdsl.recyclerview

import android.support.annotation.IdRes
import android.support.v7.widget.RecyclerView
import android.view.View

fun View.wrapInRecyclerView(
        horizontal: Boolean = false,
        @IdRes id: Int = View.NO_ID,
        initView: RecyclerView.() -> Unit
) = recyclerView(id) {
    val contentAdapter = SingleViewAdapter(this@wrapInRecyclerView, vertical = !horizontal)
    layoutManager = contentAdapter.layoutManager
    adapter = contentAdapter
}.apply(initView)

Make wrapInRecyclerView() lambda actually optional

/*
 * Copyright (c) 2018. Louis Cognault Ayeva Derman
 *
 * 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 splitties.viewdsl.recyclerview

import android.support.annotation.IdRes
import android.support.v7.widget.RecyclerView
import android.view.View

fun View.wrapInRecyclerView(
        horizontal: Boolean = false,
        @IdRes id: Int = View.NO_ID,
        initView: RecyclerView.() -> Unit = {}
) = recyclerView(id) {
    val contentAdapter = SingleViewAdapter(this@wrapInRecyclerView, vertical = !horizontal)
    layoutManager = contentAdapter.layoutManager
    adapter = contentAdapter
}.apply(initView)


package de.christinecoenen.code.zapp.models.shows

import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import org.joda.time.DateTime

@Entity(indices = [Index(value = ["apiId"], unique = true)])
data class PersistedMediathekShow(

	@PrimaryKey(autoGenerate = true)
	var id: Int = 0,

	var createdAt: DateTime = DateTime.now(),

	var downloadId: Int = 0,

	var downloadedAt: DateTime? = null,

	var downloadedVideoPath: String? = null,

	var downloadStatus: DownloadStatus = DownloadStatus.NONE,

	var downloadProgress: Int = 0,

	var lastPlayedBackAt: DateTime? = null,

	var playbackPosition: Long = 0,

	var videoDuration: Long = 0,

	@Embedded
	var mediathekShow: MediathekShow = MediathekShow()

) {

	val playBackPercent
		get() = playbackPosition.toFloat() / videoDuration

}

Fix NaN error in downloads tab

package de.christinecoenen.code.zapp.models.shows

import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import org.joda.time.DateTime

@Entity(indices = [Index(value = ["apiId"], unique = true)])
data class PersistedMediathekShow(

	@PrimaryKey(autoGenerate = true)
	var id: Int = 0,

	var createdAt: DateTime = DateTime.now(),

	var downloadId: Int = 0,

	var downloadedAt: DateTime? = null,

	var downloadedVideoPath: String? = null,

	var downloadStatus: DownloadStatus = DownloadStatus.NONE,

	var downloadProgress: Int = 0,

	var lastPlayedBackAt: DateTime? = null,

	var playbackPosition: Long = 0,

	var videoDuration: Long = 0,

	@Embedded
	var mediathekShow: MediathekShow = MediathekShow()

) {

	val playBackPercent
		get() = (playbackPosition.toFloat() / videoDuration).let { if (it.isNaN()) 0f else it }

}


buildscript {
    val kotlinVersion = "1.0.6"
    extra["kotlinVersion"] = kotlinVersion
    repositories {
        jcenter()
    }
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
    }
}

apply {
    plugin("idea")
    plugin("kotlin")
}

repositories {
    jcenter()
}

configure<JavaPluginConvention> {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
}

val kotlinVersion: String by extra
dependencies {
    compile(gradleApi())
    compile("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
    testCompile("junit:junit:4.12")
}

Add a task about Git operation

import org.eclipse.jgit.api.Git as JGit
import org.eclipse.jgit.storage.file.FileRepositoryBuilder

buildscript {
    val kotlinVersion = "1.0.6"
    extra["kotlinVersion"] = kotlinVersion
    repositories {
        jcenter()
    }
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
        classpath("org.eclipse.jgit:org.eclipse.jgit:4.6.0.201612231935-r")
    }
}

apply {
    plugin("idea")
    plugin("kotlin")
}

repositories {
    jcenter()
}

configure<JavaPluginConvention> {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
}

val kotlinVersion: String by extra
dependencies {
    compile(gradleApi())
    compile("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
    testCompile("junit:junit:4.12")
}

val git = Git(project)

/**
 * Remove 'repository' directory from Git
 */
task("removeRepository") {
    doLast {
        git.rm("repository")
        git.commit("repository", message = "Remove repository")
    }
}

class Git(project: Project) {
    val git = JGit(FileRepositoryBuilder()
            .readEnvironment()
            .findGitDir(project.rootProject.rootDir)
            .build()
    )

    fun add(vararg patterns: String) {
        val cmd = git.add()
        if (patterns.isEmpty()) {
            cmd.isUpdate = true
        } else {
            patterns.forEach { cmd.addFilepattern(it) }
        }
        cmd.call()
    }

    fun rm(vararg patterns: String, cached: Boolean = false) {
        val cmd = git.rm()
        cmd.setCached(cached)
        patterns.forEach { cmd.addFilepattern(it) }
        cmd.call()
    }

    fun commit(vararg paths: String, message: String = "Commit by Gradle") {
        val commit = git.commit()
        commit.message = message
        paths.forEach { commit.setOnly(it) }
        commit.call()
    }
}


object PluginVersions {
    val kotlin = "1.2.50"
    val ktlintPlugin = "4.1.0"
    val gradlePublishPlugin = "0.9.10"
    val androidPlugin = "3.1.2"
    val kotlinNativePlugin = "0.7"
    val semver = "1.0.0"
    val gradleWrapper = "4.7"
    val junit = "4.12"
}

Update kotlin native to 0.7.1 version.

object PluginVersions {
    val kotlin = "1.2.50"
    val ktlintPlugin = "4.1.0"
    val gradlePublishPlugin = "0.9.10"
    val androidPlugin = "3.1.2"
    val kotlinNativePlugin = "0.7.1"
    val semver = "1.0.0"
    val gradleWrapper = "4.7"
    val junit = "4.12"
}


package nl.dionsegijn.konfettidemo.widgets

import android.content.Context
import android.support.v4.view.ViewPager
import android.util.AttributeSet
import android.view.MotionEvent

/**
 * Created by dionsegijn on 5/23/17.
 */
class NonSwipeableViewPager : ViewPager {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return false
    }

}

Fix nullable context and use expression body

package nl.dionsegijn.konfettidemo.widgets

import android.content.Context
import android.support.v4.view.ViewPager
import android.util.AttributeSet
import android.view.MotionEvent

/**
 * Created by dionsegijn on 5/23/17.
 */
class NonSwipeableViewPager : ViewPager {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    override fun onTouchEvent(event: MotionEvent): Boolean = false

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean = false

}


package com.pr0gramm.app

import android.content.Context
import android.os.Build
import android.os.Debug
import android.os.StrictMode
import androidx.multidex.MultiDex
import com.pr0gramm.app.util.doInBackground
import kotlinx.coroutines.delay

class DebugApplicationClass : ApplicationClass() {
    init {
        StrictMode.enableDefaults()

        if (true) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                try {
                    // Debug.startMethodTracing(null, 128 * 1024 * 1024)
                    Debug.startMethodTracingSampling(null, 16 * 1024 * 1042, 500)

                    doInBackground {
                        delay(6000)
                        Debug.stopMethodTracing()
                    }
                } catch (err: Throwable) {
                    Logger("DebugApplicationClass").error(err) {
                        "Could not start method sampling during bootup."
                    }
                }
            }
        }
    }

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Allow tracing on earlier android versions.

package com.pr0gramm.app

import android.content.Context
import android.os.Build
import android.os.Debug
import android.os.StrictMode
import androidx.multidex.MultiDex
import com.pr0gramm.app.util.doInBackground
import kotlinx.coroutines.delay

class DebugApplicationClass : ApplicationClass() {
    init {
        StrictMode.enableDefaults()

        if (true) {
            if (Build.VERSION.SDK_INT >= 21) {
                try {
                    // Debug.startMethodTracing(null, 128 * 1024 * 1024)
                    Debug.startMethodTracingSampling(null, 16 * 1024 * 1042, 500)

                    doInBackground {
                        delay(6000)
                        Debug.stopMethodTracing()
                    }
                } catch (err: Throwable) {
                    Logger("DebugApplicationClass").error(err) {
                        "Could not start method sampling during bootup."
                    }
                }
            }
        }
    }

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}


//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras

package pythagoras.util

/**
 * Handles differences between the JDK and GWT platforms.
 */
object Platform {
    /**
     * Returns a hash code for the supplied float value.
     */
    fun hashCode(f1: Float): Int {
        return java.lang.Float.floatToIntBits(f1)
    }

    /**
     * Returns a hash code for the supplied double value.
     */
    fun hashCode(d1: Double): Int {
        val bits = java.lang.Double.doubleToLongBits(d1)
        return (bits xor bits.ushr(32)).toInt()
    }

    /**
     * Clones the supplied array of bytes.
     */
    fun clone(values: ByteArray): ByteArray {
        return values.clone()
    }

    /**
     * Clones the supplied array of ints.
     */
    fun clone(values: IntArray): IntArray {
        return values.clone()
    }

    /**
     * Clones the supplied array of floats.
     */
    fun clone(values: FloatArray): FloatArray {
        return values.clone()
    }

    /**
     * Clones the supplied array of doubles.
     */
    fun clone(values: DoubleArray): DoubleArray {
        return values.clone()
    }
}

Make pythagoras.util kotlin JS compatible

//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras

package pythagoras.util

/**
 * Handles differences between the JDK and GWT platforms.
 */
object Platform {
    /**
     * Returns a hash code for the supplied float value.
     */
    fun hashCode(f1: Float): Int {
        return f1.hashCode()
    }

    /**
     * Returns a hash code for the supplied double value.
     */
    fun hashCode(d1: Double): Int {
        return d1.hashCode()
    }

    /**
     * Clones the supplied array of bytes.
     */
    fun clone(values: ByteArray): ByteArray {
        return values.copyOf()
    }

    /**
     * Clones the supplied array of ints.
     */
    fun clone(values: IntArray): IntArray {
        return values.copyOf()
    }

    /**
     * Clones the supplied array of floats.
     */
    fun clone(values: FloatArray): FloatArray {
        return values.copyOf()
    }

    /**
     * Clones the supplied array of doubles.
     */
    fun clone(values: DoubleArray): DoubleArray {
        return values.copyOf()
    }
}


import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  kotlin("jvm").version("1.6.20")
  id("com.vanniktech.maven.publish") version ("0.19.0")
  id("com.github.ben-manes.versions") version "0.42.0"
}

repositories {
  mavenCentral()
}

buildscript {
  extra["kotlinVersion"] = "1.6.20"
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath(kotlin("gradle-plugin", version = rootProject.extra["kotlinVersion"] as String?))
    classpath("com.github.ben-manes:gradle-versions-plugin:0.42.0")
    classpath("com.vanniktech:gradle-maven-publish-plugin:0.19.0")
  }
}

dependencies {
  api("org.jsoup:jsoup:1.14.3")
  api("com.squareup.okhttp3:okhttp:4.9.3")
  implementation("org.apache.commons:commons-text:1.9")
  testImplementation("junit:junit:4.13.2")
}

configurations.all {
  // Re-run tests every time test cases are updated, even if sources haven’t changed.
  resolutionStrategy.cacheChangingModulesFor(0, "seconds")
}

tasks.jar {
  archiveBaseName.set("crux")
}

tasks.withType<KotlinCompile>().configureEach {
  kotlinOptions {
    allWarningsAsErrors = true
  }
}

Use consistent formatting with specifying the `version` in `plugins`.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  kotlin("jvm") version "1.6.20"
  id("com.vanniktech.maven.publish") version "0.19.0"
  id("com.github.ben-manes.versions") version "0.42.0"
}

repositories {
  mavenCentral()
}

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath(kotlin("gradle-plugin", version = "1.6.20"))
    classpath("com.github.ben-manes:gradle-versions-plugin:0.42.0")
    classpath("com.vanniktech:gradle-maven-publish-plugin:0.19.0")
  }
}

dependencies {
  api("org.jsoup:jsoup:1.14.3")
  api("com.squareup.okhttp3:okhttp:4.9.3")
  implementation("org.apache.commons:commons-text:1.9")
  testImplementation("junit:junit:4.13.2")
}

configurations.all {
  // Re-run tests every time test cases are updated, even if sources haven’t changed.
  resolutionStrategy.cacheChangingModulesFor(0, "seconds")
}

tasks.jar {
  archiveBaseName.set("crux")
}

tasks.withType<KotlinCompile>().configureEach {
  kotlinOptions {
    allWarningsAsErrors = true
  }
}


/*
 * A set of generic services and utilities.
 *
 * Should have a very small set of dependencies, and should be appropriate to embed in an external
 * application (eg as part of the tooling API).
 */

import java.util.concurrent.Callable

plugins {
    `java-library`
    id("classycle")
}

val javaVersion: JavaVersion by rootProject.extra
val generatedTestResourcesDir: File by extra
val buildReceiptPackage: String by rootProject.extra

java {
    sourceCompatibility = if (javaVersion.isJava9Compatible) JavaVersion.VERSION_1_6 else JavaVersion.VERSION_1_5
}

dependencies {
    compile(project(":distributionsDependencies"))

    api(library("guava"))
    api(library("jsr305"))
    api(library("fastutil"))

    implementation(library("slf4j_api"))
    implementation(library("commons_lang"))
    implementation(library("commons_io"))
    implementation(library("jcip"))

    jmh(library("bouncycastle_provider")) {
        version {
            prefer(libraries["bouncycastle_provider"]!!["version"])
        }
    }
}

testFixtures {
    from(":core")
}

val buildReceiptResource by tasks.creating(Copy::class) {
    from(Callable { tasks.getByPath(":createBuildReceipt").outputs.files })
    destinationDir = file("$generatedTestResourcesDir/$buildReceiptPackage")
}

java {
    sourceSets {
        "main" {
            output.dir(mapOf("builtBy" to buildReceiptResource), generatedTestResourcesDir)
        }
    }
}

Configure `jmh` extension dynamically via `withGroovyBuilder`

/*
 * A set of generic services and utilities.
 *
 * Should have a very small set of dependencies, and should be appropriate to embed in an external
 * application (eg as part of the tooling API).
 */

import java.util.concurrent.Callable

plugins {
    `java-library`
    id("classycle")
}

val javaVersion: JavaVersion by rootProject.extra
val generatedTestResourcesDir: File by extra
val buildReceiptPackage: String by rootProject.extra

java {
    sourceCompatibility = if (javaVersion.isJava9Compatible) JavaVersion.VERSION_1_6 else JavaVersion.VERSION_1_5
}

dependencies {
    compile(project(":distributionsDependencies"))

    api(library("guava"))
    api(library("jsr305"))
    api(library("fastutil"))

    implementation(library("slf4j_api"))
    implementation(library("commons_lang"))
    implementation(library("commons_io"))
    implementation(library("jcip"))

    jmh(library("bouncycastle_provider")) {
        version {
            prefer(libraries["bouncycastle_provider"]!!["version"])
        }
    }
}

testFixtures {
    from(":core")
}

jmh {
    withGroovyBuilder {
        setProperty("include", listOf("HashingAlgorithmsBenchmark"))
    }
}

val buildReceiptResource by tasks.creating(Copy::class) {
    from(Callable { tasks.getByPath(":createBuildReceipt").outputs.files })
    destinationDir = file("$generatedTestResourcesDir/$buildReceiptPackage")
}

java {
    sourceSets {
        "main" {
            output.dir(mapOf("builtBy" to buildReceiptResource), generatedTestResourcesDir)
        }
    }
}


/*
 * Copyright 2013-2018 Julien Guerinet
 *
 * 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.guerinet.sp

import kotlinx.serialization.Serializable

/**
 * One language that the Strings are in
 * @author Julien Guerinet
 * @since 2.0.0
 *
 * @param id            Language Id
 * @param path          Path to the file for the Strings in this language
 * @param columnIndex   Index of the column of this language in the CSV file (starts as -1)
 */
@Serializable
class Language(val id: String, val path: String, var columnIndex: Int = -1) {

    companion object {

        /** Dummy [Language]  object to use when we do not care about the language */
        val EMPTY = Language("en", "", 0)
    }
}

Remove need for columnIndex within the config file

/*
 * Copyright 2013-2018 Julien Guerinet
 *
 * 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.guerinet.sp

import kotlinx.serialization.Optional
import kotlinx.serialization.Serializable

/**
 * One language that the Strings are in
 * @author Julien Guerinet
 * @since 2.0.0
 *
 * @param id            Language Id
 * @param path          Path to the file for the Strings in this language
 * @param columnIndex   Index of the column of this language in the CSV file (starts as -1)
 */
@Serializable
class Language(val id: String, val path: String, @Optional var columnIndex: Int = -1) {

    companion object {

        /** Dummy [Language]  object to use when we do not care about the language */
        val EMPTY = Language("en", "", 0)
    }
}


object Ci {

   // this is the version used for building snapshots
   // .buildnumber-snapshot will be appended
   private const val snapshotBase = "4.7.0"

   private val githubBuildNumber = System.getenv("GITHUB_RUN_NUMBER")

   private val snapshotVersion = when (githubBuildNumber) {
      null -> "$snapshotBase-LOCAL"
      else -> "$snapshotBase.${githubBuildNumber}-SNAPSHOT"
   }

   private val releaseVersion = System.getenv("RELEASE_VERSION")

   val isRelease = releaseVersion != null
   val publishVersion = releaseVersion ?: snapshotVersion
}

Set snapshots to 5.0.0 base

object Ci {

   // this is the version used for building snapshots
   // .buildnumber-snapshot will be appended
   private const val snapshotBase = "5.0.0"

   private val githubBuildNumber = System.getenv("GITHUB_RUN_NUMBER")

   private val snapshotVersion = when (githubBuildNumber) {
      null -> "$snapshotBase-LOCAL"
      else -> "$snapshotBase.${githubBuildNumber}-SNAPSHOT"
   }

   private val releaseVersion = System.getenv("RELEASE_VERSION")

   val isRelease = releaseVersion != null
   val publishVersion = releaseVersion ?: snapshotVersion
}


/*
 * Copyright 2016 Nicolas Fränkel
 *
 * 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 ch.frankel.kaadin

import com.vaadin.server.*
import java.net.URI

fun page(init: Page.() -> Unit) = Page.getCurrent().apply(init)
fun location(uri: String) = page { setLocation(uri) }
fun location(uri: URI) = page { setLocation(uri) }
fun title(title: String) = page { setTitle(title) }
fun uriFragment(newUriFragment: String = "", fireEvents: Boolean = true) = page { setUriFragment(newUriFragment, fireEvents) }

Add function to get current UI and set theme

/*
 * Copyright 2016 Nicolas Fränkel
 *
 * 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 ch.frankel.kaadin

import com.vaadin.server.*
import com.vaadin.ui.*
import java.net.URI

fun page(init: Page.() -> Unit) = Page.getCurrent().apply(init)
fun location(uri: String) = page { setLocation(uri) }
fun location(uri: URI) = page { setLocation(uri) }
fun title(title: String) = page { setTitle(title) }
fun uriFragment(newUriFragment: String = "", fireEvents: Boolean = true) = page { setUriFragment(newUriFragment, fireEvents) }

fun ui(init: UI.() -> Unit) = UI.getCurrent().apply(init)
fun theme(theme: String) = ui { setTheme(theme) }


package org.jetbrains.ktor.routing

import org.jetbrains.ktor.http.*

class RoutingPath private constructor(val parts: List<RoutingPathSegment>) {
    companion object {
        val root: RoutingPath = RoutingPath(listOf())
        fun parse(path: String): RoutingPath {
            if (path == "/") return root
            val segments = path.splitToSequence("/").filter { it.length > 0 }.map { segment ->
                when {
                    segment.contains('{') && segment.contains('}') -> RoutingPathSegment(segment, RoutingPathSegmentKind.Parameter)
                    else -> RoutingPathSegment(decodeURLPart(segment), RoutingPathSegmentKind.Constant)
                }
            }

            return RoutingPath(segments.toList())
        }
    }

    override fun toString(): String = parts.map { it.value }.joinToString("/")
}

data class RoutingPathSegment(val value: String, val kind: RoutingPathSegmentKind)

enum class RoutingPathSegmentKind {
    Constant, Parameter
}

Replace size check with isNotEmpty

package org.jetbrains.ktor.routing

import org.jetbrains.ktor.http.decodeURLPart

class RoutingPath private constructor(val parts: List<RoutingPathSegment>) {
    companion object {
        val root: RoutingPath = RoutingPath(listOf())
        fun parse(path: String): RoutingPath {
            if (path == "/") return root
            val segments = path.splitToSequence("/").filter { it.isNotEmpty() }.map { segment ->
                when {
                    segment.contains('{') && segment.contains('}') -> RoutingPathSegment(segment, RoutingPathSegmentKind.Parameter)
                    else -> RoutingPathSegment(decodeURLPart(segment), RoutingPathSegmentKind.Constant)
                }
            }

            return RoutingPath(segments.toList())
        }
    }

    override fun toString(): String = parts.map { it.value }.joinToString("/")
}

data class RoutingPathSegment(val value: String, val kind: RoutingPathSegmentKind)

enum class RoutingPathSegmentKind {
    Constant, Parameter
}


package org.nwapw.abacus.function

/**
 * A data class used for storing information about a function.
 *
 * The Documentation class holds the information necessary to display the information
 * about a function to the user.
 *
 * @param codeName the name of the function as it occurs in code.
 * @param name the name of the function in English.
 * @param description the short description of this function.
 * @param longDescription the full description of this function.
 */
data class Documentation(val codeName: String, val name: String,
                         val description: String, val longDescription: String)


package nl.rubensten.texifyidea.run.evince

import com.intellij.execution.runners.ExecutionEnvironment
import nl.rubensten.texifyidea.TeXception
import nl.rubensten.texifyidea.psi.LatexEnvironment
import nl.rubensten.texifyidea.run.LatexRunConfiguration
import nl.rubensten.texifyidea.util.*
import org.jetbrains.concurrency.runAsync

/**
 * Provides forward search for Evince.
 */
class EvinceForwardSearch {

    /**
     * Execute forward search based on the given environment.
     */
    fun execute(runConfig: LatexRunConfiguration, environment: ExecutionEnvironment) {
        run {
            val psiFile = runConfig.mainFile.psiFile(environment.project) ?: return@run
            val document = psiFile.document() ?: return@run
            val editor = psiFile.openedEditor() ?: return@run

            if (document != editor.document) {
                return@run
            }

            // Do not do forward search when editing the preamble.
            if (psiFile.isRoot()) {
                val element = psiFile.findElementAt(editor.caretOffset()) ?: return@run
                val environment = element.parentOfType(LatexEnvironment::class) ?: return@run
                if (environment.name()?.text != "document") {
                    return@run
                }
            }

            val line = document.getLineNumber(editor.caretOffset()) + 1

            runAsync {
                try {
                    // This will start Evince if it is not running yet
                    EvinceConversation.forwardSearch(pdfFilePath = runConfig.outputFilePath, sourceFilePath = psiFile.virtualFile.path, line = line)
                } catch (ignored: TeXception) {
                }
            }
        }
    }
}

Remove check which does not do forward search in preamble because this is unnecessary (forward search works fine) and behaves incorrectly (at least in one case).

package nl.rubensten.texifyidea.run.evince

import com.intellij.execution.runners.ExecutionEnvironment
import nl.rubensten.texifyidea.TeXception
import nl.rubensten.texifyidea.psi.LatexEnvironment
import nl.rubensten.texifyidea.run.LatexRunConfiguration
import nl.rubensten.texifyidea.util.*
import org.jetbrains.concurrency.runAsync

/**
 * Provides forward search for Evince.
 */
class EvinceForwardSearch {

    /**
     * Execute forward search based on the given environment.
     */
    fun execute(runConfig: LatexRunConfiguration, environment: ExecutionEnvironment) {
        run {
            val psiFile = runConfig.mainFile.psiFile(environment.project) ?: return@run
            val document = psiFile.document() ?: return@run
            val editor = psiFile.openedEditor() ?: return@run

            if (document != editor.document) {
                return@run
            }

            val line = document.getLineNumber(editor.caretOffset()) + 1

            runAsync {
                try {
                    // This will start Evince if it is not running yet
                    EvinceConversation.forwardSearch(pdfFilePath = runConfig.outputFilePath, sourceFilePath = psiFile.virtualFile.path, line = line)
                } catch (ignored: TeXception) {
                }
            }
        }
    }
}


package com.beust.kobalt.maven

import com.beust.kobalt.misc.Strings
import java.io.File

/**
 * Represents a dependency that doesn't have a version: "org.testng:testng:". Such dependencies
 * eventually resolve to the latest version of the artifact.
 */
open public class UnversionedDep(open val groupId: String, open val artifactId: String) {
    open public fun toMetadataXmlPath(fileSystem: Boolean = true): String {
        return toDirectory("", fileSystem) + "maven-metadata.xml"
    }

    /**
     * Turn this dependency to a directory. If fileSystem is true, use the file system
     * dependent path separator, otherwise, use '/' (used to create URL's)
     */
    public fun toDirectory(v: String, fileSystem: Boolean = true): String {
        val sep = if (fileSystem) File.separator else "/"
        val l = listOf(groupId.replace(".", sep), artifactId, v)
        return Strings.Companion.join(sep, l)
    }
}

Fix snapshot id resolution bug.

package com.beust.kobalt.maven

import com.beust.kobalt.misc.Strings
import java.io.File

/**
 * Represents a dependency that doesn't have a version: "org.testng:testng:". Such dependencies
 * eventually resolve to the latest version of the artifact.
 */
open public class UnversionedDep(open val groupId: String, open val artifactId: String) {
    open public fun toMetadataXmlPath(fileSystem: Boolean = true): String {
        return toDirectory("", fileSystem) + "maven-metadata.xml"
    }

    /**
     * Turn this dependency to a directory. If fileSystem is true, use the file system
     * dependent path separator, otherwise, use '/' (used to create URL's)
     */
    public fun toDirectory(v: String, fileSystem: Boolean = true): String {
        val sep = if (fileSystem) File.separator else "/"
        val l = listOf(groupId.replace(".", sep), artifactId, v)
        return Strings.Companion.join(sep, l) + "/"
    }
}


/*
 * Copyright (C) 2020 Reece H. Dunn
 *
 * 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 uk.co.reecedunn.intellij.plugin.xquery.intellij.spellchecker

import com.intellij.psi.PsiElement
import com.intellij.spellchecker.tokenizer.SpellcheckingStrategy
import com.intellij.spellchecker.tokenizer.Tokenizer

object XQuerySpellcheckingStrategy : SpellcheckingStrategy() {
    override fun getTokenizer(element: PsiElement?): Tokenizer<*> {
        return super.getTokenizer(element)
    }
}

Use a class or the XQuery spellchecking strategy.

/*
 * Copyright (C) 2020 Reece H. Dunn
 *
 * 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 uk.co.reecedunn.intellij.plugin.xquery.intellij.spellchecker

import com.intellij.psi.PsiElement
import com.intellij.spellchecker.tokenizer.SpellcheckingStrategy
import com.intellij.spellchecker.tokenizer.Tokenizer

class XQuerySpellcheckingStrategy : SpellcheckingStrategy() {
    override fun getTokenizer(element: PsiElement?): Tokenizer<*> {
        return super.getTokenizer(element)
    }
}


package pink.madis.agptweeter.store

import com.google.common.truth.Truth.assertThat
import org.junit.Test
import pink.madis.agptweeter.moshi
import java.lang.IllegalStateException

private fun Store.readOnly() = object : Store {
  override fun read(key: String) = this@readOnly.read(key)

  override fun write(key: String, value: String) {
    throw IllegalStateException("Not supposed to write here")
  }
}

class MigrateTest {
  private val store = MemStore()

  @Test
  fun migrateEmpty() {
    migrate(store, moshi)

    assertThat(store.read("db_version")).isEqualTo("2")
    assertThat(store.read("db_keys")).isNotEmpty()
  }

  @Test
  fun migrateTwice() {
    migrate(store, moshi)
    // second migration is completely read-only - nothing to migrate
    migrate(store.readOnly(), moshi)
  }
}


// Copyright 2020 Google LLC
//
// 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 app.evergreen.services

import android.util.Log

fun log(tag: String, message: String) {
  Log.i(tag, message)
}

fun log(tag: String, e: Throwable) {
  if (e.message != null) {
    Log.e(tag, e.message!!)
  }
  e.printStackTrace()
}

Use Kotlin ?.let instead of null-checking.

// Copyright 2020 Google LLC
//
// 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 app.evergreen.services

import android.util.Log

fun log(tag: String, message: String) {
  Log.i(tag, message)
}

fun log(tag: String, e: Throwable) {
  e.message?.let { Log.e(tag, it) }
  e.printStackTrace()
}


package ee.email

import ee.design.gen.DesingKotlinGenerator
import ee.lang.integ.eePath

fun main(args: Array<String>) {
    val generator = DesingKotlinGenerator(model())
    generator.generate(eePath)
}

Improve deletion of src-gen folders

package ee.email

import ee.design.gen.DesignKotlinGenerator
import ee.lang.integ.eePath

fun main(args: Array<String>) {
    val generator = DesignKotlinGenerator(model())
    generator.generate(eePath)
}


/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.cargo.toolchain.wsl

import com.intellij.execution.wsl.WSLDistribution
import com.intellij.util.io.isFile
import java.nio.file.Path

const val WSL_TOOLCHAIN: String = "org.rust.wsl"

fun WSLDistribution.expandUserHome(path: String): String {
    if (!path.startsWith("~/")) return path
    val userHome = userHome ?: return path
    return "$userHome${path.substring(1)}"
}

fun Path.hasExecutableOnWsl(toolName: String): Boolean = pathToExecutableOnWsl(toolName).isFile()

fun Path.pathToExecutableOnWsl(toolName: String): Path = resolve(toolName)

Fix toolchain validation on WSL

/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.cargo.toolchain.wsl

import com.intellij.execution.wsl.WSLDistribution
import java.nio.file.Path

const val WSL_TOOLCHAIN: String = "org.rust.wsl"

fun WSLDistribution.expandUserHome(path: String): String {
    if (!path.startsWith("~/")) return path
    val userHome = userHome ?: return path
    return "$userHome${path.substring(1)}"
}

fun Path.hasExecutableOnWsl(toolName: String): Boolean = pathToExecutableOnWsl(toolName).toFile().isFile

fun Path.pathToExecutableOnWsl(toolName: String): Path = resolve(toolName)


package org.purescript.psi

import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.util.collectDescendantsOfType
import javax.swing.Icon

class PSValueDeclaration(node: ASTNode) : PSPsiElement(node),
    PsiNameIdentifierOwner {
    override fun getName(): String {
        return findChildByClass(PSIdentifierImpl::class.java)!!
            .name
    }

    override fun getPresentation(): ItemPresentation {
        val name = this.name
        val fileName = this.containingFile.name
        return object : ItemPresentation {
            override fun getPresentableText(): String {
                return name
            }

            override fun getLocationString(): String {
                return fileName
            }

            override fun getIcon(unused: Boolean): Icon? {
                return null
            }
        }
    }

    override fun setName(name: String): PsiElement? {
        return null
    }

    override fun getNameIdentifier(): PsiElement? {
        return findChildByClass(PSIdentifierImpl::class.java)
    }

    val varBindersInParameters: Map<String, PSVarBinderImpl>
        get() {
            return collectDescendantsOfType<PSVarBinderImpl>()
                .asSequence()
                .filterNotNull()
                .map { Pair(it.name, it) }
                .toMap()
        }
}

Add parameters to presentable text of value declaration

package org.purescript.psi

import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.util.collectDescendantsOfType
import javax.swing.Icon

class PSValueDeclaration(node: ASTNode) : PSPsiElement(node),
    PsiNameIdentifierOwner {
    override fun getName(): String {
        return findChildByClass(PSIdentifierImpl::class.java)!!
            .name
    }

    override fun getPresentation(): ItemPresentation {
        val name = this.name
        val parameters = findChildrenByClass(PSBinderImpl::class.java)
        val parameterList = parameters
            .asSequence()
            .map { it.text.trim() }
            .joinToString(" ")
        val presentableText = "$name $parameterList"
        val fileName = this.containingFile.name
        return object : ItemPresentation {
            override fun getPresentableText(): String {
                return presentableText
            }

            override fun getLocationString(): String {
                return fileName
            }

            override fun getIcon(unused: Boolean): Icon? {
                return null
            }
        }
    }

    override fun setName(name: String): PsiElement? {
        return null
    }

    override fun getNameIdentifier(): PsiElement? {
        return findChildByClass(PSIdentifierImpl::class.java)
    }

    val varBindersInParameters: Map<String, PSVarBinderImpl>
        get() {
            return collectDescendantsOfType<PSVarBinderImpl>()
                .asSequence()
                .filterNotNull()
                .map { Pair(it.name, it) }
                .toMap()
        }
}


Add Configuration and Bean for Braintree Payments

package backend.configuration

import backend.services.ConfigurationService
import com.braintreegateway.BraintreeGateway
import com.braintreegateway.Environment
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
open class BraintreeConfiguration {

    private val configurationService: ConfigurationService
    private val environment: String
    private val merchantID: String
    private val publicKey: String
    private val privateKey: String

    @Autowired
    constructor(configurationService: ConfigurationService) {
        this.configurationService = configurationService
        this.environment = configurationService.get("org.breakout.payment.braintree.environment") ?: "sandbox"
        this.merchantID = configurationService.getRequired("org.breakout.payment.braintree.merchantid")
        this.publicKey = configurationService.getRequired("org.breakout.payment.braintree.publickey")
        this.privateKey = configurationService.getRequired("org.breakout.payment.braintree.privatekey")
    }

    @Bean
    open fun BraintreeGateway(): BraintreeGateway {
        val env = Environment.parseEnvironment(environment)
        return com.braintreegateway.BraintreeGateway(env, merchantID, publicKey, privateKey)
    }
}


package net.expandable.sample

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Toast
import net.expandable.ExpandableTextView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView = findViewById(R.id.text) as ExpandableTextView
        textView.text = getString(R.string.long_text)
        textView.setCollapseLines(2)
        textView.setOnExpandableClickListener(
                onExpand = { showToast("Expand") },
                onCollapse = { showToast("Collapse") }
        )
    }

    private fun showToast(text: String) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
    }
}

Convert cast to findViewById with type parameter

package net.expandable.sample

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Toast
import net.expandable.ExpandableTextView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView = findViewById<ExpandableTextView>(R.id.text)
        textView.text = getString(R.string.long_text)
        textView.setCollapseLines(2)
        textView.setOnExpandableClickListener(
                onExpand = { showToast("Expand") },
                onCollapse = { showToast("Collapse") }
        )
    }

    private fun showToast(text: String) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
    }
}


package org.javacs.kt

import java.nio.file.Path

// TODO: Read exclusions from gitignore/settings.json/... instead of
// hardcoding them
class SourceExclusions(private val workspaceRoots: Collection<Path>) {
	private val excludedFolders = listOf("bin", "build", "target")

	constructor(workspaceRoot: Path) : this(listOf(workspaceRoot)) {}

    fun isIncluded(file: Path) =
        excludedFolders.none {
            workspaceRoots.map { it.relativize(file) }
                .flatMap { it } // Extract path segments
                .any { segment -> segment.toString() == it }
        }
}

Add node_modules to source exclusions

package org.javacs.kt

import java.nio.file.Path

// TODO: Read exclusions from gitignore/settings.json/... instead of
// hardcoding them
class SourceExclusions(private val workspaceRoots: Collection<Path>) {
	private val excludedFolders = listOf("bin", "build", "target", "node_modules")

	constructor(workspaceRoot: Path) : this(listOf(workspaceRoot)) {}

    fun isIncluded(file: Path) =
        excludedFolders.none {
            workspaceRoots.map { it.relativize(file) }
                .flatMap { it } // Extract path segments
                .any { segment -> segment.toString() == it }
        }
}