--- a/src/Tools/VSCode/etc/options Sat Dec 31 15:32:54 2016 +0100
+++ b/src/Tools/VSCode/etc/options Sat Dec 31 20:26:34 2016 +0100
@@ -6,6 +6,9 @@
option vscode_output_delay : real = 0.5
-- "delay for client output (rendering)"
+option vscode_load_delay : real = 0.5
+ -- "delay for file load operations"
+
option vscode_tooltip_margin : int = 60
-- "margin for pretty-printing of tooltips"
--- a/src/Tools/VSCode/src/document_model.scala Sat Dec 31 15:32:54 2016 +0100
+++ b/src/Tools/VSCode/src/document_model.scala Sat Dec 31 20:26:34 2016 +0100
@@ -47,6 +47,8 @@
val file: JFile = VSCode_Resources.canonical_file(uri)
+ def external(b: Boolean): Document_Model = copy(external_file = b)
+
def register(watcher: File_Watcher)
{
val dir = file.getParentFile
--- a/src/Tools/VSCode/src/server.scala Sat Dec 31 15:32:54 2016 +0100
+++ b/src/Tools/VSCode/src/server.scala Sat Dec 31 20:26:34 2016 +0100
@@ -114,7 +114,12 @@
Standard_Thread.delay_last(options.seconds("vscode_input_delay"))
{ resources.flush_input(session) }
- private val watcher = File_Watcher(sync_documents(_))
+ private val delay_load =
+ Standard_Thread.delay_last(options.seconds("vscode_load_delay"))
+ { if (resources.resolve_dependencies(session)) delay_input.invoke() }
+
+ private val watcher =
+ File_Watcher(sync_documents(_), options.seconds("vscode_load_delay"))
private def sync_documents(changed: Set[JFile]): Unit =
if (resources.sync_models(changed)) delay_input.invoke()
@@ -178,7 +183,10 @@
val content = Build.session_content(options, false, session_dirs, session_name)
val resources =
new VSCode_Resources(options, text_length, content.loaded_theories,
- content.known_theories, content.syntax, log)
+ content.known_theories, content.syntax, log) {
+ override def commit(change: Session.Change): Unit =
+ if (change.deps_changed) delay_load.invoke()
+ }
Some(new Session(resources) {
override def output_delay = options.seconds("editor_output_delay")
--- a/src/Tools/VSCode/src/vscode_resources.scala Sat Dec 31 15:32:54 2016 +0100
+++ b/src/Tools/VSCode/src/vscode_resources.scala Sat Dec 31 20:26:34 2016 +0100
@@ -12,6 +12,8 @@
import java.net.{URI, URISyntaxException}
import java.io.{File => JFile}
+import scala.util.parsing.input.{Reader, CharSequenceReader}
+
object VSCode_Resources
{
@@ -64,6 +66,23 @@
else name.copy(node = "file://" + name.node)
}
+ override def with_thy_reader[A](name: Document.Node.Name, f: Reader[Char] => A): A =
+ {
+ val uri = name.node
+ get_model(uri) match {
+ case Some(model) =>
+ val reader = new CharSequenceReader(model.doc.make_text)
+ f(reader)
+
+ case None =>
+ val file = VSCode_Resources.canonical_file(uri)
+ if (!file.isFile) error("No such file: " + quote(file.toString))
+
+ val reader = Scan.byte_reader(file)
+ try { f(reader) } finally { reader.close }
+ }
+ }
+
/* document models */
@@ -74,7 +93,7 @@
state.change(st =>
{
val model = st.models.getOrElse(uri, Document_Model.init(session, uri))
- val model1 = (model.update_text(text) getOrElse model).copy(external_file = false)
+ val model1 = (model.update_text(text) getOrElse model).external(false)
st.copy(
models = st.models + (uri -> model1),
pending_input = st.pending_input + uri)
@@ -86,7 +105,7 @@
st.models.get(uri) match {
case None => (None, st)
case Some(model) =>
- (Some(model), st.copy(models = st.models + (uri -> model.copy(external_file = true))))
+ (Some(model), st.copy(models = st.models + (uri -> model.external(true))))
})
def sync_models(changed_files: Set[JFile]): Boolean =
@@ -106,6 +125,40 @@
})
+ /* resolve dependencies */
+
+ def resolve_dependencies(session: Session): Boolean =
+ {
+ val thys =
+ (for ((_, model) <- state.value.models.iterator if model.is_theory)
+ yield (model.node_name, Position.none)).toList
+ val deps = new Thy_Info(this).dependencies("", thys).deps
+
+ state.change_result(st =>
+ {
+ val loaded_models =
+ for {
+ uri <- deps.map(_.name.node)
+ if get_model(uri).isEmpty
+ text <-
+ try { Some(File.read(VSCode_Resources.canonical_file(uri))) }
+ catch { case ERROR(_) => None }
+ }
+ yield {
+ val model = Document_Model.init(session, uri)
+ val model1 = (model.update_text(text) getOrElse model).external(true)
+ (uri, model1)
+ }
+ if (loaded_models.isEmpty) (false, st)
+ else
+ (true,
+ st.copy(
+ models = st.models ++ loaded_models,
+ pending_input = st.pending_input ++ loaded_models.map(_._1)))
+ })
+ }
+
+
/* pending input */
def flush_input(session: Session)