diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..881aeb3 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,38 @@ +name: Build Plugin + +on: push +#on: +# push: +# branches: [ "master" ] +# pull_request: +# branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CI: true + CI_BUILD_VERSION: 1.1.${{ github.run_number }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Build + run: | + chmod 777 gradlew + ./gradlew buildPlugin + + - name: Upload artifact + uses: actions/upload-artifact@v3.1.0 + with: + name: v${{ env.CI_BUILD_VERSION }} + path: build/distributions/*.zip diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 76bc588..0000000 --- a/build.gradle +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2017. tangzx(love.tangzx@qq.com) - * - * 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. - */ - -plugins { - id 'org.jetbrains.intellij' version "0.6.5" - id "org.jetbrains.kotlin.jvm" version "1.4.20" - id "de.undercouch.download" version "3.4.3" -} - -repositories { - mavenCentral() - jcenter() -} - -intellij { - pluginName 'EmmyLua-AttachDebugger' - type 'IU' - updateSinceUntilBuild false - downloadSources false - version = "IC-202.6397.94" - localPath System.getenv("IDEA_HOME_202") - plugins 'com.tang:1.3.5.185-IDEA203' -} - -sourceSets { - main { - java.srcDirs 'src' - resources { - srcDirs 'resources' - exclude "debugger/**" - } - } -} - -// Appveyor CI -if (System.env['APPVEYOR']) { - if (System.env['APPVEYOR_REPO_TAG_NAME']) { - version = System.env['APPVEYOR_REPO_TAG_NAME'] - } else { - version = System.env['APPVEYOR_BUILD_VERSION'] - } -} - -def RES_DIR = "resources" - -task downloadEmmyDebugger(type: Download) { - src ([ - "https://github.com/EmmyLua/EmmyLuaDebugger/releases/download/${emmyDebuggerVersion}/emmy_core@x64.zip", - "https://github.com/EmmyLua/EmmyLuaDebugger/releases/download/${emmyDebuggerVersion}/emmy_core@x86.zip", - ]) - dest "temp" -} - -task unzipEmmyDebugger(type: Copy, dependsOn: downloadEmmyDebugger) { - from(zipTree("temp/emmy_core@x64.zip")) { - into "x64" - } - from(zipTree("temp/emmy_core@x86.zip")) { - into "x86" - } - destinationDir file("temp") -} - -task installEmmyDebugger(dependsOn: unzipEmmyDebugger, type: Copy) { - from("temp/x64/") { - include "*.*" - into "debugger/emmy/windows/x64" - } - from("temp/x86/") { - include "*.*" - into "debugger/emmy/windows/x86" - } - destinationDir file(RES_DIR) -} -buildPlugin.dependsOn([installEmmyDebugger]) -buildPlugin.from(fileTree(dir: RES_DIR, includes: ['debugger/**'])) { - into "/${project.name}/classes/" -} -buildPlugin.from(fileTree(dir: RES_DIR, include: '!!DONT_UNZIP_ME!!.txt')) { - into "/${project.name}" -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..77ee969 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017. tangzx(love.tangzx@qq.com) + * + * 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. + */ + +import de.undercouch.gradle.tasks.download.* + +plugins { + id("java") + id("org.jetbrains.kotlin.jvm") version "1.7.20" + id("org.jetbrains.intellij") version "1.13.2" + id("de.undercouch.download").version("5.3.0") +} + +repositories { + mavenCentral() +} + +intellij { + pluginName.set("EmmyLua-AttachDebugger") + version.set("2023.1") + type.set("IC") // Target IDE Platform + + plugins.set(listOf("com.tang:1.4.8-IDEA231")) +} + +val emmyluaDebuggerVersion = "1.8.2" +val emmyluaDebuggerProjectUrl = "https://github.com/EmmyLua/EmmyLuaDebugger" + +task("downloadDebugger", type = Download::class) { + src(arrayOf( + "${emmyluaDebuggerProjectUrl }/releases/download/${emmyluaDebuggerVersion}/win32-x86.zip", + "${emmyluaDebuggerProjectUrl }/releases/download/${emmyluaDebuggerVersion}/win32-x64.zip", + )) + + dest("temp") +} + +task("unzipDebugger", type = Copy::class) { + dependsOn("downloadDebugger") + from(zipTree("temp/win32-x64.zip")) { + into("bin/win32-x64") + } + from(zipTree("temp/win32-x86.zip")) { + into("bin/win32-x86") + } + destinationDir = file("temp") +} + +task("installDebugger", type = Copy::class) { + dependsOn("unzipDebugger") + from("temp/bin") { + into("bin") + } + + destinationDir = file("src/main/resources/debugger") +} + +tasks { + // Set the JVM compatibility versions + withType { + sourceCompatibility = "17" + targetCompatibility = "17" + } + withType { + kotlinOptions.jvmTarget = "17" + } + + patchPluginXml { + sinceBuild.set("223") + untilBuild.set("242.*") + } + + signPlugin { + certificateChain.set(System.getenv("CERTIFICATE_CHAIN")) + privateKey.set(System.getenv("PRIVATE_KEY")) + password.set(System.getenv("PRIVATE_KEY_PASSWORD")) + } + + publishPlugin { + token.set(System.getenv("PUBLISH_TOKEN")) + } + + buildPlugin { + dependsOn("installDebugger") + } + + withType { + doLast { + copy { + from("src/main/resources/debugger/bin") + into("$destinationDir/${pluginName.get()}/debugger/bin") + } + } + } +} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index b9ad18a..0000000 --- a/gradle.properties +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (c) 2017. tangzx(love.tangzx@qq.com) -# -# 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. -# - -version = 1.0.0 -# https://github.com/EmmyLua/EmmyLuaDebugger/releases -emmyDebuggerVersion = 1.0.16 -# https://github.com/EmmyLua/EmmyLuaLegacyDebugger/releases - -javaVersion = 1.8 - -artifactsPath = build/artifacts - -org.gradle.jvmargs=-Xmx1536m -Dfile.encoding=utf-8 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e499bd6..fa64699 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -16,6 +16,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..dbb10a8 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "EmmyLua-AttachDebugger" \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachConfigurationType.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachConfigurationType.kt new file mode 100644 index 0000000..51211d2 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachConfigurationType.kt @@ -0,0 +1,106 @@ +package com.tang.intellij.lua.debugger.emmyAttach + +import com.intellij.execution.Executor +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.execution.configurations.ConfigurationType +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.execution.configurations.RunProfileState +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.runners.RunConfigurationWithSuppressedDefaultRunAction +import com.intellij.openapi.module.Module +import com.intellij.openapi.options.SettingsEditor +import com.intellij.openapi.options.SettingsEditorGroup +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.JDOMExternalizerUtil +import com.tang.intellij.lua.debugger.LuaCommandLineState +import com.tang.intellij.lua.debugger.LuaRunConfiguration +import com.tang.intellij.lua.lang.LuaIcons +import org.jdom.Element +import javax.swing.Icon +import com.tang.intellij.lua.debugger.LuaConfigurationFactory +import com.tang.intellij.lua.debugger.emmy.EmmyDebugTransportType + +class EmmyAttachConfigurationType : ConfigurationType { + override fun getIcon(): Icon { + return LuaIcons.FILE + } + + override fun getConfigurationTypeDescription(): String { + return "Emmy Attach Debugger" + } + + override fun getId(): String { + return "lua.emmyAttach.debugger" + } + + override fun getDisplayName(): String { + return "Emmy Attach Debugger" + } + + override fun getConfigurationFactories(): Array { + return arrayOf(EmmyAttachDebuggerConfigurationFactory(this)) + } +} + +enum class EmmyAttachMode(private val desc: String) { + Pid("Pid"), + ProcessName("ProcessName"); + + override fun toString(): String { + return desc; + } +} + +class EmmyAttachDebuggerConfigurationFactory(val type: EmmyAttachConfigurationType) : LuaConfigurationFactory(type) { + override fun createTemplateConfiguration(project: Project): RunConfiguration { + return EmmyAttachDebugConfiguration(project, this) + } +} + +class EmmyAttachDebugConfiguration(project: Project, factory: EmmyAttachDebuggerConfigurationFactory) : + LuaRunConfiguration(project, factory), + RunConfigurationWithSuppressedDefaultRunAction { + var attachMode = EmmyAttachMode.Pid; + var pid = "0" + var processName = "" + var encoding = "gbk" + + override fun getConfigurationEditor(): SettingsEditor { + val group = SettingsEditorGroup() + group.addEditor("emmy", EmmyAttachDebugSettingsPanel(project)) + return group + } + + override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState { + return LuaCommandLineState(environment) + } + + override fun getValidModules(): Collection { + return emptyList() + } + + override fun writeExternal(element: Element) { + super.writeExternal(element) + JDOMExternalizerUtil.writeField(element, "AttachMode", attachMode.ordinal.toString()) + JDOMExternalizerUtil.writeField(element, "Pid", pid) + JDOMExternalizerUtil.writeField(element, "ProcessName", processName) + JDOMExternalizerUtil.writeField(element, "Encoding", encoding) + } + + override fun readExternal(element: Element) { + super.readExternal(element) + JDOMExternalizerUtil.readField(element, "AttachMode")?.let { value -> + val i = value.toInt() + attachMode = EmmyAttachMode.values().find { it.ordinal == i } ?: EmmyAttachMode.Pid + } + JDOMExternalizerUtil.readField(element, "Pid")?.let { + pid = it + } + JDOMExternalizerUtil.readField(element, "ProcessName")?.let { + processName = it + } + JDOMExternalizerUtil.readField(element, "Encoding")?.let { + encoding = it + } + } +} \ No newline at end of file diff --git a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt similarity index 69% rename from src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt rename to src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt index ca92e21..9535ef5 100644 --- a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugProcess.kt @@ -26,7 +26,10 @@ import com.tang.intellij.lua.debugger.LogConsoleType import com.tang.intellij.lua.debugger.emmy.* import com.tang.intellij.lua.debugger.utils.FileUtils -class EmmyAttachDebugProcess(session: XDebugSession, private val processInfo: ProcessInfo) : EmmyDebugProcessBase(session) { +class EmmyAttachDebugProcess( + session: XDebugSession, + private val processInfo: ProcessInfo +) : EmmyDebugProcessBase(session) { override fun setupTransporter() { val suc = attach() if (!suc) { @@ -45,8 +48,8 @@ class EmmyAttachDebugProcess(session: XDebugSession, private val processInfo: Pr transporter.start() } - private fun detectArch(pid: Int): EmmyWinArch { - val tool = FileUtils.getPluginVirtualFile("debugger/emmy/windows/x86/emmy_tool.exe") + private fun detectArchByPid(pid: Int): EmmyWinArch { + val tool = FileUtils.getPluginVirtualFile("debugger/bin/win32-x86/emmy_tool.exe") val commandLine = GeneralCommandLine(tool) commandLine.addParameters("arch_pid", "$pid") val process = commandLine.createProcess() @@ -56,17 +59,17 @@ class EmmyAttachDebugProcess(session: XDebugSession, private val processInfo: Pr } private fun attach(): Boolean { - val arch = detectArch(processInfo.pid) - val path = FileUtils.getPluginVirtualFile("debugger/emmy/windows/${arch}") + val arch = detectArchByPid(processInfo.pid) + val path = FileUtils.getPluginVirtualFile("debugger/bin/win32-${arch}") val commandLine = GeneralCommandLine("${path}/emmy_tool.exe") commandLine.addParameters( - "attach", - "-p", - "${processInfo.pid}", - "-dir", - path, - "-dll", - "emmy_hook.dll" + "attach", + "-p", + "${processInfo.pid}", + "-dir", + path, + "-dll", + "emmy_hook.dll" ) val handler = OSProcessHandler(commandLine) handler.addProcessListener(object : ProcessListener { @@ -81,8 +84,16 @@ class EmmyAttachDebugProcess(session: XDebugSession, private val processInfo: Pr override fun onTextAvailable(processEvent: ProcessEvent, key: Key<*>) { when (key) { - ProcessOutputTypes.STDERR -> print(processEvent.text, LogConsoleType.NORMAL, ConsoleViewContentType.ERROR_OUTPUT) - ProcessOutputTypes.STDOUT -> print(processEvent.text, LogConsoleType.NORMAL, ConsoleViewContentType.SYSTEM_OUTPUT) + ProcessOutputTypes.STDERR -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.ERROR_OUTPUT + ) + ProcessOutputTypes.STDOUT -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) } } }) @@ -94,8 +105,11 @@ class EmmyAttachDebugProcess(session: XDebugSession, private val processInfo: Pr override fun onReceiveMessage(cmd: MessageCMD, json: String) { if (cmd == MessageCMD.AttachedNotify) { val msg = Gson().fromJson(json, AttachedNotify::class.java) - println("Attached to lua state 0x${msg.state.toString(16)}", LogConsoleType.NORMAL, ConsoleViewContentType.SYSTEM_OUTPUT) - } - else super.onReceiveMessage(cmd, json) + println( + "Attached to lua state 0x${msg.state.toString(16)}", + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } else super.onReceiveMessage(cmd, json) } } \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.form b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.form new file mode 100644 index 0000000..bca49bb --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.form @@ -0,0 +1,93 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.java b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.java new file mode 100644 index 0000000..1df8332 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugSettingsPanel.java @@ -0,0 +1,92 @@ +package com.tang.intellij.lua.debugger.emmyAttach; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SettingsEditor; +import com.intellij.openapi.project.Project; +import com.tang.intellij.lua.debugger.utils.ProcessDetailInfo; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class EmmyAttachDebugSettingsPanel extends SettingsEditor implements DocumentListener { + private JTextField ProcessId; + + private JPanel panel; + private JTextField ProcessName; + private JTextField Encoding; + + private JRadioButton UsePid; + private JRadioButton UseProcessName; + private JPanel AttachMode; + private ButtonGroup AttachModeGroup; + + public EmmyAttachDebugSettingsPanel(Project project) { + ProcessId.getDocument().addDocumentListener(this); + ProcessName.getDocument().addDocumentListener(this); + + Encoding.setText("gbk"); + Encoding.getDocument().addDocumentListener(this); + + AttachModeGroup = new ButtonGroup(); + AttachModeGroup.add(UsePid); + AttachModeGroup.add(UseProcessName); + UsePid.addChangeListener(e -> onChanged()); + UseProcessName.addChangeListener(e -> onChanged()); + } + + + @Override + protected void resetEditorFrom(@NotNull EmmyAttachDebugConfiguration configuration) { + ProcessId.setText(configuration.getPid()); + ProcessName.setText(configuration.getProcessName()); + Encoding.setText(configuration.getEncoding()); + + if(configuration.getAttachMode() == EmmyAttachMode.Pid){ + UsePid.setSelected(true); + } + else if(configuration.getAttachMode() == EmmyAttachMode.ProcessName){ + UseProcessName.setSelected(true); + } + + } + + @Override + protected void applyEditorTo(@NotNull EmmyAttachDebugConfiguration configuration) throws ConfigurationException { + configuration.setPid(ProcessId.getText()); + configuration.setProcessName(ProcessName.getText()); + configuration.setEncoding(Encoding.getText()); + + if (UsePid.isSelected()) { + configuration.setAttachMode(EmmyAttachMode.Pid); + } else if (UseProcessName.isSelected()) { + configuration.setAttachMode(EmmyAttachMode.ProcessName); + } + } + + @Override + protected @NotNull + JComponent createEditor() { + return panel; + } + + @Override + public void insertUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + @Override + public void removeUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + @Override + public void changedUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + private void onChanged() { + fireEditorStateChanged(); + } +} diff --git a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt similarity index 82% rename from src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt rename to src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt index 97daf8a..88cf15a 100644 --- a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebugger.kt @@ -27,15 +27,16 @@ import com.tang.intellij.lua.debugger.utils.ProcessDetailInfo import com.tang.intellij.lua.debugger.utils.getDisplayName class EmmyAttachDebugger( - private val processInfo: ProcessInfo, - private val detailInfo: ProcessDetailInfo + private val processInfo: ProcessInfo, + private val detailInfo: ProcessDetailInfo ) : XLocalAttachDebugger { override fun attachDebugSession(project: Project, processInfo: ProcessInfo) { val displayName = "PID:${processInfo.pid}($debuggerDisplayName)" - XDebuggerManager.getInstance(project).startSessionAndShowTab(displayName, null, object : XDebugProcessStarter() { - override fun start(xDebugSession: XDebugSession): XDebugProcess = + XDebuggerManager.getInstance(project) + .startSessionAndShowTab(displayName, null, object : XDebugProcessStarter() { + override fun start(xDebugSession: XDebugSession): XDebugProcess = EmmyAttachDebugProcess(xDebugSession, processInfo) - }) + }) } override fun getDebuggerDisplayName(): String { diff --git a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt similarity index 82% rename from src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt rename to src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt index fd5d1a1..cb4340a 100644 --- a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachDebuggerProvider.kt @@ -25,20 +25,25 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Key import com.intellij.openapi.util.SystemInfoRt import com.intellij.openapi.util.UserDataHolder +import com.intellij.xdebugger.attach.XAttachDebuggerProvider +import com.intellij.xdebugger.attach.XAttachHost import com.intellij.xdebugger.attach.XLocalAttachDebugger -import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider import com.tang.intellij.lua.debugger.utils.FileUtils import com.tang.intellij.lua.debugger.utils.ProcessDetailInfo import com.tang.intellij.lua.debugger.utils.listProcesses -class EmmyAttachDebuggerProvider : XLocalAttachDebuggerProvider { +class EmmyAttachDebuggerProvider : XAttachDebuggerProvider { companion object { val DETAIL_KEY = Key.create>("LuaLocalAttachDebuggerProvider.key") } private var processMap = mapOf() - override fun getAvailableDebuggers(project: Project, processInfo: ProcessInfo, userDataHolder: UserDataHolder): List { + override fun isAttachHostApplicable(p0: XAttachHost): Boolean { + return true + } + + override fun getAvailableDebuggers(project: Project, attachHost: XAttachHost , processInfo: ProcessInfo, userDataHolder: UserDataHolder): List { if (!SystemInfoRt.isWindows) return emptyList() if (userDataHolder.getUserData(DETAIL_KEY) == null) { @@ -48,7 +53,7 @@ class EmmyAttachDebuggerProvider : XLocalAttachDebuggerProvider { val notification = Notification( "Emmylua", "Error", - "Debugging tool 'emmy.arch.exe' has been removed, please reinstall the 'emmylua' plugin", + "Debugging tool 'emmy_tool.exe' has been removed, please reinstall the 'emmylua' plugin", NotificationType.WARNING) notification.isImportant = true Notifications.Bus.notify(notification) @@ -69,5 +74,6 @@ class EmmyAttachDebuggerProvider : XLocalAttachDebuggerProvider { return emptyList() } - override fun getAttachGroup() = EmmyAttachGroup.instance + override fun getPresentationGroup() = EmmyAttachGroup.instance + } \ No newline at end of file diff --git a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt similarity index 78% rename from src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt rename to src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt index 80e7e9c..0bade35 100644 --- a/src/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachGroup.kt @@ -14,25 +14,30 @@ * limitations under the License. */ + package com.tang.intellij.lua.debugger.emmyAttach import com.intellij.execution.process.ProcessInfo import com.intellij.openapi.project.Project import com.intellij.openapi.util.UserDataHolder -import com.intellij.xdebugger.attach.XLocalAttachGroup +import com.intellij.xdebugger.attach.XAttachProcessPresentationGroup import com.tang.intellij.lua.debugger.utils.getDisplayName import com.tang.intellij.lua.lang.LuaIcons import java.io.File import javax.swing.Icon import javax.swing.filechooser.FileSystemView -class EmmyAttachGroup : XLocalAttachGroup { +class EmmyAttachGroup : XAttachProcessPresentationGroup { companion object { val instance = EmmyAttachGroup() } - override fun getProcessDisplayText(project: Project, processInfo: ProcessInfo, userDataHolder: UserDataHolder): String { + override fun getItemDisplayText( + project: Project, + processInfo: ProcessInfo, + userDataHolder: UserDataHolder + ): String { val map = userDataHolder.getUserData(EmmyAttachDebuggerProvider.DETAIL_KEY) if (map != null) { val detail = map[processInfo.pid] @@ -42,7 +47,7 @@ class EmmyAttachGroup : XLocalAttachGroup { return processInfo.executableName } - override fun getProcessIcon(project: Project, processInfo: ProcessInfo, userDataHolder: UserDataHolder): Icon { + override fun getItemIcon(project: Project, processInfo: ProcessInfo, userDataHolder: UserDataHolder): Icon { val map = userDataHolder.getUserData(EmmyAttachDebuggerProvider.DETAIL_KEY) if (map != null) { val detail = map[processInfo.pid] @@ -59,8 +64,8 @@ class EmmyAttachGroup : XLocalAttachGroup { override fun getGroupName() = "EmmyLua Attach Debugger" - override fun compare(project: Project, a: ProcessInfo, b: ProcessInfo, userDataHolder: UserDataHolder) = - a.executableName.toLowerCase().compareTo(b.executableName.toLowerCase()) + override fun compare(a: ProcessInfo, b: ProcessInfo): Int = + a.executableName.lowercase().compareTo(b.executableName.lowercase()) override fun getOrder(): Int { return 0 diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachRunner.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachRunner.kt new file mode 100644 index 0000000..d3cc0e5 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyAttachRunner.kt @@ -0,0 +1,50 @@ +package com.tang.intellij.lua.debugger.emmyAttach + +import com.intellij.execution.configurations.RunProfile +import com.intellij.execution.configurations.RunProfileState +import com.intellij.execution.configurations.RunnerSettings +import com.intellij.execution.executors.DefaultDebugExecutor +import com.intellij.execution.process.ProcessInfo +import com.intellij.execution.runners.AsyncProgramRunner +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.runners.GenericProgramRunner +import com.intellij.execution.runners.ProgramRunner +import com.intellij.execution.ui.RunContentDescriptor +import com.intellij.openapi.ui.popup.JBPopupFactory +import com.intellij.xdebugger.XDebugProcess +import com.intellij.xdebugger.XDebugProcessStarter +import com.intellij.xdebugger.XDebugSession +import com.intellij.xdebugger.XDebuggerManager +import com.tang.intellij.lua.debugger.LuaRunner +import org.jetbrains.concurrency.AsyncPromise +import org.jetbrains.concurrency.Promise + + +class EmmyAttachRunner : LuaRunner() { + companion object { + const val ID = "lua.emmyAttach.runner" + } + + var configuration: EmmyAttachDebugConfiguration? = null; + + override fun getRunnerId() = ID + + override fun canRun(executorId: String, runProfile: RunProfile): Boolean { + if (DefaultDebugExecutor.EXECUTOR_ID == executorId && runProfile is EmmyAttachDebugConfiguration) { + configuration = runProfile + return true + } + return false + } + + override fun doExecute(state: RunProfileState, environment: ExecutionEnvironment): RunContentDescriptor { + val manager = XDebuggerManager.getInstance(environment.project) + val session = manager.startSession(environment, object : XDebugProcessStarter() { + override fun start(session: XDebugSession): XDebugProcess { + return EmmyConfigAttachDebugProcess(session, configuration!!) + } + }) + return session.runContentDescriptor + } + +} \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyConfigAttachDebugProcess.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyConfigAttachDebugProcess.kt new file mode 100644 index 0000000..a7282be --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyAttach/EmmyConfigAttachDebugProcess.kt @@ -0,0 +1,151 @@ +package com.tang.intellij.lua.debugger.emmyAttach + +import com.google.gson.Gson +import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.execution.process.OSProcessHandler +import com.intellij.execution.process.ProcessEvent +import com.intellij.execution.process.ProcessListener +import com.intellij.execution.process.ProcessOutputTypes +import com.intellij.execution.ui.ConsoleViewContentType +import com.intellij.openapi.ui.popup.JBPopupFactory +import com.intellij.openapi.util.Key +import com.intellij.xdebugger.XDebugSession +import com.tang.intellij.lua.debugger.LogConsoleType +import com.tang.intellij.lua.debugger.emmy.* +import com.tang.intellij.lua.debugger.utils.FileUtils +import com.tang.intellij.lua.debugger.utils.ProcessDetailInfo +import com.tang.intellij.lua.debugger.utils.listProcessesByEncoding + + +class EmmyConfigAttachDebugProcess( + session: XDebugSession, + val configuration: EmmyAttachDebugConfiguration +) : EmmyDebugProcessBase(session) { + + private var pid: Int = 0 + + override fun sessionInitialized() { + val attachMode = configuration.attachMode + + + if (attachMode == EmmyAttachMode.Pid) { + pid = configuration.pid.toInt() + return super.sessionInitialized() + } + + val processName = configuration.processName + val processes = listProcessesByEncoding(configuration.encoding) + val attachableList = mutableListOf() + for (info in processes) { + if (info.title.indexOf(processName) != -1 || info.path.indexOf(processName) != -1) { + attachableList.add(info) + } + } + + if (attachableList.size == 1) { + pid = attachableList.first().pid + return super.sessionInitialized() + } + + val jbInstance = JBPopupFactory.getInstance() + val displayMap = mutableMapOf() + + for (processDetailInfo in attachableList) { + displayMap["${processDetailInfo.pid}:${processDetailInfo.title}"] = processDetailInfo + } + + jbInstance.createPopupChooserBuilder(displayMap.keys.toList()) + .setTitle("choose best match process") + .setMovable(true) + .setItemChosenCallback { + val processDetailInfo = displayMap[it] + if (processDetailInfo != null) { + pid = processDetailInfo.pid + } + super.sessionInitialized() + }.createPopup().showInFocusCenter() + } + + override fun setupTransporter() { + val suc = attach() + if (!suc) { + session.stop() + return + } + var port = pid + // 1024 - 65535 + while (port > 0xffff) port -= 0xffff + while (port < 0x400) port += 0x400 + + val transporter = SocketClientTransporter("localhost", port) + transporter.handler = this + transporter.logger = this + this.transporter = transporter + transporter.start() + } + + private fun detectArchByPid(pid: Int): EmmyWinArch { + val tool = FileUtils.getPluginVirtualFile("debugger/bin/win32-x86/emmy_tool.exe") + val commandLine = GeneralCommandLine(tool) + commandLine.addParameters("arch_pid", "$pid") + val process = commandLine.createProcess() + process.waitFor() + val exitValue = process.exitValue() + return if (exitValue == 0) EmmyWinArch.X64 else EmmyWinArch.X86 + } + + private fun attach(): Boolean { + val arch = detectArchByPid(pid) + val path = FileUtils.getPluginVirtualFile("debugger/bin/win32-${arch}") + val commandLine = GeneralCommandLine("${path}/emmy_tool.exe") + commandLine.addParameters( + "attach", + "-p", + "${pid}", + "-dir", + path, + "-dll", + "emmy_hook.dll" + ) + val handler = OSProcessHandler(commandLine) + handler.addProcessListener(object : ProcessListener { + override fun startNotified(processEvent: ProcessEvent) { + } + + override fun processTerminated(processEvent: ProcessEvent) { + } + + override fun processWillTerminate(processEvent: ProcessEvent, b: Boolean) { + } + + override fun onTextAvailable(processEvent: ProcessEvent, key: Key<*>) { + when (key) { + ProcessOutputTypes.STDERR -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.ERROR_OUTPUT + ) + ProcessOutputTypes.STDOUT -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } + } + }) + handler.startNotify() + handler.waitFor() + return handler.exitCode == 0 + } + + override fun onReceiveMessage(cmd: MessageCMD, json: String) { + if (cmd == MessageCMD.AttachedNotify) { + val msg = Gson().fromJson(json, AttachedNotify::class.java) + println( + "Attached to lua state 0x${msg.state.toString(16)}", + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } else super.onReceiveMessage(cmd, json) + } +} \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchConfigurationType.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchConfigurationType.kt new file mode 100644 index 0000000..03cdc63 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchConfigurationType.kt @@ -0,0 +1,95 @@ +package com.tang.intellij.lua.debugger.emmyLaunch + +import com.intellij.execution.Executor +import com.intellij.execution.configurations.* +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.runners.RunConfigurationWithSuppressedDefaultRunAction +import com.intellij.openapi.module.Module +import com.intellij.openapi.options.SettingsEditor +import com.intellij.openapi.options.SettingsEditorGroup +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.JDOMExternalizerUtil +import com.tang.intellij.lua.debugger.LuaCommandLineState +import com.tang.intellij.lua.debugger.LuaConfigurationFactory +import com.tang.intellij.lua.debugger.LuaRunConfiguration +import com.tang.intellij.lua.lang.LuaIcons +import org.jdom.Element +import javax.swing.Icon + + +class EmmyLaunchConfigurationType : ConfigurationType { + override fun getIcon(): Icon { + return LuaIcons.FILE + } + + override fun getConfigurationTypeDescription(): String { + return "Emmy Launch debugger" + } + + override fun getId(): String { + return "lua.emmyLaunch.debugger" + } + + override fun getDisplayName(): String { + return "Emmy Launch debugger" + } + + override fun getConfigurationFactories(): Array { + return arrayOf( EmmyLaunchDebuggerConfigurationFactory(this)) + } +} + + +class EmmyLaunchDebuggerConfigurationFactory(val type: EmmyLaunchConfigurationType) : LuaConfigurationFactory(type) { + override fun createTemplateConfiguration(project: Project): RunConfiguration { + return EmmyLaunchDebugConfiguration(project, this) + } +} + +class EmmyLaunchDebugConfiguration(project: Project, factory: EmmyLaunchDebuggerConfigurationFactory) : LuaRunConfiguration(project, factory), + RunConfigurationWithSuppressedDefaultRunAction { + var program = "lua" + var workingDirectory = "" + var parameter = "" + var useWindowsTerminal = false + + override fun getConfigurationEditor(): SettingsEditor { + val group = SettingsEditorGroup() + group.addEditor("emmy", EmmyLaunchDebugSettingsPanel(project)) + return group + } + + override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState { + return LuaCommandLineState(environment) + } + + override fun getValidModules(): Collection { + return emptyList() + } + + override fun writeExternal(element: Element) { + super.writeExternal(element) + JDOMExternalizerUtil.writeField(element, "Program", program) + JDOMExternalizerUtil.writeField(element, "WorkingDirectory", workingDirectory) + JDOMExternalizerUtil.writeField(element, "Parameter", parameter) + JDOMExternalizerUtil.writeField(element, "UseWindowsTerminal", useWindowsTerminal.toString()) + } + + override fun readExternal(element: Element) { + super.readExternal(element) + JDOMExternalizerUtil.readField(element, "Program")?.let { + program = it + } + JDOMExternalizerUtil.readField(element, "WorkingDirectory")?.let { + workingDirectory = it + } + JDOMExternalizerUtil.readField(element, "Parameter")?.let { + parameter = it + } + JDOMExternalizerUtil.readField(element, "UseWindowsTerminal")?.let { value -> + useWindowsTerminal = value == "true" + } + } + + +} \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugProcess.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugProcess.kt new file mode 100644 index 0000000..5b5cc40 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugProcess.kt @@ -0,0 +1,213 @@ +package com.tang.intellij.lua.debugger.emmyLaunch + +import com.google.gson.Gson +import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.execution.process.* +import com.intellij.execution.ui.ConsoleViewContentType +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.xdebugger.XDebugSession +import com.tang.intellij.lua.debugger.LogConsoleType +import com.tang.intellij.lua.debugger.emmy.* +import com.tang.intellij.lua.debugger.utils.FileUtils +import java.io.BufferedReader +import java.io.BufferedWriter +import java.io.InputStreamReader +import java.io.OutputStreamWriter +import java.net.Socket +import java.nio.charset.Charset +import java.util.concurrent.ThreadLocalRandom + + +class EmmyLaunchDebugProcess( + session: XDebugSession, + private val configuration: EmmyLaunchDebugConfiguration, + val project: Project +) : + EmmyDebugProcessBase(session) { + private var toolProcessHandler: ColoredProcessHandler? = null; + + override fun setupTransporter() { + LaunchDebug() { it -> + attachTo(it) + Thread.sleep(300) + toolProcessHandler?.let { tool -> + tool.processInput.write("connected\n".toByteArray()) + tool.processInput.flush() + } + } + } + + private fun attachTo(pid: Int) { + val port = getPort(pid) + val transporter = SocketClientTransporter("localhost", port) + transporter.handler = this + transporter.logger = this + this.transporter = transporter + transporter.start() + } + + private fun getPort(pid: Int): Int { + var port = pid + // 1024 - 65535 + while (port > 0xffff) port -= 0xffff + while (port < 0x400) port += 0x400 + return port; + } + + private fun detectArch(): EmmyWinArch { + val tool = FileUtils.getPluginVirtualFile("debugger/bin/win32-x64/emmy_tool.exe") + val commandLine = GeneralCommandLine(tool) + commandLine.addParameters("arch_file", configuration.program) + val process = commandLine.createProcess() + process.waitFor() + val exitValue = process.exitValue() + return if (exitValue == 0) EmmyWinArch.X64 else EmmyWinArch.X86 + } + + private fun LaunchWithWindows() { + val port = getPort(ThreadLocalRandom.current().nextInt(10240) + 10240); + val arch = detectArch() + val path = FileUtils.getPluginVirtualFile("debugger/bin/win32-${arch}") + val re = Regex("[^/\\\\]+\$") + val mc = re.find(configuration.program) + + val commandLine = GeneralCommandLine() + commandLine.exePath = "wt" + commandLine.setWorkDirectory(path) + commandLine.addParameters( + "--title", + if (mc != null) mc.groups[0]?.value else configuration.program, + "emmy_tool.exe", + "run_and_attach", + "-dll", + "emmy_hook.dll", + "-dir", + "\"${path}\"", + "-work", + "\"${configuration.workingDirectory}\"", + "-block-on-exit", + "-exe", + "\"${configuration.program}\"", + "-debug-port", + port.toString(), + "-listen-mode", + "-args", + "\"${configuration.parameter}\"" + ) + + val handler = OSProcessHandler(commandLine) + handler.addProcessListener(object : ProcessListener { + override fun startNotified(processEvent: ProcessEvent) { + } + + override fun processTerminated(processEvent: ProcessEvent) { + } + + override fun processWillTerminate(processEvent: ProcessEvent, b: Boolean) { + } + + override fun onTextAvailable(processEvent: ProcessEvent, key: Key<*>) { + when (key) { + ProcessOutputTypes.STDERR -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.ERROR_OUTPUT + ) + + ProcessOutputTypes.STDOUT -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } + } + }) + handler.startNotify() + } + + private fun LaunchDebug(onConnected: (pid: Int) -> Unit) { + val arch = detectArch() + val path = FileUtils.getPluginVirtualFile("debugger/bin/win32-${arch}") + + val commandLine = GeneralCommandLine().apply { + exePath = "${path}/emmy_tool.exe" + setWorkDirectory(path) + addParameter("launch") + if (configuration.useWindowsTerminal) { + addParameter("-create-new-window") + } + addParameters( + "-dll", + "emmy_hook.dll", + "-dir", + "\"${path}\"", + "-work", + "\"${configuration.workingDirectory}\"", + "-exe", + "\"${configuration.program}\"", + "-args", + "\"${configuration.parameter}\"" + ) + + charset = Charset.forName("utf8") + } + + var forOut = false; + toolProcessHandler = ColoredProcessHandler(commandLine) + toolProcessHandler?.addProcessListener(object : ProcessListener { + override fun startNotified(processEvent: ProcessEvent) { + } + + override fun processTerminated(processEvent: ProcessEvent) { + toolProcessHandler = null + } + + override fun processWillTerminate(processEvent: ProcessEvent, b: Boolean) { + } + + override fun onTextAvailable(processEvent: ProcessEvent, key: Key<*>) { + when (key) { + ProcessOutputTypes.STDERR -> print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.ERROR_OUTPUT + ) + + ProcessOutputTypes.STDOUT -> { + if (!forOut) { + forOut = true + val pid = processEvent.text.trim().toInt() + onConnected(pid) + return + } + print( + processEvent.text, + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } + } + } + }) + + toolProcessHandler?.startNotify() + } + + override fun onDisconnect() { + super.onDisconnect() + toolProcessHandler?.processInput?.write("close\n".toByteArray()) + toolProcessHandler = null + } + + override fun onReceiveMessage(cmd: MessageCMD, json: String) { + if (cmd == MessageCMD.AttachedNotify) { + val msg = Gson().fromJson(json, AttachedNotify::class.java) + println( + "Attached to lua state 0x${msg.state.toString(16)}", + LogConsoleType.NORMAL, + ConsoleViewContentType.SYSTEM_OUTPUT + ) + } else super.onReceiveMessage(cmd, json) + } +} \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.form b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.form new file mode 100644 index 0000000..4097d58 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.form @@ -0,0 +1,86 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.java b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.java new file mode 100644 index 0000000..29bd50e --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchDebugSettingsPanel.java @@ -0,0 +1,67 @@ +package com.tang.intellij.lua.debugger.emmyLaunch; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SettingsEditor; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class EmmyLaunchDebugSettingsPanel extends SettingsEditor implements DocumentListener { + private JTextField Program; + private JTextField WorkingDirectory; + private JTextField Parameters; + private JCheckBox useWindowsTerminalCheckBox; + private JPanel panel; + + public EmmyLaunchDebugSettingsPanel(Project project) { + Program.getDocument().addDocumentListener(this); + WorkingDirectory.getDocument().addDocumentListener(this); + Parameters.getDocument().addDocumentListener(this); + useWindowsTerminalCheckBox.addActionListener(e -> onChanged()); + } + + + @Override + protected void resetEditorFrom(@NotNull EmmyLaunchDebugConfiguration emmyLaunchDebugConfiguration) { + Program.setText(emmyLaunchDebugConfiguration.getProgram()); + WorkingDirectory.setText(emmyLaunchDebugConfiguration.getWorkingDirectory()); + Parameters.setText(emmyLaunchDebugConfiguration.getParameter()); + useWindowsTerminalCheckBox.setSelected(emmyLaunchDebugConfiguration.getUseWindowsTerminal()); + } + + @Override + protected void applyEditorTo(@NotNull EmmyLaunchDebugConfiguration emmyLaunchDebugConfiguration) throws ConfigurationException { + emmyLaunchDebugConfiguration.setProgram(Program.getText()); + emmyLaunchDebugConfiguration.setWorkingDirectory(WorkingDirectory.getText()); + emmyLaunchDebugConfiguration.setParameter(Parameters.getText()); + emmyLaunchDebugConfiguration.setUseWindowsTerminal(useWindowsTerminalCheckBox.isSelected()); + } + + @Override + protected @NotNull + JComponent createEditor() { + return panel; + } + + @Override + public void insertUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + @Override + public void removeUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + @Override + public void changedUpdate(DocumentEvent documentEvent) { + onChanged(); + } + + private void onChanged() { + fireEditorStateChanged(); + } +} diff --git a/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchRunner.kt b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchRunner.kt new file mode 100644 index 0000000..838aae9 --- /dev/null +++ b/src/main/java/com/tang/intellij/lua/debugger/emmyLaunch/EmmyLaunchRunner.kt @@ -0,0 +1,40 @@ +package com.tang.intellij.lua.debugger.emmyLaunch + +import com.intellij.execution.configurations.RunProfile +import com.intellij.execution.configurations.RunProfileState +import com.intellij.execution.executors.DefaultDebugExecutor +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.ui.RunContentDescriptor +import com.intellij.xdebugger.XDebugProcess +import com.intellij.xdebugger.XDebugProcessStarter +import com.intellij.xdebugger.XDebugSession +import com.intellij.xdebugger.XDebuggerManager +import com.tang.intellij.lua.debugger.LuaRunner + +class EmmyLaunchRunner : LuaRunner() { + companion object { + const val ID = "lua.emmyLaunch.runner" + } + var configuration: EmmyLaunchDebugConfiguration? = null; + + override fun getRunnerId() = ID + + override fun canRun(executorId: String, runProfile: RunProfile): Boolean { + if(DefaultDebugExecutor.EXECUTOR_ID == executorId && runProfile is EmmyLaunchDebugConfiguration){ + configuration = runProfile + return true + } + return false + } + + override fun doExecute(state: RunProfileState, environment: ExecutionEnvironment): RunContentDescriptor { + val project = environment.project + val manager = XDebuggerManager.getInstance(project) + val session = manager.startSession(environment, object : XDebugProcessStarter() { + override fun start(session: XDebugSession): XDebugProcess { + return EmmyLaunchDebugProcess(session, configuration!!, project) + } + }) + return session.runContentDescriptor + } +} \ No newline at end of file diff --git a/src/com/tang/intellij/lua/debugger/utils/FileUtils.kt b/src/main/java/com/tang/intellij/lua/debugger/utils/FileUtils.kt similarity index 82% rename from src/com/tang/intellij/lua/debugger/utils/FileUtils.kt rename to src/main/java/com/tang/intellij/lua/debugger/utils/FileUtils.kt index d089482..2ebe4ce 100644 --- a/src/com/tang/intellij/lua/debugger/utils/FileUtils.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/utils/FileUtils.kt @@ -1,16 +1,16 @@ package com.tang.intellij.lua.debugger.utils -import com.intellij.ide.plugins.PluginManager import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.ide.plugins.PluginManagerCore import java.io.File object FileUtils { private val pluginVirtualDirectory: VirtualFile? get() { - val descriptor = PluginManager.getPlugin(PluginId.getId("com.tang.emmylua.attach-debugger")) + val descriptor = PluginManagerCore.getPlugin(PluginId.getId("com.tang.emmylua.attach-debugger")) if (descriptor != null) { val pluginPath = descriptor.path @@ -23,7 +23,7 @@ object FileUtils { } val archExeFile: String? - get() = getPluginVirtualFile("debugger/emmy/windows/x86/emmy_tool.exe") + get() = getPluginVirtualFile("debugger/bin/win32-x86/emmy_tool.exe") fun getPluginVirtualFile(path: String): String? { val directory = pluginVirtualDirectory diff --git a/src/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt b/src/main/java/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt similarity index 69% rename from src/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt rename to src/main/java/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt index 360165e..87d2520 100644 --- a/src/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/utils/ProcessUtils.kt @@ -19,11 +19,12 @@ package com.tang.intellij.lua.debugger.utils import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.ProcessInfo import com.intellij.execution.util.ExecUtil +import java.nio.charset.Charset data class ProcessDetailInfo( - var pid: Int = 0, - var path: String = "", - var title: String = "" + var pid: Int = 0, + var path: String = "", + var title: String = "", ) private const val MAX_DISPLAY_LEN = 60 @@ -58,4 +59,26 @@ fun listProcesses(): Map { processMap[pid] = p } return processMap +} + +fun listProcessesByEncoding(encoding: String): List { + val processes = mutableListOf() + val archExe = FileUtils.archExeFile ?: return processes + val commandLine = GeneralCommandLine(archExe) + commandLine.charset = Charset.forName(encoding) + commandLine.addParameters("list_processes") + + val processOutput = ExecUtil.execAndGetOutput(commandLine) + + val text = processOutput.stdout + val lines= text.split("\n") + val size = lines.size / 4 + for (i in 0 until size) { + val pid = lines[i * 4 + 0].toInt() + val title = lines[i * 4 + 1] + val path = lines[i * 4 + 2] + val p = ProcessDetailInfo(pid, path, title) + processes.add(p) + } + return processes } \ No newline at end of file diff --git a/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml similarity index 53% rename from resources/META-INF/plugin.xml rename to src/main/resources/META-INF/plugin.xml index eaf84e7..328dd6e 100644 --- a/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,14 +1,14 @@ com.tang.emmylua.attach-debugger EmmyLua Attach Debugger - 1.0 + 1.1 tangzx - + com.intellij.modules.platform com.tang @@ -16,6 +16,12 @@ + + + + + + \ No newline at end of file