manateelazycat / lsp-bridge

A blazingly fast LSP client for Emacs
GNU General Public License v3.0
1.44k stars 209 forks source link

lsp-bridge-find-def 卡顿,没有跳转 #1049

Closed getong closed 1 month ago

getong commented 1 month ago

rust project

--- [22:59:28.601146] Send textDocument/didOpen notification to 'rust-analyzer' for project 
Eval in Emacs: (lsp-bridge-set-server-names '"/Users/gerald/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/v8-129.0.0/src/context.rs" '"" '("rust-analyzer"))
{
   "method": "textDocument/didOpen",
   "params": {
      "textDocument": {
         "uri": "file:///Users/gerald/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/v8-129.0.0/src/context.rs",
         "languageId": "rust",
         "version": 0,
         "text": "// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.\nuse crate::handle::UnsafeRefHandle;\nuse crate::isolate::BuildTypeIdHasher;\nuse crate::isolate::Isolate;\nuse crate::isolate::RawSlot;\nuse crate::support::int;\nuse crate::Context;\nuse crate::HandleScope;\nuse crate::Local;\nuse crate::MicrotaskQueue;\nuse crate::Object;\nuse crate::ObjectTemplate;\nuse crate::Value;\nuse crate::Weak;\nuse std::any::TypeId;\nuse std::collections::HashMap;\nuse std::ffi::c_void;\nuse std::ptr::{null, null_mut};\n\nextern \"C\" {\n  fn v8__Context__New(\n    isolate: *mut Isolate,\n    templ: *const ObjectTemplate,\n    global_object: *const Value,\n    microtask_queue: *mut MicrotaskQueue,\n  ) -> *const Context;\n  fn v8__Context__GetIsolate(this: *const Context) -> *mut Isolate;\n  fn v8__Context__Global(this: *const Context) -> *const Object;\n  fn v8__Context__GetExtrasBindingObject(this: *const Context)\n    -> *const Object;\n  fn v8__Context__GetNumberOfEmbedderDataFields(this: *const Context) -> u32;\n  fn v8__Context__GetAlignedPointerFromEmbedderData(\n    this: *const Context,\n    index: int,\n  ) -> *mut c_void;\n  fn v8__Context__SetAlignedPointerInEmbedderData(\n    this: *const Context,\n    index: int,\n    value: *mut c_void,\n  );\n  fn v8__Context__FromSnapshot(\n    isolate: *mut Isolate,\n    context_snapshot_index: usize,\n    global_object: *const Value,\n    microtask_queue: *mut MicrotaskQueue,\n  ) -> *const Context;\n  pub(super) fn v8__Context__GetSecurityToken(\n    this: *const Context,\n  ) -> *const Value;\n  pub(super) fn v8__Context__SetSecurityToken(\n    this: *const Context,\n    value: *const Value,\n  );\n  pub(super) fn v8__Context__UseDefaultSecurityToken(this: *const Context);\n  pub(super) fn v8__Context__AllowCodeGenerationFromStrings(\n    this: *const Context,\n    allow: bool,\n  );\n  pub(super) fn v8__Context_IsCodeGenerationFromStringsAllowed(\n    this: *const Context,\n  ) -> bool;\n  fn v8__Context__GetMicrotaskQueue(\n    this: *const Context,\n  ) -> *const MicrotaskQueue;\n  fn v8__Context__SetMicrotaskQueue(\n    this: *const Context,\n    microtask_queue: *const MicrotaskQueue,\n  );\n}\n\n#[derive(Default)]\npub struct ContextOptions<'s> {\n  /// An optional object template from which the global object for the newly created context will\n  /// be created.\n  pub global_template: Option<Local<'s, ObjectTemplate>>,\n  /// An optional global object to be reused for the newly created context. This global object\n  /// must have been created by a previous call to Context::New with the same global template.\n  /// The state of the global object will be completely reset and only object identify will\n  /// remain.\n  pub global_object: Option<Local<'s, Value>>,\n  /// An optional microtask queue used to manage the microtasks created in this context. If not\n  /// set the per-isolate default microtask queue would be used.\n  pub microtask_queue: Option<*mut MicrotaskQueue>,\n}\n\nimpl Context {\n  const ANNEX_SLOT: int = 1;\n  const INTERNAL_SLOT_COUNT: int = 1;\n\n  /// Creates a new context.\n  #[inline(always)]\n  pub fn new<'s>(\n    scope: &mut HandleScope<'s, ()>,\n    options: ContextOptions,\n  ) -> Local<'s, Context> {\n    unsafe {\n      scope.cast_local(|sd| {\n        v8__Context__New(\n          sd.get_isolate_ptr(),\n          options\n            .global_template\n            .map(|t| &*t as *const _)\n            .unwrap_or_else(null),\n          options\n            .global_object\n            .map(|o| &*o as *const _)\n            .unwrap_or_else(null),\n          options.microtask_queue.unwrap_or_else(null_mut),\n        )\n      })\n    }\n    .unwrap()\n  }\n\n  #[inline(always)]\n  pub fn get_extras_binding_object<'s>(\n    &self,\n    scope: &mut HandleScope<'s, ()>,\n  ) -> Local<'s, Object> {\n    unsafe { scope.cast_local(|_| v8__Context__GetExtrasBindingObject(self)) }\n      .unwrap()\n  }\n\n  /// Returns the global proxy object.\n  ///\n  /// Global proxy object is a thin wrapper whose prototype points to actual\n  /// context's global object with the properties like Object, etc. This is done\n  /// that way for security reasons (for more details see\n  /// https://wiki.mozilla.org/Gecko:SplitWindow).\n  ///\n  /// Please note that changes to global proxy object prototype most probably\n  /// would break VM---v8 expects only global object as a prototype of global\n  /// proxy object.\n  #[inline(always)]\n  pub fn global<'s>(\n    &self,\n    scope: &mut HandleScope<'s, ()>,\n  ) -> Local<'s, Object> {\n    unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap()\n  }\n\n  #[inline(always)]\n  pub fn get_microtask_queue(&self) -> &MicrotaskQueue {\n    unsafe { &*v8__Context__GetMicrotaskQueue(self) }\n  }\n\n  #[inline(always)]\n  pub fn set_microtask_queue(&self, microtask_queue: &MicrotaskQueue) {\n    unsafe {\n      v8__Context__SetMicrotaskQueue(self, microtask_queue);\n    }\n  }\n\n  #[inline]\n  fn get_annex_mut(\n    &self,\n    create_if_not_present: bool,\n  ) -> Option<&mut ContextAnnex> {\n    let isolate = unsafe { &mut *v8__Context__GetIsolate(self) };\n\n    let num_data_fields =\n      unsafe { v8__Context__GetNumberOfEmbedderDataFields(self) } as int;\n    if num_data_fields > Self::ANNEX_SLOT {\n      let annex_ptr = unsafe {\n        v8__Context__GetAlignedPointerFromEmbedderData(self, Self::ANNEX_SLOT)\n      } as *mut ContextAnnex;\n      if !annex_ptr.is_null() {\n        // SAFETY: This reference doesn't outlive the Context, so it can't outlive\n        // the annex itself. Also, any mutations or accesses to the annex after\n        // its creation require a mutable reference to the context's isolate, but\n        // such a mutable reference is consumed by this reference during its\n        // lifetime.\n        return Some(unsafe { &mut *annex_ptr });\n      }\n    }\n\n    if !create_if_not_present {\n      return None;\n    }\n\n    let annex = Box::new(ContextAnnex {\n      slots: Default::default(),\n      // Gets replaced later in the method.\n      self_weak: Weak::empty(isolate),\n    });\n    let annex_ptr = Box::into_raw(annex);\n    unsafe {\n      v8__Context__SetAlignedPointerInEmbedderData(\n        self,\n        Self::ANNEX_SLOT,\n        annex_ptr as *mut _,\n      )\n    };\n    assert!(\n      unsafe { v8__Context__GetNumberOfEmbedderDataFields(self) } as int\n        > Self::ANNEX_SLOT\n    );\n\n    // Make sure to drop the annex after the context is dropped, by creating a\n    // weak handle with a finalizer that drops the annex, and storing the weak\n    // in the annex itself.\n    let weak = {\n      // SAFETY: `self` can only have been derived from a `Local` or `Global`,\n      // and assuming the caller is only using safe code, the `Local` or\n      // `Global` must still be alive, so `self_ref_handle` won't outlive it.\n      // We also check above that `isolate` is the context's isolate.\n      let self_ref_handle = unsafe { UnsafeRefHandle::new(self, isolate) };\n\n      Weak::with_guaranteed_finalizer(\n        isolate,\n        self_ref_handle,\n        Box::new(move || {\n          // SAFETY: The lifetimes of references to the annex returned by this\n          // method are always tied to the context, and because this is the\n          // context's finalizer, we know there are no living references to\n          // the annex. And since the finalizer is only called once, the annex\n          // can't have been dropped before.\n          let _ = unsafe { Box::from_raw(annex_ptr) };\n        }),\n      )\n    };\n\n    // SAFETY: This reference doesn't outlive the Context, so it can't outlive\n    // the annex itself. Also, any mutations or accesses to the annex after\n    // its creation require a mutable reference to the context's isolate, but\n    // such a mutable reference is consumed by this reference during its\n    // lifetime.\n    let annex_mut = unsafe { &mut *annex_ptr };\n    annex_mut.self_weak = weak;\n    Some(annex_mut)\n  }\n\n  /// Get a reference to embedder data added with [`Self::set_slot()`].\n  #[inline(always)]\n  pub fn get_slot<T: 'static>(&self) -> Option<&T> {\n    if let Some(annex) = self.get_annex_mut(false) {\n      annex.slots.get(&TypeId::of::<T>()).map(|slot| {\n        // SAFETY: `Self::set_slot` guarantees that only values of type T will be\n        // stored with T's TypeId as their key.\n        unsafe { slot.borrow::<T>() }\n      })\n    } else {\n      None\n    }\n  }\n\n  /// Get a mutable reference to embedder data added with [`Self::set_slot()`].\n  #[inline(always)]\n  pub fn get_slot_mut<T: 'static>(&self) -> Option<&mut T> {\n    if let Some(annex) = self.get_annex_mut(false) {\n      annex.slots.get_mut(&TypeId::of::<T>()).map(|slot| {\n        // SAFETY: `Self::set_slot` guarantees that only values of type T will be\n        // stored with T's TypeId as their key.\n        unsafe { slot.borrow_mut::<T>() }\n      })\n    } else {\n      None\n    }\n  }\n\n  /// Use with [`Context::get_slot`] and [`Context::get_slot_mut`] to associate\n  /// state with a Context.\n  ///\n  /// This method gives ownership of value to the Context. Exactly one object of\n  /// each type can be associated with a Context. If called more than once with\n  /// an object of the same type, the earlier version will be dropped and\n  /// replaced.\n  ///\n  /// Returns true if value was set without replacing an existing value.\n  ///\n  /// The value will be dropped when the context is garbage collected.\n  #[inline(always)]\n  pub fn set_slot<T: 'static>(&self, value: T) -> bool {\n    self\n      .get_annex_mut(true)\n      .unwrap()\n      .slots\n      .insert(TypeId::of::<T>(), RawSlot::new(value))\n      .is_none()\n  }\n\n  /// Removes the embedder data added with [`Self::set_slot()`] and returns it\n  /// if it exists.\n  #[inline(always)]\n  pub fn remove_slot<T: 'static>(&self) -> Option<T> {\n    if let Some(annex) = self.get_annex_mut(false) {\n      annex.slots.remove(&TypeId::of::<T>()).map(|slot| {\n        // SAFETY: `Self::set_slot` guarantees that only values of type T will be\n        // stored with T's TypeId as their key.\n        unsafe { slot.into_inner::<T>() }\n      })\n    } else {\n      None\n    }\n  }\n\n  /// Removes all embedder data added with [`Self::set_slot()`], and\n  /// deletes any internal state needed to keep track of such slots.\n  ///\n  /// This is needed to make a snapshot with\n  /// [`SnapshotCreator`](crate::SnapshotCreator), since the internal embedder\n  /// state uses [`Weak`] handles, which cannot be alive at the time of\n  /// snapshotting.\n  #[inline(always)]\n  pub fn clear_all_slots(&self) {\n    if let Some(annex_mut) = self.get_annex_mut(false) {\n      let annex_ptr = annex_mut as *mut ContextAnnex;\n      let _ = unsafe { Box::from_raw(annex_ptr) };\n      unsafe {\n        v8__Context__SetAlignedPointerInEmbedderData(\n          self,\n          Self::ANNEX_SLOT,\n          null_mut(),\n        )\n      };\n    }\n  }\n\n  #[inline(always)]\n  pub unsafe fn set_aligned_pointer_in_embedder_data(\n    &self,\n    slot: i32,\n    data: *mut c_void,\n  ) {\n    // Initialize the annex when slot count > INTERNAL_SLOT_COUNT.\n    self.get_annex_mut(true);\n\n    v8__Context__SetAlignedPointerInEmbedderData(\n      self,\n      slot + Self::INTERNAL_SLOT_COUNT,\n      data,\n    )\n  }\n\n  #[inline(always)]\n  pub fn get_aligned_pointer_from_embedder_data(\n    &self,\n    slot: i32,\n  ) -> *mut c_void {\n    unsafe {\n      v8__Context__GetAlignedPointerFromEmbedderData(\n        self,\n        slot + Self::INTERNAL_SLOT_COUNT,\n      )\n    }\n  }\n\n  /// Create a new context from a (non-default) context snapshot. There\n  /// is no way to provide a global object template since we do not create\n  /// a new global object from template, but we can reuse a global object.\n  pub fn from_snapshot<'s>(\n    scope: &mut HandleScope<'s, ()>,\n    context_snapshot_index: usize,\n    options: ContextOptions,\n  ) -> Option<Local<'s, Context>> {\n    unsafe {\n      scope.cast_local(|sd| {\n        v8__Context__FromSnapshot(\n          sd.get_isolate_mut(),\n          context_snapshot_index,\n          options\n            .global_object\n            .map(|o| &*o as *const _)\n            .unwrap_or_else(null),\n          options.microtask_queue.unwrap_or_else(null_mut),\n        )\n      })\n    }\n  }\n\n  #[inline(always)]\n  pub fn get_security_token<'s>(\n    &self,\n    scope: &mut HandleScope<'s, ()>,\n  ) -> Local<'s, Value> {\n    unsafe { scope.cast_local(|_| v8__Context__GetSecurityToken(self)) }\n      .unwrap()\n  }\n\n  #[inline(always)]\n  pub fn set_security_token(&self, token: Local<Value>) {\n    unsafe {\n      v8__Context__SetSecurityToken(self, &*token);\n    }\n  }\n\n  #[inline(always)]\n  pub fn use_default_security_token(&self) {\n    unsafe {\n      v8__Context__UseDefaultSecurityToken(self);\n    }\n  }\n\n  pub fn set_allow_generation_from_strings(&self, allow: bool) {\n    unsafe {\n      v8__Context__AllowCodeGenerationFromStrings(self, allow);\n    }\n  }\n\n  pub fn is_code_generation_from_strings_allowed(&self) -> bool {\n    unsafe { v8__Context_IsCodeGenerationFromStringsAllowed(self) }\n  }\n}\n\nstruct ContextAnnex {\n  slots: HashMap<TypeId, RawSlot, BuildTypeIdHasher>,\n  // In order to run the finalizer that drops the ContextAnnex when the Context\n  // is GC'd, the corresponding Weak must be kept alive until that time.\n  self_weak: Weak<Context>,\n}\n"
      }
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}
Eval in Emacs: (lsp-bridge-define--jump '"/Users/gerald/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/v8-129.0.0/src/context.rs" '"" '(:line 91 :character 9))
Eval in Emacs: (lsp-bridge-diagnostic--render '"/private/tmp/rusty_v8_example/src/main.rs" '"" '() '0)
{
   "jsonrpc": "2.0",
   "id": 58329,
   "result": [
      {
         "uri": "file:///Users/gerald/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/v8-129.0.0/src/context.rs",
         "range": {
            "start": {
               "line": 91,
               "character": 9
            },
            "end": {
               "line": 91,
               "character": 12
            }
         }
      }
   ]
}

--- [22:59:29.373502] Recv $/progress notification from 'rust-analyzer' for project 
Eval in Emacs: (lsp-bridge--record-work-done-progress '"[LSP-Bridge] Indexing (98%%) 60/61 (bindgen)")
{
   "jsonrpc": "2.0",
   "method": "$/progress",
   "params": {
      "token": "rustAnalyzer/Indexing",
      "value": {
         "kind": "report",
         "cancellable": false,
         "message": "60/61 (bindgen)",
         "percentage": 98
      }
   }
}

--- [22:59:29.373951] Recv $/progress notification from 'rust-analyzer' for project 
Eval in Emacs: (lsp-bridge--record-work-done-progress '"[LSP-Bridge] Indexing (100%%)")
{
   "jsonrpc": "2.0",
   "method": "$/progress",
   "params": {
      "token": "rustAnalyzer/Indexing",
      "value": {
         "kind": "report",
         "cancellable": false,
         "percentage": 100
      }
   }
}

--- [22:59:59.101758] Recv $/progress notification from 'rust-analyzer' for project 
{
   "jsonrpc": "2.0",
   "method": "$/progress",
   "params": {
      "token": "rustAnalyzer/Indexing",
      "value": {
         "kind": "end"
      }
   }
}

--- [22:59:59.101912] Recv window/showMessage notification from 'rust-analyzer' for project 
{
   "jsonrpc": "2.0",
   "method": "window/showMessage",
   "params": {
      "type": 2,
      "message": "Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required."
   }
}

看日志,应该找到了对应的文件,但没有进行跳转。

manateelazycat commented 1 month ago

这个补丁之前是不是好的呢? https://github.com/manateelazycat/lsp-bridge/commit/82580331a736290f106f455efda130ecf56ad5b4

getong commented 1 month ago

没有。我设置了false,也不行。

getong commented 1 month ago

卡顿很厉害,会卡住我的lsp-bridge buffer,不给日志输出。

manateelazycat commented 1 month ago

emacs -Q 试过吗?

getong commented 1 month ago

试过了,我手动启用了lsp-bridge,但lsp-bridge-find-def 就不起效了。 你可以试试我的仓库,https://github.com/getong/rust_example/tree/main/rusty_v8_example 就是这个仓库,查找v8模块调用卡顿很明显。

manateelazycat commented 1 month ago

你要怎么设置? cargo 先 build ?

最好给我完整的重现步骤

getong commented 1 month ago
(use-package
 lsp-bridge
 :straight '(lsp-bridge :type git :host github :repo "manateelazycat/lsp-bridge" :files (:defaults "*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources") :build (:not compile))
 :defer t
 :commands (lsp-bridge-mode)
 ;; (add-hook 'lsp-bridge-mode-hook #'lsp-bridge-mode-hook-func)

 :hook
 ((dart-mode
   ;; emacs-lisp-mode
   lua-mode c++-mode swift-mode c-mode)
  . lsp-bridge-mode)
 ((java-mode kotlin-mode) . setup-lsp-bridge-kotlin-mode)
 ((csharp-mode python-mode) . setup-lsp-bridge-python-mode)
 ((rust-mode rustic-mode) . setup-lsp-bridge-rust-mode)
 (go-mode . setup-lsp-bridge-golang-mode)
 ((typescript-mode js-mode vue-mode solidity-mode) . setup-lsp-bridge-vue-mode)

 :bind
 (:map
  lsp-bridge-mode-map
  ("M-." . lsp-bridge-find-def)
  ("M-n ." . lsp-bridge-find-def-other-window)
  ("M-n i" . lsp-bridge-find-impl)
  ("M-n I" . lsp-bridge-find-impl-other-window)
  ("M-," . lsp-bridge-find-def-return)
  ("M-?" . lsp-bridge-find-references)
  ("M-n r" . lsp-bridge-rename)
  ("M-n l" . lsp-bridge-diagnostic-list)
  ("M-n n" . lsp-bridge-diagnostic-jump-next)
  ("M-n p" . lsp-bridge-diagnostic-jump-prev)
  ("M-n h" . lsp-bridge-popup-documentation)
  ("M-n u" . lsp-bridge-popup-documentation-scroll-up)
  ("M-n d" . lsp-bridge-popup-documentation-scroll-down)
  ;; ("C-c M-f" . lsp-bridge-code-format)  ;; replace by blacken
  )
 :custom
 (cond
  ((eq system-type 'darwin) ; macOS
   (setq lsp-bridge-python-command "/usr/local/bin/python3")
   (setq lsp-pyright-python-executable-cmd "/usr/local/bin/python3"))
  ((eq system-type 'gnu/linux) ; Linux
   (setq lsp-bridge-python-command "/usr/bin/python3")
   (setq lsp-pyright-python-executable-cmd "/usr/bin/python3")))
 (acm-backend-lsp-enable-auto-import t)
 (lsp-bridge-enable-with-tramp t)
 (lsp-bridge-remote-start-automatically t)
 (lsp-bridge-enable-org-babel t)
 (tabnine-bridge-binaries-folder (expand-file-name "~/.backup-emacs/tabnine-bridge/tabnine-binaries"))
 (lsp-bridge-enable-log t)
 (lsp-bridge-symbols-enable-which-func t)
 (acm-enable-icon t)
 (acm-enable-doc t)
 (acm-enable-tabnine t)
 (acm-enable-quick-access t)
 (lsp-bridge-enable-inlay-hint t)
 (lsp-bridge-find-def-select-in-open-windows t)
 ;; (lsp-bridge-signature-show-function 'lsp-bridge-signature-show-with-frame)
 ;; (lsp-bridge-signature-show-with-frame-position 'top-right)
 (lsp-bridge-enable-completion-in-minibuffer t)
 (acm-backend-yas-match-by-trigger-keyword t)
 ;; (lsp-bridge-signature-show-function 'lsp-bridge-signature-posframe)
 (lsp-bridge-c-lsp-server "ccls")
 (acm-enable-codeium t)
 (lsp-bridge-enable-signature-help t)
 ;; (lsp-bridge-complete-manually t)
 (codeium-bridge-folder (expand-file-name "~/.backup-emacs/codeium"))
 (acm-backend-codeium-api-key-path (expand-file-name "~/.backup-emacs/codeium/codeium_api_key.txt"))
 (lsp-bridge-popup-documentation-buffer "*lsp-bridge-hover*")
 (lsp-bridge-signature-buffer "*lsp-bridge-signature*")
 (lsp-bridge-diagnostic-buffer "*lsp-bridge-diagnostic*")
 (lsp-bridge-csharp-lsp-server "csharp-ls")
 (acm-candidate-match-function #'orderless-flex)
 :config (advice-add #'save-buffer :after #'acm-hide)
 ;; (global-lsp-bridge-mode)
 (unless (file-exists-p (expand-file-name "~/.backup-emacs/tabnine-bridge/tabnine-binaries"))
   (funcall-interactively #'lsp-bridge-install-tabnine))

 (unless (file-exists-p (expand-file-name "~/.backup-emacs/codeium"))
   (funcall-interactively #'lsp-bridge-install-update-codeium))

 ;; detect rust project
 (defun find-rust-prj-root (dir)
   "Find the Rust project root of DIR."
   (file-truename (locate-dominating-file dir "Cargo.toml")))
 (defun setup-lsp-bridge-rust-mode ()
   (setq lsp-bridge-get-project-path-by-filepath #'find-rust-prj-root)
   (lsp-bridge-mode))

 ;; detect gradle project
 (defun find-gradle-prj-root (dir)
   "Find the gradle project root of DIR."
   (file-truename (locate-dominating-file dir "gradlew")))
 (defun setup-lsp-bridge-kotlin-mode ()
   (setq lsp-bridge-get-project-path-by-filepath #'find-gradle-prj-root)
   (lsp-bridge-mode))

 ;; detect python project
 (defun find-python-prj-root (dir)
   "Find the python project root of DIR."
   (file-truename (locate-dominating-file dir ".git")))
 (defun setup-lsp-bridge-python-mode ()
   (setq lsp-bridge-get-project-path-by-filepath #'find-python-prj-root)
   (lsp-bridge-mode))

 ;; detect go project
 (defun find-golang-prj-root (dir)
   "Find the golang project root of DIR."
   (file-truename (locate-dominating-file dir "go.mod")))
 (defun setup-lsp-bridge-golang-mode ()
   (setq lsp-bridge-get-project-path-by-filepath #'find-golang-prj-root)
   (lsp-bridge-mode))

 ;; detect vue project
 (defun find-vue-prj-root (dir)
   "Find the vue project root of DIR."
   (file-truename (locate-dominating-file dir "package.json")))
 (defun setup-lsp-bridge-vue-mode ()
   (setq lsp-bridge-get-project-path-by-filepath #'find-vue-prj-root)
   (lsp-bridge-mode)))

拷贝这个目录到本地目录, 直接打开 src/main.rs, 然后试着对着几个v8::*函数进行lsp-bridge-find-find, 每个都会卡住。我就是这样操作的。

manateelazycat commented 1 month ago

我的意思是, Rust这个项目需要怎么构建一下? 我的每次都是 [LSP-Bridge] No definition found.

getong commented 1 month ago

cargo build

getong commented 1 month ago

把这个目录里面两个文件拷贝到一个单独目录就可以了,cargo build, 这是个独立的rust项目

manateelazycat commented 1 month ago

我看到你有几个 detect 函数, 我写了一个补丁 https://github.com/manateelazycat/lsp-bridge/commit/34f92a50eb77452147c8b8ba23707c809a617e32

你的那几个 detect 函数都可以删除啦。

manateelazycat commented 1 month ago

我看了是因为, rust_example 是一个 git 目录, 但是 rust_example 下没有 Cargo.toml, 所以 rust lsp server 一直都在 workspace progress 中, 如果你把 rusty_v8_example 单独拷贝出来 cargo build 是可以定义跳转的