mirror of
https://github.com/apple/pkl.git
synced 2026-04-10 10:53:40 +02:00
Remove intellij plugin (#1510)
This plugin is being moved to pkl-project-commons. Closes #1491 See https://github.com/apple/pkl-project-commons/pull/75
This commit is contained in:
@@ -92,14 +92,9 @@ Example: `./gradlew test -Djvmdebug=true`
|
||||
|
||||
== Snippet Test Plugin
|
||||
|
||||
There is an IntelliJ plugin meant for development on the Pkl project itself.
|
||||
This plugin provides a split pane window when viewing snippet tests such as LanguageSnippetTests and FormatterSnippetTests.
|
||||
There is an IntelliJ plugin meant for development on the Pkl project itself located in https://github.com/apple/pkl-project-commons[pkl-project-commons].
|
||||
|
||||
To install:
|
||||
|
||||
1. Run `./gradlew pkl-internal-intellij-plugin:buildPlugin`.
|
||||
2. Within IntelliJ, run the action "Install Plugin From Disk...".
|
||||
3. Select the zip file within `pkl-internal-intellij-plugin/build/distributions`.
|
||||
See https://github.com/apple/pkl-project-commons?tab=readme-ov-file#internal-intellij-plugin[its readme] for instructions on how to set it up.
|
||||
|
||||
== Resources
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ graalVmSha256-linux-aarch64 = "7aa0b9935a80e67f37c6025678393dbd123bb6f2226811dec
|
||||
#noinspection UnusedVersionCatalogEntry
|
||||
graalVmSha256-windows-x64 = "fde83c5ceec2c75560c747ccd9f314f90e4cf5c5287416e67c4ce442e344ca27"
|
||||
ideaExtPlugin = "1.4.1"
|
||||
intellijPlugin = "2.10.1"
|
||||
intellij = "2025.2.3"
|
||||
javaPoet = "0.+"
|
||||
javaxInject = "1"
|
||||
jansi = "2.+"
|
||||
@@ -73,8 +71,6 @@ geantyref = { group = "io.leangen.geantyref", name = "geantyref", version.ref =
|
||||
graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" }
|
||||
graalSdk = { group = "org.graalvm.sdk", name = "graal-sdk", version.ref = "graalVm" }
|
||||
graalJs = { group = "org.graalvm.js", name = "js", version.ref = "graalVm" }
|
||||
#noinspection UnusedVersionCatalogEntry
|
||||
intellij = { group = "com.jetbrains.intellij.idea", name = "ideaIC", version.ref = "intellij" }
|
||||
javaPoet = { group = "com.palantir.javapoet", name = "javapoet", version.ref = "javaPoet" }
|
||||
javaxInject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" }
|
||||
jansi = { group = "org.fusesource.jansi", name = "jansi", version.ref = "jansi" }
|
||||
@@ -123,4 +119,3 @@ jmh = { id = "me.champeau.jmh", version.ref = "jmhPlugin" }
|
||||
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublishPlugin" }
|
||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadowPlugin" }
|
||||
intellij = { id = "org.jetbrains.intellij.platform", version.ref = "intellijPlugin" }
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
Internal IntelliJ plugin for developing the Pkl codebase.
|
||||
|
||||
This plugin is intentionally not published anywhere.
|
||||
For usage, see the docs in link:../DEVELOPMENT.adoc[DEVELOPMENT.adoc].
|
||||
@@ -1,63 +0,0 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
bundledModule:intellij-platform-test-runtime:IC-252.26830.84=intellijPlatformTestRuntimeFixClasspath
|
||||
bundledModule:intellij.libraries.ai.grazie.spell.gec.engine.local:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.libraries.lucene.common:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.libraries.microba:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.platform.backend:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.platform.vcs.impl.lang:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.platform.vcs.impl.shared:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.platform.vcs.impl:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledModule:intellij.spellchecker:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledPlugin:JUnit:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledPlugin:com.intellij.gradle:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledPlugin:com.intellij.java:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
bundledPlugin:org.jetbrains.plugins.gradle:IC-252.26830.84=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformBundledPlugins,intellijPlatformDependencies,intellijPlatformTestBundledPlugins,intellijPlatformTestClasspath,intellijPlatformTestDependencies,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
com.github.ben-manes.caffeine:caffeine:2.9.3=swiftExportClasspathResolvable
|
||||
com.google.errorprone:error_prone_annotations:2.28.0=swiftExportClasspathResolvable
|
||||
com.jetbrains.intellij.java:java-compiler-ant-tasks:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jetbrains.intellij.java:java-compiler-instrumentation-util-java8:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jetbrains.intellij.java:java-compiler-instrumentation-util:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jetbrains.intellij.java:java-gui-forms-compiler:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jetbrains.intellij.java:java-gui-forms-rt:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jetbrains.intellij.platform:util-jdom:252.26830.84=intellijPlatformJavaCompiler
|
||||
com.jgoodies:forms:1.1-preview=intellijPlatformJavaCompiler
|
||||
idea:ideaIC:2025.2.3=compileClasspath,compileOnlyDependenciesMetadata,intellijPlatformClasspath,intellijPlatformDependency,intellijPlatformDependencyArchive,intellijPlatformTestClasspath,testCompileClasspath,testCompileOnlyDependenciesMetadata
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation
|
||||
io.opentelemetry:opentelemetry-api:1.41.0=swiftExportClasspathResolvable
|
||||
io.opentelemetry:opentelemetry-context:1.41.0=swiftExportClasspathResolvable
|
||||
jaxen:jaxen:1.2.0=intellijPlatformJavaCompiler
|
||||
org.bouncycastle:bcpg-jdk18on:1.80=kotlinBouncyCastleConfiguration
|
||||
org.bouncycastle:bcpkix-jdk18on:1.80=kotlinBouncyCastleConfiguration
|
||||
org.bouncycastle:bcprov-jdk18on:1.80=kotlinBouncyCastleConfiguration
|
||||
org.bouncycastle:bcutil-jdk18on:1.80=kotlinBouncyCastleConfiguration
|
||||
org.checkerframework:checker-qual:3.43.0=swiftExportClasspathResolvable
|
||||
org.jetbrains.intellij.deps:asm-all:9.6.1=intellijPlatformJavaCompiler
|
||||
org.jetbrains.intellij.plugins:verifier-cli:1.402=intellijPluginVerifier
|
||||
org.jetbrains.kotlin:abi-tools-api:2.2.21=kotlinInternalAbiValidation
|
||||
org.jetbrains.kotlin:abi-tools:2.2.21=kotlinInternalAbiValidation
|
||||
org.jetbrains.kotlin:kotlin-build-tools-api:2.2.21=kotlinBuildToolsApiClasspath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-impl:2.2.21=kotlinBuildToolsApiClasspath
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:2.2.21=kotlinBuildToolsApiClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:2.2.21=kotlinBuildToolsApiClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.2.21=kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-metadata-jvm:2.2.21=kotlinInternalAbiValidation
|
||||
org.jetbrains.kotlin:kotlin-reflect:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlin:kotlin-script-runtime:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlin:kotlin-scripting-common:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-jvm:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-stdlib:2.2.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlin:swift-export-embeddable:2.2.21=swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=swiftExportClasspathResolvable
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResolvable
|
||||
org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable
|
||||
org.jetbrains:annotations:26.0.2=intellijPlatformJavaCompiler
|
||||
org.jetbrains:marketplace-zip-signer:0.1.43=marketplaceZipSigner
|
||||
empty=annotationProcessor,apiDependenciesMetadata,implementationDependenciesMetadata,intellijPlatformBundledModules,intellijPlatformComposedJar,intellijPlatformLocal,intellijPlatformPlugin,intellijPlatformPluginComposedModule,intellijPlatformPluginDependency,intellijPlatformPluginLocal,intellijPlatformPluginModule,intellijPlatformRuntimeClasspath,intellijPlatformTestBundledModules,intellijPlatformTestPlugin,intellijPlatformTestPluginDependency,intellijPlatformTestPluginLocal,intellijPlatformTestRuntimeClasspath,intellijPluginVerifierIdes,intellijPluginVerifierIdesDependency,intellijPluginVerifierIdesLocalInstance,intransitiveDependenciesMetadata,jetbrainsRuntime,jetbrainsRuntimeDependency,jetbrainsRuntimeLocalInstance,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,runtimeClasspath,testAnnotationProcessor,testApiDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions,testRuntimeClasspath
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
plugins {
|
||||
pklAllProjects
|
||||
kotlin("jvm")
|
||||
alias(libs.plugins.intellij)
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
intellijPlatform { defaultRepositories() }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
intellijPlatform {
|
||||
create("IC", libs.versions.intellij.get())
|
||||
bundledPlugin("com.intellij.java")
|
||||
bundledPlugin("org.jetbrains.plugins.gradle")
|
||||
bundledPlugin("JUnit")
|
||||
}
|
||||
}
|
||||
|
||||
spotless {
|
||||
kotlin {
|
||||
ktfmt(libs.versions.ktfmt.get()).googleStyle()
|
||||
target("src/*/kotlin/**/*.kt")
|
||||
licenseHeaderFile(rootProject.file("buildSrc/src/main/resources/license-header.star-block.txt"))
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* 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 org.pkl.internal.intellij
|
||||
|
||||
import com.intellij.openapi.fileEditor.*
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
class SnippetTestEditorProvider : FileEditorProvider, DumbAware {
|
||||
override fun accept(project: Project, file: VirtualFile): Boolean = file.isSnippetTestInputFile()
|
||||
|
||||
override fun createEditor(project: Project, file: VirtualFile): FileEditor {
|
||||
val textEditorProvider = TextEditorProvider.getInstance()
|
||||
val outputFile = findOutputFile(file)
|
||||
|
||||
val inputEditor = textEditorProvider.createEditor(project, file) as TextEditor
|
||||
val outputEditor =
|
||||
outputFile?.let { textEditorProvider.createEditor(project, it) as TextEditor }
|
||||
|
||||
return SnippetTestSplitEditor(inputEditor, outputEditor)
|
||||
}
|
||||
|
||||
override fun getEditorTypeId(): String = "snippet-test-split-editor"
|
||||
|
||||
override fun getPolicy(): FileEditorPolicy = FileEditorPolicy.HIDE_DEFAULT_EDITOR
|
||||
}
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* 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 org.pkl.internal.intellij
|
||||
|
||||
import com.intellij.execution.ExecutionListener
|
||||
import com.intellij.execution.ExecutionManager
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.ProgramRunnerUtil
|
||||
import com.intellij.execution.RunManager
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor
|
||||
import com.intellij.execution.executors.DefaultRunExecutor
|
||||
import com.intellij.execution.junit.JUnitConfiguration
|
||||
import com.intellij.execution.junit.JUnitConfigurationType
|
||||
import com.intellij.execution.process.ProcessHandler
|
||||
import com.intellij.execution.runners.ExecutionEnvironment
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorLocation
|
||||
import com.intellij.openapi.fileEditor.FileEditorState
|
||||
import com.intellij.openapi.fileEditor.FileEditorStateLevel
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import com.intellij.openapi.module.ModuleUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.UserDataHolderBase
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.ui.components.JBPanel
|
||||
import java.awt.BorderLayout
|
||||
import java.beans.PropertyChangeListener
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JSplitPane
|
||||
|
||||
class SnippetTestSplitEditor(
|
||||
private val inputEditor: TextEditor,
|
||||
private var outputEditor: TextEditor?,
|
||||
) : UserDataHolderBase(), FileEditor {
|
||||
|
||||
private var currentViewMode = if (outputEditor != null) ViewMode.SPLIT else ViewMode.INPUT_ONLY
|
||||
|
||||
private val splitPane: JSplitPane =
|
||||
JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inputEditor.component, outputEditor?.component).apply {
|
||||
resizeWeight = 0.5
|
||||
}
|
||||
|
||||
private val mainPanel =
|
||||
JBPanel<JBPanel<*>>(BorderLayout()).apply {
|
||||
add(createToolbar(), BorderLayout.NORTH)
|
||||
when (currentViewMode) {
|
||||
ViewMode.INPUT_ONLY -> add(inputEditor.component, BorderLayout.CENTER)
|
||||
ViewMode.SPLIT -> add(splitPane, BorderLayout.CENTER)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createToolbar(): JComponent {
|
||||
val actionGroup =
|
||||
DefaultActionGroup().apply {
|
||||
add(RunTestAction())
|
||||
add(DebugTestAction())
|
||||
add(RunAllTestsAction())
|
||||
add(OverwriteSnippetAction())
|
||||
addSeparator()
|
||||
add(ShowInputOnlyAction())
|
||||
add(ShowSplitAction())
|
||||
}
|
||||
|
||||
val toolbar =
|
||||
ActionManager.getInstance().createActionToolbar("SnippetTestEditor", actionGroup, true)
|
||||
toolbar.targetComponent = mainPanel
|
||||
return toolbar.component
|
||||
}
|
||||
|
||||
private fun setViewMode(mode: ViewMode) {
|
||||
if (currentViewMode == mode || outputEditor == null) return
|
||||
currentViewMode = mode
|
||||
|
||||
// Remove the current center component
|
||||
val layout = mainPanel.layout as BorderLayout
|
||||
layout.getLayoutComponent(BorderLayout.CENTER)?.let { mainPanel.remove(it) }
|
||||
|
||||
when (mode) {
|
||||
ViewMode.INPUT_ONLY -> {
|
||||
mainPanel.add(inputEditor.component, BorderLayout.CENTER)
|
||||
}
|
||||
ViewMode.SPLIT -> {
|
||||
// Re-add components to splitPane in case they were removed
|
||||
splitPane.leftComponent = inputEditor.component
|
||||
splitPane.rightComponent = outputEditor!!.component
|
||||
mainPanel.add(splitPane, BorderLayout.CENTER)
|
||||
}
|
||||
}
|
||||
|
||||
mainPanel.revalidate()
|
||||
mainPanel.repaint()
|
||||
}
|
||||
|
||||
override fun getComponent(): JComponent = mainPanel
|
||||
|
||||
override fun getPreferredFocusedComponent(): JComponent? = inputEditor.preferredFocusedComponent
|
||||
|
||||
override fun getName(): String = "Snippet Test"
|
||||
|
||||
override fun getFile(): VirtualFile? = inputEditor.file
|
||||
|
||||
override fun setState(state: FileEditorState) {
|
||||
if (state is SnippetTestSplitEditorState) {
|
||||
inputEditor.setState(state.inputState)
|
||||
if (outputEditor != null && state.outputState != null) {
|
||||
outputEditor!!.setState(state.outputState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getState(level: FileEditorStateLevel): FileEditorState {
|
||||
return SnippetTestSplitEditorState(inputEditor.getState(level), outputEditor?.getState(level))
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean = inputEditor.isModified || outputEditor?.isModified ?: false
|
||||
|
||||
override fun isValid(): Boolean = inputEditor.isValid && outputEditor?.isValid ?: true
|
||||
|
||||
override fun addPropertyChangeListener(listener: PropertyChangeListener) {
|
||||
inputEditor.addPropertyChangeListener(listener)
|
||||
outputEditor?.addPropertyChangeListener(listener)
|
||||
}
|
||||
|
||||
override fun removePropertyChangeListener(listener: PropertyChangeListener) {
|
||||
inputEditor.removePropertyChangeListener(listener)
|
||||
outputEditor?.removePropertyChangeListener(listener)
|
||||
}
|
||||
|
||||
override fun getCurrentLocation(): FileEditorLocation? = inputEditor.currentLocation
|
||||
|
||||
override fun dispose() {
|
||||
inputEditor.dispose()
|
||||
outputEditor?.dispose()
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the output editor by reloading the output file from disk. This is useful after
|
||||
* running tests, as the output file may have been created or changed (e.g., from .pcf to .err).
|
||||
*/
|
||||
private fun refreshOutputEditor(project: Project) {
|
||||
val inputFile = inputEditor.file ?: return
|
||||
|
||||
// Refresh the input file's parent to pick up any new output files
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
VirtualFileManager.getInstance().asyncRefresh {
|
||||
val currentOutputFile = findOutputFile(inputFile)
|
||||
val editorOutputFile = outputEditor?.file
|
||||
when {
|
||||
currentOutputFile != null && currentOutputFile != editorOutputFile -> {
|
||||
// No output file exists; set split mode.
|
||||
if (editorOutputFile == null) {
|
||||
replaceOutputEditorAndSetSplitMode(project, currentOutputFile)
|
||||
} else {
|
||||
// The output file has changed (e.g., .pcf to .err or vice versa), or got created.
|
||||
// We need to replace the output editor with a new one for the new file
|
||||
replaceOutputEditor(project, currentOutputFile)
|
||||
}
|
||||
}
|
||||
else -> currentOutputFile?.refresh(true, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current output editor with a new one for the specified file. This is necessary
|
||||
* when the output file type changes (e.g., from .pcf to .err).
|
||||
*/
|
||||
private fun replaceOutputEditorAndSetSplitMode(project: Project, newOutputFile: VirtualFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val textEditorProvider = TextEditorProvider.getInstance()
|
||||
val newEditor = textEditorProvider.createEditor(project, newOutputFile) as TextEditor
|
||||
|
||||
// Dispose the old editor
|
||||
outputEditor?.dispose()
|
||||
|
||||
// Update the reference to the new editor
|
||||
outputEditor = newEditor
|
||||
setViewMode(ViewMode.SPLIT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current output editor with a new one for the specified file. This is necessary
|
||||
* when the output file type changes (e.g., from .pcf to .err).
|
||||
*/
|
||||
private fun replaceOutputEditor(project: Project, newOutputFile: VirtualFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val textEditorProvider = TextEditorProvider.getInstance()
|
||||
val newEditor = textEditorProvider.createEditor(project, newOutputFile) as TextEditor
|
||||
|
||||
// Dispose the old editor
|
||||
outputEditor?.dispose()
|
||||
|
||||
// Update the reference to the new editor
|
||||
outputEditor = newEditor
|
||||
|
||||
// Update the split pane with the new editor
|
||||
when (currentViewMode) {
|
||||
ViewMode.SPLIT -> {
|
||||
splitPane.rightComponent = newEditor.component
|
||||
splitPane.revalidate()
|
||||
splitPane.repaint()
|
||||
}
|
||||
ViewMode.INPUT_ONLY -> {
|
||||
// Nothing to do, output is not visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class ViewMode {
|
||||
INPUT_ONLY,
|
||||
SPLIT,
|
||||
}
|
||||
|
||||
private inner class ShowInputOnlyAction :
|
||||
ToggleAction("Show Input Only", "Show only the input file", AllIcons.General.LayoutEditorOnly) {
|
||||
override fun isSelected(e: AnActionEvent): Boolean = currentViewMode == ViewMode.INPUT_ONLY
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
if (state) setViewMode(ViewMode.INPUT_ONLY)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ShowSplitAction :
|
||||
ToggleAction(
|
||||
"Show Split",
|
||||
"Show input and output side by side",
|
||||
AllIcons.General.LayoutEditorPreview,
|
||||
) {
|
||||
override fun isSelected(e: AnActionEvent): Boolean = currentViewMode == ViewMode.SPLIT
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
if (state) setViewMode(ViewMode.SPLIT)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class RunTestAction :
|
||||
AnAction("Run Test", "Run the snippet test", AllIcons.Actions.Execute) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
executeTest(project, DefaultRunExecutor.getRunExecutorInstance())
|
||||
}
|
||||
}
|
||||
|
||||
private inner class RunAllTestsAction :
|
||||
AnAction("Run All Tests", "Run all snippet tests", AllIcons.Actions.RunAll) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
executeAllTests(project, DefaultRunExecutor.getRunExecutorInstance())
|
||||
}
|
||||
}
|
||||
|
||||
private inner class DebugTestAction :
|
||||
AnAction("Debug Test", "Debug the snippet test", AllIcons.Actions.StartDebugger) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
executeTest(project, DefaultDebugExecutor.getDebugExecutorInstance())
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OverwriteSnippetAction :
|
||||
AnAction(
|
||||
"Overwrite Snippet",
|
||||
"Run test and regenerate expected output",
|
||||
AllIcons.Actions.RerunAutomatically,
|
||||
) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
|
||||
executeTest(
|
||||
project,
|
||||
DefaultRunExecutor.getRunExecutorInstance(),
|
||||
mapOf("OVERWRITE_SNIPPETS" to "1"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JUnit UniqueID selector for the snippet test. E.g.
|
||||
*
|
||||
* ```
|
||||
* [engine:LanguageSnippetTestsEngine]/[inputDirNode:lambdas]/[inputFileNode:lambdaStackTrace2.pkl]
|
||||
* ```
|
||||
*/
|
||||
private fun buildUniqueId(file: VirtualFile): String? {
|
||||
val path = file.path
|
||||
// Pattern: .../LanguageSnippetTests/input/lambdas/lambdaStackTrace2.pkl
|
||||
val pattern = Regex(".*/([^/]+)/src/test/files/(\\w+)/input/(.+)$")
|
||||
val match = pattern.find(path) ?: return null
|
||||
|
||||
val testType = match.groupValues[2] // e.g., "LanguageSnippetTests"
|
||||
val relativePath = match.groupValues[3] // e.g., "lambdas/lambdaStackTrace2.pkl"
|
||||
|
||||
// Extract directory and filename
|
||||
val parts = relativePath.split("/")
|
||||
val fileName = parts.last()
|
||||
val engineName = testType + "Engine"
|
||||
val uniqueId = buildString {
|
||||
append("[engine:$engineName]")
|
||||
if (parts.size > 1) {
|
||||
for (dir in parts.dropLast(1)) {
|
||||
append("/[inputDirNode:$dir]")
|
||||
}
|
||||
}
|
||||
append("/[inputFileNode:$fileName]")
|
||||
}
|
||||
|
||||
return uniqueId
|
||||
}
|
||||
|
||||
private fun getTestClass(project: Project, file: VirtualFile): PsiClass {
|
||||
val path = file.path
|
||||
// Pattern: .../LanguageSnippetTests/input/lambdas/lambdaStackTrace2.pkl
|
||||
val pattern = Regex(".*/([^/]+)/src/test/files/(\\w+)/input/(.+)$")
|
||||
val match = pattern.find(path)!!
|
||||
val folder = match.groupValues[2]
|
||||
val className =
|
||||
when (folder) {
|
||||
"LanguageSnippetTests" -> "org.pkl.core.LanguageSnippetTests"
|
||||
"FormatterSnippetTests" -> "org.pkl.formatter.FormatterSnippetTests"
|
||||
// legacy; doesn't exist on main branch
|
||||
"SnippetTests" -> "org.pkl.server.SnippetTests"
|
||||
else -> throw IllegalStateException("")
|
||||
}
|
||||
return JavaPsiFacade.getInstance(project)
|
||||
.findClass(className, GlobalSearchScope.allScope(project))!!
|
||||
}
|
||||
|
||||
private fun executeAllTests(project: Project, executor: Executor) {
|
||||
val file = inputEditor.file ?: return
|
||||
|
||||
val path = file.path
|
||||
// Pattern: .../LanguageSnippetTests/input/lambdas/lambdaStackTrace2.pkl
|
||||
val pattern = Regex(".*/([^/]+)/src/test/files/(\\w+)/input/(.+)$")
|
||||
val match = pattern.find(path) ?: return
|
||||
|
||||
val testType = match.groupValues[2] // e.g., "LanguageSnippetTests"
|
||||
executeTest(project, executor, testType) { data ->
|
||||
data.TEST_OBJECT = JUnitConfiguration.TEST_CLASS
|
||||
data.setMainClass(getTestClass(project, file))
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeTest(
|
||||
project: Project,
|
||||
executor: Executor,
|
||||
envVars: Map<String, String> = emptyMap(),
|
||||
) {
|
||||
val file = inputEditor.file ?: return
|
||||
val uniqueId = buildUniqueId(file) ?: return
|
||||
executeTest(project, executor, file.name) { data ->
|
||||
data.TEST_OBJECT = JUnitConfiguration.TEST_UNIQUE_ID
|
||||
data.setUniqueIds(uniqueId)
|
||||
|
||||
if (envVars.isNotEmpty()) {
|
||||
data.envs = envVars.toMutableMap()
|
||||
data.PASS_PARENT_ENVS = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeTest(
|
||||
project: Project,
|
||||
executor: Executor,
|
||||
title: String,
|
||||
configure: (JUnitConfiguration.Data) -> Unit,
|
||||
) {
|
||||
val file = inputEditor.file ?: return
|
||||
val module = ModuleUtil.findModuleForFile(file, project) ?: return
|
||||
|
||||
val runManager = RunManager.getInstance(project)
|
||||
val configurationType = JUnitConfigurationType.getInstance()
|
||||
val configurationFactory = configurationType.configurationFactories.first()
|
||||
|
||||
val settings = runManager.createConfiguration(title, configurationFactory)
|
||||
|
||||
val configuration = settings.configuration as? JUnitConfiguration ?: return
|
||||
configure(configuration.persistentData)
|
||||
|
||||
configuration.setModule(module)
|
||||
|
||||
// Add the configuration to the RunManager so it appears in recent configurations
|
||||
runManager.addConfiguration(settings)
|
||||
runManager.selectedConfiguration = settings
|
||||
|
||||
// Add listener to refresh output editor after test completes
|
||||
val messageBus = project.messageBus.connect()
|
||||
messageBus.subscribe(
|
||||
ExecutionManager.EXECUTION_TOPIC,
|
||||
object : ExecutionListener {
|
||||
override fun processTerminated(
|
||||
executorId: String,
|
||||
env: ExecutionEnvironment,
|
||||
handler: ProcessHandler,
|
||||
exitCode: Int,
|
||||
) {
|
||||
// Check if this is our test run
|
||||
if (env.runProfile == configuration) {
|
||||
// Refresh the output editor after the test completes
|
||||
refreshOutputEditor(project)
|
||||
// Disconnect the listener after use
|
||||
messageBus.disconnect()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
ProgramRunnerUtil.executeConfiguration(settings, executor)
|
||||
}
|
||||
}
|
||||
|
||||
data class SnippetTestSplitEditorState(
|
||||
val inputState: FileEditorState,
|
||||
val outputState: FileEditorState?,
|
||||
) : FileEditorState {
|
||||
override fun canBeMergedWith(otherState: FileEditorState, level: FileEditorStateLevel): Boolean {
|
||||
val other = otherState as? SnippetTestSplitEditorState ?: return false
|
||||
if (!inputState.canBeMergedWith(other.inputState, level)) return false
|
||||
val otherState = other.outputState
|
||||
return when {
|
||||
outputState == null && otherState == null -> true
|
||||
outputState != null && otherState != null -> outputState.canBeMergedWith(otherState, level)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* 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 org.pkl.internal.intellij
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
|
||||
internal fun VirtualFile.isSnippetTestInputFile(): Boolean {
|
||||
return path.contains("/src/test/files/") && path.contains("/input/") && extension == "pkl"
|
||||
}
|
||||
|
||||
private val hiddenExtensionRegex = Regex(".*[.]([^.]*)[.]pkl")
|
||||
|
||||
private fun possibleOutputPaths(testType: String, relativePath: String): String? {
|
||||
return when (testType) {
|
||||
"LanguageSnippetTests" ->
|
||||
if (relativePath.matches(hiddenExtensionRegex)) relativePath.dropLast(4)
|
||||
else relativePath.dropLast(3) + "pcf"
|
||||
"FormatterSnippetTests" -> relativePath
|
||||
"SnippetTests" -> relativePath.replaceAfterLast('.', "yaml")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun findOutputFile(inputFile: VirtualFile): VirtualFile? {
|
||||
val path = inputFile.path
|
||||
val inputPattern = Regex(".*/src/test/files/(\\w+)/input/(.+)$")
|
||||
val match = inputPattern.find(path) ?: return null
|
||||
|
||||
val testType = match.groupValues[1]
|
||||
val relativePath = match.groupValues[2]
|
||||
val relativeOutputPath = possibleOutputPaths(testType, relativePath) ?: return null
|
||||
val outputPath = path.replace("/input/$relativePath", "/output/$relativeOutputPath")
|
||||
val fileManager = VirtualFileManager.getInstance()
|
||||
return fileManager.findFileByUrl("file://$outputPath")
|
||||
?: fileManager.findFileByUrl("file://${outputPath.replaceAfterLast('.', "err")}")
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<idea-plugin>
|
||||
<id>org.pkl.intellij.snippet-test-helper</id>
|
||||
<name>Pkl Snippet Test Helper</name>
|
||||
<vendor>Apple Inc. and the Pkl project authors</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Automatically opens snippet test output files when input files are opened.
|
||||
|
||||
This is an internal plugin that is meant for development on the Pkl project itself.
|
||||
]]></description>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.java</depends>
|
||||
<depends>org.jetbrains.plugins.gradle</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileEditorProvider implementation="org.pkl.internal.intellij.SnippetTestEditorProvider"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -47,8 +47,6 @@ include("pkl-formatter")
|
||||
|
||||
include("pkl-gradle")
|
||||
|
||||
include("pkl-internal-intellij-plugin")
|
||||
|
||||
include("pkl-parser")
|
||||
|
||||
include("pkl-server")
|
||||
|
||||
Reference in New Issue
Block a user