diff --git a/gradle-plugin/build.gradle.kts b/gradle-plugin/build.gradle.kts new file mode 100644 index 000000000..741181c4b --- /dev/null +++ b/gradle-plugin/build.gradle.kts @@ -0,0 +1,67 @@ +@file:Suppress("UnusedImport") + +plugins { + kotlin("jvm") + id("java") + `maven-publish` + id("com.jfrog.bintray") +} + +version = Versions.console +description = "Gradle plugin for Mirai Console" + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.withType(JavaCompile::class.java) { + options.encoding = "UTF8" +} + +kotlin { + sourceSets.all { + target.compilations.all { + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + //useIR = true + } + } + languageSettings.apply { + progressiveMode = true + + useExperimentalAnnotation("kotlin.Experimental") + useExperimentalAnnotation("kotlin.RequiresOptIn") + + useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI") + useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI") + useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalApi") + useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") + useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference") + useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalApi") + } + } +} + +dependencies { + api("org.jetbrains:annotations:19.0.0") + api(kotlinx("coroutines-jdk8", Versions.coroutines)) + + testApi(kotlin("test")) + testApi(kotlin("test-junit5")) + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0") +} + +tasks { + "test"(Test::class) { + useJUnitPlatform() + } +} + +// setupPublishing("mirai-console-gradle") \ No newline at end of file diff --git a/intellij-plugin/build.gradle.kts b/intellij-plugin/build.gradle.kts new file mode 100644 index 000000000..33558763a --- /dev/null +++ b/intellij-plugin/build.gradle.kts @@ -0,0 +1,107 @@ +@file:Suppress("UnusedImport") + +plugins { + kotlin("jvm") + id("java") + `maven-publish` + id("com.jfrog.bintray") + + id("org.jetbrains.intellij") version "0.4.16" + +} + +repositories { + maven("http://maven.aliyun.com/nexus/content/groups/public/") +} + +version = Versions.console +description = "IntelliJ plugin for Mirai Console" + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.withType(JavaCompile::class.java) { + options.encoding = "UTF8" +} + +// See https://github.com/JetBrains/gradle-intellij-plugin/ +intellij { + version = "2020.2.1" + isDownloadSources = true + updateSinceUntilBuild = false + + setPlugins( + "org.jetbrains.kotlin:1.4.10-release-IJ2020.2.1-1@staging" + ) +} + +tasks.getByName("publishPlugin", org.jetbrains.intellij.tasks.PublishTask::class) { + val pluginKey = project.findProperty("jetbrains.hub.key")?.toString() + if (pluginKey != null) { + logger.info("Found jetbrains.hub.key") + setToken(pluginKey) + } else { + logger.info("jetbrains.hub.key not found") + } +} + +tasks.withType { + sinceBuild("193.*") + untilBuild("205.*") + changeNotes(""" + Fix cancellation on analyzing augments + """.trimIndent()) +} + +kotlin { + sourceSets.all { + target.compilations.all { + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + //useIR = true + } + } + languageSettings.apply { + progressiveMode = true + + useExperimentalAnnotation("kotlin.Experimental") + useExperimentalAnnotation("kotlin.RequiresOptIn") + + useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI") + useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI") + useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalApi") + useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") + useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference") + useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalApi") + } + } +} + +dependencies { + api("org.jetbrains:annotations:19.0.0") + api(kotlinx("coroutines-jdk8", Versions.coroutines)) + + compileOnly("org.jetbrains.kotlin:kotlin-compiler:${Versions.kotlinCompiler}") + compileOnly("org.jetbrains.kotlin:kotlin-compiler:${Versions.kotlinCompiler}") + compileOnly(files("libs/ide-common.jar")) + + testApi(kotlin("test")) + testApi(kotlin("test-junit5")) + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0") +} + +tasks { + "test"(Test::class) { + useJUnitPlatform() + } +} + +// setupPublishing("mirai-console-intellij") \ No newline at end of file diff --git a/intellij-plugin/libs/ide-common.jar b/intellij-plugin/libs/ide-common.jar new file mode 100644 index 000000000..724e639bd Binary files /dev/null and b/intellij-plugin/libs/ide-common.jar differ diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/BlockingBridgeLineMarkerProvider.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/BlockingBridgeLineMarkerProvider.kt new file mode 100644 index 000000000..ccaf76327 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/BlockingBridgeLineMarkerProvider.kt @@ -0,0 +1,94 @@ +package net.mamoe.mirai.console.intellij + +import com.intellij.codeHighlighting.Pass +import com.intellij.codeInsight.daemon.LineMarkerInfo +import com.intellij.codeInsight.daemon.LineMarkerProvider +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.editor.markup.GutterIconRenderer +import com.intellij.openapi.progress.ProgressManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiJavaCodeReferenceCodeFragment +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.PsiReferenceExpression +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.idea.core.util.getLineNumber +import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.kotlin.psi.KtSimpleNameExpression + +class MiraiConsoleLineMarkerProvider : LineMarkerProvider { + override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? { + return null + } + + override fun collectSlowLineMarkers( + elements: MutableList, + result: MutableCollection>, + ) { + val markedLineNumbers = HashSet() + + for (element in elements) { + ProgressManager.checkCanceled() + + if (element !is PsiReferenceExpression) continue + + val containingFile = element.containingFile + if (containingFile !is PsiJavaFile || containingFile is PsiJavaCodeReferenceCodeFragment) { + continue + } + + val lineNumber = element.getLineNumber() + if (lineNumber in markedLineNumbers) continue + if (!element.hasBridgeCalls()) continue + + + markedLineNumbers += lineNumber + result += if (element is KtForExpression) { + CommandDeclarationLineMarkerInfo( + getElementForLineMark(element.loopRange!!), + // KotlinBundle.message("highlighter.message.suspending.iteration") + ) + } else { + CommandDeclarationLineMarkerInfo( + getElementForLineMark(element), + //KotlinBundle.message("highlighter.message.suspend.function.call") + ) + } + } + } + + @Suppress("DEPRECATION") + class CommandDeclarationLineMarkerInfo( + callElement: PsiElement, + ) : LineMarkerInfo( + callElement, + callElement.textRange, + Icons.CommandDeclaration, + Pass.LINE_MARKERS, + { + "Mirai Console Command" + }, + null, + GutterIconRenderer.Alignment.RIGHT + ) { + override fun createGutterRenderer(): GutterIconRenderer? { + return object : LineMarkerInfo.LineMarkerGutterIconRenderer(this) { + override fun getClickAction(): AnAction? = null + } + } + } +} + +fun PsiReferenceExpression.hasBridgeCalls(): Boolean { + val resolved = this.resolve() as? KtLightMethod ?: return false + + TODO() +} + +internal fun getElementForLineMark(callElement: PsiElement): PsiElement = + when (callElement) { + is KtSimpleNameExpression -> callElement.getReferencedNameElement() + else -> + // a fallback, + //but who knows what to reference in KtArrayAccessExpression ? + generateSequence(callElement, { it.firstChild }).last() + } \ No newline at end of file diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/IDEContainerContributor.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/IDEContainerContributor.kt new file mode 100644 index 000000000..cff72d5a9 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/IDEContainerContributor.kt @@ -0,0 +1,16 @@ +package net.mamoe.mirai.console.intellij + +import org.jetbrains.kotlin.container.StorageComponentContainer +import org.jetbrains.kotlin.container.useInstance +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor + +class IDEContainerContributor : StorageComponentContainerContributor { + override fun registerModuleComponents( + container: StorageComponentContainer, + platform: org.jetbrains.kotlin.platform.TargetPlatform, + moduleDescriptor: ModuleDescriptor, + ) { + container.useInstance(MiraiConsoleDeclarationChecker()) + } +} \ No newline at end of file diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/Icons.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/Icons.kt new file mode 100644 index 000000000..b4551fe87 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/Icons.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.intellij + +import com.intellij.openapi.util.IconLoader +import javax.swing.Icon + +object Icons { + val CommandDeclaration: Icon = IconLoader.getIcon("/icons/commandDeclaration.svg") +} \ No newline at end of file diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/MiraiConsoleDeclarationChecker.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/MiraiConsoleDeclarationChecker.kt new file mode 100644 index 000000000..f2d99b213 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/MiraiConsoleDeclarationChecker.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.intellij + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker +import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext + +class MiraiConsoleDeclarationChecker : DeclarationChecker { + override fun check( + declaration: KtDeclaration, + descriptor: DeclarationDescriptor, + context: DeclarationCheckerContext, + ) { + + } +} \ No newline at end of file diff --git a/intellij-plugin/src/main/resources/META-INF/plugin.xml b/intellij-plugin/src/main/resources/META-INF/plugin.xml new file mode 100644 index 000000000..54c5f4070 --- /dev/null +++ b/intellij-plugin/src/main/resources/META-INF/plugin.xml @@ -0,0 +1,28 @@ + + net.mamoe.mirai-console-dev + + Mirai Console Dev + + + Mamoe Technologies + + + com.intellij.modules.platform + org.jetbrains.kotlin + + + + + + + + + + + + + \ No newline at end of file diff --git a/intellij-plugin/src/main/resources/icons/commandDeclaration.svg b/intellij-plugin/src/main/resources/icons/commandDeclaration.svg new file mode 100644 index 000000000..1e1c7a10e --- /dev/null +++ b/intellij-plugin/src/main/resources/icons/commandDeclaration.svg @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 29aabb3f9..e1b5cfd3a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,6 +20,8 @@ fun includeProject(projectPath: String, path: String? = null) { includeProject(":mirai-console", "backend/mirai-console") includeProject(":mirai-console.codegen", "backend/codegen") includeProject(":mirai-console-pure", "frontend/mirai-console-pure") +includeProject(":mirai-console-intellij", "intellij-plugin") +includeProject(":mirai-console-gradle", "gradle-plugin") @Suppress("ConstantConditionIf") if (!disableOldFrontEnds) {