From e9467fc8a45670101f3516d5055c8b3e0628450b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 17 May 2017 20:57:32 -0400
Subject: [PATCH 05/31] FIXME: initial LSP implementation

---
 gcc/Makefile.in          |   1 +
 gcc/json-rpc.c           |   5 +-
 gcc/lsp.c                | 126 +++++++++++++++++++++++++++++++++++++++++++++++
 gcc/selftest-run-tests.c |   1 +
 gcc/selftest.h           |   1 +
 5 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 gcc/lsp.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index abc286d..046a7c2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1373,6 +1373,7 @@ OBJS = \
 	loop-iv.o \
 	loop-unroll.o \
 	lower-subreg.o \
+	lsp.o \
 	lra.o \
 	lra-assigns.o \
 	lra-coalesce.o \
diff --git a/gcc/json-rpc.c b/gcc/json-rpc.c
index a0b624e..3656a87 100644
--- a/gcc/json-rpc.c
+++ b/gcc/json-rpc.c
@@ -94,7 +94,10 @@ jsonrpc::server::handle_request (json::value *request)
   if (m_verbose)
     {
       fprintf (stderr, "response: ");
-      response->dump (stderr);
+      if (response)
+	response->dump (stderr);
+      else
+	fprintf (stderr, "NULL");
       fprintf (stderr, "\n");
     }
 
diff --git a/gcc/lsp.c b/gcc/lsp.c
new file mode 100644
index 0000000..02d59ad
--- /dev/null
+++ b/gcc/lsp.c
@@ -0,0 +1,126 @@
+/* Language Server Protocol implementation.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "json.h"
+#include "json-rpc.h"
+#include "selftest.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests.  */
+
+using namespace jsonrpc;
+
+class lsp_server : public jsonrpc::server
+{
+ public:
+  lsp_server (bool verbose) : server (verbose) {}
+
+  json::value *
+  dispatch (const char *method, const json::value *params,
+	    const json::value *id) FINAL OVERRIDE
+  {
+    if (0 == strcmp (method, "initialize"))
+      return do_initialize (id, params);
+    if (0 == strcmp (method, "textDocument/didOpen"))
+      return do_text_document_did_open (params);
+    if (0 == strcmp (method, "textDocument/didChange"))
+      return do_text_document_did_change (params);
+    return make_method_not_found (id, method);
+  }
+
+  json::value *
+  do_initialize (const json::value *id, const json::value *params)
+  {
+    // FIXME: for now, ignore params
+
+    json::object *server_caps = new json::object ();
+    json::object *result = new json::object ();
+    result->set ("capabilities", server_caps);
+    return make_success (id, result);
+  }
+
+  json::value *
+  do_text_document_did_open (const json::value *params)
+  {
+    // params ought to be a "DidOpenTextDocumentParams",
+    // which is a "textDocument" holding a TextDocumentItem
+    // FIXME: for now, ignore params
+    return NULL; // notification, so no response
+  }
+
+  json::value *
+  do_text_document_did_change (const json::value *params)
+  {
+    // params ought to be a "DidChangeTextDocumentParams"
+    // FIXME: for now, ignore params
+    return NULL; // notification, so no response
+  }
+};
+
+static void
+test_simple ()
+{
+  lsp_server s (true);
+  const char *init_request
+    = ("{\"jsonrpc\": \"2.0\", \"method\": \"initialize\","
+       " \"params\": [42, 23], \"id\": 1}"); // FIXME
+  json::value *init_response = s.handle_request_string (init_request);
+  //const json::value *result = assert_is_success (response, 1);
+  //ASSERT_EQ (19, result->as_number ()->get ());
+  delete init_response;
+
+  const char *did_open_note
+    = ("{\"jsonrpc\": \"2.0\", \"method\": \"textDocument/didOpen\","
+       " \"params\": {"
+       " \"textDocument\": "
+       " { \"uri\": \"DocumentUri goes here\","
+         " \"languageId\": \"c++\","
+         " \"version\": 0,"
+         " \"text\": \"/* Initial content.  */\"}}}");
+  json::value *did_open_response = s.handle_request_string (did_open_note);
+  delete did_open_response;
+
+  const char *did_change_note
+    = ("{\"jsonrpc\": \"2.0\", \"method\": \"textDocument/didChange\","
+       " \"params\": {"
+         " \"textDocument\": {\"version\": 1},"
+         " \"contentChanges\": [{\"text\": \"/* Hello world.  */\"}]"
+       "}}"); // FIXME
+  json::value *did_change_response = s.handle_request_string (did_change_note);
+  delete did_change_response;
+}
+
+
+/* Run all of the selftests within this file.  */
+
+void
+lsp_c_tests ()
+{
+  test_simple ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 49aa263..5a11148 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -68,6 +68,7 @@ selftest::run_tests ()
   typed_splay_tree_c_tests ();
   json_c_tests ();
   json_rpc_c_tests ();
+  lsp_c_tests ();
 
   /* Mid-level data structures.  */
   input_c_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 3a5402b..8ce0f27 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -185,6 +185,7 @@ extern void hash_set_tests_c_tests ();
 extern void input_c_tests ();
 extern void json_c_tests ();
 extern void json_rpc_c_tests ();
+extern void lsp_c_tests ();
 extern void pretty_print_c_tests ();
 extern void read_rtl_function_c_tests ();
 extern void rtl_tests_c_tests ();
-- 
1.8.5.3

