package khronos

import org.junit.Assert
import java.util.*

fun assertEquals(expected: Date, actual: Date) {
    Assert.assertEquals(expected.toString(), actual.toString())
}

fun assertEquals(expected: Duration, actual: Duration) {
    Assert.assertEquals(expected, actual)
}

Make assertEquals as precise as Date (precise to milliseconds)

package khronos

import org.junit.Assert
import java.text.SimpleDateFormat
import java.util.*

internal val iso8601: SimpleDateFormat by lazy {
    SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")
}

fun assertEquals(expected: Date, actual: Date) {
    Assert.assertEquals(iso8601.format(expected), iso8601.format(actual))
}

fun assertEquals(expected: Duration, actual: Duration) {
    Assert.assertEquals(expected, actual)
}


Move Notification Settings into a dedicated wrapper class

// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.notification.impl.ui

import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationGroup.Companion.getGroupTitle
import com.intellij.notification.impl.NotificationSettings
import com.intellij.notification.impl.NotificationsConfigurationImpl

/**
 * @author Konstantin Bulenkov
 */
class NotificationSettingsWrapper internal constructor(var version: NotificationSettings) {
  var isRemoved = false
  var title: String? = null
  fun hasChanged(): Boolean {
    return isRemoved || originalSettings != version
  }

  //todo[kb]: reconsider and remove this functionality
  fun remove() {
    isRemoved = true
  }

  val originalSettings: NotificationSettings
    get() = NotificationsConfigurationImpl.getSettings(groupId)

  fun apply() {
    if (isRemoved) {
      NotificationsConfigurationImpl.remove(groupId)
    }
    else {
      NotificationsConfigurationImpl.getInstanceImpl().changeSettings(version)
    }
  }

  fun reset() {
    version = originalSettings
    isRemoved = false
  }

  val groupId: String
    get() = version.groupId

  override fun toString(): String {
    if (title == null) {
      val groupId = groupId
      val title = getGroupTitle(groupId)
      return title ?: groupId
    }
    return title!!
  }

  var isShouldLog: Boolean
    get() = version.isShouldLog
    set(shouldLog) {
      version = version.withShouldLog(shouldLog)
    }

  var isShouldReadAloud: Boolean
    get() = version.isShouldReadAloud
    set(readAloud) {
      version = version.withShouldReadAloud(readAloud)
    }

  var displayType: NotificationDisplayType?
    get() = version.displayType
    set(type) {
      version = version.withDisplayType(type)
    }

}


/*
 *     Charlatano: Free and open-source (FOSS) cheat for CS:GO/CS:CO
 *     Copyright (C) 2017 - Thomas G. P. Nappo, Jonathan Beaudoin
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.charlatano.utils

import com.charlatano.utils.natives.CUser32

private const val MOUSEEVENTF_MOVE = 0x0001

fun mouseMove(dx: Int, dy: Int) = CUser32.mouse_event(MOUSEEVENTF_MOVE, dx, dy, 0, 0)

Allow `dwFlags` arg for `mouseMove`

/*
 *     Charlatano: Free and open-source (FOSS) cheat for CS:GO/CS:CO
 *     Copyright (C) 2017 - Thomas G. P. Nappo, Jonathan Beaudoin
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.charlatano.utils

import com.charlatano.utils.natives.CUser32

const val MOUSEEVENTF_MOVE = 0x0001

fun mouseMove(dx: Int, dy: Int, dwFlags: Int = MOUSEEVENTF_MOVE) = CUser32.mouse_event(dwFlags, dx, dy, 0, 0)


package me.echeung.moemoekyun.cast

import android.content.Context
import android.view.Menu

/**
 * No-op versions of functions used in Play Store version for Google Cast support
 */
class CastDelegate(
    context: Context,
    radioViewModel: RadioViewModel,
    stream: Stream,
    socket: Socket
) {

    fun onDestroy() {
    }

    fun initCastButton(menu: Menu?) {
    }
}

Hide cast button in F-Droid builds

package me.echeung.moemoekyun.cast

import android.content.Context
import android.view.Menu
import me.echeung.moemoekyun.R
import me.echeung.moemoekyun.client.api.socket.Socket
import me.echeung.moemoekyun.client.stream.Stream
import me.echeung.moemoekyun.viewmodel.RadioViewModel

/**
 * No-op versions of functions used in Play Store version for Google Cast support
 */
class CastDelegate(
    context: Context,
    radioViewModel: RadioViewModel,
    stream: Stream,
    socket: Socket
) {

    fun onDestroy() {
    }

    fun initCastButton(menu: Menu?) {
        menu?.findItem(R.id.media_route_menu_item)?.isVisible = false
    }
}


package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val isTravis = "TRAVIS" in System.getenv()
    val isJenkins = "JENKINS_HOME" in System.getenv()
    val gradleKotlinDslVersion = "1.1.1"
    val kotlinVersion = "1.3.11"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}

Upgrade Kotlin DSL to 1.1.2

package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val isTravis = "TRAVIS" in System.getenv()
    val isJenkins = "JENKINS_HOME" in System.getenv()
    val gradleKotlinDslVersion = "1.1.2"
    val kotlinVersion = "1.3.11"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}


package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val gradleKotlinDslVersion = "1.0-rc-9"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}

Upgrade Kotlin DSL to 1.0-rc-10

package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val gradleKotlinDslVersion = "1.0-rc-10"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}


/*
 * IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
 * Copyright (C) 2003-2019 The IdeaVim authors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package org.jetbrains.plugins.ideavim.action

import org.jetbrains.plugins.ideavim.VimTestCase
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
import org.junit.Test

class RepeatActionTest : VimTestCase() {

    @Test
    fun testSimpleRepeatLastCommand() {
        configureByText("foo foo")
        typeText(parseKeys("cw", "bar", "<Esc>", "w", "."))
        myFixture.checkResult("bar bar")
    }

    @Test
    fun testRepeatChangeToCharInNextLine() {
        configureByText("The first line.\n" +
                "This is the second line.\n" +
                "Third line here, with a comma.\n" +
                "Last line.")
        typeText(parseKeys("j", "ct.", "Change the line to point", "<Esc>", "j0", "."))
        myFixture.checkResult("The first line.\n" +
                "Change the line to point.\n" +
                "Change the line to point.\n" +
                "Last line.")
    }

}


plugins {
    id("myproject.java-library-conventions")
}

// tag::dependencies[]
dependencies {
    implementation(project(":lib"))
}
// end::dependencies[]

// tag::substitution_rule[]
configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute(platform(module("com.google.guava:guava:28.2-jre")))
            .using(module("com.google.guava:guava:28.2-jre"))
    }
}
// end::substitution_rule[]

// tag::substitution_rule_alternative[]
configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute(variant(module("com.google.guava:guava:28.2-jre")) {
            attributes {
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.REGULAR_PLATFORM))
            }
        }).using(module("com.google.guava:guava:28.2-jre"))
    }
}
// end::substitution_rule_alternative[]

tasks.register("resolve") {
    val classpath: Provider<out FileCollection> = configurations.runtimeClasspath
    inputs.files(classpath)
    doLast {
        println(classpath.get().files.map { it.name })
    }
}

Align Kotlin snippet with the Groovy version

plugins {
    id("myproject.java-library-conventions")
}

// tag::dependencies[]
dependencies {
    implementation(project(":lib"))
}
// end::dependencies[]

// tag::substitution_rule[]
configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute(platform(module("com.google.guava:guava:28.2-jre")))
            .using(module("com.google.guava:guava:28.2-jre"))
    }
}
// end::substitution_rule[]

// tag::substitution_rule_alternative[]
configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute(variant(module("com.google.guava:guava:28.2-jre")) {
            attributes {
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.REGULAR_PLATFORM))
            }
        }).using(module("com.google.guava:guava:28.2-jre"))
    }
}
// end::substitution_rule_alternative[]

tasks.register("resolve") {
    val classpath: FileCollection = configurations.runtimeClasspath.get()
    inputs.files(classpath)
    doLast {
        println(classpath.files.map { it.name })
    }
}


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

buildscript {
    repositories { gradleScriptKotlin() }
    dependencies { classpath(kotlinModule("gradle-plugin")) }
}

allprojects {

    group = "org.gradle.script.kotlin.samples.multiprojectci"

    version = "1.0"

    configure(listOf(repositories, buildscript.repositories)) {
        gradleScriptKotlin()
    }
}

// Configure all KotlinCompile tasks on each sub-project
subprojects {
    tasks.withType<KotlinCompile> {
        println("Configuring ${name} in project ${project.name}...")
        kotlinOptions.suppressWarnings = true
    }
}

apply {
    plugin("base")
}

dependencies {
    // Make the root project archives configuration depend on every subproject
    subprojects.forEach {
        archives(it)
    }
}

Revert sample to block structure

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

buildscript {
    repositories { gradleScriptKotlin() }
    dependencies { classpath(kotlinModule("gradle-plugin")) }
}

allprojects {

    group = "org.gradle.script.kotlin.samples.multiprojectci"

    version = "1.0"

    configure(listOf(repositories, buildscript.repositories)) {
        gradleScriptKotlin()
    }
}

// Configure all KotlinCompile tasks on each sub-project
subprojects {
    tasks.withType<KotlinCompile> {
        println("Configuring ${name} in project ${project.name}...")
        kotlinOptions {
            suppressWarnings = true
        }
    }
}

apply {
    plugin("base")
}

dependencies {
    // Make the root project archives configuration depend on every subproject
    subprojects.forEach {
        archives(it)
    }
}


package net.squanchy.schedule.domain.view

import net.squanchy.support.system.CurrentTime
import org.joda.time.DateTimeZone

private const val NOT_FOUND_INDEX = -1
private const val FIRST_PAGE_INDEX = 0

data class Schedule(val pages: List<SchedulePage>, val timezone: DateTimeZone) {

    val isEmpty: Boolean
        get() = pages.isEmpty()

    companion object {

        fun create(pages: List<SchedulePage>, timezone: DateTimeZone) = Schedule(pages, timezone)
    }

    fun findTodayIndexOrDefault(currentTime: CurrentTime) =
        pages
            .indexOfFirst { page ->
                val now = currentTime.currentDateTime().toDateTime(timezone)
                page.date.toLocalDate().isEqual(now.toLocalDate())
            }
            .let {
                when (it) {
                    NOT_FOUND_INDEX -> FIRST_PAGE_INDEX
                    else -> it
                }
            }

    fun findNextEventForPage(page: SchedulePage, currentTime: CurrentTime) =
        page
            .events
            .firstOrNull { event ->
                val startDateTime = event.startTime.toDateTime().withZone(event.timeZone)
                val currentDateTime = currentTime.currentDateTime().toDateTime().withZone(event.timeZone)
                startDateTime.isAfter(currentDateTime)
            }
}

Change scrolling to next event logic

package net.squanchy.schedule.domain.view

import net.squanchy.support.system.CurrentTime
import org.joda.time.DateTimeZone

private const val NOT_FOUND_INDEX = -1
private const val FIRST_PAGE_INDEX = 0

private const val CURRENT_SLOT_THRESHOLD = .6f

data class Schedule(val pages: List<SchedulePage>, val timezone: DateTimeZone) {

    val isEmpty: Boolean
        get() = pages.isEmpty()

    companion object {

        fun create(pages: List<SchedulePage>, timezone: DateTimeZone) = Schedule(pages, timezone)
    }

    fun findTodayIndexOrDefault(currentTime: CurrentTime) =
        pages
            .indexOfFirst { page ->
                val now = currentTime.currentDateTime().toDateTime(timezone)
                page.date.toLocalDate().isEqual(now.toLocalDate())
            }
            .let {
                when (it) {
                    NOT_FOUND_INDEX -> FIRST_PAGE_INDEX
                    else -> it
                }
            }

    fun findNextEventForPage(page: SchedulePage, currentTime: CurrentTime) =
        page.events
            .firstOrNull { event ->
                val startDateTime = event.startTime.toDateTime().withZone(event.timeZone)
                val currentDateTime = currentTime.currentDateTime().toDateTime().withZone(event.timeZone)
                val endDateTime = event.endTime.toDateTime().withZone(event.timeZone)

                if (currentDateTime.isAfter(endDateTime)) {
                    false
                } else {
                    val duration = endDateTime.millis - startDateTime.millis
                    val offset = currentDateTime.millis - startDateTime.millis

                    offset.toFloat() / duration < CURRENT_SLOT_THRESHOLD
                }
            }
}


/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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 androidx.build.metalava

import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.Input

/** Base class for invoking Metalava. */
abstract class MetalavaTask : DefaultTask() {
    /** Configuration containing Metalava and its dependencies. */
    @get:Input
    var configuration: Configuration? = null

    protected fun runWithArgs(vararg args: String) {
        project.javaexec {
            it.classpath = checkNotNull(configuration) { "Configuration not set." }
            it.main = "com.android.tools.metalava.Driver"
            it.args = args.toList()
        }
    }
}

Annotate metalava's classpath as such for Gradle

/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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 androidx.build.metalava

import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.Classpath

/** Base class for invoking Metalava. */
abstract class MetalavaTask : DefaultTask() {
    /** Configuration containing Metalava and its dependencies. */
    @get:Classpath
    var configuration: Configuration? = null

    protected fun runWithArgs(vararg args: String) {
        project.javaexec {
            it.classpath = checkNotNull(configuration) { "Configuration not set." }
            it.main = "com.android.tools.metalava.Driver"
            it.args = args.toList()
        }
    }
}


package com.marverenic.reader.ui.login

import android.content.Context
import android.databinding.BaseObservable
import android.net.Uri
import android.support.customtabs.CustomTabsIntent
import com.marverenic.reader.R
import com.marverenic.reader.data.AuthenticationManager
import com.marverenic.reader.utils.resolveIntAttr

class LoginViewModel(
        private val context: Context,
        private val authManager: AuthenticationManager
) : BaseObservable() {

    fun onClickLogin() {
        val intent = CustomTabsIntent.Builder()
                .addDefaultShareMenuItem()
                .setToolbarColor(context.resolveIntAttr(R.attr.colorPrimary))
                .enableUrlBarHiding()
                .build()

        intent.launchUrl(context, Uri.parse(authManager.loginUrl))
    }

}

Remove share menu for login page

package com.marverenic.reader.ui.login

import android.content.Context
import android.databinding.BaseObservable
import android.net.Uri
import android.support.customtabs.CustomTabsIntent
import com.marverenic.reader.R
import com.marverenic.reader.data.AuthenticationManager
import com.marverenic.reader.utils.resolveIntAttr

class LoginViewModel(
        private val context: Context,
        private val authManager: AuthenticationManager
) : BaseObservable() {

    fun onClickLogin() {
        val intent = CustomTabsIntent.Builder()
                .setToolbarColor(context.resolveIntAttr(R.attr.colorPrimary))
                .build()

        intent.launchUrl(context, Uri.parse(authManager.loginUrl))
    }

}


package pl.droidsonroids.droidsmap

import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.whenever
import org.junit.Before
import org.junit.Test
import pl.droidsonroids.droidsmap.feature.office.business_logic.OfficeEntity
import pl.droidsonroids.droidsmap.feature.office.business_logic.OfficeFeatureBoundary
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficeMvpView
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficePresenter
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficeUiModel

class OfficePresenterTest {

    lateinit var officeView : OfficeMvpView
    lateinit var officeBoundary : OfficeFeatureBoundary
    lateinit var presenter: OfficePresenter

    @Before
    fun setUp() {
        officeView = mock<OfficeMvpView>()
        officeBoundary = mock<OfficeFeatureBoundary>()
        presenter = OfficePresenter.create(officeView, officeBoundary)
    }

    @Test
    fun `should show map once data is provided`() {
        val officeEntity = OfficeEntity()
        whenever(officeBoundary.requestOffice(any())).thenAnswer {
            (it.arguments[0] as OfficeFeatureBoundary.Gateway).onOfficeEntityAvailable(officeEntity)
        }

        presenter.onRequestOffice()
        verify(officeView).displayOfficeRooms(OfficeUiModel.from(officeEntity))
    }
}

Test office view methods invocation order

package pl.droidsonroids.droidsmap

import com.nhaarman.mockito_kotlin.*
import org.junit.Before
import org.junit.Test
import pl.droidsonroids.droidsmap.feature.office.business_logic.OfficeEntity
import pl.droidsonroids.droidsmap.feature.office.business_logic.OfficeFeatureBoundary
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficeMvpView
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficePresenter
import pl.droidsonroids.droidsmap.feature.office.mvp.OfficeUiModel

class OfficePresenterTest {

    lateinit var officeView : OfficeMvpView
    lateinit var officeBoundary : OfficeFeatureBoundary
    lateinit var presenter: OfficePresenter

    @Before
    fun setUp() {
        officeView = mock<OfficeMvpView>()
        officeBoundary = mock<OfficeFeatureBoundary>()
        presenter = OfficePresenter.create(officeView, officeBoundary)
    }

    @Test
    fun `should show map once data is provided`() {
        val officeEntity = OfficeEntity()
        whenever(officeBoundary.requestOffice(any())).thenAnswer {
            (it.arguments[0] as OfficeFeatureBoundary.Gateway).onOfficeEntityAvailable(officeEntity)
        }

        presenter.onRequestOffice()
        with(OfficeUiModel.from(officeEntity)) {
            inOrder(officeView) {
                verify(officeView).setMapPanningConstraints(this@with)
                verify(officeView).focusMapOnOfficeLocation(this@with)
                verify(officeView).displayOfficeRooms(this@with)
            }
        }
    }
}


rootProject.name = "bean-validators"

plugins {
    id("com.gradle.enterprise") version "3.1.1"
}

gradleEnterprise {
    buildScan {
        val isCi = !System.getenv("GITHUB_WORKFLOW").isNullOrEmpty()
        if(isCi || file("gradle/.build-scans-tos-agree").exists()) {
            termsOfServiceUrl = "https://gradle.com/terms-of-service"
            termsOfServiceAgree = "yes"
            publishAlways()
            tag(System.getProperty("os.name"))
            tag(if (isCi) "CI" else "LOCAL")
            val repo = System.getenv("GITHUB_REPOSITORY")
            val runId = System.getenv("GITHUB_RUN_ID")
            if (!repo.isNullOrEmpty() && !runId.isNullOrBlank()) {
                link("GitHub Actions run", "https://github.com/$repo/actions/runs/$runId")
            }
        }
    }
}

Update to Gradle Enterprise plugin 3.2.1

rootProject.name = "bean-validators"

plugins {
    id("com.gradle.enterprise") version "3.2.1"
}

gradleEnterprise {
    buildScan {
        val isCi = !System.getenv("GITHUB_WORKFLOW").isNullOrEmpty()
        if(isCi || file("gradle/.build-scans-tos-agree").exists()) {
            termsOfServiceUrl = "https://gradle.com/terms-of-service"
            termsOfServiceAgree = "yes"
            publishAlways()
            tag(System.getProperty("os.name"))
            tag(if (isCi) "CI" else "LOCAL")
            val repo = System.getenv("GITHUB_REPOSITORY")
            val runId = System.getenv("GITHUB_RUN_ID")
            if (!repo.isNullOrEmpty() && !runId.isNullOrBlank()) {
                link("GitHub Actions run", "https://github.com/$repo/actions/runs/$runId")
            }
        }
    }
}


Add data structures for resolved KTX elements

package org.jetbrains.kotlin.r4a.ast

import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtxElement
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType

class AttributeNode(
    val name: String,
    val isStatic: Boolean,
    val expression: KtExpression,
    val type: KotlinType,
    val descriptor: DeclarationDescriptor
)

enum class ValidationType {
    CHANGED,
    SET,
    UPDATE
}

class ValidationNode(
    val validationType: ValidationType,
    val resolvedCall: ResolvedCall<*>,
    val attribute: AttributeNode,
    val assignment: ResolvedCall<*>
)

class StaticAssignment(
    val resolvedCall: ResolvedCall<*>,
    val attribute: AttributeNode
)

class ComposerCallNode(
    val pivotals: List<AttributeNode>,
    val joinKeyCall: ResolvedCall<*>,
    val ctorCall: ResolvedCall<*>?,
    val ctorParams: List<AttributeNode>,
    val staticAssignments: List<StaticAssignment>,
    val validations: List<ValidationNode>
)

sealed class RecursiveCallNode

class CallNode(
    val resolvedCall: ResolvedCall<*>,
    val params: List<AttributeNode>
): RecursiveCallNode()

class MemoizedCallNode(
    val memoize: ComposerCallNode?,
    val call: RecursiveCallNode
): RecursiveCallNode()

class EmitCallNode(
    val memoize: ComposerCallNode
)

class ResolvedKtxElementCall(
    val attributes: List<AttributeNode>,
    val emit: EmitCallNode?,
    val call: RecursiveCallNode?
)


Add a test for grouping by "usage type" in the Find window

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

package org.rust.ide.search

import com.intellij.usages.UsageViewSettings
import com.intellij.util.xmlb.XmlSerializerUtil
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
import org.rust.lang.core.psi.ext.RsNamedElement

class RsUsageViewTreeTest : RsTestBase() {

    fun `test grouping function usages`() = doTestByText("""
        fn foo() {}
          //^

        fn bar() {
            foo();
        }

        fn baz() {
            foo();
        }
    """, """
        Usage (2 usages)
         Function
          foo
         Found usages (2 usages)
          function call (2 usages)
           main.rs (2 usages)
            6foo();
            10foo();
    """)

    fun `test grouping struct usages`() = doTestByText("""
        struct S {
             //^
            a: usize,
        }

        impl S {}
        impl S {}

        fn foo(s1: &S) {}

        fn bar() {
            let s1 = S { a: 1 };
            let a = 1;
            let s2 = S { a };
        }
    """, """
        Usage (5 usages)
         Struct
          S
         Found usages (5 usages)
          impl (2 usages)
           main.rs (2 usages)
            7impl S {}
            8impl S {}
          init struct (2 usages)
           main.rs (2 usages)
            13let s1 = S { a: 1 };
            15let s2 = S { a };
          type reference (1 usage)
           main.rs (1 usage)
            10fn foo(s1: &S) {}
    """)

    private fun doTestByText(@Language("Rust") code: String, representation: String) {
        InlineFile(code)
        val source = findElementInEditor<RsNamedElement>()

        val textRepresentation = myFixture.getUsageViewTreeTextRepresentation(source)
        assertEquals(representation.trimIndent(), textRepresentation.trimIndent())
    }

    private val originalSettings = UsageViewSettings()
    override fun setUp() {
        super.setUp()
        val settings = UsageViewSettings.instance
        XmlSerializerUtil.copyBean(settings.state, originalSettings)

        settings.isGroupByFileStructure = false
        settings.isGroupByModule = false
        settings.isGroupByPackage = false
        settings.isGroupByUsageType = true
        settings.isGroupByScope = false
    }

    override fun tearDown() {
        UsageViewSettings.instance.loadState(originalSettings)
        super.tearDown()
    }
}


package org.jetbrains.ktor.netty

import io.netty.channel.*
import io.netty.handler.codec.http.*
import io.netty.util.*
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.future.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.host.*

@ChannelHandler.Sharable
class NettyHostHttp1Handler(private val host: NettyApplicationHost, private val hostPipeline: HostPipeline) : SimpleChannelInboundHandler<Any>(false) {

    override fun channelRead0(context: ChannelHandlerContext, message: Any) {
        when (message) {
            is HttpRequest -> {
                context.channel().config().isAutoRead = false
                val httpContentQueue = HttpContentQueue(context)
                context.pipeline().addLast(httpContentQueue)

                if (message is HttpContent) {
                    httpContentQueue.queue.push(message, message is LastHttpContent)
                }

                ReferenceCountUtil.retain(message)
                val call = NettyApplicationCall(host.application, context, message, httpContentQueue.queue)
                executeCall(call)
            }
            else -> context.fireChannelRead(message)
        }
    }

    private fun executeCall(call: ApplicationCall) {
        future(host.callDispatcher) {
            hostPipeline.execute(call)
        }
    }
}

Fix hanging of content queue for TLS connections that doesn't automatically read first content.

package org.jetbrains.ktor.netty

import io.netty.channel.*
import io.netty.handler.codec.http.*
import io.netty.util.*
import kotlinx.coroutines.experimental.future.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.host.*

@ChannelHandler.Sharable
class NettyHostHttp1Handler(private val host: NettyApplicationHost, private val hostPipeline: HostPipeline) : SimpleChannelInboundHandler<Any>(false) {

    override fun channelRead0(context: ChannelHandlerContext, message: Any) {
        when (message) {
            is HttpRequest -> {
                context.channel().config().isAutoRead = false
                val httpContentQueue = HttpContentQueue(context)
                context.pipeline().addLast(httpContentQueue)
                context.read() // request first content to be fetched into queue

                if (message is HttpContent) {
                    httpContentQueue.queue.push(message, message is LastHttpContent)
                }

                ReferenceCountUtil.retain(message)
                val call = NettyApplicationCall(host.application, context, message, httpContentQueue.queue)
                executeCall(call)
            }
            else -> context.fireChannelRead(message)
        }
    }

    private fun executeCall(call: ApplicationCall) {
        future(host.callDispatcher) {
            hostPipeline.execute(call)
        }
    }
}


package se.ansman.kotshi

@JsonSerializable
data class ClassWithBoundGeneric<out Data>(val data: List<Data>)

Add an additional test case

package se.ansman.kotshi

@JsonSerializable
data class ClassWithBoundGeneric<out Data>(val data: List<Data>)

@JsonSerializable
data class ParameterizedModel<out Data>(val data: Data)

@JsonSerializable
data class TripleParameterizedModel<out Data, out T : CharSequence, out E : Any>(
        val e: E,
        val data: Data,
        val t: T
)

@JsonSerializable
data class TypeCeption<out D : Any>(
        val tpm: TripleParameterizedModel<ParameterizedModel<IntArray>, String, D>,
        val pm: ParameterizedModel<List<D>>
)


package androidx.ui.widgets.binding

// / A concrete binding for applications based on the Widgets framework.
// / This is the glue that binds the framework to the Flutter engine.
class WidgetsFlutterBinding {
// TODO(Migration/Filip): extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, RendererBinding, WidgetsBinding

    companion object {

        // / Returns an instance of the [WidgetsBinding], creating and
        // / initializing it if necessary. If one is created, it will be a
        // / [WidgetsFlutterBinding]. If one was previously initialized, then
        // / it will at least implement [WidgetsBinding].
        // /
        // / You only need to call this method if you need the binding to be
        // / initialized before calling [runApp].
        // /
        // / In the `flutter_test` framework, [testWidgets] initializes the
        // / binding instance to a [TestWidgetsFlutterBinding], not a
        // / [WidgetsFlutterBinding].
        val ensureInitialized: WidgetsBinding by lazy { WidgetsBinding() }
    }
}

Fix compilation after merging bindings refactoring. Why it wasn't detected via Presubmit-Verified?

package androidx.ui.widgets.binding

// / A concrete binding for applications based on the Widgets framework.
// / This is the glue that binds the framework to the Flutter engine.
class WidgetsFlutterBinding {
// TODO(Migration/Filip): extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, RendererBinding, WidgetsBinding

    companion object {

        // / Returns an instance of the [WidgetsBinding], creating and
        // / initializing it if necessary. If one is created, it will be a
        // / [WidgetsFlutterBinding]. If one was previously initialized, then
        // / it will at least implement [WidgetsBinding].
        // /
        // / You only need to call this method if you need the binding to be
        // / initialized before calling [runApp].
        // /
        // / In the `flutter_test` framework, [testWidgets] initializes the
        // / binding instance to a [TestWidgetsFlutterBinding], not a
        // / [WidgetsFlutterBinding].
        val ensureInitialized: WidgetsBinding = WidgetsBindingImpl
    }
}


package com.example.david.kotlinchuck.findJoke

import com.example.david.kotlinchuck.findJoke.event.FindJokeEvent
import com.example.david.kotlinchuck.findJoke.ui.FindJokeView
import com.example.david.kotlinchuck.lib.EventBus
import com.example.david.kotlinchuck.lib.GreenRobotEventBus
import org.greenrobot.eventbus.Subscribe

/**
 * Created by david on 28/6/17.
 */
class FindJokePresenterImpl(view: FindJokeView) : FindJokePresenter {

    var view: FindJokeView? = view
    var eventBus: EventBus = GreenRobotEventBus.INSTANCE
    var repository: FindJokeRepository = FindJokeRepositoryImpl()

    override fun onCreate() {
        if(view != null){
            this.eventBus.register(this)
        }
    }

    override fun onDestroy() {
        this.eventBus.unregister(this)
        view = null
    }

    override fun findJoke(name: String, lastname: String) {

        var finalName: String? = null
        var finalLastName: String? = null

        if(!name.isEmpty())
            finalName = name

        if(!lastname.isEmpty())
            finalLastName = lastname

        repository.findJoke(name, lastname)
    }

    @Subscribe
    override fun onEventMainThread(event: FindJokeEvent) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

Call the view method when the event is successfull

package com.example.david.kotlinchuck.findJoke

import com.example.david.kotlinchuck.findJoke.event.FindJokeEvent
import com.example.david.kotlinchuck.findJoke.ui.FindJokeView
import com.example.david.kotlinchuck.lib.EventBus
import com.example.david.kotlinchuck.lib.GreenRobotEventBus
import org.greenrobot.eventbus.Subscribe

/**
 * Created by david on 28/6/17.
 */
class FindJokePresenterImpl(view: FindJokeView) : FindJokePresenter {

    var view: FindJokeView? = view
    var eventBus: EventBus = GreenRobotEventBus.INSTANCE
    var repository: FindJokeRepository = FindJokeRepositoryImpl()

    override fun onCreate() {
        if(view != null){
            this.eventBus.register(this)
        }
    }

    override fun onDestroy() {
        this.eventBus.unregister(this)
        view = null
    }

    override fun findJoke(name: String, lastname: String) {

        var finalName: String? = null
        var finalLastName: String? = null

        if(!name.isEmpty())
            finalName = name

        if(!lastname.isEmpty())
            finalLastName = lastname

        repository.findJoke(name, lastname)
    }

    @Subscribe
    override fun onEventMainThread(event: FindJokeEvent) {

        when(event.type){
            FindJokeEvent.onSuccess -> view?.jokeSuccess(event.joke!!)
        }
    }

}


/*
 * Copyright 2018 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.tivi.data.repositories.search

import app.tivi.data.entities.Result
import app.tivi.data.entities.TiviShow
import app.tivi.data.mappers.TmdbShowResultsPageToTiviShows
import app.tivi.data.mappers.toLambda
import app.tivi.extensions.executeWithRetry
import app.tivi.extensions.toResult
import com.uwetrottmann.tmdb2.Tmdb
import javax.inject.Inject

class TmdbSearchDataSource @Inject constructor(
    private val tmdb: Tmdb,
    private val mapper: TmdbShowResultsPageToTiviShows
) : SearchDataSource {
    override suspend fun search(query: String): Result<List<TiviShow>> {
        return tmdb.searchService().tv(query, 1, null, null)
                .executeWithRetry()
                .toResult(mapper.toLambda())
    }
}

Fix crash when searching and TMDb isn't reachable

/*
 * Copyright 2018 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.tivi.data.repositories.search

import app.tivi.data.entities.ErrorResult
import app.tivi.data.entities.Result
import app.tivi.data.entities.TiviShow
import app.tivi.data.mappers.TmdbShowResultsPageToTiviShows
import app.tivi.data.mappers.toLambda
import app.tivi.extensions.executeWithRetry
import app.tivi.extensions.toResult
import com.uwetrottmann.tmdb2.Tmdb
import javax.inject.Inject

class TmdbSearchDataSource @Inject constructor(
    private val tmdb: Tmdb,
    private val mapper: TmdbShowResultsPageToTiviShows
) : SearchDataSource {
    override suspend fun search(query: String): Result<List<TiviShow>> = try {
        tmdb.searchService().tv(query, 1, null, null)
                .executeWithRetry()
                .toResult(mapper.toLambda())
    } catch (t: Throwable) {
        ErrorResult(t)
    }
}


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

package com.demonwav.mcdev.platform.mixin

import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.OVERWRITE

import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.javadoc.CustomJavadocTagProvider
import com.intellij.psi.javadoc.JavadocTagInfo
import com.intellij.psi.javadoc.PsiDocTagValue

class MixinCustomJavaDocTagProvider : CustomJavadocTagProvider {

    override fun getSupportedTags(): List<JavadocTagInfo> = listOf(OverwriteTag.Author, OverwriteTag.Reason)

    private sealed class OverwriteTag : JavadocTagInfo {

        override fun isInline() = false

        override fun isValidInContext(element: PsiElement?): Boolean {
            return element is PsiMethod && element.modifierList.findAnnotation(OVERWRITE) != null
        }

        override fun checkTagValue(value: PsiDocTagValue?): String? = null
        override fun getReference(value: PsiDocTagValue?) = null

        object Author : OverwriteTag() {

            override fun getName() = "author"

            override fun checkTagValue(value: PsiDocTagValue?): String? {
                return "The @author JavaDoc tag on @Overwrite methods must be filled in.".takeIf { value?.text?.trim().isNullOrEmpty() }
            }
        }

        object Reason : OverwriteTag() {
            override fun getName() = "reason"
        }
    }
}

Allow custom Javadoc tags on all Mixin injectors

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

package com.demonwav.mcdev.platform.mixin

import com.demonwav.mcdev.platform.mixin.util.MixinConstants

import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.javadoc.CustomJavadocTagProvider
import com.intellij.psi.javadoc.JavadocTagInfo
import com.intellij.psi.javadoc.PsiDocTagValue

class MixinCustomJavaDocTagProvider : CustomJavadocTagProvider {

    override fun getSupportedTags(): List<JavadocTagInfo> = listOf(InjectorTag.Author, InjectorTag.Reason)

    private sealed class InjectorTag : JavadocTagInfo {

        override fun isInline() = false

        override fun isValidInContext(element: PsiElement?): Boolean {
            val modifierList = (element as? PsiMethod)?.modifierList ?: return false
            return MixinConstants.Annotations.ENTRY_POINTS.any {
                modifierList.findAnnotation(it) != null
            }
        }

        override fun checkTagValue(value: PsiDocTagValue?): String? = null
        override fun getReference(value: PsiDocTagValue?) = null

        object Author : InjectorTag() {

            override fun getName() = "author"

            override fun checkTagValue(value: PsiDocTagValue?): String? {
                return "The @author JavaDoc tag must be filled in.".takeIf { value?.text?.trim().isNullOrEmpty() }
            }
        }

        object Reason : InjectorTag() {
            override fun getName() = "reason"
        }
    }
}


package com.github.jackparisi.droidbox.binding

import android.databinding.BindingAdapter
import android.widget.ListPopupWindow
import android.widget.Spinner
import com.github.jackparisi.droidbox.utility.dpToPx

/**
 * Created by Giacomo Parisi on 21/08/17.
 * https://github.com/JackParisi
 */

@BindingAdapter("popupHeight")
fun bindSpinnerPopupHeight(spinner: Spinner, height: Float) {

    try {
        val popup = Spinner::class.java.getDeclaredField("mPopup")
        popup.isAccessible = true

        val popupWindow = popup.get(spinner)

        if (popupWindow is ListPopupWindow) {
            popupWindow.height = dpToPx(height, spinner.context).toInt()
        }

    } catch (e: NoSuchFieldException) {
        e.printStackTrace()
    } catch (e: IllegalAccessException) {
        e.printStackTrace()
    }
}

Add docs for spinnerAdapter + methods refactor

package com.github.jackparisi.droidbox.binding

import android.databinding.BindingAdapter
import android.widget.ListPopupWindow
import android.widget.Spinner
import com.github.jackparisi.droidbox.utility.dpToPx

/**
 * Created by Giacomo Parisi on 21/08/17.
 * https://github.com/JackParisi
 */

/**
 *
 * Set a fixed height for the view dropdown popup
 *
 * @param view The spinner view that need a custom dropdown popup height
 * @param height The height value in dp for the dropdown popup
 *
 */
@BindingAdapter("popupHeight")
fun bindSpinnerPopupHeight(view: Spinner, height: Float) {

    try {
        val popup = Spinner::class.java.getDeclaredField("mPopup")
        popup.isAccessible = true

        val popupWindow = popup.get(view)

        if (popupWindow is ListPopupWindow) {
            popupWindow.height = dpToPx(height, view.context).toInt()
        }

    } catch (e: NoSuchFieldException) {
        e.printStackTrace()
    } catch (e: IllegalAccessException) {
        e.printStackTrace()
    }
}


package ss.proximityservice.data

import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener

class ProximityDetector(private val listener: ProximityListener) : SensorEventListener {

    interface ProximityListener {
        fun onNear()
        fun onFar()
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}

    override fun onSensorChanged(event: SensorEvent) {
        val distance = event.values[0]
        val max = event.sensor.maximumRange

        if (distance < Math.min(max, 8f)) {
            listener.onNear()
        } else {
            listener.onFar()
        }
    }
}

Replace with kotlin min function

package ss.proximityservice.data

import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import kotlin.math.min

class ProximityDetector(private val listener: ProximityListener) : SensorEventListener {

    interface ProximityListener {
        fun onNear()
        fun onFar()
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}

    override fun onSensorChanged(event: SensorEvent) {
        val distance = event.values[0]
        val max = event.sensor.maximumRange

        if (distance < min(max, 8f)) {
            listener.onNear()
        } else {
            listener.onFar()
        }
    }
}


package org.wordpress.aztec

/**
 * Describes styles that could be applied to text
 */
enum class TextFormat {
    FORMAT_HEADER_1,
    FORMAT_HEADER_2,
    FORMAT_HEADER_3,
    FORMAT_HEADER_4,
    FORMAT_HEADER_5,
    FORMAT_HEADER_6,
    FORMAT_BOLD,
    FORMAT_ITALIC,
    FORMAT_UNDERLINED,
    FORMAT_STRIKETHROUGH,
    FORMAT_BULLET,
    FORMAT_QUOTE,
    FORMAT_LINK
}

Add normal to text format

package org.wordpress.aztec

/**
 * Describes styles that could be applied to text
 */
enum class TextFormat {
    FORMAT_HEADER_1,
    FORMAT_HEADER_2,
    FORMAT_HEADER_3,
    FORMAT_HEADER_4,
    FORMAT_HEADER_5,
    FORMAT_HEADER_6,
    FORMAT_BOLD,
    FORMAT_ITALIC,
    FORMAT_UNDERLINED,
    FORMAT_STRIKETHROUGH,
    FORMAT_BULLET,
    FORMAT_QUOTE,
    FORMAT_LINK,
    FORMAT_NORMAL
}


package io.polymorphicpanda.kspec.tag

open class Tag(val name: String) {
    init {
        if (name.isEmpty()) {
            throw IllegalArgumentException("Tag name can't be empty.")
        }
    }

    final override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other?.javaClass != javaClass) return false

        other as Tag

        if (name != other.name) return false

        return true
    }

    final override fun hashCode(): Int{
        return name.hashCode()
    }

}

Remove final on equals and hashCode methods

package io.polymorphicpanda.kspec.tag

open class Tag(val name: String) {
    init {
        if (name.isEmpty()) {
            throw IllegalArgumentException("Tag name can't be empty.")
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other?.javaClass != javaClass) return false

        other as Tag

        if (name != other.name) return false

        return true
    }

    override fun hashCode(): Int{
        return name.hashCode()
    }
}


Create a class to represent an academic term

package com.satsumasoftware.timetable.framework

import org.threeten.bp.LocalDate

class Term(val id: Int, val name: String, val startDate: LocalDate, val endDate: LocalDate)


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

plugins {
    id("com.android.library")
    kotlin("multiplatform")
    `maven-publish`
}

android {
    setDefaults()
}

kotlin {
    android()

    configure(targets) { configureMavenPublication() }
    sourceSets {
        commonMain.dependencies {
            api(splitties("experimental"))
        }
        androidMain.dependencies {
            api(AndroidX.fragment)
            api(splitties("lifecycle-coroutines"))
        }
        all {
            languageSettings.apply {
                useExperimentalAnnotation("kotlin.RequiresOptIn")
            }
        }
    }
}

afterEvaluate {
    publishing {
        setupAllPublications(project)
    }
}

Make the Fragments split depend on Fragments KTX

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

plugins {
    id("com.android.library")
    kotlin("multiplatform")
    `maven-publish`
}

android {
    setDefaults()
}

kotlin {
    android()

    configure(targets) { configureMavenPublication() }
    sourceSets {
        commonMain.dependencies {
            api(splitties("experimental"))
        }
        androidMain.dependencies {
            api(AndroidX.fragment)
            api(AndroidX.fragmentKtx)
            api(splitties("lifecycle-coroutines"))
        }
        all {
            languageSettings.apply {
                useExperimentalAnnotation("kotlin.RequiresOptIn")
            }
        }
    }
}

afterEvaluate {
    publishing {
        setupAllPublications(project)
    }
}


package com.bmuschko.gradle.docker

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.GroovySourceSet
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.*

class TestSetupPlugin : Plugin<Project> {
    override fun apply(project: Project): Unit = project.run {
        val sourceSets = project.the<JavaPluginConvention>().sourceSets
        val testRuntimeClasspath by configurations

        sourceSets.create("testSetup") {
            withConvention(GroovySourceSet::class) {
                groovy.srcDir("src/testSetup/groovy")
            }
            resources.srcDir("src/testSetup/resources")
            compileClasspath += sourceSets["main"]!!.output + testRuntimeClasspath
            runtimeClasspath += output + compileClasspath
        }

        tasks.withType<Test>().configureEach {
            testLogging {
                events("skipped")
            }
            failFast = true
        }
    }
}

Speed up build time by running tests in parallel

package com.bmuschko.gradle.docker

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.GroovySourceSet
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.*

class TestSetupPlugin : Plugin<Project> {
    override fun apply(project: Project): Unit = project.run {
        val sourceSets = project.the<JavaPluginConvention>().sourceSets
        val testRuntimeClasspath by configurations

        sourceSets.create("testSetup") {
            withConvention(GroovySourceSet::class) {
                groovy.srcDir("src/testSetup/groovy")
            }
            resources.srcDir("src/testSetup/resources")
            compileClasspath += sourceSets["main"]!!.output + testRuntimeClasspath
            runtimeClasspath += output + compileClasspath
        }

        tasks.withType<Test>().configureEach {
            testLogging {
                events("skipped")
            }

            maxParallelForks = determineMaxParallelForks()
            failFast = true
        }
    }

    private
    fun determineMaxParallelForks(): Int {
        return if ((Runtime.getRuntime().availableProcessors() / 2) < 1) 1 else (Runtime.getRuntime().availableProcessors() / 2)
    }
}


// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.completion.ml.ranker

import com.jetbrains.completion.ml.ranker.ExperimentKotlinMLRankingProvider
import com.jetbrains.completion.ml.ranker.ExperimentScalaMLRankingProvider
import org.junit.Test

class MetadataConsistencyTest {
  @Test
  fun testKotlinMetadata() = ExperimentKotlinMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testScalaMetadata() = ExperimentScalaMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testJavaMetadata() = ExperimentJavaMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testRustMetadata() = ExperimentRustMLRankingProvider().assertModelMetadataConsistent()
}

Add missed tests for Python and PHP

// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.completion.ml.ranker

import org.junit.Test

class MetadataConsistencyTest {
  @Test
  fun testKotlinMetadata() = ExperimentKotlinMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testScalaMetadata() = ExperimentScalaMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testJavaMetadata() = ExperimentJavaMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testRustMetadata() = ExperimentRustMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testPythonMetadata() = ExperimentPythonMLRankingProvider().assertModelMetadataConsistent()

  @Test
  fun testPHPMetadata() = ExperimentPhpMLRankingProvider().assertModelMetadataConsistent()
}


package views

import models.Image
import models.Thumbnail

/**
 * Created by allen on 3/30/17.
 */

class ImageView{
    fun urlForImage(image: Image?): String{
        if(image != null){
            return "http://photog.alaska.dev/media/images/" + image.path
        }
        return ""
    }

    fun urlForThumbnail(thumbnail: Thumbnail?): String{
        if(thumbnail != null){
            return "http://photog.alaska.dev/media/thumbnails/" + thumbnail.miniThumbnailPath
        }
        return ""
    }
}

Edit thumbnail links to escape % signs in file path

package views

import models.Image
import models.Thumbnail

/**
 * Created by allen on 3/30/17.
 */

class ImageView{
    fun urlForImage(image: Image?): String{
        if(image != null){
            return "http://photog.alaska.dev/media/images/" + image.path
        }
        return ""
    }

    fun urlForThumbnail(thumbnail: Thumbnail?): String{
        if(thumbnail != null){
            //some thumbnail paths contain '%'
            return "http://photog.alaska.dev/media/thumbnails/" + thumbnail.miniThumbnailPath.replace("%", "%25")
        }
        return ""
    }
}


package me.ycdev.android.lib.common.async

import android.os.Looper
import android.os.SystemClock
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import java.util.ArrayList
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@LargeTest
class HandlerTaskExecutorTest {
    @Test
    @Throws(InterruptedException::class)
    fun checkLooper() {
        println("test thread id=" + Thread.currentThread().id)
        val executor = HandlerTaskExecutor.withMainLooper()
        val latch = CountDownLatch(4)
        createTasks(latch, 4, 150).forEach {
            executor.postTask(it)
        }
        latch.await(1, TimeUnit.SECONDS)
        assertThat(latch.count).isEqualTo(0L)
    }

    @Suppress("SameParameterValue")
    private fun createTasks(latch: CountDownLatch, count: Int, sleepMs: Long): List<Runnable> {
        val tasks = ArrayList<Runnable>(count)
        for (i in 0 until count) {
            tasks.add(Runnable {
                println("main thread id=" + Thread.currentThread().id)
                assertThat(Looper.myLooper()).isSameInstanceAs(Looper.getMainLooper())
                SystemClock.sleep(sleepMs)
                latch.countDown()
            })
        }
        return tasks
    }
}

Add longer timeout for GitHub actions

package me.ycdev.android.lib.common.async

import android.os.Looper
import android.os.SystemClock
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import java.util.ArrayList
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@LargeTest
class HandlerTaskExecutorTest {
    @Test
    @Throws(InterruptedException::class)
    fun checkLooper() {
        println("test thread id=" + Thread.currentThread().id)
        val executor = HandlerTaskExecutor.withMainLooper()
        val latch = CountDownLatch(4)
        createTasks(latch, 4, 150).forEach {
            executor.postTask(it)
        }
        latch.await(10, TimeUnit.SECONDS)
        assertThat(latch.count).isEqualTo(0L)
    }

    @Suppress("SameParameterValue")
    private fun createTasks(latch: CountDownLatch, count: Int, sleepMs: Long): List<Runnable> {
        val tasks = ArrayList<Runnable>(count)
        for (i in 0 until count) {
            tasks.add(Runnable {
                println("main thread id=" + Thread.currentThread().id)
                assertThat(Looper.myLooper()).isSameInstanceAs(Looper.getMainLooper())
                SystemClock.sleep(sleepMs)
                latch.countDown()
            })
        }
        return tasks
    }
}


/*
 * IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
 * Copyright (C) 2003-2019 The IdeaVim authors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package org.jetbrains.plugins.ideavim.group.visual

import com.intellij.codeInsight.editorActions.BackspaceHandler
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.LogicalPosition
import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.group.VimListenerManager
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
import org.jetbrains.plugins.ideavim.VimTestCase

/**
 * @author Alex Plate
 */
class NonVimVisualChangeTest : VimTestCase() {
    fun `test save mode after removing text`() {
        // PyCharm uses BackspaceHandler.deleteToTargetPosition to remove indent
        // See https://github.com/JetBrains/ideavim/pull/186#issuecomment-486656093
        configureByText("""
            A Discovery

            I ${c}found it in a legendary land
            all rocks and lavender and tufted grass,
            where it was settled on some sodden sand
            hard by the torrent of a mountain pass.
        """.trimIndent())
        VimListenerManager.addEditorListeners(myFixture.editor)
        typeText(parseKeys("i"))
        assertMode(CommandState.Mode.INSERT)
        ApplicationManager.getApplication().runWriteAction {
            CommandProcessor.getInstance().runUndoTransparentAction {
                BackspaceHandler.deleteToTargetPosition(myFixture.editor, LogicalPosition(2, 0))
            }
        }
        myFixture.checkResult("""
            A Discovery

            found it in a legendary land
            all rocks and lavender and tufted grass,
            where it was settled on some sodden sand
            hard by the torrent of a mountain pass.
        """.trimIndent())
        assertMode(CommandState.Mode.INSERT)
    }
}


package org.jetbrains.ktor.tests.full

import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.content.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.testing.*
import org.jetbrains.ktor.tests.*
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.runner.*
import org.openjdk.jmh.runner.options.*
import java.util.concurrent.*

@State(Scope.Benchmark)
open class FullBenchmark {
    private val testHost: TestApplicationHost = createTestHost()
    private val classSignature =  listOf(0xca, 0xfe, 0xba, 0xbe).map(Int::toByte)

    @Setup
    fun configureServer() {
        testHost.application.routing {
            get("/sayOK") {
                call.respond("OK")
            }
            get("/jarfile") {
                call.respond(call.resolveClasspathWithPath("java/lang/", "String.class")!!)
            }
        }
    }

    @Benchmark
    fun sayOK() = handle("/sayOK") {
        if (response.content != "OK") {
            throw IllegalStateException()
        }
    }

    @Benchmark
    fun sayClasspathResourceFromJar() = handle("/jarfile") {
        if (response.byteContent!!.take(4) != classSignature) {
            throw IllegalStateException("Wrong class signature")
        }
    }

    private inline fun <R> handle(url: String, block: TestApplicationCall.() -> R) = testHost.handleRequest(HttpMethod.Get, url).apply {
        await()

        if (response.status() != HttpStatusCode.OK) {
            throw IllegalStateException("wrong response code")
        }

        block()
    }

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val options = OptionsBuilder()
                    .mode(Mode.AverageTime)
                    .timeUnit(TimeUnit.MICROSECONDS)
                    .include(FullBenchmark::class.java.name)
                    .warmupIterations(7)
                    .measurementIterations(25)
                    .measurementTime(TimeValue.milliseconds(500))
                    .forks(1)

            Runner(options.build()).run()

//            FullBenchmark().apply {
//                configureServer()
//
//                while (true) {
//                    sayClasspathResourceFromJar()
//                }
//            }
        }
    }
}


package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val gradleKotlinDslVersion = "1.0-rc-10"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}

Upgrade to Kotlin DSL 1.0-rc-11

package org.gradle.gradlebuild

import org.gradle.api.JavaVersion
import org.gradle.internal.os.OperatingSystem

object BuildEnvironment {
    val isCiServer = "CI" in System.getenv()
    val gradleKotlinDslVersion = "1.0-rc-11"
    val jvm = org.gradle.internal.jvm.Jvm.current()
    val javaVersion = JavaVersion.current()
    val isWindows = OperatingSystem.current().isWindows
    val isSlowInternetConnection
        get() = System.getProperty("slow.internet.connection", "false").toBoolean()
    val agentNum: Int
        get() {
            if (System.getenv().containsKey("USERNAME")) {
                val agentNumEnv = System.getenv("USERNAME").replaceFirst("tcagent", "")
                if (Regex("""\d+""").containsMatchIn(agentNumEnv)) {
                    return agentNumEnv.toInt()
                }
            }
            return 1
        }
}


import com.beust.kobalt.*
import com.beust.kobalt.plugin.android.*
import com.beust.kobalt.plugin.java.*

val r = repos(file("d:\\android\\adt-bundle-windows-x86_64-20140321\\sdk\\extras\\android\\m2repository"))

val p = javaProject {
    name = "intro_android_demo"
    group = "com.example"
    artifactId = name
    version = "0.1"
    directory = homeDir("android/intro_android_demo")

    sourceDirectories {
        listOf(path("app/src/main/java"))
    }

    dependencies {
        compile(file("app/libs/android-async-http-1.4.3.jar"),
            "com.android.support:support-v4:aar:23.0.1")
    }

    android {
        applicationId = name
        buildToolsVersion = "21.1.3"
    }
}

Fix the build file for the examples.

import com.beust.kobalt.*
import com.beust.kobalt.plugin.android.*
import com.beust.kobalt.plugin.java.*

val r = repos(file("d:\\android\\adt-bundle-windows-x86_64-20140321\\sdk\\extras\\android\\m2repository"))

val p = javaProject {
    name = "intro_android_demo"
    group = "com.example"
    artifactId = name
    version = "0.1"
    directory = homeDir("android/intro_android_demo")

    sourceDirectories {
        listOf(path("app/src/main/java"))
    }

    dependencies {
        compile(file("app/libs/android-async-http-1.4.3.jar"),
            "com.android.support:support-v4:aar:21.0.3")
    }

    android {
        compileSdkVersion = "21"
        applicationId = "codepath.apps.demointroandroid"
        buildToolsVersion = "21.1.2"
    }
}


package ii_collections

import util.TODO

fun todoTask24(): Nothing = TODO(
    """
        Task 24.
        The function should behave the same as '_24_JavaCode.doSomethingStrangeWithCollection'
        Replace all invocations of 'todoTask9()' with the appropriate code.
    """,
        references = { c: Collection<String> -> _24_JavaCode().doSomethingStrangeWithCollection(c) }
)

fun doSomethingStrangeWithCollection(collection: Collection<String>): Collection<String>? {
    val groupsByLength = collection. groupBy { s -> todoTask24() }

    val maximumSizeOfGroup = groupsByLength.values. map { group -> todoTask24() }. max()

    return groupsByLength.values. firstOrNull { group -> todoTask24() }
}

Fix typo in task description

package ii_collections

import util.TODO

fun todoTask24(): Nothing = TODO(
    """
        Task 24.
        The function should behave the same as '_24_JavaCode.doSomethingStrangeWithCollection'
        Replace all invocations of 'todoTask24()' with the appropriate code.
    """,
        references = { c: Collection<String> -> _24_JavaCode().doSomethingStrangeWithCollection(c) }
)

fun doSomethingStrangeWithCollection(collection: Collection<String>): Collection<String>? {
    val groupsByLength = collection. groupBy { s -> todoTask24() }

    val maximumSizeOfGroup = groupsByLength.values. map { group -> todoTask24() }. max()

    return groupsByLength.values. firstOrNull { group -> todoTask24() }
}


package org.wikipedia.page

import android.annotation.SuppressLint
import kotlinx.coroutines.*
import org.wikipedia.WikipediaApp
import org.wikipedia.readinglist.database.ReadingListDbHelper
import org.wikipedia.readinglist.database.ReadingListPage
import org.wikipedia.util.log.L

object PageAvailableOfflineHandler {
    interface Callback {
        fun onFinish(available: Boolean)
    }

    fun check(page: ReadingListPage, callback: Callback) {
        callback.onFinish(WikipediaApp.getInstance().isOnline || (page.offline() && !page.saving()))
    }

    @SuppressLint("CheckResult")
    fun check(pageTitle: PageTitle, callback: Callback) {
        if (WikipediaApp.getInstance().isOnline) {
            callback.onFinish(true)
            return
        }
        CoroutineScope(Dispatchers.Main).launch(CoroutineExceptionHandler { _, exception ->
            run {
                callback.onFinish(false)
                L.w(exception)
            }
        }) {
            val readingListPage = withContext(Dispatchers.IO) { ReadingListDbHelper.instance().findPageInAnyList(pageTitle) }
            callback.onFinish(readingListPage!!.offline() && !readingListPage.saving())
        }
    }
}

Fix possible crash if cannot find any reading list

package org.wikipedia.page

import android.annotation.SuppressLint
import kotlinx.coroutines.*
import org.wikipedia.WikipediaApp
import org.wikipedia.readinglist.database.ReadingListDbHelper
import org.wikipedia.readinglist.database.ReadingListPage
import org.wikipedia.util.log.L

object PageAvailableOfflineHandler {
    interface Callback {
        fun onFinish(available: Boolean)
    }

    fun check(page: ReadingListPage, callback: Callback) {
        callback.onFinish(WikipediaApp.getInstance().isOnline || (page.offline() && !page.saving()))
    }

    @SuppressLint("CheckResult")
    fun check(pageTitle: PageTitle, callback: Callback) {
        if (WikipediaApp.getInstance().isOnline) {
            callback.onFinish(true)
            return
        }
        CoroutineScope(Dispatchers.Main).launch(CoroutineExceptionHandler { _, exception ->
            run {
                callback.onFinish(false)
                L.w(exception)
            }
        }) {
            val readingListPage = withContext(Dispatchers.IO) { ReadingListDbHelper.instance().findPageInAnyList(pageTitle) }
            callback.onFinish(readingListPage != null && readingListPage.offline() && !readingListPage.saving())
        }
    }
}


package io.ktor.sessions

import io.ktor.util.*
import java.security.*
import javax.crypto.*
import javax.crypto.spec.*

/**
 * Session transformer that appends an [algorithm] MAC (Message Authentication Code) hash of the input.
 * Where the input is either a session contents or a previous transformation.
 * It uses a specified [keySpec] when generating the Mac hash.
 *
 * @property keySpec is a secret key spec for message authentication
 * @property algorithm is a message authentication algorithm name
 */
class SessionTransportTransformerMessageAuthentication(val keySpec: SecretKeySpec, val algorithm: String = "HmacSHA1") :
    SessionTransportTransformer {
    constructor(key: ByteArray, algorithm: String = "HmacSHA1") : this(SecretKeySpec(key, algorithm), algorithm)

    override fun transformRead(transportValue: String): String? {
        val expectedSignature = transportValue.substringAfterLast('/', "")
        val value = transportValue.substringBeforeLast('/')
        if (MessageDigest.isEqual(mac(value).toByteArray(), expectedSignature.toByteArray()))
            return value
        return null
    }

    override fun transformWrite(transportValue: String): String = "$transportValue/${mac(transportValue)}"

    private fun mac(value: String): String {
        val mac = Mac.getInstance(algorithm)
        mac.init(keySpec)

        return hex(mac.doFinal(value.toByteArray()))
    }
}

Switch default algorithm to SHA-256 from SHA-1 for signed cookies

package io.ktor.sessions

import io.ktor.util.*
import java.security.*
import javax.crypto.*
import javax.crypto.spec.*

/**
 * Session transformer that appends an [algorithm] MAC (Message Authentication Code) hash of the input.
 * Where the input is either a session contents or a previous transformation.
 * It uses a specified [keySpec] when generating the Mac hash.
 *
 * @property keySpec is a secret key spec for message authentication
 * @property algorithm is a message authentication algorithm name
 */
class SessionTransportTransformerMessageAuthentication(val keySpec: SecretKeySpec, val algorithm: String = "HmacSHA256") :
    SessionTransportTransformer {
    constructor(key: ByteArray, algorithm: String = "HmacSHA256") : this(SecretKeySpec(key, algorithm), algorithm)

    override fun transformRead(transportValue: String): String? {
        val expectedSignature = transportValue.substringAfterLast('/', "")
        val value = transportValue.substringBeforeLast('/')
        if (MessageDigest.isEqual(mac(value).toByteArray(), expectedSignature.toByteArray()))
            return value
        return null
    }

    override fun transformWrite(transportValue: String): String = "$transportValue/${mac(transportValue)}"

    private fun mac(value: String): String {
        val mac = Mac.getInstance(algorithm)
        mac.init(keySpec)

        return hex(mac.doFinal(value.toByteArray()))
    }
}


package com.ids1024.whitakerswords

import android.os.Bundle
import android.support.v7.app.AppCompatActivity

import kotlinx.android.synthetic.main.main.drawer_layout
import kotlinx.android.synthetic.main.main.nav_view

class WhitakersWords : AppCompatActivity() {
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.main)
        supportFragmentManager.beginTransaction()
                              .replace(R.id.content, SearchFragment(false, false))
                              .commit()

        nav_view.inflateMenu(R.menu.navigation)
        nav_view.setCheckedItem(R.id.action_latin_to_english)
        nav_view.setNavigationItemSelectedListener { item ->
            drawer_layout.closeDrawers()
            val fragment = when (item.itemId) {
                R.id.action_latin_to_english -> {
                    SearchFragment(false, true)
                }
                R.id.action_english_to_latin -> {
                    SearchFragment(true, true)
                }
                R.id.action_settings -> {
                    WhitakersSettingsFragment()
                }
                R.id.action_about -> {
                    AboutFragment()
                }
                else -> {
                    throw RuntimeException() // Unreachable
                }
            }
            supportFragmentManager.beginTransaction()
                                  .addToBackStack(null)
                                  .replace(R.id.content, fragment)
                                  .commit()

            true
        }
    }
}

Fix indenting issues reported by ktlint


/*
 * Javalin - https://javalin.io
 * Copyright 2017 David Åse
 * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
 */

package io.javalin.embeddedserver.jetty

import io.javalin.core.ErrorMapper
import io.javalin.core.ExceptionMapper
import io.javalin.core.JavalinServlet
import io.javalin.core.PathMatcher
import io.javalin.embeddedserver.EmbeddedServer
import io.javalin.embeddedserver.EmbeddedServerFactory
import io.javalin.embeddedserver.StaticFileConfig
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.ServerConnector
import org.eclipse.jetty.util.thread.QueuedThreadPool
import java.util.concurrent.TimeUnit

class EmbeddedJettyFactory : EmbeddedServerFactory {

    private var server: Server;

    constructor() {
        this.server = Server(QueuedThreadPool(200, 8, 60000))
    }

    constructor(jettyServer: () -> Server) {
        this.server = jettyServer.invoke()
    }

    override fun create(pathMatcher: PathMatcher, exceptionMapper: ExceptionMapper, errorMapper: ErrorMapper, staticFileConfig: StaticFileConfig?): EmbeddedServer {
        val resourceHandler = JettyResourceHandler(staticFileConfig)
        val javalinServlet = JavalinServlet(pathMatcher, exceptionMapper, errorMapper, resourceHandler)
        return EmbeddedJettyServer(server, JettyHandler(javalinServlet))
    }

}

Remove temp values in factory

/*
 * Javalin - https://javalin.io
 * Copyright 2017 David Åse
 * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
 */

package io.javalin.embeddedserver.jetty

import io.javalin.core.ErrorMapper
import io.javalin.core.ExceptionMapper
import io.javalin.core.JavalinServlet
import io.javalin.core.PathMatcher
import io.javalin.embeddedserver.EmbeddedServer
import io.javalin.embeddedserver.EmbeddedServerFactory
import io.javalin.embeddedserver.StaticFileConfig
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.util.thread.QueuedThreadPool

class EmbeddedJettyFactory : EmbeddedServerFactory {

    private val server: Server;

    constructor() {
        this.server = Server(QueuedThreadPool(200, 8, 60000))
    }

    constructor(jettyServer: () -> Server) {
        this.server = jettyServer.invoke()
    }

    override fun create(pathMatcher: PathMatcher, exceptionMapper: ExceptionMapper, errorMapper: ErrorMapper, staticFileConfig: StaticFileConfig?): EmbeddedServer {
        return EmbeddedJettyServer(server, JettyHandler(
                JavalinServlet(pathMatcher, exceptionMapper, errorMapper, JettyResourceHandler(staticFileConfig))
        ))
    }

}


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

plugins {
    kotlin("jvm") version "1.5.31"
    jacoco
}

group = "ar.edu.unsam.algo2"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

val kotestVersion = "5.1.0"

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation("io.mockk:mockk:1.12.2")
    testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
    testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
    testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "14"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.test {
    finalizedBy(tasks.jacocoTestReport)
}

tasks.jacocoTestReport {
    dependsOn(tasks.test)
}

jacoco {
    toolVersion = "0.8.7"
}

tasks.jacocoTestReport {
    reports {
        xml.isEnabled = true
        csv.isEnabled = false
        html.isEnabled = false
    }
}

tasks.register("runOnGitHub") {
    dependsOn("jacocoTestReport")
    group = "custom"
    description = "$ ./gradlew runOnGitHub # runs on GitHub Action"
}

Update to new version of Kotlin plugin

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

plugins {
    kotlin("jvm") version "1.6.10"
    jacoco
}

group = "ar.edu.unsam.algo2"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

val kotestVersion = "5.1.0"

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation("io.mockk:mockk:1.12.2")
    testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
    testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
    testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "14"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.test {
    finalizedBy(tasks.jacocoTestReport)
}

tasks.jacocoTestReport {
    dependsOn(tasks.test)
}

jacoco {
    toolVersion = "0.8.7"
}

tasks.jacocoTestReport {
    reports {
        xml.isEnabled = true
        csv.isEnabled = false
        html.isEnabled = false
    }
}

tasks.register("runOnGitHub") {
    dependsOn("jacocoTestReport")
    group = "custom"
    description = "$ ./gradlew runOnGitHub # runs on GitHub Action"
}


package com.github.ramonrabello.kiphy.trends.data

import io.reactivex.Single

class TrendingRepository(
        private val localDataSource: TrendingDataSource,
        private val remoteDataSource: TrendingDataSource) {

    fun loadTrending() = Single.merge(
            remoteDataSource.loadTrending(),
            localDataSource.loadTrending())
}

Update constructor to use both local and remote data source.

package com.github.ramonrabello.kiphy.trends.data

import com.github.ramonrabello.kiphy.trends.data.source.TrendingDataSource
import io.reactivex.Single

class TrendingRepository(
        private val localDataSource: TrendingDataSource,
        private val remoteDataSource: TrendingDataSource) {

    fun loadTrending() = Single.merge(
            remoteDataSource.loadTrending(),
            localDataSource.loadTrending())
}


import java.math.*

class MyExn: Throwable() {}

public class Test2 {
    @Throws(Throwable::class)
	fun f() {}

    @Throws(Throwable::class)
	fun g(b: Boolean) {
		while (b) {
			if (b) {
			} else {
				try {
					f()
				} catch (e: MyExn) {}
				;
			}
		}
	}

	fun t(x: Int) {
		if (x < 0) {
			return
		}
        var y = x
		while(y >= 0) {
			if (y > 10) {
				try {
					val n: BigInteger = BigInteger( "wrong" );
				} catch (e: NumberFormatException) { // unchecked exception
				}
			}
			y--
		}
	}
}

Disable part of a test that gives us DB check inconsistencies

import java.math.*

class MyExn: Throwable() {}

public class Test2 {
    @Throws(Throwable::class)
	fun f() {}

    @Throws(Throwable::class)
	fun g(b: Boolean) {
		while (b) {
			if (b) {
			} else {
				try {
					f()
				} catch (e: MyExn) {}
				;
			}
		}
	}

	fun t(x: Int) {
		if (x < 0) {
			return
		}
        var y = x
		while(y >= 0) {
			if (y > 10) {
/*
TODO
				try {
					val n: BigInteger = BigInteger( "wrong" );
				} catch (e: NumberFormatException) { // unchecked exception
				}
*/
			}
			y--
		}
	}
}


Add worker action to load KtLint rulesets and serialize them into file.

package org.jlleitschuh.gradle.ktlint.worker

import com.pinterest.ktlint.core.RuleSet
import com.pinterest.ktlint.core.RuleSetProvider
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.SetProperty
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import java.io.FileOutputStream
import java.io.ObjectOutputStream
import java.util.ServiceLoader

/**
 * Preloads KtLint [RuleSet]s and serialize them into [RuleSetLoaderWorkParameters.serializeResultIntoFile] file,
 * so other [WorkAction] could use it.
 */
@Suppress("UnstableApiUsage")
internal abstract class RuleSetLoaderWorkAction :
    WorkAction<RuleSetLoaderWorkAction.RuleSetLoaderWorkParameters> {

    override fun execute() {
        val ruleSets = loadRuleSetsAndFilterThem(
            parameters.enableExperimentalRules.get(),
            parameters.disabledRules.get()
        )

        val fileSerializeInto = parameters.serializeResultIntoFile.asFile.get()
        ObjectOutputStream(FileOutputStream(fileSerializeInto)).use { oos ->
            oos.writeObject(
                ruleSets.map { SerializableRuleSet(it) }
            )
        }
    }

    private fun loadRuleSetsAndFilterThem(
        enableExperimental: Boolean,
        disabledRules: Set<String>
    ): Set<RuleSet> = loadRuleSetsFromClasspath()
        .filterKeys { enableExperimental || it != "experimental" }
        .filterKeys { !(disabledRules.contains("standard") && it == "\u0000standard") }
        .toSortedMap()
        .mapValues { it.value.get() }
        .values
        .toSet()

    private fun loadRuleSetsFromClasspath(): Map<String, RuleSetProvider> = ServiceLoader
        .load(RuleSetProvider::class.java)
        .associateBy {
            val key = it.get().id
            // Adapted from KtLint CLI module
            if (key == "standard") "\u0000$key" else key
        }

    @Suppress("UnstableApiUsage")
    interface RuleSetLoaderWorkParameters : WorkParameters {
        val serializeResultIntoFile: RegularFileProperty
        val enableExperimentalRules: Property<Boolean>
        val disabledRules: SetProperty<String>
    }
}


Add an extension function for DirectedGraph that build a reverse graph

/*
 * Copyright 2016 Michael Rozumyanskiy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.michaelrocks.lightsaber.processor.graph

fun <T> DirectedGraph<T>.reversed(): DirectedGraph<T> {
  val reversed = HashDirectedGraph<T>()
  for (vertex in vertices) {
    for (adjacentVertex in getAdjacentVertices(vertex)!!) {
      reversed.put(adjacentVertex, vertex)
    }
  }
  return reversed
}


/*
 * Copyright 2017 The Android Open Source Project
 *
 * 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 androidx.build

import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import java.io.File

object SupportConfig {
    const val DEFAULT_MIN_SDK_VERSION = 14
    const val INSTRUMENTATION_RUNNER = "androidx.test.runner.AndroidJUnitRunner"
    const val BUILD_TOOLS_VERSION = "28.0.2"
    const val CURRENT_SDK_VERSION = 28

    fun getKeystore(project: Project): File {
        val supportRoot = (project.rootProject.property("ext") as ExtraPropertiesExtension)
                .get("supportRootFolder") as File
        return File(supportRoot, "development/keystore/debug.keystore")
    }
}

Move to using build tools 28.0.3.

/*
 * Copyright 2017 The Android Open Source Project
 *
 * 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 androidx.build

import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import java.io.File

object SupportConfig {
    const val DEFAULT_MIN_SDK_VERSION = 14
    const val INSTRUMENTATION_RUNNER = "androidx.test.runner.AndroidJUnitRunner"
    const val BUILD_TOOLS_VERSION = "28.0.3"
    const val CURRENT_SDK_VERSION = 28

    fun getKeystore(project: Project): File {
        val supportRoot = (project.rootProject.property("ext") as ExtraPropertiesExtension)
                .get("supportRootFolder") as File
        return File(supportRoot, "development/keystore/debug.keystore")
    }
}


package dagger.hilt.android.plugin.util

import com.android.Version

/**
 * Simple Android Gradle Plugin version class since there is no public API one. b/175816217
 */
internal data class SimpleAGPVersion(
  val major: Int,
  val minor: Int,
) : Comparable<SimpleAGPVersion> {

  override fun compareTo(other: SimpleAGPVersion): Int {
    return compareValuesBy(
      this,
      other,
      compareBy(SimpleAGPVersion::major).thenBy(SimpleAGPVersion::minor)
    ) { it }
  }

  companion object {

    val ANDROID_GRADLE_PLUGIN_VERSION by lazy { parse(Version.ANDROID_GRADLE_PLUGIN_VERSION) }

    fun parse(version: String?) =
      tryParse(version) ?: error("Unable to parse AGP version: $version")

    private fun tryParse(version: String?): SimpleAGPVersion? {
      if (version == null) {
        return null
      }

      val parts = version.split('.')
      if (parts.size == 1) {
        return SimpleAGPVersion(parts[0].toInt(), 0)
      }

      return SimpleAGPVersion(parts[0].toInt(), parts[1].toInt())
    }
  }
}

Use reflection for obtaining the AGP version since the Version class was moved between 3.5 and 3.6

package dagger.hilt.android.plugin.util

/**
 * Simple Android Gradle Plugin version class since there is no public API one. b/175816217
 */
internal data class SimpleAGPVersion(
  val major: Int,
  val minor: Int,
) : Comparable<SimpleAGPVersion> {

  override fun compareTo(other: SimpleAGPVersion): Int {
    return compareValuesBy(
      this,
      other,
      compareBy(SimpleAGPVersion::major).thenBy(SimpleAGPVersion::minor)
    ) { it }
  }

  companion object {

    // TODO(danysantiago): Migrate to AndroidPluginVersion once it is available (b/175816217)
    val ANDROID_GRADLE_PLUGIN_VERSION by lazy {
      val clazz =
        findClass("com.android.Version")
          ?: findClass("com.android.builder.model.Version")
      if (clazz != null) {
        return@lazy parse(clazz.getField("ANDROID_GRADLE_PLUGIN_VERSION").get(null) as String)
      }
      error(
        "Unable to obtain AGP version. It is likely that the AGP version being used is too old."
      )
    }

    fun parse(version: String?) =
      tryParse(version) ?: error("Unable to parse AGP version: $version")

    private fun tryParse(version: String?): SimpleAGPVersion? {
      if (version == null) {
        return null
      }

      val parts = version.split('.')
      if (parts.size == 1) {
        return SimpleAGPVersion(parts[0].toInt(), 0)
      }

      return SimpleAGPVersion(parts[0].toInt(), parts[1].toInt())
    }

    private fun findClass(fqName: String) = try {
      Class.forName(fqName)
    } catch (ex: ClassNotFoundException) {
      null
    }
  }
}


plugins {
    id("public-kotlin-dsl-module")
}

base {
    archivesBaseName = "gradle-kotlin-dsl-tooling-models"
}

Add Kotlin stdlib dependency to `:tooling-models`

import build.futureKotlin

plugins {
    id("public-kotlin-dsl-module")
}

base {
    archivesBaseName = "gradle-kotlin-dsl-tooling-models"
}

dependencies {
    implementation(futureKotlin("stdlib-jdk8"))
}


import enmasse.perf.Environment
import enmasse.perf.TestReceiver
import enmasse.perf.TestSender
import enmasse.perf.createQueueContext
import io.kotlintest.specs.StringSpec
import java.util.concurrent.TimeUnit

/**
 * @author Ulf Lilleengen
 */
class NoStoreAnycastTest: StringSpec() {
    init {
        val ctx = createQueueContext(Environment.endpoint, "anycast")
        "Messages should be delivered to receiver" {
            val sender = TestSender(ctx, "myqueue")
            val msgs = listOf("foo", "bar", "baz")
            sender.sendMessages(msgs) shouldBe msgs.size
            println("Sent ${msgs.size} messages")

            val receiver = TestReceiver(ctx, "myqueue")
            val received = receiver.recvMessages(msgs.size)

            println("Received ${received.size} messages")
            received.size shouldBe msgs.size
        }
    }
}


package iii_conventions

import util.TODO

class Invokable(var numberInvocations: Int = 0) {

    operator fun invoke(): Invokable {
        numberInvocations++
        return this
    }

    fun getNumberOfInvocations() = numberInvocations
}

fun todoTask31(): Nothing = TODO(
    """
        Task 31.
        Change class Invokable to count the number of invocations (round brackets).
        Uncomment the commented code - it should return 4.
    """,
    references = { invokable: Invokable -> })

fun task31(invokable: Invokable): Int {
//    todoTask31()
    return invokable()()()().getNumberOfInvocations()
}

Make var private, smaller scope

package iii_conventions

import util.TODO

class Invokable(private var nInvocations: Int = 0) {

    operator fun invoke(): Invokable {
        nInvocations++
        return this
    }

    fun getNumberOfInvocations() = nInvocations
}

fun todoTask31(): Nothing = TODO(
    """
        Task 31.
        Change class Invokable to count the number of invocations (round brackets).
        Uncomment the commented code - it should return 4.
    """,
    references = { invokable: Invokable -> })

fun task31(invokable: Invokable): Int {
//    todoTask31()
    return invokable()()()().getNumberOfInvocations()
}


Add test for AddFeatureDialogFragment and setup kapt

/*
 * Copyright 2022 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.gnd.ui.home

import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import com.google.android.gnd.BaseHiltTest
import javax.inject.Inject
import com.google.android.gnd.ui.home.AddFeatureDialogFragment
import org.junit.Before
import org.robolectric.android.controller.ActivityController
import com.google.android.gnd.MainActivity
import org.robolectric.Robolectric
import org.robolectric.Shadows
import android.os.Looper
import android.view.View
import com.google.common.truth.Truth
import com.google.android.gnd.R
import org.junit.Test

@HiltAndroidTest
@RunWith(RobolectricTestRunner::class)
class AddFeatureDialogFragmentTest : BaseHiltTest() {
    @Inject
    var addFeatureDialogFragment: AddFeatureDialogFragment? = null
    @Before
    override fun setUp() {
        super.setUp()
        setUpFragment()
    }

    private fun setUpFragment() {
        val activityController = Robolectric.buildActivity(
            MainActivity::class.java
        )
        val activity = activityController.setup().get()
        addFeatureDialogFragment!!.showNow(
            activity.supportFragmentManager, AddFeatureDialogFragment::class.java.simpleName
        )
        Shadows.shadowOf(Looper.getMainLooper()).idle()
    }

    @Test
    fun show_dialogIsShown() {
        val listView = addFeatureDialogFragment!!.dialog!!.currentFocus
        Truth.assertThat(listView).isNotNull()
        Truth.assertThat(listView!!.visibility).isEqualTo(View.VISIBLE)
        Truth.assertThat(listView.findViewById<View>(R.id.project_name).visibility)
            .isEqualTo(View.VISIBLE)
    } //  @Test
    //  public void show_dataTypeSelected_correctDataTypeIsPassed() {
    //    ListView listView =
    //        (ListView) addFeatureDialogFragment.getDialog().getCurrentFocus();
    //
    //    int positionToSelect = 1;
    //    shadowOf(listView).performItemClick(positionToSelect);
    //    shadowOf(getMainLooper()).idle();
    //
    //    // Verify Dialog is dismissed
    //    assertThat(addFeatureDialogFragment.getDialog()).isNull();
    //
    //    assertThat(selectedPosition).isEqualTo(1);
    //  }
}