src/Tools/VSCode/src/document_model.scala
author wenzelm
Sun, 01 Jan 2017 11:38:29 +0100
changeset 64729 4eccd9bc5fd9
parent 64727 13e37567a0d6
child 64775 dd3797f1e0d6
permissions -rw-r--r--
clarified file URI 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/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
import scala.util.parsing.input.CharSequenceReader
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
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    17
object Document_Model
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    18
{
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    19
  def init(session: Session, uri: String): Document_Model =
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    20
  {
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    21
    val resources = session.resources.asInstanceOf[VSCode_Resources]
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    22
    val node_name = resources.node_name(uri)
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    23
    val doc = Line.Document("", resources.text_length)
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    24
    Document_Model(session, node_name, doc)
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    25
  }
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    26
}
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    27
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    28
sealed case class Document_Model(
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    29
  session: Session,
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    30
  node_name: Document.Node.Name,
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    31
  doc: Line.Document,
64726
c534a2ac537d clarified;
wenzelm
parents: 64725
diff changeset
    32
  external_file: Boolean = false,
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    33
  node_required: Boolean = false,
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    34
  last_perspective: Document.Node.Perspective_Text = Document.Node.no_perspective_text,
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    35
  pending_edits: Vector[Text.Edit] = Vector.empty,
64679
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
    36
  published_diagnostics: List[Text.Info[Command.Results]] = Nil)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    37
{
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
    38
  /* name */
64680
wenzelm
parents: 64679
diff changeset
    39
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
    40
  override def toString: String = node_name.toString
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    41
64690
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    42
  def uri: String = node_name.node
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    43
  def is_theory: Boolean = node_name.is_theory
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    44
64690
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    45
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    46
  /* external file */
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    47
64729
4eccd9bc5fd9 clarified file URI operations;
wenzelm
parents: 64727
diff changeset
    48
  val file: JFile = Url.file(uri).getCanonicalFile
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    49
64727
13e37567a0d6 automatically resolve dependencies from document models and file-system;
wenzelm
parents: 64726
diff changeset
    50
  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
    51
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    52
  def register(watcher: File_Watcher)
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    53
  {
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    54
    val dir = file.getParentFile
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    55
    if (dir != null && dir.isDirectory) watcher.register(dir)
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    56
  }
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    57
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    58
64690
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    59
  /* header */
599873de8b01 more uniform pending_input / pending_output;
wenzelm
parents: 64683
diff changeset
    60
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
    61
  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
    62
    resources.special_header(node_name) getOrElse
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    63
    {
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    64
      if (is_theory)
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
    65
        resources.check_thy_reader(
64673
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    66
          "", node_name, new CharSequenceReader(Thy_Header.header_text(doc)), Token.Pos.command)
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    67
      else Document.Node.no_header
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 64672
diff changeset
    68
    }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    69
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    70
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    71
  /* perspective */
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    72
64726
c534a2ac537d clarified;
wenzelm
parents: 64725
diff changeset
    73
  def node_visible: Boolean = !external_file
64723
65bcb1fbaa73 clarified node_visible;
wenzelm
parents: 64710
diff changeset
    74
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    75
  def text_perspective: Text.Perspective =
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    76
    if (node_visible) Text.Perspective.full else Text.Perspective.empty
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    77
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    78
  def node_perspective: Document.Node.Perspective_Text =
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    79
    Document.Node.Perspective(node_required, text_perspective, Document.Node.Overlays.empty)
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    80
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
    81
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    82
  /* edits */
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
    83
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    84
  def update_text(new_text: String): Option[Document_Model] =
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    85
  {
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    86
    val old_text = doc.make_text
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    87
    if (new_text == old_text) None
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    88
    else {
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    89
      val doc1 = Line.Document(new_text, doc.text_length)
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    90
      val pending_edits1 =
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    91
        if (old_text != "") pending_edits :+ Text.Edit.remove(0, old_text) else pending_edits
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    92
      val pending_edits2 = pending_edits1 :+ Text.Edit.insert(0, new_text)
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    93
      Some(copy(doc = doc1, pending_edits = pending_edits2))
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    94
    }
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    95
  }
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
    96
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    97
  def update_file: Option[Document_Model] =
64726
c534a2ac537d clarified;
wenzelm
parents: 64725
diff changeset
    98
    if (external_file) {
64710
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
    99
      try { update_text(File.read(file)) }
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
   100
      catch { case ERROR(_) => None }
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
   101
    }
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
   102
    else None
72ca4e5f976e manage changes of external files;
wenzelm
parents: 64709
diff changeset
   103
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   104
  def flush_edits: Option[(List[Document.Edit_Text], Document_Model)] =
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   105
  {
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   106
    val perspective = node_perspective
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   107
    if (pending_edits.nonEmpty || last_perspective != perspective) {
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   108
      val text_edits = pending_edits.toList
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   109
      val edits =
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   110
        session.header_edit(node_name, node_header) ::
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   111
        (if (text_edits.isEmpty) Nil
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   112
         else List[Document.Edit_Text](node_name -> Document.Node.Edits(text_edits))) :::
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   113
        (if (last_perspective == perspective) Nil
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   114
         else List[Document.Edit_Text](node_name -> perspective))
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   115
      Some((edits, copy(pending_edits = Vector.empty, last_perspective = perspective)))
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   116
    }
64707
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   117
    else None
7157685b71e3 clarified Document_Model perspective and edits;
wenzelm
parents: 64704
diff changeset
   118
  }
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   119
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   120
64679
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   121
  /* diagnostics */
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   122
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   123
  def publish_diagnostics(rendering: VSCode_Rendering)
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   124
    : Option[(List[Text.Info[Command.Results]], Document_Model)] =
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   125
  {
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   126
    val diagnostics = rendering.diagnostics
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   127
    if (diagnostics == published_diagnostics) None
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   128
    else Some(diagnostics, copy(published_diagnostics = diagnostics))
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   129
  }
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   130
b2bf280b7e13 more uniform treatment of input/output wrt. client;
wenzelm
parents: 64673
diff changeset
   131
64725
wenzelm
parents: 64723
diff changeset
   132
  /* prover session */
64702
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
   133
d95b9117cb5b re-use resources from session;
wenzelm
parents: 64690
diff changeset
   134
  def resources: VSCode_Resources = session.resources.asInstanceOf[VSCode_Resources]
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   135
64709
5e6566ab78bf more explicit edits -- eliminated Clear;
wenzelm
parents: 64707
diff changeset
   136
  def snapshot(): Document.Snapshot = session.snapshot(node_name, pending_edits.toList)
64622
529bbb8977c7 more uniform rendering for Isabelle/jEdit and Isabelle/VSCode;
wenzelm
parents: 64605
diff changeset
   137
64704
08c2d80428ff re-use options from resources;
wenzelm
parents: 64703
diff changeset
   138
  def rendering(): VSCode_Rendering = new VSCode_Rendering(this, snapshot(), resources)
64605
9c1173a7e4cb basic support for VSCode Language Server protocol;
wenzelm
parents:
diff changeset
   139
}