src/Tools/VSCode/src/vscode_resources.scala
author wenzelm
Thu, 29 Dec 2016 21:54:04 +0100
changeset 64703 a115391494ed
parent 64640 f9470490e682
child 64704 08c2d80428ff
permissions -rw-r--r--
moved main state to VSCode_Resources; misc tuning;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
64623
83f012ce2567 clarified module name;
wenzelm
parents: 64605
diff changeset
     1
/*  Title:      Tools/VSCode/src/vscode_resources.scala
64605
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
64623
83f012ce2567 clarified module name;
wenzelm
parents: 64605
diff changeset
     4
Resources for VSCode Language Server, based on file-system URIs.
64605
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
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    12
import java.net.{URI, URISyntaxException}
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    13
import java.io.{File => JFile}
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    14
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    15
64623
83f012ce2567 clarified module name;
wenzelm
parents: 64605
diff changeset
    16
object VSCode_Resources
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    17
{
64703
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    18
  /* file URIs */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    19
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    20
  def is_wellformed(uri: String): Boolean =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    21
    try { new JFile(new URI(uri)); true }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    22
    catch { case _: URISyntaxException | _: IllegalArgumentException => false }
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    23
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    24
  def canonical_file(uri: String): JFile =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    25
    new JFile(new URI(uri)).getCanonicalFile
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    26
64703
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    27
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    28
  /* internal state */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    29
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    30
  sealed case class State(
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    31
    models: Map[String, Document_Model] = Map.empty,
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    32
    pending_input: Set[Document.Node.Name] = Set.empty,
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    33
    pending_output: Set[Document.Node.Name] = Set.empty)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    34
}
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    35
64623
83f012ce2567 clarified module name;
wenzelm
parents: 64605
diff changeset
    36
class VSCode_Resources(
64703
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    37
    val options: Options,
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    38
    loaded_theories: Set[String],
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    39
    known_theories: Map[String, Document.Node.Name],
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    40
    base_syntax: Outer_Syntax)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    41
  extends Resources(loaded_theories, known_theories, base_syntax)
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    42
{
64703
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    43
  private val state = Synchronized(VSCode_Resources.State())
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    44
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    45
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    46
  /* document node name */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    47
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    48
  def node_name(uri: String): Document.Node.Name =
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    49
  {
64640
f9470490e682 clarified node_name: preserve original uri;
wenzelm
parents: 64623
diff changeset
    50
    val theory = Thy_Header.thy_name(uri).getOrElse("")
f9470490e682 clarified node_name: preserve original uri;
wenzelm
parents: 64623
diff changeset
    51
    val master_dir =
f9470490e682 clarified node_name: preserve original uri;
wenzelm
parents: 64623
diff changeset
    52
      if (!VSCode_Resources.is_wellformed(uri) || theory == "") ""
f9470490e682 clarified node_name: preserve original uri;
wenzelm
parents: 64623
diff changeset
    53
      else VSCode_Resources.canonical_file(uri).getParent
f9470490e682 clarified node_name: preserve original uri;
wenzelm
parents: 64623
diff changeset
    54
    Document.Node.Name(uri, master_dir, theory)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    55
  }
64703
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    56
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    57
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    58
  /* document models */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    59
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    60
  def get_model(uri: String): Option[Document_Model] = state.value.models.get(uri)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    61
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    62
  def update_model(model: Document_Model)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    63
  {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    64
    state.change(st =>
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    65
      st.copy(
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    66
        models = st.models + (model.node_name.node -> model),
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    67
        pending_input = st.pending_input + model.node_name))
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    68
  }
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    69
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    70
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    71
  /* pending input */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    72
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    73
  def flush_input(session: Session)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    74
  {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    75
    state.change(st =>
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    76
      {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    77
        val changed =
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    78
          (for {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    79
            node_name <- st.pending_input.iterator
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    80
            model <- st.models.get(node_name.node)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    81
            if model.changed } yield model).toList
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    82
        val edits = for { model <- changed; edit <- model.node_edits } yield edit
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    83
        session.update(Document.Blobs.empty, edits)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    84
        st.copy(
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    85
          models = (st.models /: changed) { case (ms, m) => ms + (m.uri -> m.unchanged) },
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    86
          pending_input = Set.empty)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    87
      })
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    88
  }
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    89
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    90
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    91
  /* pending output */
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    92
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    93
  def update_output(changed_nodes: Set[Document.Node.Name]): Unit =
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    94
    state.change(st => st.copy(pending_output = st.pending_output ++ changed_nodes))
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    95
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    96
  def flush_output(channel: Channel)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    97
  {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    98
    state.change(st =>
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
    99
      {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   100
        val changed_iterator =
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   101
          for {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   102
            node_name <- st.pending_output.iterator
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   103
            model <- st.models.get(node_name.node)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   104
            rendering = model.rendering(options)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   105
            (diagnostics, model1) <- model.publish_diagnostics(rendering)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   106
          } yield {
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   107
            channel.diagnostics(model1.uri, rendering.diagnostics_output(diagnostics))
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   108
            model1
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   109
          }
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   110
        st.copy(
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   111
          models = (st.models /: changed_iterator) { case (ms, m) => ms + (m.uri -> m) },
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   112
          pending_output = Set.empty)
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   113
      }
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   114
    )
a115391494ed moved main state to VSCode_Resources;
wenzelm
parents: 64640
diff changeset
   115
  }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   116
}