Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Project Gen to Skate #744

Merged
merged 13 commits into from
Feb 20, 2024
5 changes: 5 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ agp = "8.2.2"
agpAlpha = "8.3.0-rc01"
anvil = "2.4.9-1-8"
bugsnagGradle = "8.1.0"
circuit = "0.19.1"
compose-jb = "1.5.12"
coroutines = "1.7.3"
dependencyAnalysisPlugin = "1.29.0"
Expand All @@ -12,6 +13,7 @@ errorproneGradle = "3.0.1"
jdk = "21"
jna = "5.14.0"
kotlin = "1.9.22"
kotlinPoet = "1.16.0"
ksp = "1.9.22-1.0.17"
ktfmt = "0.47"
mavenPublish = "0.27.0"
Expand All @@ -30,6 +32,7 @@ wire = "4.9.3"
[plugins]
bestPracticesPlugin = { id = "com.autonomousapps.plugin-best-practices-plugin", version = "0.10" }
buildConfig = { id = "com.github.gmazzo.buildconfig", version = "5.0.0" }
compose = { id = "org.jetbrains.compose", version = "1.5.12"}
dependencyAnalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysisPlugin" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
Expand All @@ -55,6 +58,7 @@ autoService-ksp = "dev.zacsweers.autoservice:auto-service-ksp:1.1.0"
bugsnag = "com.bugsnag:bugsnag:3.7.1"
clikt = "com.github.ajalt.clikt:clikt:4.2.2"
commonsText = "org.apache.commons:commons-text:1.11.0"
circuit = { module = "com.slack.circuit:circuit-foundation", version.ref = "circuit"}
coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "coroutines" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" }
coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test" }
Expand Down Expand Up @@ -84,6 +88,7 @@ gradlePlugins-wire = { module = "com.squareup.wire:wire-gradle-plugin", version.
guava = "com.google.guava:guava:33.0.0-jre"
kotlinCliUtil = "com.slack.cli:kotlin-cli-util:2.6.3"
kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
kotlin-poet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinPoet"}
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
ktfmt = { module = "com.facebook:ktfmt", version.ref = "ktfmt" }
jgrapht = "org.jgrapht:jgrapht-core:1.5.2"
Expand Down
10 changes: 10 additions & 0 deletions skate-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ plugins {
alias(libs.plugins.intellij)
alias(libs.plugins.pluginUploader)
alias(libs.plugins.buildConfig)
alias(libs.plugins.compose)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We may also need the kotlin.multiplatform plugin here in place of kotlin.jvm but not sure

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was thinking since Skate is Intellij plugin, having kotlin.jvm should be enough. Does having kotlin.multiplatform mean we'll extend to other platforms like iOS?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not necessarily, it just sets up the KMP structure. If you look at the build file in the original repo, it does the same thing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ah I see. I can try moving the KMP structure over

}

group = "com.slack.intellij"
Expand Down Expand Up @@ -92,7 +93,16 @@ buildConfig {
}

dependencies {
implementation(compose.animation)
implementation(compose.desktop.currentOs)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.material3)
implementation(compose.ui)
implementation(libs.bugsnag) { exclude(group = "org.slf4j") }
implementation(libs.circuit)
implementation(libs.gradlePlugins.compose)
implementation(libs.kotlin.poet)
implementation(libs.okhttp)
implementation(libs.okhttp.loggingInterceptor)
implementation(projects.tracing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import org.jetbrains.annotations.VisibleForTesting
internal const val DEFAULT_TRANSLATOR_SOURCE_MODELS_PACKAGE_NAME = "slack.api.schemas"
@VisibleForTesting internal const val DEFAULT_TRANSLATOR_FILE_NAME_SUFFIX = "Translator.kt"
@VisibleForTesting internal const val DEFAULT_TRANSLATOR_ENUM_IDENTIFIER = "name"
internal const val DEFAULT_PROJECT_GEN_CLI_COMMAND = "./slackw generate-project"
internal const val DEFAULT_CODE_OWNER_FILE_PATH = "config/code-ownership/code_ownership.csv"

/** Manages user-specific settings for the Skate plugin */
Expand Down Expand Up @@ -70,12 +69,6 @@ class SkatePluginSettings : SimplePersistentStateComponent<SkatePluginSettings.S
state.isProjectGenMenuActionEnabled = value
}

var projectGenRunCommand: String
get() = state.projectGenCliCommand ?: DEFAULT_PROJECT_GEN_CLI_COMMAND
set(value) {
state.projectGenCliCommand = value
}

var isLinkifiedFeatureFlagsEnabled: Boolean
get() = state.isLinkifiedFeatureFlagsEnabled
set(value) {
Expand Down Expand Up @@ -137,7 +130,6 @@ class SkatePluginSettings : SimplePersistentStateComponent<SkatePluginSettings.S
var translatorFileNameSuffix by string()
var translatorEnumIdentifier by string()
var isProjectGenMenuActionEnabled by property(true)
var projectGenCliCommand by string()
var isLinkifiedFeatureFlagsEnabled by property(false)
var featureFlagBaseUrl by string()
var featureFlagAnnotation by string()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright (C) 2024 Slack Technologies, 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.
*/
@file:Suppress("MagicNumber")

package com.slack.sgp.intellij.projectgen

import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color

/** Borrowed from `MaterialColors` in SKColors.kt. */
internal object DesktopColors {
private val mdThemeLightPrimary = Color(0xFF1264A3)
private val mdThemeLightOnPrimary = Color(0xFFFFFFFF)
private val mdThemeLightInversePrimary = mdThemeLightOnPrimary
private val mdThemeLightPrimaryContainer = Color(0xFF9ED6FA) // On Inverse Highlight 1
private val mdThemeLightOnPrimaryContainer = Color(0xFF1D1C1D) // On Inverse Highlight 1
private val mdThemeLightSecondary = Color(0xFF1264A3)
private val mdThemeLightOnSecondary = Color(0xFFFFFFFF)
private val mdThemeLightSecondaryContainer = Color(0xFF9ED6FA) // Highlight 3, Jade 0
private val mdThemeLightOnSecondaryContainer = Color(0xFF1D1C1D) // Highlight 3, Jade 0
private val mdThemeLightTertiary = Color(0xFF007A5A)
private val mdThemeLightOnTertiary = Color(0xFFFFFFFF)
private val mdThemeLightTertiaryContainer = Color(0xFFE3FFF3) // Highlight 3, Jade 0
private val mdThemeLightOnTertiaryContainer = Color(0xFF1D1C1D) // Highlight 3, Jade 0
private val mdThemeLightError = Color(0xFFE01E5A)
private val mdThemeLightOnError = Color(0xFFFFFFFF)
private val mdThemeLightErrorContainer = Color(0xFFFFE8EF) // Destructive, Flamingo 0
private val mdThemeLightOnErrorContainer = Color(0xFF1D1C1D) // Destructive, Flamingo 0
private val mdThemeLightBackground = Color(0xFFFFFFFF)
private val mdThemeLightOnBackground = Color(0xFF1D1C1D)
private val mdThemeLightSurface = Color(0xFFFFFFFF)
private val mdThemeLightOnSurface = Color(0xFF1D1C1D)
private val mdThemeLightInverseSurface = Color(0xFF1D1C1D) // Inverse of surface
private val mdThemeLightInverseOnSurface = Color(0xFFFFFFFF) // Inverse of onSurface
private val mdThemeLightSurfaceVariant = Color(0xFFEAEAEA) // On Inverse Variant 1
private val mdThemeLightOnSurfaceVariant = Color(0xFF1D1C1D) // On Inverse Variant 1
// We don't want m3's tonal tinting for this so we just reuse the surface value
private val mdThemeLightSurfaceTint = mdThemeLightSurface
private val mdThemeLightOutline = Color(0xFF5E5D60) // Outline Primary
private val mdThemeLightShadow = Color(0xB31D1C1D) // Background / Modal

// We reuse the same values for primary/secondary/tertiary in both light and dark
private val mdThemeDarkPrimary = mdThemeLightPrimary
private val mdThemeDarkOnPrimary = mdThemeLightOnPrimary
private val mdThemeDarkInversePrimary = mdThemeDarkOnPrimary
private val mdThemeDarkPrimaryContainer = mdThemeLightPrimaryContainer
private val mdThemeDarkOnPrimaryContainer = mdThemeLightOnPrimaryContainer
private val mdThemeDarkSecondary = mdThemeLightSecondary
private val mdThemeDarkOnSecondary = mdThemeLightOnSecondary
private val mdThemeDarkSecondaryContainer = mdThemeLightSecondaryContainer
private val mdThemeDarkOnSecondaryContainer = mdThemeLightOnSecondaryContainer
private val mdThemeDarkTertiary = mdThemeLightTertiary
private val mdThemeDarkOnTertiary = mdThemeLightOnTertiary
private val mdThemeDarkTertiaryContainer = mdThemeLightTertiaryContainer
private val mdThemeDarkOnTertiaryContainer = mdThemeLightOnTertiaryContainer
private val mdThemeDarkError = mdThemeLightError
private val mdThemeDarkOnError = mdThemeLightOnError
private val mdThemeDarkErrorContainer = Color(0xFF93000A) // Destructive, Flamingo 0
private val mdThemeDarkOnErrorContainer = Color(0xFFFFDAD6) // Destructive, Flamingo 0
private val mdThemeDarkBackground = Color(0xFF1A1D21)
private val mdThemeDarkOnBackground = Color(0xFFD1D2D3)
private val mdThemeDarkSurface = Color(0xFF1A1D21)
private val mdThemeDarkOnSurface = Color(0xFFD1D2D3)
private val mdThemeDarkInverseSurface = Color(0xFFE4E2E6) // Inverse of surface
private val mdThemeDarkInverseOnSurface = Color(0xFF1B1B1F) // Inverse of onSurface
private val mdThemeDarkSurfaceVariant = Color(0xFF252425) // Container Gray 10
private val mdThemeDarkOnSurfaceVariant = Color(0xFFC5C6D0) // On Inverse Variant 1
/**
* We don't want tonal tinting but we _do_ want to lighten the surface color when elevated. The
* metaphor is that it's closer to the light source, so we just lighten with white.
*/
private val mdThemeDarkSurfaceTint = Color(0xFFFFFFFF)
private val mdThemeDarkOutline = Color(0xFF8F9099) // Outline Primary
private val mdThemeDarkShadow = Color(0xFF000000) // Background / Modal

val LightTheme =
lightColorScheme(
primary = mdThemeLightPrimary,
onPrimary = mdThemeLightOnPrimary,
primaryContainer = mdThemeLightPrimaryContainer,
onPrimaryContainer = mdThemeLightOnPrimaryContainer,
secondary = mdThemeLightSecondary,
onSecondary = mdThemeLightOnSecondary,
secondaryContainer = mdThemeLightSecondaryContainer,
onSecondaryContainer = mdThemeLightOnSecondaryContainer,
tertiary = mdThemeLightTertiary,
onTertiary = mdThemeLightOnTertiary,
tertiaryContainer = mdThemeLightTertiaryContainer,
onTertiaryContainer = mdThemeLightOnTertiaryContainer,
error = mdThemeLightError,
errorContainer = mdThemeLightErrorContainer,
onError = mdThemeLightOnError,
onErrorContainer = mdThemeLightOnErrorContainer,
background = mdThemeLightBackground,
onBackground = mdThemeLightOnBackground,
surface = mdThemeLightSurface,
onSurface = mdThemeLightOnSurface,
surfaceVariant = mdThemeLightSurfaceVariant,
onSurfaceVariant = mdThemeLightOnSurfaceVariant,
outline = mdThemeLightOutline,
inverseOnSurface = mdThemeLightInverseOnSurface,
inverseSurface = mdThemeLightInverseSurface,
inversePrimary = mdThemeLightInversePrimary,
surfaceTint = mdThemeLightSurfaceTint,
scrim = mdThemeLightShadow,
)

val DarkTheme =
darkColorScheme(
primary = mdThemeDarkPrimary,
onPrimary = mdThemeDarkOnPrimary,
primaryContainer = mdThemeDarkPrimaryContainer,
onPrimaryContainer = mdThemeDarkOnPrimaryContainer,
secondary = mdThemeDarkSecondary,
onSecondary = mdThemeDarkOnSecondary,
secondaryContainer = mdThemeDarkSecondaryContainer,
onSecondaryContainer = mdThemeDarkOnSecondaryContainer,
tertiary = mdThemeDarkTertiary,
onTertiary = mdThemeDarkOnTertiary,
tertiaryContainer = mdThemeDarkTertiaryContainer,
onTertiaryContainer = mdThemeDarkOnTertiaryContainer,
error = mdThemeDarkError,
errorContainer = mdThemeDarkErrorContainer,
onError = mdThemeDarkOnError,
onErrorContainer = mdThemeDarkOnErrorContainer,
background = mdThemeDarkBackground,
onBackground = mdThemeDarkOnBackground,
surface = mdThemeDarkSurface,
onSurface = mdThemeDarkOnSurface,
surfaceVariant = mdThemeDarkSurfaceVariant,
onSurfaceVariant = mdThemeDarkOnSurfaceVariant,
outline = mdThemeDarkOutline,
inverseOnSurface = mdThemeDarkInverseOnSurface,
inverseSurface = mdThemeDarkInverseSurface,
inversePrimary = mdThemeDarkInversePrimary,
surfaceTint = mdThemeDarkSurfaceTint,
scrim = mdThemeDarkShadow,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2024 Slack Technologies, 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.slack.sgp.intellij.projectgen

import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation

class PrefixTransformation(val prefix: String) : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
return prefixFilter(text, prefix)
}
}

private fun prefixFilter(number: AnnotatedString, prefix: String): TransformedText {

val out = prefix + number.text
val prefixOffset = prefix.length

val numberOffsetTranslator =
object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
return offset + prefixOffset
}

override fun transformedToOriginal(offset: Int): Int {
if (offset <= prefixOffset - 1) return prefixOffset
return offset - prefixOffset
}
}

return TransformedText(AnnotatedString(out), numberOffsetTranslator)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,31 @@ import com.slack.sgp.intellij.tracing.SkateTracingEvent
import com.slack.sgp.intellij.tracing.SkateTracingEvent.EventType.PROJECT_GEN_OPENED
import com.slack.sgp.intellij.util.isProjectGenMenuActionEnabled
import com.slack.sgp.intellij.util.isTracingEnabled
import com.slack.sgp.intellij.util.projectGenRunCommand
import java.time.Instant

class ProjectGenMenuAction
@JvmOverloads
constructor(
private val terminalViewWrapper: (Project) -> TerminalViewWrapper = ::RealTerminalViewWrapper,
private val offline: Boolean = false,
) : AnAction() {
class ProjectGenMenuAction @JvmOverloads constructor(private val offline: Boolean = false) :
AnAction() {

private val skateSpanBuilder = SkateSpanBuilder()
private val startTimestamp = Instant.now()

override fun actionPerformed(e: AnActionEvent) {
val currentProject: Project = e.project ?: return
val projectGenRunCommand = currentProject.projectGenRunCommand()
if (!currentProject.isProjectGenMenuActionEnabled()) return

executeProjectGenCommand(projectGenRunCommand, currentProject)
ProjectGenWindow(currentProject).show()

if (currentProject.isTracingEnabled()) {
sendUsageTrace(currentProject)
}
}

fun executeProjectGenCommand(command: String, project: Project) {
val terminalCommand = TerminalCommand(command, project.basePath, PROJECT_GEN_TAB_NAME)
terminalViewWrapper(project).executeCommand(terminalCommand)
skateSpanBuilder.addSpanTag("event", SkateTracingEvent(PROJECT_GEN_OPENED))
}

fun sendUsageTrace(project: Project) {
skateSpanBuilder.addSpanTag("event", SkateTracingEvent(PROJECT_GEN_OPENED))
SkateTraceReporter(project, offline)
.createPluginUsageTraceAndSendTrace(
"project_generator",
startTimestamp,
skateSpanBuilder.getKeyValueList(),
)
}

companion object {
const val PROJECT_GEN_TAB_NAME: String = "ProjectGen"
}
}
Loading