src/Tools/VSCode/src/document_model.scala
author wenzelm
Sun, 05 Mar 2017 13:34:35 +0100
changeset 65111 3224a6f7bd6b
parent 65105 1f47b92021de
child 65115 93a0683e075a
permissions -rw-r--r--
more robust treatment of pending input/output: these are often correlated; no decorations for invisible node;
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/document_model.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
Document model for line-oriented text.
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
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    12
import java.io.{File => JFile}
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    13
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    14
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    15
object Document_Model
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    16
{
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    17
  /* decorations */
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    18
65105
1f47b92021de clarified signature;
wenzelm
parents: 65095
diff changeset
    19
  sealed case class Decoration(typ: String, content: List[Text.Info[List[XML.Body]]])
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    20
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    21
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    22
  /* content */
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    23
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    24
  sealed case class Content(doc: Line.Document)
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    25
  {
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    26
    def text_range: Text.Range = doc.text_range
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    27
    def text: String = doc.text
64877
31e9920a0dc1 support for semantic completion;
wenzelm
parents: 64867
diff changeset
    28
    def try_get_text(range: Text.Range): Option[String] = doc.try_get_text(range)
64833
0f410e3b1d20 support for bibtex entries;
wenzelm
parents: 64830
diff changeset
    29
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    30
    lazy val bytes: Bytes = Bytes(text)
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    31
    lazy val chunk: Symbol.Text_Chunk = Symbol.Text_Chunk(text)
64833
0f410e3b1d20 support for bibtex entries;
wenzelm
parents: 64830
diff changeset
    32
    lazy val bibtex_entries: List[Text.Info[String]] =
0f410e3b1d20 support for bibtex entries;
wenzelm
parents: 64830
diff changeset
    33
      try { Bibtex.document_entries(text) }
0f410e3b1d20 support for bibtex entries;
wenzelm
parents: 64830
diff changeset
    34
      catch { case ERROR(_) => Nil }
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    35
  }
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    36
64777
ca09695eb43c clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents: 64775
diff changeset
    37
  def init(session: Session, node_name: Document.Node.Name): Document_Model =
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    38
  {
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    39
    val resources = session.resources.asInstanceOf[VSCode_Resources]
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    40
    val content = Content(Line.Document("", resources.text_length))
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    41
    Document_Model(session, node_name, content)
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    42
  }
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    43
}
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    44
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    45
sealed case class Document_Model(
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    46
  session: Session,
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    47
  node_name: Document.Node.Name,
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    48
  content: Document_Model.Content,
64726
c534a2ac537d clarified;
wenzelm
parents: 64725
diff changeset
    49
  external_file: Boolean = false,
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    50
  node_required: Boolean = false,
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    51
  last_perspective: Document.Node.Perspective_Text = Document.Node.no_perspective_text,
64816
wenzelm
parents: 64815
diff changeset
    52
  pending_edits: List[Text.Edit] = Nil,
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    53
  published_diagnostics: List[Text.Info[Command.Results]] = Nil,
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
    54
  published_decorations: List[Document_Model.Decoration] = Nil) extends Document.Model
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    55
{
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    56
  /* external file */
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    57
64727
13e37567a0d6 automatically resolve dependencies from document models and file-system;
wenzelm
parents: 64726
diff changeset
    58
  def external(b: Boolean): Document_Model = copy(external_file = b)
13e37567a0d6 automatically resolve dependencies from document models and file-system;
wenzelm
parents: 64726
diff changeset
    59
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    60
  def node_visible: Boolean = !external_file
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    61
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    62
64690
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    63
  /* header */
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    64
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
    65
  def node_header: Document.Node.Header =
64673
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    66
    resources.special_header(node_name) getOrElse
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    67
      resources.check_thy_reader("", node_name, Scan.char_reader(content.text))
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    68
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    69
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    70
  /* perspective */
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    71
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    72
  def node_perspective(doc_blobs: Document.Blobs): (Boolean, Document.Node.Perspective_Text) =
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    73
  {
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    74
    if (is_theory) {
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    75
      val snapshot = this.snapshot()
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    76
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    77
      val text_perspective =
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    78
        if (node_visible || snapshot.commands_loading_ranges(resources.visible_node(_)).nonEmpty)
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    79
          Text.Perspective.full
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    80
        else Text.Perspective.empty
64723
65bcb1fbaa73 clarified node_visible;
wenzelm
parents: 64710
diff changeset
    81
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    82
      (snapshot.node.load_commands_changed(doc_blobs),
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    83
        Document.Node.Perspective(node_required, text_perspective, Document.Node.Overlays.empty))
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    84
    }
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    85
    else (false, Document.Node.no_perspective_text)
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    86
  }
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    87
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    88
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    89
  /* blob */
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    90
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    91
  def get_blob: Option[Document.Blob] =
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
    92
    if (is_theory) None
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
    93
    else Some((Document.Blob(content.bytes, content.chunk, pending_edits.nonEmpty)))
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    94
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    95
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    96
  /* edits */
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    97
64806
99f49258b02b more robust treatment of logical lines;
wenzelm
parents: 64800
diff changeset
    98
  def update_text(text: String): Option[Document_Model] =
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    99
  {
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
   100
    val old_text = content.text
64806
99f49258b02b more robust treatment of logical lines;
wenzelm
parents: 64800
diff changeset
   101
    val new_text = Line.normalize(text)
64816
wenzelm
parents: 64815
diff changeset
   102
    Text.Edit.replace(0, old_text, new_text) match {
wenzelm
parents: 64815
diff changeset
   103
      case Nil => None
wenzelm
parents: 64815
diff changeset
   104
      case edits =>
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
   105
        val content1 = Document_Model.Content(Line.Document(new_text, content.doc.text_length))
64816
wenzelm
parents: 64815
diff changeset
   106
        val pending_edits1 = pending_edits ::: edits
64830
9bc44bef99e6 more explocit Document_Model.Content;
wenzelm
parents: 64827
diff changeset
   107
        Some(copy(content = content1, pending_edits = pending_edits1))
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   108
    }
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   109
  }
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   110
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
   111
  def flush_edits(doc_blobs: Document.Blobs): Option[(List[Document.Edit_Text], Document_Model)] =
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   112
  {
64800
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
   113
    val (reparse, perspective) = node_perspective(doc_blobs)
415dafeb9669 manage document blobs as well;
wenzelm
parents: 64777
diff changeset
   114
    if (reparse || pending_edits.nonEmpty || last_perspective != perspective) {
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64833
diff changeset
   115
      val edits = node_edits(node_header, pending_edits, perspective)
64816
wenzelm
parents: 64815
diff changeset
   116
      Some((edits, copy(pending_edits = Nil, last_perspective = perspective)))
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   117
    }
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   118
    else None
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   119
  }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   120
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   121
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   122
  /* publish annotations */
64679
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   123
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   124
  def publish(rendering: VSCode_Rendering)
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   125
    : Option[((List[Text.Info[Command.Results]], List[Document_Model.Decoration]), Document_Model)] =
64679
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   126
  {
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   127
    val diagnostics = rendering.diagnostics
65111
3224a6f7bd6b more robust treatment of pending input/output: these are often correlated;
wenzelm
parents: 65105
diff changeset
   128
    val decorations = if (node_visible) rendering.decorations else Nil
65095
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   129
    if (diagnostics == published_diagnostics && decorations == published_decorations) None
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   130
    else {
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   131
      val new_decorations =
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   132
        if (decorations.length != published_decorations.length) decorations
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   133
        else for { (a, b) <- decorations zip published_decorations if a != b } yield a
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   134
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   135
      Some((diagnostics, new_decorations),
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   136
        copy(published_diagnostics = diagnostics, published_decorations = decorations))
eb21a4f70b0e publish decorations like diagnostics;
wenzelm
parents: 64877
diff changeset
   137
    }
64679
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   138
  }
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   139
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   140
64725
wenzelm
parents: 64723
diff changeset
   141
  /* prover session */
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
   142
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
   143
  def resources: VSCode_Resources = session.resources.asInstanceOf[VSCode_Resources]
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   144
64816
wenzelm
parents: 64815
diff changeset
   145
  def is_stable: Boolean = pending_edits.isEmpty
wenzelm
parents: 64815
diff changeset
   146
  def snapshot(): Document.Snapshot = session.snapshot(node_name, pending_edits)
64622
529bbb8977c7 more uniform rendering for Isabelle/jEdit and Isabelle/VSCode;
wenzelm
parents: 64605
diff changeset
   147
64704
08c2d80428ff re-use options from resources;
wenzelm
parents: 64703
diff changeset
   148
  def rendering(): VSCode_Rendering = new VSCode_Rendering(this, snapshot(), resources)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   149
}