1919// SOFTWARE.
2020
2121import * as path from "node:path" ;
22- import { Enumeration , isRequest , MetaModel , Structure , toCppType , Type , TypeAlias } from "./MetaModel.js" ;
22+ import { isRequest , MetaModel , Structure , toCppType , Type } from "./MetaModel.js" ;
2323import { writeFileSync } from "node:fs" ;
2424import { copyrightHeader } from "./copyrightHeader.js" ;
25+ import { TypeGenerator } from "./gen_types_cc.js" ;
2526
26- class RequestGenerator {
27- readonly structByName : Map < string , Structure > ;
28- readonly enumByName : Map < string , Enumeration > ;
29- readonly typeAliasByName : Map < string , TypeAlias > ;
30- readonly model : MetaModel ;
31- readonly outputDirectory : string ;
32- out : string = "" ;
33-
27+ class RequestGenerator extends TypeGenerator {
3428 constructor ( { model, outputDirectory } : { model : MetaModel ; outputDirectory : string } ) {
35- this . model = model ;
36- this . outputDirectory = outputDirectory ;
37- this . structByName = new Map ( model . structures . map ( ( s ) => [ s . name , s ] ) ) ;
38- this . enumByName = new Map ( model . enumerations . map ( ( e ) => [ e . name , e ] ) ) ;
39- this . typeAliasByName = new Map ( model . typeAliases . map ( ( t ) => [ t . name , t ] ) ) ;
29+ super ( { model, outputDirectory } ) ;
4030 }
4131
4232 genTypes ( ) {
@@ -50,9 +40,44 @@ class RequestGenerator {
5040 this . emit ( ` return id.get<long>();` ) ;
5141 this . emit ( `}` ) ;
5242 this . emit ( ) ;
43+ this . emit ( `auto LSPRequest::id(std::optional<std::variant<long, std::string>> id)` ) ;
44+ this . emit ( ` -> LSPRequest& {` ) ;
45+ this . emit ( ` if (!id.has_value()) {` ) ;
46+ this . emit ( ` repr_->erase("id");` ) ;
47+ this . emit ( ` return *this;` ) ;
48+ this . emit ( ` }` ) ;
49+ this . emit ( ` if (std::holds_alternative<long>(*id)) {` ) ;
50+ this . emit ( ` (*repr_)["id"] = std::get<long>(*id);` ) ;
51+ this . emit ( ` } else {` ) ;
52+ this . emit ( ` (*repr_)["id"] = std::get<std::string>(*id);` ) ;
53+ this . emit ( ` }` ) ;
54+ this . emit ( ` return *this;` ) ;
55+ this . emit ( `}` ) ;
56+ this . emit ( ) ;
5357 this . emit ( `auto LSPRequest::method() const -> std::string {` ) ;
5458 this . emit ( ` return repr_->at("method");` ) ;
5559 this . emit ( `}` ) ;
60+ this . emit ( ) ;
61+ this . emit ( `auto LSPResponse::id() const -> std::optional<std::variant<long, std::string>> {` ) ;
62+ this . emit ( ` if (!repr_->contains("id")) return std::nullopt;` ) ;
63+ this . emit ( ` const auto& id = repr_->at("id");` ) ;
64+ this . emit ( ` if (id.is_string()) return id.get<std::string>();` ) ;
65+ this . emit ( ` return id.get<long>();` ) ;
66+ this . emit ( `}` ) ;
67+ this . emit ( ) ;
68+ this . emit ( `auto LSPResponse::id(std::optional<std::variant<long, std::string>> id)` ) ;
69+ this . emit ( ` -> LSPResponse& {` ) ;
70+ this . emit ( ` if (!id.has_value()) {` ) ;
71+ this . emit ( ` repr_->erase("id");` ) ;
72+ this . emit ( ` return *this;` ) ;
73+ this . emit ( ` }` ) ;
74+ this . emit ( ` if (std::holds_alternative<long>(*id)) {` ) ;
75+ this . emit ( ` (*repr_)["id"] = std::get<long>(*id);` ) ;
76+ this . emit ( ` } else {` ) ;
77+ this . emit ( ` (*repr_)["id"] = std::get<std::string>(*id);` ) ;
78+ this . emit ( ` }` ) ;
79+ this . emit ( ` return *this;` ) ;
80+ this . emit ( `}` ) ;
5681
5782 const requestsAndNotifications = [ ...this . model . requests , ...this . model . notifications ] ;
5883
@@ -65,12 +90,7 @@ class RequestGenerator {
6590 this . emit ( `}` ) ;
6691 this . emit ( ) ;
6792 this . emit ( `auto ${ typeName } ::id(std::variant<long, std::string> id) -> ${ typeName } & {` ) ;
68- this . emit ( ` if (std::holds_alternative<long>(id)) {` ) ;
69- this . emit ( ` (*repr_)["id"] = std::get<long>(id);` ) ;
70- this . emit ( ` } else {` ) ;
71- this . emit ( ` (*repr_)["id"] = std::get<std::string>(id);` ) ;
72- this . emit ( ` }` ) ;
73- this . emit ( ` return *this;` ) ;
93+ this . emit ( ` return static_cast<${ typeName } &>(LSPRequest::id(std::move(id)));` ) ;
7494 this . emit ( `}` ) ;
7595
7696 if ( request . params ) {
@@ -90,66 +110,26 @@ class RequestGenerator {
90110
91111 if ( isRequest ( request ) && request . result ) {
92112 const responseTypeName = typeName . replace ( / R e q u e s t $ / , "Response" ) ;
93- const resultTypeName = toCppType ( request . result ) ;
94113
95114 this . emit ( ) ;
96- this . emit ( `auto ${ responseTypeName } ::id(long id) -> ${ responseTypeName } & {` ) ;
97- this . emit ( ` (*repr_)["id"] = id;` ) ;
98- this . emit ( ` return *this;` ) ;
99- this . emit ( `}` ) ;
100- this . emit ( ) ;
101- this . emit ( `auto ${ responseTypeName } ::id(std::string id) -> ${ responseTypeName } & {` ) ;
102- this . emit ( ` (*repr_)["id"] = std::move(id);` ) ;
103- this . emit ( ` return *this;` ) ;
104- this . emit ( `}` ) ;
105- this . emit ( ) ;
106- this . emit ( `auto ${ responseTypeName } ::result() const -> ${ resultTypeName } {` ) ;
107- switch ( request . result . kind ) {
108- case "base" : {
109- if ( request . result . name === "null" ) {
110- this . emit ( ` return nullptr;` ) ;
111- } else {
112- this . emit ( ` return repr_->at("result").get<${ toCppType ( request . result ) } >(); // base` ) ;
113- }
114- break ;
115- }
116-
117- case "reference" : {
118- if ( this . structByName . has ( request . result . name ) ) {
119- this . emit ( ` if (!repr_->contains("result")) (*repr_)["result"] = nullptr;` ) ;
120- this . emit ( ` return ${ resultTypeName } (repr_->at("result")); // reference` ) ;
121- } else {
122- this . emit ( ` lsp_runtime_error("${ responseTypeName } ::result() - not implemented yet");` ) ;
123- }
124- break ;
125- }
126-
127- default : {
128- this . emit ( ` lsp_runtime_error("${ responseTypeName } ::result() - not implemented yet");` ) ;
129- }
130- } // swtch
131- this . emit ( `}` ) ;
132- this . emit ( ) ;
133- this . emit ( `auto ${ responseTypeName } ::result(${ resultTypeName } result) -> ${ responseTypeName } & {` ) ;
134- switch ( request . result . kind ) {
135- case "base" :
136- this . emit ( ` (*repr_)["result"] = std::move(result); // base` ) ;
137- break ;
138- default :
139- this . emit ( ` lsp_runtime_error("${ responseTypeName } ::result() - not implemented yet");` ) ;
140- } // switch
141- this . emit ( ` return *this;` ) ;
115+ this . emit ( `auto ${ responseTypeName } ::id(std::variant<long, std::string> id) -> ${ responseTypeName } & {` ) ;
116+ this . emit ( ` return static_cast<${ responseTypeName } &>(LSPResponse::id(std::move(id)));` ) ;
142117 this . emit ( `}` ) ;
118+
119+ // synthetic structure with result property
120+
121+ const structure : Structure = {
122+ name : responseTypeName ,
123+ properties : [ { name : "result" , type : request . result , optional : false } ] ,
124+ } ;
125+
126+ this . generateGetters ( { structure, properties : structure . properties } ) ;
143127 }
144128 } ) ;
145129
146130 this . end ( ) ;
147131 }
148132
149- emit ( s : string = "" ) {
150- this . out += `${ s } \n` ;
151- }
152-
153133 getPropertyType ( { type, optional } : { type : Type ; optional ?: boolean } ) : string {
154134 let propertyType = toCppType ( type ) ;
155135
0 commit comments