All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aya.lsp.LspMain Maven / Gradle / Ivy

The newest version!
// Copyright (c) 2020-2024 Tesla (Yinsen) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.lsp;

import org.aya.cli.library.incremental.CompilerAdvisor;
import org.aya.lsp.server.AyaLanguageClient;
import org.aya.lsp.server.AyaLanguageServer;
import org.aya.lsp.utils.Log;
import org.aya.lsp.utils.LspArgs;
import org.javacs.lsp.LSP;
import org.jetbrains.annotations.NotNull;
import picocli.CommandLine;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;

public class LspMain extends LspArgs implements Callable {
  public static void main(String[] args) {
    new CommandLine(new LspMain()).execute(args);
  }

  @Override public Integer call() throws Exception {
    Log.i("Hello, this is Aya language server");
    var startup = switch (mode) {
      case server -> runServer();
      case client -> runClient();
      case debug -> runDebug();
    };

    LSP.connect(
      AyaLanguageClient.class,
      client -> new AyaLanguageServer(CompilerAdvisor.inMemory(), client),
      startup.in,
      startup.out
    );
    return 0;
  }

  private static @NotNull Startup runDebug() {
    Log.i("Debug mode, using stdin and stdout");
    return new Startup(System.in, System.out);
  }

  private @NotNull Startup runClient() throws IOException {
    Log.i("Client mode, connecting to %s:%d", host, port);
    var socket = new Socket(host, port);
    return new Startup(new CloseAwareInputStream(socket.getInputStream()), socket.getOutputStream());
  }

  private @NotNull Startup runServer() throws IOException {
    Log.i("Server mode, listening on %s:%d", host, port);
    try (var server = new ServerSocket(port, 0, InetAddress.getByName(host))) {
      var client = server.accept();
      return new Startup(new CloseAwareInputStream(client.getInputStream()), client.getOutputStream());
    }
  }

  private static class CloseAwareInputStream extends InputStream {
    private final InputStream inputStream;

    private CloseAwareInputStream(InputStream inputStream) {
      this.inputStream = inputStream;
    }

    private int closeIfRemoteClosed(int len) throws IOException {
      if (len < 0) inputStream.close();
      return len;
    }

    @Override public int read() throws IOException {
      return closeIfRemoteClosed(inputStream.read());
    }

    @Override public int read(byte @NotNull [] b) throws IOException {
      return closeIfRemoteClosed(inputStream.read(b));
    }

    @Override public int read(byte @NotNull [] b, int off, int len) throws IOException {
      return closeIfRemoteClosed(inputStream.read(b, off, len));
    }
  }

  private record Startup(
    @NotNull InputStream in,
    @NotNull OutputStream out
  ) {
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy