Class LanguageService

java.lang.Object
smile.util.lsp.LanguageService
All Implemented Interfaces:
AutoCloseable

public class LanguageService extends Object implements AutoCloseable
An LSP (Language Server Protocol) service that manages the full lifecycle of a language server process and exposes high-level navigation and search operations.

Lifecycle

  1. Construct a LanguageService with the server launch command and the workspace root directory.
  2. Call start() to launch the server process, connect the LSP4J launcher over the process's stdin/stdout, and perform the LSP initialize / initialized handshake.
  3. Use the navigation methods.
  4. Call close() (or use try-with-resources) to send the LSP shutdown + exit messages and terminate the server process.

All position parameters are 1-based

The line and character parameters accepted by every operation use the same 1-based numbering displayed in editors. The client converts them to the 0-based coordinates required by the LSP specification transparently.

Thread safety

Each operation method may be called from any thread after start() returns. Internally, all calls are forwarded over the single LSP4J channel whose threading is managed by the LSP4J message reader/writer threads.

  • Constructor Details

    • LanguageService

      public LanguageService(List<String> command, Path workspaceRoot)
      Creates a LanguageService using a pre-parsed command list.
      Parameters:
      command - the command and arguments used to start the language server process (e.g. ["java", "-jar", "jdt-ls.jar", ...]).
      workspaceRoot - the workspace root directory sent to the server in the initialize request.
    • LanguageService

      public LanguageService(List<String> command, Path workspaceRoot, int timeoutSeconds)
      Creates a LanguageService with a custom per-request timeout.
      Parameters:
      command - the command used to start the language server.
      workspaceRoot - the workspace root directory.
      timeoutSeconds - how many seconds to wait for each LSP response before throwing a TimeoutException.
  • Method Details

    • get

      public static LanguageService get(String lang)
      Returns the service for the given language.
      Parameters:
      lang - the language ID (e.g. "java", "python").
      Returns:
      the corresponding LanguageService, or null if not found.
    • put

      public static void put(String lang, LanguageService service)
      Registers a LanguageService for the given language ID.
      Parameters:
      lang - the language ID (e.g. "java", "python").
      service - the service to register.
    • server

      public org.eclipse.lsp4j.services.LanguageServer server()
      Returns the underlying language server.
      Returns:
      the underlying language server.
    • isInitialized

      public boolean isInitialized()
      Returns true if the service has been started and initialized.
      Returns:
      true if the service is initialized, false otherwise.
    • start

      Launches the language server process, connects the LSP4J launcher over the process's stdin/stdout, and performs the LSP initialize / initialized handshake. The server may send notifications (e.g. publishDiagnostics) back to the client. This overload uses a no-op LSP4J client implementation that log all server notifications at DEBUG or INFO level.

      This method blocks until the server has acknowledged the initialize request.

      Throws:
      IOException - if the server process cannot be started.
      InterruptedException - if the thread is interrupted while waiting for the initialize response.
      ExecutionException - if the initialize request fails.
      TimeoutException - if the server does not respond within the configured timeout.
    • start

      public void start(org.eclipse.lsp4j.services.LanguageClient client) throws IOException, InterruptedException, ExecutionException, TimeoutException
      Launches the language server process, connects the LSP4J launcher over the process's stdin/stdout, and performs the LSP initialize / initialized handshake.

      This method blocks until the server has acknowledged the initialize request.

      Parameters:
      client - an implementation of LSP4J's LanguageClient interface to receive server notifications.
      Throws:
      IOException - if the server process cannot be started.
      InterruptedException - if the thread is interrupted while waiting for the initialize response.
      ExecutionException - if the initialize request fails.
      TimeoutException - if the server does not respond within the configured timeout.
    • close

      public void close()
      Sends the LSP shutdown request followed by the exit notification, then forcibly terminates the server process if it is still running.
      Specified by:
      close in interface AutoCloseable
    • goToDefinition

      public List<LspLocation> goToDefinition(String filePath, int line, int character)
      Finds the definition location(s) of the symbol at the given position.

      Corresponds to the LSP textDocument/definition request.

      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the list of definition locations; empty if none found.
      Throws:
      LspException - if the request fails or times out.
    • findReferences

      public List<LspLocation> findReferences(String filePath, int line, int character, boolean includeDeclaration)
      Finds all references to the symbol at the given position.

      Corresponds to the LSP textDocument/references request. The definition location is included in the results when includeDeclaration is true.

      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      includeDeclaration - whether to include the declaration site.
      Returns:
      the list of reference locations; empty if none found.
      Throws:
      LspException - if the request fails or times out.
    • findReferences

      public List<LspLocation> findReferences(String filePath, int line, int character)
      Finds all references to the symbol at the given position, including the declaration site.
      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the list of reference locations; empty if none found.
      Throws:
      LspException - if the request fails or times out.
    • hover

      public String hover(String filePath, int line, int character)
      Returns hover information (documentation, type info) for the symbol at the given position.

      Corresponds to the LSP textDocument/hover request.

      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the hover text, or an empty string if no hover info is available.
      Throws:
      LspException - if the request fails or times out.
    • documentSymbol

      public List<LspSymbol> documentSymbol(String filePath)
      Returns all symbols defined in the given document.

      Corresponds to the LSP textDocument/documentSymbol request.

      Parameters:
      filePath - the absolute file path to query.
      Returns:
      the list of symbols; empty if the server returns nothing.
      Throws:
      LspException - if the request fails or times out.
    • workspaceSymbol

      public List<LspSymbol> workspaceSymbol(String query)
      Searches for symbols whose names match the given query across the entire workspace.

      Corresponds to the LSP workspace/symbol request.

      Parameters:
      query - the search query string (may be empty to list all symbols).
      Returns:
      the list of matching symbols; empty if the server returns nothing.
      Throws:
      LspException - if the request fails or times out.
    • goToImplementation

      public List<LspLocation> goToImplementation(String filePath, int line, int character)
      Finds all implementations of the interface or abstract method at the given position.

      Corresponds to the LSP textDocument/implementation request.

      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the list of implementation locations; empty if none found.
      Throws:
      LspException - if the request fails or times out.
    • prepareCallHierarchy

      public List<CallHierarchyItem> prepareCallHierarchy(String filePath, int line, int character)
      Resolves the call-hierarchy item at the given position.

      This is the first step of a call-hierarchy query. Pass the returned items to incomingCalls(CallHierarchyItem) or outgoingCalls(CallHierarchyItem) to traverse the hierarchy.

      Corresponds to the LSP textDocument/prepareCallHierarchy request.

      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the list of call-hierarchy items at the position; empty if none.
      Throws:
      LspException - if the request fails or times out.
    • incomingCalls

      public List<CallHierarchyCall> incomingCalls(CallHierarchyItem item)
      Returns all callers of the given call-hierarchy item.

      Corresponds to the LSP callHierarchy/incomingCalls request.

      Parameters:
      item - the call-hierarchy item to query (typically obtained from prepareCallHierarchy(String, int, int)).
      Returns:
      the list of incoming calls; empty if none.
      Throws:
      LspException - if the request fails or times out.
    • outgoingCalls

      public List<CallHierarchyCall> outgoingCalls(CallHierarchyItem item)
      Returns all functions or methods called by the given call-hierarchy item.

      Corresponds to the LSP callHierarchy/outgoingCalls request.

      Parameters:
      item - the call-hierarchy item to query (typically obtained from prepareCallHierarchy(String, int, int)).
      Returns:
      the list of outgoing calls; empty if none.
      Throws:
      LspException - if the request fails or times out.
    • incomingCalls

      public List<CallHierarchyCall> incomingCalls(String filePath, int line, int character)
      Convenience method that combines prepareCallHierarchy(String, int, int) and incomingCalls(CallHierarchyItem) into a single call.
      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the flat list of all incoming calls; empty if none.
      Throws:
      LspException - if any request fails or times out.
    • outgoingCalls

      public List<CallHierarchyCall> outgoingCalls(String filePath, int line, int character)
      Convenience method that combines prepareCallHierarchy(String, int, int) and outgoingCalls(CallHierarchyItem) into a single call.
      Parameters:
      filePath - the absolute file path to query.
      line - the 1-based line number.
      character - the 1-based character offset.
      Returns:
      the flat list of all outgoing calls; empty if none.
      Throws:
      LspException - if any request fails or times out.
    • workspaceRoot

      public Path workspaceRoot()
      Returns the workspace root directory used by this client.
      Returns:
      the workspace root.
    • isStarted

      public boolean isStarted()
      Returns true if the client has been successfully started and the initialize handshake has completed.
      Returns:
      true if ready.
    • jdtLs

      public static LanguageService jdtLs(Path workspaceRoot, Path jdtLsJar, Path jdtLsHome, Path dataDir)
      Creates a LanguageService pre-configured to launch the Eclipse JDT Language Server (JDT-LS).

      The jdtLsJar path must point to the JDT-LS launcher JAR (plugins/org.eclipse.equinox.launcher_*.jar inside the JDT-LS installation directory).

      The data directory is where JDT-LS stores its workspace index. It must be writable and is typically a subdirectory of the user's home directory.

      Parameters:
      workspaceRoot - the project root to analyze.
      jdtLsJar - path to the JDT-LS equinox launcher JAR.
      jdtLsHome - the JDT-LS installation directory (contains plugins/ and config_linux/ etc.).
      dataDir - writable directory for JDT-LS workspace data.
      Returns:
      a configured (but not yet started) LanguageService.
    • of

      public static LanguageService of(Path workspaceRoot, String serverCommand)
      Creates a LanguageService for any language server that accepts a simple stdio launch command (e.g. Pyright, TypeScript LS, rust-analyzer, clangd).
      Parameters:
      workspaceRoot - the project root to analyze.
      serverCommand - the full launch command as a single string (e.g. "pyright-langserver --stdio").
      Returns:
      a configured (but not yet started) LanguageService.