diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 9ce0c14..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "codemp-intellij" -version = "0.1.0" -edition = "2021" - -[dependencies] -codemp = { path = "../../lib", features = ["global", "sync", "transport"] } -#codemp = { git = "ssh://git@github.com/codewithotherpeopleandchangenamelater/codemp.git", branch = "workspace", features = ["global", "sync"] } -jni = { version = "0.21.1", features = ["invocation"] } -jni-sys = "0.3.0" -lazy_static = "1.4.0" -log = "0.4.20" -rifgen = { git = "https://github.com/Kofituo/rifgen.git", rev = "d27d9785b2febcf5527f1deb6a846be5d583f7d7"} -tokio = "1.35.1" -uuid = { version = "1.4.1", features = ["v4"] } - -[build-dependencies] -flapigen = "0.6.0" -rifgen = { git = "https://github.com/Kofituo/rifgen.git", rev = "d27d9785b2febcf5527f1deb6a846be5d583f7d7"} - -[lib] -crate_type = ["cdylib"] -path = "src/main/rust/lib.rs" diff --git a/build.gradle b/build.gradle index 0dbc3ea..a55f393 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ plugins { id 'java' id 'org.jetbrains.intellij' version '1.16.0' id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.palantir.git-version' version '3.1.0' } -group = 'com.codemp' -version = '0.1.0' +group = 'mp.code' +//version = versionDetails().lastTag java { sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17 @@ -17,9 +18,9 @@ repositories { } dependencies { - implementation 'com.github.adamheinrich:native-utils:master-SNAPSHOT' implementation 'org.slf4j:slf4j-api:2.0.9' implementation 'ch.qos.logback:logback-classic:1.4.12' + implementation files('../../lib/dist/java/build/libs/codemp-0.6.2.jar') } intellij { @@ -30,24 +31,14 @@ intellij { shadowJar { archiveClassifier.set('') dependencies { - include(dependency('com.github.adamheinrich:native-utils:master-SNAPSHOT')) - } -} - -def cargoDir = projectDir.toPath().resolve('target').resolve('release').toFile() - -processResources { - from(cargoDir) { - include('*.dll') - include('*.so') - into('natives/') + include(dependency(files('../../lib/java/build/libs/codemp-6645c46.jar'))) } } tasks { patchPluginXml { sinceBuild.set('222') - untilBuild.set('232.*') + untilBuild.set('233.*') } signPlugin { @@ -61,27 +52,4 @@ tasks { } } -//run cargo build -tasks.register('cargoBuild', Exec) { - workingDir '.' - commandLine 'cargo', 'build', '--release' -} - -//must act before all other tasks who mess with resources to reliably get the binary in -patchPluginXml.dependsOn cargoBuild - -//delete old jni generated files -tasks.register('deleteGeneratedNativeInterface', Delete) { - delete 'src/main/java/com/codemp/intellij/jni' -} - -//delete cargo build files -tasks.register('cargoClean', Exec) { - workingDir '.' - commandLine 'cargo', 'clean' - dependsOn deleteGeneratedNativeInterface -} - -clean.dependsOn cargoClean - instrumentedJar.dependsOn shadowJar //TODO: instrumentedJar should use fatjar as input diff --git a/build.rs b/build.rs deleted file mode 100644 index 7b3eb74..0000000 --- a/build.rs +++ /dev/null @@ -1,45 +0,0 @@ -use flapigen::{JavaConfig, LanguageConfig}; -use std::{env, fs, path::Path}; -use rifgen::{Generator as RifgenGenerator, TypeCases, Language}; -use flapigen::Generator as FlapigenGenerator; - -fn main() { - let out_dir_var = env::var("OUT_DIR") - .expect("no OUT_DIR, but cargo should provide it"); - let out_dir = Path::new(&out_dir_var); - let generated_glue_file = out_dir.join("generated_glue.in"); - - let src_dir = Path::new("src") - .join("main") - .join("rust"); - let glue_file = src_dir.join("glue.in"); - - RifgenGenerator::new(TypeCases::CamelCase,Language::Java, vec!(src_dir)) - .generate_interface(&generated_glue_file); - - let jni_path = Path::new("src") - .join("main") - .join("java") - .join("com") - .join("codemp") - .join("intellij") - .join("jni"); - - //create folder if it doesn't exist - fs::create_dir_all(&jni_path) - .expect("An error occurred while creating the JNI folder!"); - - let java_gen = FlapigenGenerator::new(LanguageConfig::JavaConfig( - JavaConfig::new( - jni_path, - "com.codemp.intellij.jni".into() - ))).rustfmt_bindings(true); - - java_gen.expand_many( - "codemp-intellij", - &[&generated_glue_file, &glue_file], - out_dir.join("glue.rs"), - ); - - println!("cargo:rerun-if-changed={}", generated_glue_file.display()); -} diff --git a/src/main/java/com/codemp/intellij/CodeMP.java b/src/main/java/com/codemp/intellij/CodeMP.java deleted file mode 100644 index 52d572d..0000000 --- a/src/main/java/com/codemp/intellij/CodeMP.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.codemp.intellij; - -import com.codemp.intellij.exceptions.ide.NotConnectedException; -import com.codemp.intellij.jni.ClientHandler; -import com.codemp.intellij.workspace.Workspace; -import com.intellij.openapi.util.SystemInfo; -import cz.adamh.utils.NativeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class CodeMP { - public static Logger LOGGER = LoggerFactory.getLogger(CodeMP.class); - public static final Map ACTIVE_WORKSPACES = new ConcurrentHashMap<>(); - private static ClientHandler CLIENT = null; - - public static void connect(String url) { - CodeMP.loadLibrary(); //will only load it the first time - CLIENT = new ClientHandler(url); - } - - public static void disconnect() { - CLIENT = null; - } - - public static ClientHandler getClient(String reason) throws NotConnectedException { - if(CLIENT == null) throw new NotConnectedException(reason); - return CLIENT; - } - - private static boolean loadedLibrary = false; - - public static void loadLibrary() { - if(!loadedLibrary) { - try { - if(SystemInfo.isWindows) - NativeUtils.loadLibraryFromJar("/natives/codemp_intellij.dll"); - else NativeUtils.loadLibraryFromJar("/natives/libcodemp_intellij.so"); - } catch(IOException e) { - throw new RuntimeException(e); - } finally { - LOGGER.info("Loaded CodeMP library!"); - loadedLibrary = false; - } - } - } -} diff --git a/src/main/java/com/codemp/intellij/actions/ConnectAction.java b/src/main/java/com/codemp/intellij/actions/ConnectAction.java deleted file mode 100644 index 297b6a7..0000000 --- a/src/main/java/com/codemp/intellij/actions/ConnectAction.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.codemp.intellij.actions; - -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.util.ActionUtil; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.ui.Messages; -import org.jetbrains.annotations.NotNull; - -public class ConnectAction extends AnAction { - public static void connect(AnActionEvent e, String url, boolean silent) { - CodeMP.connect(url); - if(!silent) ActionUtil.notify(e, - "Success", String.format("Connected to %s!", url)); - CodeMP.LOGGER.debug("Connected to {}!", url); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - String url = Messages.showInputDialog("URL to CodeMP instance:", "CodeMP Connect", - Messages.getQuestionIcon()); - try { - connect(e, url, false); - } catch(Exception ex) { - ActionUtil.notifyError(e, String.format( - "Failed to connect to %s!", - url), ex); - } - } -} diff --git a/src/main/java/com/codemp/intellij/actions/FastForwardAction.java b/src/main/java/com/codemp/intellij/actions/FastForwardAction.java deleted file mode 100644 index 09eaf76..0000000 --- a/src/main/java/com/codemp/intellij/actions/FastForwardAction.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.codemp.intellij.actions; - -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.actions.workspace.WorkspaceJoinAction; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Used exclusively to streamline debugging. - */ -public class FastForwardAction extends AnAction { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - ConnectAction.connect(e, "http://alemi.dev:50052", true); - WorkspaceJoinAction.join(e, "default", true); - CodeMP.LOGGER.debug("Completed quick startup for testing!"); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/CodeMPException.java b/src/main/java/com/codemp/intellij/exceptions/CodeMPException.java deleted file mode 100644 index d66b698..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/CodeMPException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.codemp.intellij.exceptions; - -public class CodeMPException extends RuntimeException { - public CodeMPException(String s) { - super(s); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/ide/BadActionEventStateException.java b/src/main/java/com/codemp/intellij/exceptions/ide/BadActionEventStateException.java deleted file mode 100644 index 23bc357..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/ide/BadActionEventStateException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.codemp.intellij.exceptions.ide; - -import com.codemp.intellij.exceptions.CodeMPException; -import com.intellij.openapi.actionSystem.AnActionEvent; - -/** - * Fired when trying to use {@link com.intellij.openapi.actionSystem.AnActionEvent}'s context - * from a state where that use is not supported. - */ -public class BadActionEventStateException extends CodeMPException { - public BadActionEventStateException(String s) { - super(s); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/lib/ChannelException.java b/src/main/java/com/codemp/intellij/exceptions/lib/ChannelException.java deleted file mode 100644 index 07890f3..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/lib/ChannelException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.codemp.intellij.exceptions.lib; - -import com.codemp.intellij.exceptions.CodeMPException; - -public class ChannelException extends CodeMPException { - public ChannelException(String input) { - super(input); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/lib/DeadlockedException.java b/src/main/java/com/codemp/intellij/exceptions/lib/DeadlockedException.java deleted file mode 100644 index 9637fdb..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/lib/DeadlockedException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.codemp.intellij.exceptions.lib; - -import com.codemp.intellij.exceptions.CodeMPException; - -public class DeadlockedException extends CodeMPException { - public DeadlockedException(String s) { - super(s); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/lib/InvalidStateException.java b/src/main/java/com/codemp/intellij/exceptions/lib/InvalidStateException.java deleted file mode 100644 index 82f216d..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/lib/InvalidStateException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.codemp.intellij.exceptions.lib; - -import com.codemp.intellij.exceptions.CodeMPException; - -public class InvalidStateException extends CodeMPException { - public InvalidStateException(String message) { - super(message); - } -} diff --git a/src/main/java/com/codemp/intellij/exceptions/lib/TransportException.java b/src/main/java/com/codemp/intellij/exceptions/lib/TransportException.java deleted file mode 100644 index 1a2436d..0000000 --- a/src/main/java/com/codemp/intellij/exceptions/lib/TransportException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.codemp.intellij.exceptions.lib; - -import com.codemp.intellij.exceptions.CodeMPException; - -public class TransportException extends CodeMPException { - public TransportException(String message) { - super(message); - } -} diff --git a/src/main/java/mp/code/intellij/CodeMP.java b/src/main/java/mp/code/intellij/CodeMP.java new file mode 100644 index 0000000..d64a532 --- /dev/null +++ b/src/main/java/mp/code/intellij/CodeMP.java @@ -0,0 +1,30 @@ +package mp.code.intellij; + +import mp.code.intellij.exceptions.ide.NotConnectedException; +import mp.code.intellij.workspace.IJWorkspace; +import mp.code.Client; +import mp.code.exceptions.CodeMPException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class CodeMP { + public static Logger LOGGER = LoggerFactory.getLogger(CodeMP.class); + public static final Map ACTIVE_WORKSPACES = new ConcurrentHashMap<>(); + private static Client CLIENT = null; + + public static void connect(String url, String username, String password) throws CodeMPException { + CLIENT = Client.connect(url, username, password); + } + + public static void disconnect() { + CLIENT = null; + } + + public static Client getClient(String reason) throws NotConnectedException { + if(CLIENT == null) throw new NotConnectedException(reason); + return CLIENT; + } +} diff --git a/src/main/java/mp/code/intellij/actions/ConnectAction.java b/src/main/java/mp/code/intellij/actions/ConnectAction.java new file mode 100644 index 0000000..4fa6cee --- /dev/null +++ b/src/main/java/mp/code/intellij/actions/ConnectAction.java @@ -0,0 +1,35 @@ +package mp.code.intellij.actions; + +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.ActionUtil; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import mp.code.exceptions.CodeMPException; +import org.jetbrains.annotations.NotNull; + +public class ConnectAction extends AnAction { + public static void connect(AnActionEvent e, String url, String username, String password, boolean silent) throws CodeMPException { + System.out.printf("%s %s %s", url, username, password); + CodeMP.connect(url, username, password); + if(!silent) ActionUtil.notify(e, + "Success", String.format("Connected to %s!", url)); + CodeMP.LOGGER.debug("Connected to {}!", url); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + /* + LoginDialog dialog = new LoginDialog(e.getProject(), "Please input your login credentials!", "Connect to CodeMP server"); + if(dialog.showAndGet()) { + try { + connect(e, dialog.urlField.getText(), dialog.usernameField.getText(), dialog.passwordField.getText(), false); + } catch(Exception exception) { + ActionUtil.notifyError( + e, + String.format("Failed to connect to %s!", dialog.urlField.getText()), + exception + ); + } + }*/ + } +} diff --git a/src/main/java/com/codemp/intellij/actions/DisconnectAction.java b/src/main/java/mp/code/intellij/actions/DisconnectAction.java similarity index 85% rename from src/main/java/com/codemp/intellij/actions/DisconnectAction.java rename to src/main/java/mp/code/intellij/actions/DisconnectAction.java index 396f887..51bf2db 100644 --- a/src/main/java/com/codemp/intellij/actions/DisconnectAction.java +++ b/src/main/java/mp/code/intellij/actions/DisconnectAction.java @@ -1,7 +1,7 @@ -package com.codemp.intellij.actions; +package mp.code.intellij.actions; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.util.ActionUtil; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.ActionUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/mp/code/intellij/actions/FastForwardAction.java b/src/main/java/mp/code/intellij/actions/FastForwardAction.java new file mode 100644 index 0000000..8dcb21e --- /dev/null +++ b/src/main/java/mp/code/intellij/actions/FastForwardAction.java @@ -0,0 +1,24 @@ +package mp.code.intellij.actions; + +import mp.code.intellij.CodeMP; +import mp.code.intellij.actions.workspace.WorkspaceJoinAction; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import mp.code.exceptions.CodeMPException; +import org.jetbrains.annotations.NotNull; + +/** + * Used exclusively to streamline debugging. + */ +public class FastForwardAction extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + try { + ConnectAction.connect(e, "http://alemi.dev:50053", "", "", true); + WorkspaceJoinAction.join(e, "glue", true); + CodeMP.LOGGER.debug("Completed quick startup for testing!"); + } catch(CodeMPException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java b/src/main/java/mp/code/intellij/actions/workspace/WorkspaceJoinAction.java similarity index 75% rename from src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java rename to src/main/java/mp/code/intellij/actions/workspace/WorkspaceJoinAction.java index 022fb9a..2f1bfae 100644 --- a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java +++ b/src/main/java/mp/code/intellij/actions/workspace/WorkspaceJoinAction.java @@ -1,16 +1,17 @@ -package com.codemp.intellij.actions.workspace; +package mp.code.intellij.actions.workspace; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.util.ActionUtil; -import com.codemp.intellij.workspace.Workspace; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.ActionUtil; +import mp.code.intellij.workspace.IJWorkspace; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.Messages; +import mp.code.exceptions.CodeMPException; import org.jetbrains.annotations.NotNull; public class WorkspaceJoinAction extends AnAction { - public static void join(AnActionEvent e, String workspaceId, boolean silent) { - CodeMP.ACTIVE_WORKSPACES.put(workspaceId, new Workspace( + public static void join(AnActionEvent e, String workspaceId, boolean silent) throws CodeMPException { + CodeMP.ACTIVE_WORKSPACES.put(workspaceId, new IJWorkspace( workspaceId, CodeMP.getClient("join workspace"), false, e.getProject() //TODO: implement remote projects )); diff --git a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java b/src/main/java/mp/code/intellij/actions/workspace/WorkspaceLeaveAction.java similarity index 82% rename from src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java rename to src/main/java/mp/code/intellij/actions/workspace/WorkspaceLeaveAction.java index 21246bd..4841239 100644 --- a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java +++ b/src/main/java/mp/code/intellij/actions/workspace/WorkspaceLeaveAction.java @@ -1,7 +1,7 @@ -package com.codemp.intellij.actions.workspace; +package mp.code.intellij.actions.workspace; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.util.ActionUtil; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.ActionUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.Messages; @@ -10,8 +10,8 @@ import org.jetbrains.annotations.NotNull; public class WorkspaceLeaveAction extends AnAction { public static void leave(AnActionEvent e, String workspaceId, boolean silent) { - CodeMP.getClient("leave workspace") - .leaveWorkspace(workspaceId); + //CodeMP.getClient("leave workspace").leaveWorkspace(workspaceId); + // TODO Disposer.dispose(CodeMP.ACTIVE_WORKSPACES.remove(workspaceId)); if(!silent) ActionUtil.notify(e, "Success", String.format("Left workspace %s!", workspaceId)); diff --git a/src/main/java/mp/code/intellij/exceptions/CodeMPIJException.java b/src/main/java/mp/code/intellij/exceptions/CodeMPIJException.java new file mode 100644 index 0000000..627b090 --- /dev/null +++ b/src/main/java/mp/code/intellij/exceptions/CodeMPIJException.java @@ -0,0 +1,7 @@ +package mp.code.intellij.exceptions; + +public class CodeMPIJException extends RuntimeException { + public CodeMPIJException(String s) { + super(s); + } +} diff --git a/src/main/java/mp/code/intellij/exceptions/ide/BadActionEventStateException.java b/src/main/java/mp/code/intellij/exceptions/ide/BadActionEventStateException.java new file mode 100644 index 0000000..ebeaa08 --- /dev/null +++ b/src/main/java/mp/code/intellij/exceptions/ide/BadActionEventStateException.java @@ -0,0 +1,13 @@ +package mp.code.intellij.exceptions.ide; + +import mp.code.intellij.exceptions.CodeMPIJException; + +/** + * Fired when trying to use {@link com.intellij.openapi.actionSystem.AnActionEvent}'s context + * from a state where that use is not supported. + */ +public class BadActionEventStateException extends CodeMPIJException { + public BadActionEventStateException(String s) { + super(s); + } +} diff --git a/src/main/java/com/codemp/intellij/exceptions/ide/BufferDetachException.java b/src/main/java/mp/code/intellij/exceptions/ide/BufferDetachException.java similarity index 53% rename from src/main/java/com/codemp/intellij/exceptions/ide/BufferDetachException.java rename to src/main/java/mp/code/intellij/exceptions/ide/BufferDetachException.java index 5f860fa..564f3d0 100644 --- a/src/main/java/com/codemp/intellij/exceptions/ide/BufferDetachException.java +++ b/src/main/java/mp/code/intellij/exceptions/ide/BufferDetachException.java @@ -1,11 +1,11 @@ -package com.codemp.intellij.exceptions.ide; +package mp.code.intellij.exceptions.ide; -import com.codemp.intellij.exceptions.CodeMPException; +import mp.code.intellij.exceptions.CodeMPIJException; /** * Thrown upon failure to detach from a buffer. */ -public class BufferDetachException extends CodeMPException { +public class BufferDetachException extends CodeMPIJException { public BufferDetachException(String name) { super(String.format("Could not detach from buffer named \"%s\"!", name)); diff --git a/src/main/java/com/codemp/intellij/exceptions/ide/NotConnectedException.java b/src/main/java/mp/code/intellij/exceptions/ide/NotConnectedException.java similarity index 59% rename from src/main/java/com/codemp/intellij/exceptions/ide/NotConnectedException.java rename to src/main/java/mp/code/intellij/exceptions/ide/NotConnectedException.java index abb6fee..0620c12 100644 --- a/src/main/java/com/codemp/intellij/exceptions/ide/NotConnectedException.java +++ b/src/main/java/mp/code/intellij/exceptions/ide/NotConnectedException.java @@ -1,12 +1,12 @@ -package com.codemp.intellij.exceptions.ide; +package mp.code.intellij.exceptions.ide; -import com.codemp.intellij.exceptions.CodeMPException; +import mp.code.intellij.exceptions.CodeMPIJException; /** * Fired when trying to access the CodeMP client without first connecting * to a server. */ -public class NotConnectedException extends CodeMPException { +public class NotConnectedException extends CodeMPIJException { public NotConnectedException(String service) { super(String.format("Failed to %s, you are not connected to a server!", service)); diff --git a/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java b/src/main/java/mp/code/intellij/listeners/BufferEventListener.java similarity index 55% rename from src/main/java/com/codemp/intellij/listeners/BufferEventListener.java rename to src/main/java/mp/code/intellij/listeners/BufferEventListener.java index 3a95da5..6121aa1 100644 --- a/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java +++ b/src/main/java/mp/code/intellij/listeners/BufferEventListener.java @@ -1,23 +1,26 @@ -package com.codemp.intellij.listeners; +package mp.code.intellij.listeners; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.exceptions.CodeMPException; -import com.codemp.intellij.jni.BufferHandler; +import mp.code.intellij.CodeMP; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; +import mp.code.BufferController; +import mp.code.data.TextChange; +import mp.code.exceptions.CodeMPException; import org.jetbrains.annotations.NotNull; +import java.util.Optional; + public class BufferEventListener implements DocumentListener { - private final BufferHandler bufferHandler; + private final BufferController controller; - public BufferEventListener(BufferHandler bufferHandler) { - this.bufferHandler = bufferHandler; + public BufferEventListener(BufferController controller) { + this.controller = controller; } @Override - public void documentChanged(@NotNull DocumentEvent event) throws CodeMPException { + public void documentChanged(@NotNull DocumentEvent event) { CodeMP.LOGGER.debug("Changed {} to {} at offset {}", event.getOldFragment(), event.getNewFragment(), event.getOffset()); @@ -29,8 +32,15 @@ public class BufferEventListener implements DocumentListener { //TODO move actions break int changeOffset = event.getOffset(); CharSequence newFragment = event.getNewFragment(); - this.bufferHandler.send(changeOffset, - changeOffset + event.getOldFragment().length(), - newFragment.toString()); + try { + this.controller.send(new TextChange( + changeOffset, + changeOffset + event.getOldFragment().length(), + newFragment.toString(), + 0L + )); + } catch(CodeMPException ignored) { + // TODO actually give a shit + } } } diff --git a/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java b/src/main/java/mp/code/intellij/listeners/CursorEventListener.java similarity index 51% rename from src/main/java/com/codemp/intellij/listeners/CursorEventListener.java rename to src/main/java/mp/code/intellij/listeners/CursorEventListener.java index 486e2c5..c12cf15 100644 --- a/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java +++ b/src/main/java/mp/code/intellij/listeners/CursorEventListener.java @@ -1,21 +1,23 @@ -package com.codemp.intellij.listeners; +package mp.code.intellij.listeners; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.jni.CursorHandler; -import com.codemp.intellij.util.FileUtil; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.FileUtil; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.event.CaretEvent; import com.intellij.openapi.editor.event.CaretListener; +import mp.code.CursorController; +import mp.code.data.Cursor; +import mp.code.exceptions.CodeMPException; import org.jetbrains.annotations.NotNull; public class CursorEventListener implements CaretListener { - private final CursorHandler handler; + private final CursorController controller; - public CursorEventListener(CursorHandler handler) { - this.handler = handler; + public CursorEventListener(CursorController controller) { + this.controller = controller; } @Override @@ -27,13 +29,21 @@ public class CursorEventListener implements CaretListener { VisualPosition startPos = caret.getSelectionStartPosition(); VisualPosition endPos = caret.getSelectionEndPosition(); CodeMP.LOGGER.debug("Caret moved from {}x {}y to {}x {}y", - startPos.line, startPos.column, endPos.line, endPos.column); + startPos.line, startPos.column, endPos.line, endPos.column + ); Editor editor = event.getEditor(); - this.handler.send( - FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile()), - startPos.line, startPos.column, - endPos.line, endPos.column - ); + try { + this.controller.send(new Cursor( + startPos.line, + startPos.column, + endPos.line, + endPos.column, + FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile()), + null + )); + } catch(CodeMPException e) { + // TODO zzzzz + } } } diff --git a/src/main/java/com/codemp/intellij/listeners/WorkspaceFileClosedListener.java b/src/main/java/mp/code/intellij/listeners/WorkspaceFileClosedListener.java similarity index 68% rename from src/main/java/com/codemp/intellij/listeners/WorkspaceFileClosedListener.java rename to src/main/java/mp/code/intellij/listeners/WorkspaceFileClosedListener.java index a2ddb34..82e440c 100644 --- a/src/main/java/com/codemp/intellij/listeners/WorkspaceFileClosedListener.java +++ b/src/main/java/mp/code/intellij/listeners/WorkspaceFileClosedListener.java @@ -1,20 +1,20 @@ -package com.codemp.intellij.listeners; +package mp.code.intellij.listeners; -import com.codemp.intellij.jni.WorkspaceHandler; -import com.codemp.intellij.task.BufferEventAwaiterTask; -import com.codemp.intellij.util.FileUtil; +import mp.code.intellij.task.BufferEventAwaiterTask; +import mp.code.intellij.util.FileUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; +import mp.code.Workspace; import org.jetbrains.annotations.NotNull; public class WorkspaceFileClosedListener implements FileEditorManagerListener.Before { - private final WorkspaceHandler handler; + private final Workspace handler; private final BufferEventAwaiterTask task; - public WorkspaceFileClosedListener(WorkspaceHandler handler, BufferEventAwaiterTask task) { + public WorkspaceFileClosedListener(Workspace handler, BufferEventAwaiterTask task) { this.handler = handler; this.task = task; } @@ -27,7 +27,7 @@ public class WorkspaceFileClosedListener implements FileEditorManagerListener.Be Disposable disp = this.task.activeBuffers.remove(path); if(disp == null) return; - this.handler.detachFromBuffer(path); + // TODO : this.handler.detachFromBuffer(path); Disposer.dispose(disp); } } diff --git a/src/main/java/com/codemp/intellij/listeners/WorkspaceFileOpenedListener.java b/src/main/java/mp/code/intellij/listeners/WorkspaceFileOpenedListener.java similarity index 69% rename from src/main/java/com/codemp/intellij/listeners/WorkspaceFileOpenedListener.java rename to src/main/java/mp/code/intellij/listeners/WorkspaceFileOpenedListener.java index 54d1dfe..4f9df0b 100644 --- a/src/main/java/com/codemp/intellij/listeners/WorkspaceFileOpenedListener.java +++ b/src/main/java/mp/code/intellij/listeners/WorkspaceFileOpenedListener.java @@ -1,10 +1,7 @@ -package com.codemp.intellij.listeners; +package mp.code.intellij.listeners; -import com.codemp.intellij.exceptions.lib.TransportException; -import com.codemp.intellij.jni.BufferHandler; -import com.codemp.intellij.jni.WorkspaceHandler; -import com.codemp.intellij.task.BufferEventAwaiterTask; -import com.codemp.intellij.util.FileUtil; +import mp.code.intellij.task.BufferEventAwaiterTask; +import mp.code.intellij.util.FileUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileOpenedSyncListener; @@ -12,15 +9,18 @@ import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; +import mp.code.BufferController; +import mp.code.Workspace; +import mp.code.exceptions.CodeMPException; import org.jetbrains.annotations.NotNull; import java.util.List; public class WorkspaceFileOpenedListener implements FileOpenedSyncListener { - private final WorkspaceHandler handler; + private final Workspace handler; private final BufferEventAwaiterTask task; - public WorkspaceFileOpenedListener(WorkspaceHandler handler, BufferEventAwaiterTask task) { + public WorkspaceFileOpenedListener(Workspace handler, BufferEventAwaiterTask task) { this.handler = handler; this.task = task; } @@ -39,9 +39,9 @@ public class WorkspaceFileOpenedListener implements FileOpenedSyncListener { String path = FileUtil.getRelativePath(editor.getProject(), file); if(path == null) return; - BufferHandler bufferHandler = this.getBufferForPath(path); + BufferController bufferController = this.getBufferForPath(path); Disposable disp = Disposer.newDisposable(String.format("codemp-buffer-%s", path)); - editor.getDocument().addDocumentListener(new BufferEventListener(bufferHandler), disp); + editor.getDocument().addDocumentListener(new BufferEventListener(bufferController), disp); editor.getDocument().setText(""); //empty it so we can start receiving this.task.activeBuffers.put(path, disp); @@ -51,13 +51,17 @@ public class WorkspaceFileOpenedListener implements FileOpenedSyncListener { /** * Attach to a buffer or, if it does not exist, implicitly create it. * @param path the buffer's name (which is the path relative to project root) - * @return the {@link BufferHandler} for it + * @return the {@link BufferController} for it */ - private BufferHandler getBufferForPath(String path) { + private BufferController getBufferForPath(String path) { try { return this.handler.attachToBuffer(path); - } catch (TransportException ignored) { - return this.handler.createBuffer(path); + } catch (CodeMPException ignored) { + try { + return this.handler.createBuffer(path); + } catch(CodeMPException e) { + throw new RuntimeException(e); + } } } } diff --git a/src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java b/src/main/java/mp/code/intellij/task/BufferEventAwaiterTask.java similarity index 66% rename from src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java rename to src/main/java/mp/code/intellij/task/BufferEventAwaiterTask.java index b4422f4..f6649fd 100644 --- a/src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java +++ b/src/main/java/mp/code/intellij/task/BufferEventAwaiterTask.java @@ -1,12 +1,7 @@ -package com.codemp.intellij.task; +package mp.code.intellij.task; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.exceptions.lib.DeadlockedException; -import com.codemp.intellij.jni.BufferHandler; -import com.codemp.intellij.jni.StringVec; -import com.codemp.intellij.jni.TextChangeWrapper; -import com.codemp.intellij.jni.WorkspaceHandler; -import com.codemp.intellij.util.FileUtil; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.FileUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -14,6 +9,11 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import mp.code.BufferController; +import mp.code.Workspace; +import mp.code.data.TextChange; +import mp.code.exceptions.CodeMPException; +import mp.code.exceptions.DeadlockedException; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -24,8 +24,8 @@ import java.util.concurrent.ConcurrentHashMap; public class BufferEventAwaiterTask extends Task.Backgroundable implements Disposable { public final Map activeBuffers; - private final WorkspaceHandler handler; - public BufferEventAwaiterTask(@NotNull Project project, @NotNull WorkspaceHandler handler) { + private final Workspace handler; + public BufferEventAwaiterTask(@NotNull Project project, @NotNull Workspace handler) { super(project, "Awaiting CodeMP buffer events", false); this.activeBuffers = new ConcurrentHashMap<>(); this.handler = handler; @@ -35,29 +35,33 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo @SuppressWarnings("InfiniteLoopStatement") public void run(@NotNull ProgressIndicator indicator) { while(true) { - StringVec buffers = new StringVec(); //jni moment - this.activeBuffers.keySet().forEach(buffers::push); - - Optional bufferOptional = this.handler.selectBuffer(buffers, 100L); + Optional bufferOptional; + try { + bufferOptional = this.handler.selectBuffer(100L); + } catch(CodeMPException e) { + bufferOptional = Optional.empty(); // TODO error handling + } if(bufferOptional.isEmpty()) continue; - BufferHandler buffer = bufferOptional.get(); + BufferController buffer = bufferOptional.get(); - List changeList = new ArrayList<>(); + List changeList = new ArrayList<>(); while(true) { - Optional changeOptional; + Optional changeOptional; try { - changeOptional = buffer.tryRecv(); + changeOptional = buffer.tryRecv(); } catch(DeadlockedException e) { CodeMP.LOGGER.error(e.getMessage()); continue; + } catch(CodeMPException e) { + throw new RuntimeException(e); } if(changeOptional.isEmpty()) break; - TextChangeWrapper change = changeOptional.get(); + TextChange change = changeOptional.get(); CodeMP.LOGGER.debug("Received text change {} from offset {} to {}!", - change.getContent(), change.getStart(), change.getEnd()); + change.content, change.start, change.end); changeList.add(change); } @@ -68,7 +72,7 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo this.myProject, () -> changeList.forEach((change) -> bufferEditor.getDocument().replaceString( - (int) change.getStart(), (int) change.getEnd(), change.getContent()) + (int) change.start, (int) change.end, change.content) ), "CodeMPBufferReceive", "codemp-buffer-receive", //TODO: mark this with the name diff --git a/src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java b/src/main/java/mp/code/intellij/task/CursorEventAwaiterTask.java similarity index 75% rename from src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java rename to src/main/java/mp/code/intellij/task/CursorEventAwaiterTask.java index 454a7f9..3f34f13 100644 --- a/src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java +++ b/src/main/java/mp/code/intellij/task/CursorEventAwaiterTask.java @@ -1,10 +1,8 @@ -package com.codemp.intellij.task; +package mp.code.intellij.task; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.jni.CursorEventWrapper; -import com.codemp.intellij.jni.CursorHandler; -import com.codemp.intellij.util.ColorUtil; -import com.codemp.intellij.util.FileUtil; +import mp.code.intellij.CodeMP; +import mp.code.intellij.util.ColorUtil; +import mp.code.intellij.util.FileUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; @@ -16,6 +14,9 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import mp.code.CursorController; +import mp.code.data.Cursor; +import mp.code.exceptions.CodeMPException; import org.jetbrains.annotations.NotNull; import java.awt.*; @@ -25,10 +26,10 @@ import java.util.concurrent.ConcurrentHashMap; //TODO this is janky as it shows a progress bar it doesn't use tbh //implements disposable so i can use it as lifetime ig public class CursorEventAwaiterTask extends Task.Backgroundable implements Disposable { - private final CursorHandler handler; + private final CursorController handler; private final Map highlighterMap = new ConcurrentHashMap<>(); - public CursorEventAwaiterTask(@NotNull Project project, @NotNull CursorHandler handler) { + public CursorEventAwaiterTask(@NotNull Project project, @NotNull CursorController handler) { super(project, "Awaiting CodeMP cursor events", false); this.handler = handler; } @@ -37,23 +38,29 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo @SuppressWarnings("InfiniteLoopStatement") public void run(@NotNull ProgressIndicator indicator) { while(true) { - CursorEventWrapper event = this.handler.recv(); - Editor editor = FileUtil.getActiveEditorByPath(this.myProject, event.getBuffer()); + Cursor event; + try { + event = this.handler.recv(); + } catch(CodeMPException ex) { + continue; // TODO proper handling + } + Editor editor = FileUtil.getActiveEditorByPath(this.myProject, event.buffer); if(editor == null) continue; CodeMP.LOGGER.debug( "Cursor moved by user {}! Start pos: {}x {}y; end pos: {}x {}y in buffer {}!", - event.getUser(), - event.getStartCol(), event.getStartCol(), - event.getEndRow(), event.getEndCol(), - event.getBuffer()); + event.user, + event.startCol, event.startRow, + event.endCol, event.endRow, + event.buffer + ); try { int startOffset = editor.getDocument() - .getLineStartOffset(event.getStartRow()) + event.getStartCol(); + .getLineStartOffset(event.startRow) + event.startCol; int endOffset = editor.getDocument() - .getLineStartOffset(event.getEndRow()) + event.getEndCol(); + .getLineStartOffset(event.startRow) + event.startCol; ApplicationManager.getApplication().invokeLater(() -> { int documentLength = editor.getDocument().getTextLength(); @@ -64,7 +71,7 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo return; } - RangeHighlighter previous = this.highlighterMap.put(event.getUser(), editor + RangeHighlighter previous = this.highlighterMap.put(event.user, editor .getMarkupModel() .addRangeHighlighter( startOffset, @@ -72,7 +79,7 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo HighlighterLayer.SELECTION, new TextAttributes( null, - ColorUtil.hashColor(event.getUser()), + ColorUtil.hashColor(event.user), null, null, Font.PLAIN diff --git a/src/main/java/com/codemp/intellij/util/ActionUtil.java b/src/main/java/mp/code/intellij/util/ActionUtil.java similarity index 91% rename from src/main/java/com/codemp/intellij/util/ActionUtil.java rename to src/main/java/mp/code/intellij/util/ActionUtil.java index 70db9e7..a579d3c 100644 --- a/src/main/java/com/codemp/intellij/util/ActionUtil.java +++ b/src/main/java/mp/code/intellij/util/ActionUtil.java @@ -1,7 +1,7 @@ -package com.codemp.intellij.util; +package mp.code.intellij.util; -import com.codemp.intellij.CodeMP; -import com.codemp.intellij.exceptions.ide.BadActionEventStateException; +import mp.code.intellij.CodeMP; +import mp.code.intellij.exceptions.ide.BadActionEventStateException; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; diff --git a/src/main/java/com/codemp/intellij/util/ColorUtil.java b/src/main/java/mp/code/intellij/util/ColorUtil.java similarity index 89% rename from src/main/java/com/codemp/intellij/util/ColorUtil.java rename to src/main/java/mp/code/intellij/util/ColorUtil.java index 66edf01..b5a9d66 100644 --- a/src/main/java/com/codemp/intellij/util/ColorUtil.java +++ b/src/main/java/mp/code/intellij/util/ColorUtil.java @@ -1,4 +1,4 @@ -package com.codemp.intellij.util; +package mp.code.intellij.util; import com.intellij.ui.JBColor; diff --git a/src/main/java/com/codemp/intellij/util/FileUtil.java b/src/main/java/mp/code/intellij/util/FileUtil.java similarity index 97% rename from src/main/java/com/codemp/intellij/util/FileUtil.java rename to src/main/java/mp/code/intellij/util/FileUtil.java index fec9be2..184074c 100644 --- a/src/main/java/com/codemp/intellij/util/FileUtil.java +++ b/src/main/java/mp/code/intellij/util/FileUtil.java @@ -1,4 +1,4 @@ -package com.codemp.intellij.util; +package mp.code.intellij.util; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; diff --git a/src/main/java/com/codemp/intellij/workspace/Workspace.java b/src/main/java/mp/code/intellij/workspace/IJWorkspace.java similarity index 73% rename from src/main/java/com/codemp/intellij/workspace/Workspace.java rename to src/main/java/mp/code/intellij/workspace/IJWorkspace.java index 9755534..cb7f553 100644 --- a/src/main/java/com/codemp/intellij/workspace/Workspace.java +++ b/src/main/java/mp/code/intellij/workspace/IJWorkspace.java @@ -1,10 +1,8 @@ -package com.codemp.intellij.workspace; +package mp.code.intellij.workspace; -import com.codemp.intellij.jni.ClientHandler; -import com.codemp.intellij.jni.WorkspaceHandler; -import com.codemp.intellij.listeners.*; -import com.codemp.intellij.task.BufferEventAwaiterTask; -import com.codemp.intellij.task.CursorEventAwaiterTask; +import mp.code.intellij.listeners.WorkspaceFileOpenedListener; +import mp.code.intellij.task.BufferEventAwaiterTask; +import mp.code.intellij.task.CursorEventAwaiterTask; import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.fileEditor.FileEditorManagerListener; @@ -12,12 +10,17 @@ import com.intellij.openapi.fileEditor.FileOpenedSyncListener; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.util.messages.MessageBusConnection; +import mp.code.Client; +import mp.code.Workspace; +import mp.code.exceptions.CodeMPException; +import mp.code.intellij.listeners.CursorEventListener; +import mp.code.intellij.listeners.WorkspaceFileClosedListener; -public class Workspace implements Disposable { +public class IJWorkspace implements Disposable { public final String id; public final String url; public final boolean isRemote; - public final WorkspaceHandler handler; + public final Workspace handler; public final Project project; public final BufferEventAwaiterTask bufferTask; public final CursorEventAwaiterTask cursorTask; @@ -25,11 +28,11 @@ public class Workspace implements Disposable { /** * The constructor, that will also take care of creating the tasks and listeners associated with it. * @param id unique id of the workspace on the server - * @param client the {@link ClientHandler} to use + * @param client the {@link Client} to use * @param isRemote whether the project is remote * @param project the {@link Project} to use */ - public Workspace(String id, ClientHandler client, boolean isRemote, Project project) { + public IJWorkspace(String id, Client client, boolean isRemote, Project project) throws CodeMPException { this.id = id; this.url = client.getUrl(); this.isRemote = isRemote; diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 934acf2..59f26ac 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,5 +1,5 @@ - com.codemp.intellij + mp.code.intellij CodeMP CodeMP @@ -10,12 +10,12 @@ - - - - + + + - diff --git a/src/main/rust/glue.in b/src/main/rust/glue.in deleted file mode 100644 index 9f75644..0000000 --- a/src/main/rust/glue.in +++ /dev/null @@ -1,39 +0,0 @@ -foreign_typemap!( //thanks @tasn on GitHub for the idea - ($p:r_type) CodempResult => swig_i_type!(T) { - $out = match $p { - Ok(x) => { - swig_from_rust_to_i_type!(T, x, ret) - ret - } - Err(err) => { - let (msg, exception_class) = match err { - CodempError::Filler { message } => ( - message, - swig_jni_find_class!(CODEMP_EXCEPTION, "com/codemp/intellij/exceptions/CodeMPException") - ), - CodempError::Transport { status, message } => ( - format!("Status {}: {}", status, message), - swig_jni_find_class!(TRANSPORT_EXCEPTION, "com/codemp/intellij/exceptions/lib/TransportException") - ), - CodempError::InvalidState { msg } => ( - msg, swig_jni_find_class!(INVALID_STATE_EXCEPTION, "com/codemp/intellij/exceptions/lib/InvalidStateException") - ), - CodempError::Deadlocked => ( - "WOOT deadlocked (safe to retry)!".to_string(), - swig_jni_find_class!(DEADLOCKED_EXCEPTION, "com/codemp/intellij/exceptions/lib/DeadlockedException") - ), - CodempError::Channel { send } => { - let verb = if send { "sending" } else { "reading" }; - ( - format!("Error while {} message on channel: the channel was closed!", verb), - swig_jni_find_class!(CHANNEL_EXCEPTION, "com/codemp/intellij/exceptions/lib/ChannelException") - ) - } - }; - jni_throw(env, exception_class, &msg); - return ::jni_invalid_value(); - } - }; - }; - ($p:f_type, unique_prefix="/*err*/") => "/*err*/swig_f_type!(T)" "swig_foreign_from_i_type!(T, $p)"; -); diff --git a/src/main/rust/lib.rs b/src/main/rust/lib.rs deleted file mode 100644 index 2c39343..0000000 --- a/src/main/rust/lib.rs +++ /dev/null @@ -1,330 +0,0 @@ -use std::sync::Arc; -use tokio::sync::RwLock; -use std::time::Duration; -use codemp::prelude::*; -use codemp::tools; -use lazy_static::lazy_static; -use rifgen::rifgen_attr::{generate_access_methods, generate_interface, generate_interface_doc}; -use uuid::Uuid; - -pub mod glue { //rifgen generated code - include!(concat!(env!("OUT_DIR"), "/glue.rs")); -} - -lazy_static! { - /// the tokio runtime, since we can't easily have Java and Rust async work together - static ref RT: tokio::runtime::Runtime = tokio::runtime::Runtime::new() - .expect("could not start tokio runtime"); -} - -#[generate_interface_doc] -/// the handler class that represent an instance of a CodeMP client -struct ClientHandler { - client: CodempClient, - url: String -} - -impl ClientHandler { - #[generate_interface(constructor)] - /// constructor required by flapigen, DO NOT CALL THIS - fn new(address: &str) -> ClientHandler { - ClientHandler { - client: RT.block_on(CodempClient::new(address)).unwrap(), - url: address.to_string() - } - } - - #[generate_interface] - /// create a new workspace - fn create_workspace(&mut self, workspace_id: &str) -> CodempResult { - RT.block_on(self.client.create_workspace(workspace_id)) - .map(|workspace| { - Self::spawn_updater(workspace.clone()); - WorkspaceHandler { workspace } - }) - } - - #[generate_interface] - /// join a workspace by name - fn join_workspace(&mut self, workspace_id: &str) -> CodempResult { - RT.block_on(self.client.join_workspace(workspace_id)) - .map(|workspace| { - Self::spawn_updater(workspace.clone()); - WorkspaceHandler { workspace } - }) - } - - #[generate_interface] - /// leave a workspace - fn leave_workspace(&mut self, workspace_id: &str) -> CodempResult<()> { - RT.block_on(self.client.leave_workspace(workspace_id)) - } - - fn spawn_updater(workspace: Arc>) { - tokio::spawn(async move { - loop { - tokio::time::sleep(Duration::from_secs(60)).await; - workspace.write().await.fetch_buffers().await.unwrap(); - workspace.write().await.fetch_users().await.unwrap(); - } - }); - } - - #[generate_interface] - /// get the url you are currently connected to - fn get_url(&self) -> String { - self.url.clone() - } -} - -#[generate_interface_doc] -/// wraps a [codemp::workspace::Workspace] to be handled by Java -struct WorkspaceHandler { - workspace: Arc> -} - -impl WorkspaceHandler { - #[generate_interface(constructor)] - /// constructor required by flapigen, DO NOT CALL THIS - fn new() -> WorkspaceHandler { - unimplemented!() - } - - #[generate_interface] - /// create a new buffer in current workspace - fn create_buffer(&mut self, path: &str) -> CodempResult { - RT.block_on(RT.block_on(self.workspace.write()).create(path))?; - Ok(self.get_buffer(path).unwrap()) - } - - #[generate_interface] - /// attach to a buffer and get a [crate::BufferHandler] for it - fn attach_to_buffer(&mut self, path: &str) -> CodempResult { - RT.block_on(RT.block_on(self.workspace.write()).attach(path)) - .map(|buffer| BufferHandler { buffer }) - } - - #[generate_interface] - /// updates the local list of the workspace's buffers - fn fetch_buffers(&mut self) -> CodempResult<()> { - RT.block_on(RT.block_on(self.workspace.write()).fetch_buffers()) - } - - #[generate_interface] - /// updates the local list of the workspace's users - fn fetch_users(&mut self) -> CodempResult<()> { - RT.block_on(RT.block_on(self.workspace.write()).fetch_users()) - } - - #[generate_interface] - /// gets a list of all users in a buffer - fn list_buffer_users(&mut self, path: &str) -> CodempResult { - let mut res = StringVec::new(); - RT.block_on(RT.block_on(self.workspace.write()) - .list_buffer_users(path))? - .iter().for_each(|u| res.push(Uuid::from(u.clone()).to_string())); - Ok(res) - } - - #[generate_interface] - /// delete a buffer - fn delete_buffer(&mut self, path: &str) -> CodempResult<()> { - RT.block_on(RT.block_on(self.workspace.write()).delete(path)) - } - - #[generate_interface] - /// detach from a buffer - fn detach_from_buffer(&mut self, path: &str) -> bool { - RT.block_on(self.workspace.write()).detach(path) - } - - #[generate_interface] - /// get the workspace id - fn get_workspace_id(&self) -> String { - RT.block_on(self.workspace.read()).id().clone() - } - - #[generate_interface] - /// get a [crate::CursorHandler] for the workspace's cursor - fn get_cursor(&self) -> CursorHandler { - CursorHandler { cursor: RT.block_on(self.workspace.read()).cursor().clone() } - } - - #[generate_interface] - /// get a [crate::BufferHandler] for one of the workspace's buffers - fn get_buffer(&self, path: &str) -> Option { - RT.block_on(self.workspace.read()).buffer_by_name(path) - .map(|buffer| BufferHandler { buffer }) - } - - #[generate_interface] - /// get the names of all buffers available in the workspace - fn get_filetree(&self) -> StringVec { - StringVec { v: RT.block_on(self.workspace.read()).filetree() } - } - - #[generate_interface] - /// polls a list of buffers, returning the first ready one - fn select_buffer(&mut self, mut buffer_ids: StringVec, timeout: i64) -> CodempResult> { - let mut buffers = Vec::new(); - for id in buffer_ids.v.iter_mut() { - match self.get_buffer(id.as_str()) { - Some(buf) => buffers.push(buf.buffer), - None => continue - } - } - - let result = RT.block_on(tools::select_buffer( - buffers.as_slice(), - Some(Duration::from_millis(timeout as u64)) - )); - - match result { - Err(e) => Err(e), - Ok(buffer) => - Ok(buffer.map(|buffer| BufferHandler { buffer })) - } - } -} - -#[generate_interface_doc] -#[generate_access_methods] -/// wraps a [codemp::proto::cursor::CursorEvent] to be handled by Java -struct CursorEventWrapper { - user: String, - buffer: String, - start_row: i32, - start_col: i32, - end_row: i32, - end_col: i32 -} - - -#[generate_interface_doc] -/// a handler providing Java access to [codemp::cursor::Controller] methods -struct CursorHandler { - pub cursor: Arc -} - -impl CursorHandler { - #[generate_interface(constructor)] - /// constructor required by flapigen, DO NOT CALL THIS - fn new() -> CursorHandler { - unimplemented!() - } - - #[generate_interface] - /// get next cursor event from current workspace, or block until one is available - fn recv(&self) -> CodempResult { - match RT.block_on(self.cursor.recv()) { - Err(err) => Err(err), - Ok(event) => Ok(CursorEventWrapper { - user: Uuid::from(event.user).to_string(), - buffer: event.position.buffer.clone(), - start_row: event.position.start.row, - start_col: event.position.start.col, - end_row: event.position.end.row, - end_col: event.position.end.col - }) - } - } - - #[generate_interface] - /// broadcast a cursor event - /// will automatically fix start and end if they are accidentally inverted - fn send(&self, buffer: String, start_row: i32, start_col: i32, end_row: i32, end_col: i32) -> CodempResult<()> { - self.cursor.send(CodempCursorPosition { - buffer, - start: CodempRowCol::from((start_row, start_col)), - end: CodempRowCol::from((end_row, end_col)) - }) - } -} - -#[generate_interface_doc] -#[generate_access_methods] -/// wraps a [codemp::api::change::TextChange] to make it accessible from Java -struct TextChangeWrapper { - start: usize, - end: usize, //not inclusive - content: String -} - -#[generate_interface_doc] -/// a handler providing Java access to [codemp::buffer::Controller] methods -struct BufferHandler { - pub buffer: Arc -} - -impl BufferHandler { - #[generate_interface(constructor)] - /// constructor required by flapigen, DO NOT CALL THIS - fn new() -> BufferHandler { - unimplemented!() - } - - #[generate_interface] - /// get the name of the buffer - fn get_name(&self) -> String { - self.buffer.name().to_string() - } - - #[generate_interface] - /// get the contents of the buffer - fn get_content(&self) -> String { - self.buffer.content() - } - - #[generate_interface] - /// if a text change is available on the buffer, return it immediately - fn try_recv(&self) -> CodempResult> { - match self.buffer.try_recv() { - Err(err) => Err(err), - Ok(None) => Ok(None), - Ok(Some(change)) => Ok(Some(TextChangeWrapper { - start: change.span.start, - end: change.span.end, - content: change.content.clone() - })) - } - } - - #[generate_interface] - /// broadcast a text change on the buffer - fn send(&self, start_offset: usize, end_offset: usize, content: String) -> CodempResult<()> { - self.buffer.send(CodempTextChange { span: start_offset..end_offset, content }) - } -} - -#[generate_interface_doc] -/// a convenience struct allowing Java access to a Rust vector -struct StringVec { //jni moment - v: Vec -} - -impl StringVec { - #[generate_interface(constructor)] - /// initialize an empty vector - fn new() -> StringVec { - Self { v: Vec::new() } - } - - #[generate_interface] - /// push a new value onto the vector - fn push(&mut self, s: String) { - self.v.push(s); - } - - #[generate_interface] - /// get the length of the underlying vector - fn length(&self) -> i64 { - self.v.len() as i64 - } - - #[generate_interface] - /// access the element at a given index - fn get(&self, idx: i64) -> Option { - let elem: Option<&String> = self.v.get(idx as usize); - elem.map(|s| s.clone()) - } -}