src/Tools/VSCode/src/channel.scala
author wenzelm
Sat, 10 Mar 2018 11:55:54 +0100
changeset 67805 2d9a265b294e
parent 65922 d2f19f05c0e9
child 67856 ec9f1ec763a0
permissions -rw-r--r--
more uniform Bytes.read_line/read_block operations;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     1
/*  Title:      Tools/VSCode/src/channel.scala
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     3
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     4
Channel with JSON RPC protocol.
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     5
*/
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     6
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     7
package isabelle.vscode
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     8
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
     9
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    10
import isabelle._
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    11
64777
ca09695eb43c clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents: 64733
diff changeset
    12
import java.io.{InputStream, OutputStream, FileOutputStream, ByteArrayOutputStream, File => JFile}
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    13
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    14
import scala.collection.mutable
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    15
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    16
65922
d2f19f05c0e9 clarified message logging;
wenzelm
parents: 65829
diff changeset
    17
class Channel(in: InputStream, out: OutputStream, log: Logger = No_Logger, verbose: Boolean = false)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    18
{
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    19
  /* read message */
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    20
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    21
  private val Content_Length = """^\s*Content-Length:\s*(\d+)\s*$""".r
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    22
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    23
  private def read_line(): String =
67805
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    24
    Bytes.read_line(in) match {
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    25
      case Some(bytes) => bytes.text
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    26
      case None => ""
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    27
    }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    28
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    29
  private def read_header(): List[String] =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    30
  {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    31
    val header = new mutable.ListBuffer[String]
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    32
    var line = ""
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    33
    while ({ line = read_line(); line != "" }) header += line
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    34
    header.toList
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    35
  }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    36
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    37
  private def read_content(n: Int): String =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    38
  {
67805
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    39
    val bytes = Bytes.read_stream(in, limit = n)
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    40
    if (bytes.length == n) bytes.text
2d9a265b294e more uniform Bytes.read_line/read_block operations;
wenzelm
parents: 65922
diff changeset
    41
    else error("Bad message content (unexpected EOF after " + bytes.length + " of " + n + " bytes)")
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    42
  }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    43
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    44
  def read(): Option[JSON.T] =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    45
  {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    46
    read_header() match {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    47
      case Nil => None
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    48
      case Content_Length(s) :: _ =>
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    49
        s match {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    50
          case Value.Int(n) if n >= 0 =>
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    51
            val msg = read_content(n)
65922
d2f19f05c0e9 clarified message logging;
wenzelm
parents: 65829
diff changeset
    52
            val json = JSON.parse(msg)
d2f19f05c0e9 clarified message logging;
wenzelm
parents: 65829
diff changeset
    53
            Protocol.Message.log("IN: " + n, json, log, verbose)
d2f19f05c0e9 clarified message logging;
wenzelm
parents: 65829
diff changeset
    54
            Some(json)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    55
          case _ => error("Bad Content-Length: " + s)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    56
        }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    57
      case header => error(cat_lines("Malformed header:" :: header))
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    58
    }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    59
  }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    60
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    61
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    62
  /* write message */
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    63
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    64
  def write(json: JSON.T)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    65
  {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    66
    val msg = JSON.Format(json)
65152
a920012ae16a tuned messages;
wenzelm
parents: 65095
diff changeset
    67
    val content = UTF8.bytes(msg)
a920012ae16a tuned messages;
wenzelm
parents: 65095
diff changeset
    68
    val n = content.length
a920012ae16a tuned messages;
wenzelm
parents: 65095
diff changeset
    69
    val header = UTF8.bytes("Content-Length: " + n + "\r\n\r\n")
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    70
65922
d2f19f05c0e9 clarified message logging;
wenzelm
parents: 65829
diff changeset
    71
    Protocol.Message.log("OUT: " + n, json, log, verbose)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    72
    out.synchronized {
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    73
      out.write(header)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    74
      out.write(content)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    75
      out.flush
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    76
    }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    77
  }
64642
c231206a84c8 display messages, according to regular Isabelle Output;
wenzelm
parents: 64605
diff changeset
    78
c231206a84c8 display messages, according to regular Isabelle Output;
wenzelm
parents: 64605
diff changeset
    79
c231206a84c8 display messages, according to regular Isabelle Output;
wenzelm
parents: 64605
diff changeset
    80
  /* display message */
c231206a84c8 display messages, according to regular Isabelle Output;
wenzelm
parents: 64605
diff changeset
    81
64686
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    82
  def display_message(message_type: Int, msg: String, show: Boolean = true): Unit =
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    83
    write(Protocol.DisplayMessage(message_type, Output.clean_yxml(msg), show))
64642
c231206a84c8 display messages, according to regular Isabelle Output;
wenzelm
parents: 64605
diff changeset
    84
64686
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    85
  def error_message(msg: String) { display_message(Protocol.MessageType.Error, msg, true) }
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    86
  def warning(msg: String) { display_message(Protocol.MessageType.Warning, msg, true) }
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    87
  def writeln(msg: String) { display_message(Protocol.MessageType.Info, msg, true) }
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    88
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    89
  def log_error_message(msg: String) { display_message(Protocol.MessageType.Error, msg, false) }
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    90
  def log_warning(msg: String) { display_message(Protocol.MessageType.Warning, msg, false) }
7888be4fa496 clarified signature;
wenzelm
parents: 64675
diff changeset
    91
  def log_writeln(msg: String) { display_message(Protocol.MessageType.Info, msg, false) }
64675
c557279d93f2 support for diagnostics;
wenzelm
parents: 64658
diff changeset
    92
64810
05b29c8f0add more informative error for spurious crash;
wenzelm
parents: 64777
diff changeset
    93
  object Error_Logger extends Logger
05b29c8f0add more informative error for spurious crash;
wenzelm
parents: 64777
diff changeset
    94
  {
05b29c8f0add more informative error for spurious crash;
wenzelm
parents: 64777
diff changeset
    95
    def apply(msg: => String) { log_error_message(msg) }
05b29c8f0add more informative error for spurious crash;
wenzelm
parents: 64777
diff changeset
    96
  }
05b29c8f0add more informative error for spurious crash;
wenzelm
parents: 64777
diff changeset
    97
64675
c557279d93f2 support for diagnostics;
wenzelm
parents: 64658
diff changeset
    98
64733
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
    99
  /* progress */
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   100
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   101
  def make_progress(verbose: Boolean = false): Progress =
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   102
    new Progress {
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   103
      override def echo(msg: String): Unit = log_writeln(msg)
65829
07e86b942a84 more explicit warning/error messages;
wenzelm
parents: 65152
diff changeset
   104
      override def echo_warning(msg: String): Unit = log_warning(msg)
07e86b942a84 more explicit warning/error messages;
wenzelm
parents: 65152
diff changeset
   105
      override def echo_error_message(msg: String): Unit = log_error_message(msg)
64733
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   106
      override def theory(session: String, theory: String): Unit =
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   107
        if (verbose) echo(session + ": theory " + theory)
20174e871623 automatically build session image;
wenzelm
parents: 64717
diff changeset
   108
    }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   109
}