From 6d8c1cc2e876448b37685793bcd0f4591d88e436 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 22 May 2017 12:18:05 -0400 Subject: [PATCH 24/31] FIXME: move attribute extraction from lsp.c to json.c --- gcc/json.c | 59 +++++++++++++++++++++++++++ gcc/json.h | 12 ++++++ gcc/lsp.c | 132 +++++++++++++++++++++---------------------------------------- gcc/lsp.h | 12 +++--- 4 files changed, 122 insertions(+), 93 deletions(-) diff --git a/gcc/json.c b/gcc/json.c index 482fede..5cd06d5 100644 --- a/gcc/json.c +++ b/gcc/json.c @@ -77,6 +77,65 @@ value::as_string () const return static_cast (this); } +/* FIXME. */ + +bool +value::get_value_by_key (const char *name, const value *&out_value, + char *&out_err) const +{ + const json::object *obj = as_object (); + if (!obj) + { + out_err = xstrdup ("not an object"); + return false; + } + const json::value *v = obj->get (name); + if (!v) + { + out_err = xasprintf ("missing attribute: \"%s\"", name); + return false; + } + out_value = v; + return true; +} + +/* FIXME. */ + +bool +value::get_int_by_key (const char *name, int &out_value, char *&out_err) const +{ + const json::value *v; + if (!get_value_by_key (name, v, out_err)) + return false; + const json::number *n = v->as_number (); + if (!n) + { + out_err = xasprintf ("not a number: \"%s\"", name); + return false; + } + out_value = n->get (); + return true; +} + +/* FIXME. */ + +bool +value::get_string_by_key (const char *name, const char *&out_value, + char *&out_err) const +{ + const json::value *v; + if (!get_value_by_key (name, v, out_err)) + return false; + const json::string *s = v->as_string (); + if (!s) + { + out_err = xasprintf ("not a string: \"%s\"", name); + return false; + } + out_value = s->get_string (); + return true; +} + object::~object () { for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it) diff --git a/gcc/json.h b/gcc/json.h index ddce444..7655d50 100644 --- a/gcc/json.h +++ b/gcc/json.h @@ -58,6 +58,18 @@ class value const array *as_array () const; const number *as_number () const; const string *as_string () const; + + /* Convenience accessors for attempting to get a value from + this value as if it is an object. + + On success, return true and write the value to OUT_VALUE. + On failure, return false and write an error message to OUT_ERR + (which must be freed by the caller). */ + bool get_value_by_key (const char *name, const value *&out_value, + char *&out_err) const; + bool get_int_by_key (const char *name, int &out_value, char *&out_err) const; + bool get_string_by_key (const char *name, const char *&out_value, + char *&out_err) const; }; /* Subclass of value for objects: key/value pairs. */ diff --git a/gcc/lsp.c b/gcc/lsp.c index f64643e..9663ccc 100644 --- a/gcc/lsp.c +++ b/gcc/lsp.c @@ -32,126 +32,73 @@ using namespace lsp; // TODO: autogenerate the interface binding/marshalling/demarshalling code // from an interface description. -#define GET_AS_OBJECT_OBJ(PARAMS) \ - const json::object *obj = (PARAMS)->as_object (); \ - if (!obj) \ - { \ - out_err = make_invalid_params (NULL, "not an object"); \ - return result; \ - } - -static bool -extract_int (const json::object *obj, const char *name, - int &out, json::value *&out_err) -{ - const json::value *v = obj->get (name); - if (!v) - { - char *msg = xasprintf ("missing int attribute: \"%s\"", name); - out_err = make_invalid_params (NULL, msg); - free (msg); - return false; - } - const json::number *n = v->as_number (); - if (!n) - { - char *msg = xasprintf ("not a number: \"%s\"", name); - out_err = make_invalid_params (NULL, msg); - free (msg); - return false; - } - out = n->get (); - return true; -} - -static bool -extract_string (const json::object *obj, const char *name, - const char *&out, json::value *&out_err) -{ - const json::value *v = obj->get (name); - if (!v) - { - char *msg = xasprintf ("missing string attribute: \"%s\"", name); - out_err = make_invalid_params (NULL, msg); - free (msg); - return false; - } - const json::string *s = v->as_string (); - if (!s) - { - char *msg = xasprintf ("not a string: \"%s\"", name); - out_err = make_invalid_params (NULL, msg); - free (msg); - return false; - } - out = s->get_string (); - return true; -} +#define SET_VALUE(LHS, VALUE, NAME) \ + do { \ + if (!(VALUE)->get_value_by_key ((NAME), (LHS), out_err)) \ + return result; \ + } while (0) -#define SET_NUMBER(LHS, NAME) \ +#define SET_NUMBER(LHS, VALUE, NAME) \ do { \ - if (!extract_int (obj, NAME, LHS, out_err)) \ + if (!(VALUE)->get_int_by_key ((NAME), (LHS), out_err)) \ return result; \ } while (0) -#define SET_STRING(LHS, NAME) \ +#define SET_STRING(LHS, VALUE, NAME) \ do { \ - if (!extract_string (obj, NAME, LHS, out_err)) \ + if (!(VALUE)->get_string_by_key ((NAME), (LHS), out_err)) \ return result; \ } while (0) Position Position::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { Position result; - GET_AS_OBJECT_OBJ (params); - SET_NUMBER (result.line, "line"); - SET_NUMBER (result.character, "character"); + SET_NUMBER (result.line, params, "line"); + SET_NUMBER (result.character, params, "character"); return result; } TextDocumentIdentifier TextDocumentIdentifier::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { TextDocumentIdentifier result; - GET_AS_OBJECT_OBJ (params); - SET_STRING (result.uri, "uri"); + SET_STRING (result.uri, params, "uri"); return result; } TextDocumentItem TextDocumentItem::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { TextDocumentItem result; - GET_AS_OBJECT_OBJ (params); - SET_STRING (result.uri, "uri"); - SET_STRING (result.languageId, "languageId"); - SET_NUMBER (result.version, "version"); - SET_STRING (result.text, "text"); + SET_STRING (result.uri, params, "uri"); + SET_STRING (result.languageId, params, "languageId"); + SET_NUMBER (result.version, params, "version"); + SET_STRING (result.text, params, "text"); return result; } DidOpenTextDocumentParams DidOpenTextDocumentParams::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { DidOpenTextDocumentParams result; - GET_AS_OBJECT_OBJ (params); // FIXME: error-handling + const json::value *text_document; + SET_VALUE (text_document, params, "textDocument"); result.textDocument - = TextDocumentItem::from_json (obj->get ("textDocument"), out_err); + = TextDocumentItem::from_json (text_document, out_err); return result; } DidChangeTextDocumentParams DidChangeTextDocumentParams::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { DidChangeTextDocumentParams result; - GET_AS_OBJECT_OBJ (params); // FIXME return result; @@ -159,14 +106,17 @@ DidChangeTextDocumentParams::from_json (const json::value *params, TextDocumentPositionParams TextDocumentPositionParams::from_json (const json::value *params, - json::value *&out_err) + char *&out_err) { TextDocumentPositionParams result; - GET_AS_OBJECT_OBJ (params); + const json::value *text_document; + const json::value *position; + SET_VALUE (text_document, params, "textDocument"); + SET_VALUE (position, params, "position"); result.textDocument - = TextDocumentIdentifier::from_json (obj->get ("textDocument"), out_err); + = TextDocumentIdentifier::from_json (text_document, out_err); result.position - = Position::from_json (obj->get ("position"), out_err); + = Position::from_json (position, out_err); return result; } @@ -232,14 +182,22 @@ lsp::jsonrpc_server::do_initialize (const json::value *id, return make_success (id, result); } +static json::value * +make_invalid_params_and_free_msg (const json::value *id, char *msg) +{ + json::value *err = make_invalid_params (id, msg); + free (msg); + return err; +} + json::value * lsp::jsonrpc_server::do_text_document_did_open (const json::value *params) { - json::value *err = NULL; + char *err = NULL; DidOpenTextDocumentParams p = DidOpenTextDocumentParams::from_json (params, err); if (err) - return err; // though we ought not to return non-NULL for a notification + return make_invalid_params_and_free_msg (NULL, err); // though we ought not to return non-NULL for a notification m_inner.do_text_document_did_open (p); return NULL; // notification, so no response @@ -248,11 +206,11 @@ lsp::jsonrpc_server::do_text_document_did_open (const json::value *params) json::value * lsp::jsonrpc_server::do_text_document_did_change (const json::value *params) { - json::value *err = NULL; + char *err = NULL; DidChangeTextDocumentParams p = DidChangeTextDocumentParams::from_json (params, err); if (err) - return err; // though we ought not to return non-NULL for a notification + return make_invalid_params_and_free_msg (NULL, err); // though we ought not to return non-NULL for a notification m_inner.do_text_document_did_change (p); @@ -262,11 +220,11 @@ lsp::jsonrpc_server::do_text_document_did_change (const json::value *params) json::value * lsp::jsonrpc_server::do_text_document_definition (const json::value *params) { - json::value *err = NULL; + char *err = NULL; TextDocumentPositionParams p = TextDocumentPositionParams::from_json (params, err); if (err) - return err; + return make_invalid_params_and_free_msg (NULL, err); auto_vec out; m_inner.do_text_document_definition (p, out); diff --git a/gcc/lsp.h b/gcc/lsp.h index b9c99c8..88f305f 100644 --- a/gcc/lsp.h +++ b/gcc/lsp.h @@ -29,7 +29,7 @@ typedef const char *DocumentUri; struct Position { static Position from_json (const json::value *params, - json::value *&out_err); + char *&out_err); json::value *to_json () const; int line; @@ -60,7 +60,7 @@ struct Location struct TextDocumentIdentifier { static TextDocumentIdentifier from_json (const json::value *params, - json::value *&out_err); + char *&out_err); DocumentUri uri; }; @@ -68,7 +68,7 @@ struct TextDocumentIdentifier struct TextDocumentItem { static TextDocumentItem from_json (const json::value *params, - json::value *&out_err); + char *&out_err); DocumentUri uri; const char *languageId; @@ -79,7 +79,7 @@ struct TextDocumentItem struct DidOpenTextDocumentParams { static DidOpenTextDocumentParams from_json (const json::value *params, - json::value *&out_err); + char *&out_err); TextDocumentItem textDocument; }; @@ -88,7 +88,7 @@ struct DidChangeTextDocumentParams { public: static DidChangeTextDocumentParams from_json (const json::value *params, - json::value *&out_err); + char *&out_err); private: #if 0 @@ -100,7 +100,7 @@ struct DidChangeTextDocumentParams struct TextDocumentPositionParams { static TextDocumentPositionParams from_json (const json::value *params, - json::value *&out_err); + char *&out_err); TextDocumentIdentifier textDocument; Position position; -- 1.8.5.3