UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

411 lines (322 loc) 10 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow * @format */ 'use strict'; import {Writable} from 'stream'; import {GeneratedHeader} from './GeneratedHeader'; import {PropsType, Type} from './Type'; import {Command} from './Command'; import {Event} from './Event'; export class ImplementationWriter { stream: Writable; types: Array<Type>; commands: Array<Command>; events: Array<Event>; constructor( stream: Writable, types: Array<Type>, commands: Array<Command>, events: Array<Event>, ) { this.stream = stream; this.types = types; this.commands = commands; this.events = events; } write() { this.writePrologue(); this.writeRequestParser(); this.writeTypeDefs(); this.writeRequestDefs(); this.writeResponseDefs(); this.writeNotificationDefs(); this.writeEpilogue(); } writePrologue() { this.stream.write(`${GeneratedHeader} #include "MessageTypes.h" #include "MessageTypesInlines.h" namespace facebook { namespace hermes { namespace inspector { namespace chrome { namespace message { `); } writeRequestParser() { emitRequestParser(this.stream, this.commands); } writeTypeDefs() { this.stream.write('\n/// Types\n'); for (const type of this.types) { if (type instanceof PropsType) { emitTypeDef(this.stream, type); } } } writeRequestDefs() { this.stream.write('\n/// Requests\n'); emitUnknownRequestDef(this.stream); for (const command of this.commands) { emitRequestDef(this.stream, command); } } writeResponseDefs() { this.stream.write('\n/// Responses\n'); emitErrorResponseDef(this.stream); emitOkResponseDef(this.stream); for (const command of this.commands) { emitResponseDef(this.stream, command); } } writeNotificationDefs() { this.stream.write('\n/// Notifications\n'); for (const event of this.events) { emitNotificationDef(this.stream, event); } } writeEpilogue() { this.stream.write(` } // namespace message } // namespace chrome } // namespace inspector } // namespace hermes } // namespace facebook `); } } function emitRequestParser(stream: Writable, commands: Array<Command>) { stream.write(` using RequestBuilder = std::unique_ptr<Request> (*)(const dynamic &); namespace { template <typename T> std::unique_ptr<Request> makeUnique(const dynamic &obj) { return std::make_unique<T>(obj); } } // namespace std::unique_ptr<Request> Request::fromJsonThrowOnError(const std::string &str) { static std::unordered_map<std::string, RequestBuilder> builders = { `); for (const command of commands) { const cppNs = command.getCppNamespace(); const cppType = command.getRequestCppType(); const dbgName = command.getDebuggerName(); stream.write(`{"${dbgName}", makeUnique<${cppNs}::${cppType}>},\n`); } stream.write(`}; dynamic obj = folly::parseJson(str); std::string method = obj.at("method").asString(); auto it = builders.find(method); if (it == builders.end()) { return std::make_unique<UnknownRequest>(obj); } auto builder = it->second; return builder(obj); } folly::Try<std::unique_ptr<Request>> Request::fromJson(const std::string &str) { return folly::makeTryWith( [&str] { return Request::fromJsonThrowOnError(str); }); }\n\n`); stream.write('\n'); } export function emitTypeDef(stream: Writable, type: PropsType) { const cppNs = type.getCppNamespace(); const cppType = type.getCppType(); const props = type.properties || []; // From-dynamic constructor stream.write(`${cppNs}::${cppType}::${cppType}(const dynamic &obj) {\n`); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`assign(${id}, obj, "${name}");\n`); } stream.write('}\n\n'); // toDynamic stream.write(`dynamic ${cppNs}::${cppType}::toDynamic() const { dynamic obj = dynamic::object;\n\n`); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`put(obj, "${name}", ${id});\n`); } stream.write('return obj;\n}\n\n'); } function emitErrorResponseDef(stream: Writable) { stream.write(`ErrorResponse::ErrorResponse(const dynamic &obj) { assign(id, obj, "id"); dynamic error = obj.at("error"); assign(code, error, "code"); assign(message, error, "message"); assign(data, error, "data"); } dynamic ErrorResponse::toDynamic() const { dynamic error = dynamic::object; put(error, "code", code); put(error, "message", message); put(error, "data", data); dynamic obj = dynamic::object; put(obj, "id", id); put(obj, "error", std::move(error)); return obj; }\n\n`); } function emitOkResponseDef(stream: Writable) { stream.write(`OkResponse::OkResponse(const dynamic &obj) { assign(id, obj, "id"); } dynamic OkResponse::toDynamic() const { dynamic result = dynamic::object; dynamic obj = dynamic::object; put(obj, "id", id); put(obj, "result", std::move(result)); return obj; }\n\n`); } function emitUnknownRequestDef(stream: Writable) { stream.write(`UnknownRequest::UnknownRequest() {} UnknownRequest::UnknownRequest(const dynamic &obj) { assign(id, obj, "id"); assign(method, obj, "method"); assign(params, obj, "params"); } dynamic UnknownRequest::toDynamic() const { dynamic obj = dynamic::object; put(obj, "id", id); put(obj, "method", method); put(obj, "params", params); return obj; } void UnknownRequest::accept(RequestHandler &handler) const { handler.handle(*this); }\n\n`); } export function emitRequestDef(stream: Writable, command: Command) { const cppNs = command.getCppNamespace(); const cppType = command.getRequestCppType(); const dbgName = command.getDebuggerName(); const props = command.parameters || []; // Default constructor stream.write(`${cppNs}::${cppType}::${cppType}() : Request("${dbgName}") {}\n\n`); // From-dynamic constructor stream.write(`${cppNs}::${cppType}::${cppType}(const dynamic &obj) : Request("${dbgName}") { assign(id, obj, "id"); assign(method, obj, "method");\n\n`); if (props.length > 0) { stream.write('dynamic params = obj.at("params");\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`assign(${id}, params, "${name}");\n`); } } stream.write('}\n\n'); // toDynamic stream.write(`dynamic ${cppNs}::${cppType}::toDynamic() const {\n`); if (props.length > 0) { stream.write('dynamic params = dynamic::object;\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`put(params, "${name}", ${id});\n`); } } stream.write(` dynamic obj = dynamic::object; put(obj, "id", id); put(obj, "method", method); `); if (props.length > 0) { stream.write('put(obj, "params", std::move(params));\n'); } stream.write(`return obj; }\n\n`); // visitor stream.write(`void ${cppNs}::${cppType}::accept(RequestHandler &handler) const { handler.handle(*this); }\n\n`); } export function emitResponseDef(stream: Writable, command: Command) { const cppNs = command.getCppNamespace(); const cppType = command.getResponseCppType(); if (!cppType) { return; } // From-dynamic constructor stream.write(`${cppNs}::${cppType}::${cppType}(const dynamic &obj) { assign(id, obj, "id");\n\n`); const props = command.returns || []; if (props.length > 0) { stream.write('dynamic res = obj.at("result");\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`assign(${id}, res, "${name}");\n`); } } stream.write('}\n\n'); // toDynamic stream.write(`dynamic ${cppNs}::${cppType}::toDynamic() const {\n`); if (props.length > 0) { stream.write('dynamic res = dynamic::object;\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`put(res, "${name}", ${id});\n`); } } stream.write(` dynamic obj = dynamic::object; put(obj, "id", id); put(obj, "result", std::move(res)); return obj; }\n\n`); } export function emitNotificationDef(stream: Writable, event: Event) { const cppNs = event.getCppNamespace(); const cppType = event.getCppType(); const dbgName = event.getDebuggerName(); const props = event.parameters || []; // Default constructor stream.write(`${cppNs}::${cppType}::${cppType}() : Notification("${dbgName}") {}\n\n`); // From-dynamic constructor stream.write(`${cppNs}::${cppType}::${cppType}(const dynamic &obj) : Notification("${dbgName}") { assign(method, obj, "method");\n\n`); if (props.length > 0) { stream.write('dynamic params = obj.at("params");\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`assign(${id}, params, "${name}");\n`); } } stream.write('}\n\n'); // toDynamic stream.write(`dynamic ${cppNs}::${cppType}::toDynamic() const {\n`); if (props.length > 0) { stream.write('dynamic params = dynamic::object;\n'); for (const prop of props) { const id = prop.getCppIdentifier(); const name = prop.name; stream.write(`put(params, "${name}", ${id});\n`); } } stream.write(` dynamic obj = dynamic::object; put(obj, "method", method); `); if (props.length > 0) { stream.write('put(obj, "params", std::move(params));\n'); } stream.write(`return obj; }\n\n`); }