diff --git a/Source/Extensions/JavaScript/Extension.json b/Source/Extensions/JavaScript/Extension.json index 6bb004c1..55e91cb2 100644 --- a/Source/Extensions/JavaScript/Extension.json +++ b/Source/Extensions/JavaScript/Extension.json @@ -7,6 +7,7 @@ "Date", "Number" ], + "ProgrammingLanguage": ["JavaScript", "TypeScript"], "DependencyTest": "dep-test", - "Execute": "node bin/l10ns-ts.js" + "Execute": "node Executables/l10ns-ts.js" } \ No newline at end of file diff --git a/Source/Program/CommandController.cpp b/Source/Program/CommandController.cpp index 1ebf1d79..cf85270b 100644 --- a/Source/Program/CommandController.cpp +++ b/Source/Program/CommandController.cpp @@ -8,8 +8,10 @@ #include "CommandParser.cpp" #include "Configurations.h" #include "Utils.cpp" +#include "json.hpp" using namespace std; +using json = nlohmann::json; namespace L10ns { @@ -49,13 +51,13 @@ class TCPServer { public: tcp::endpoint endpoint; - TCPServer(boost::asio::io_service& service) + TCPServer(boost::asio::io_service& service, string command) : endpoint(tcp::v4(), 0) , local_endpoint(acceptor.local_endpoint()) , acceptor(service, endpoint) { start_accept(); - execute_command("L10NS_IS_USING_TCP_SERVER=1 L10NS_EXTENSION_SERVER_PORT=" + port() + " ./test"); + execute_command("IS_USING_TCP_SERVER=1 EXTENSION_SERVER_PORT=" + port() + " " + command); } string port() { @@ -82,14 +84,29 @@ class TCPServer { } }; -void start_extension_server() { +void start_extension_server(Session* session) { try { + vector files = find_files(PROJECT_DIR "Source/Extensions/*/Extension.json"); + string command; + bool found_matching_programming_language = false; + for (auto const& f : files) { + json package = json::parse(read_file(f)); + vector pl = package["ProgrammingLanguage"]; + if (find(pl.begin(), pl.end(), *session->programming_language) != pl.end()) { + found_matching_programming_language = true; + command = package["Execute"]; + break; + } + } + if (!found_matching_programming_language) { + throw invalid_argument("No matching programming language for" + *session->programming_language); + } boost::asio::io_service service; - TCPServer server(service); + TCPServer server(service, command); service.run(); } catch (exception& e) { - std::cerr << e.what() << std::endl; + cerr << e.what() << endl; } } @@ -139,8 +156,8 @@ inline Action* get_action(ActionKind action) { throw logic_error("Could not get action name."); } -inline void print_action_help_info(Command* command) { - auto a = get_action(command->action); +inline void print_action_help_info(Session* session) { + auto a = get_action(session->action); auto w = new TextWriter(); w->write_line(*a->info); w->newline(); @@ -149,7 +166,7 @@ inline void print_action_help_info(Command* command) { w->add_tab(2); w->add_tab(24); w->newline(); - for (const auto& flag : *get_action_flags(command->action)) { + for (const auto& flag : *get_action_flags(session->action)) { w->tab(); if (flag.alias->length() != 0) { w->write(*flag.name + ", " + *flag.alias); @@ -163,19 +180,15 @@ inline void print_action_help_info(Command* command) { w->print(); } -inline void print_command_help_info(Command* command) { - if (command->action == ActionKind::None) { +inline void print_command_help_info(Session* session) { + if (session->action == ActionKind::None) { print_default_help_info(); } else { - print_action_help_info(command); + print_action_help_info(session); } } -void sync_keys() { - start_extension_server(); -} - inline void print_diagnostics(vector diagnostics) { for (auto const& d : diagnostics) { cout << *d->message << endl; @@ -183,19 +196,19 @@ inline void print_diagnostics(vector diagnostics) { } int init(int argc, char* argv[]) { - auto command = parse_command_args(argc, argv); - if (command->diagnostics.size() > 0) { - print_diagnostics(command->diagnostics); + auto session = parse_command_args(argc, argv); + if (session->diagnostics.size() > 0) { + print_diagnostics(session->diagnostics); return 1; } - if (command->is_requesting_version) { + if (session->is_requesting_version) { println("L10ns version ", VERSION, "."); } - else if (command->is_requesting_help) { - print_command_help_info(command); + else if (session->is_requesting_help) { + print_command_help_info(session); } - else if (command->action == ActionKind::Sync) { - sync_keys(); + else if (session->action == ActionKind::Sync) { + start_extension_server(session); } return 0; } diff --git a/Source/Program/CommandParser.cpp b/Source/Program/CommandParser.cpp index 4fb32182..91e1ff15 100644 --- a/Source/Program/CommandParser.cpp +++ b/Source/Program/CommandParser.cpp @@ -11,9 +11,11 @@ namespace L10ns { static Flag help_flag = Flag(FlagKind::Help, "--help", "-h", "Print help description.", /*has_value*/ false); static Flag language_flag = Flag(FlagKind::Language, "--language", "-l", "Specify language.", false); +static Flag root_dir = Flag(FlagKind::Help, "--rootDir", "-rd", "Specify current root dir(Mainly for testing purposes).", /*has_value*/ true); static vector default_flags = { help_flag, + root_dir, Flag(FlagKind::Version, "--version", "", "Print current version.", /*has_value*/ false), }; @@ -81,23 +83,50 @@ vector* get_action_flags(ActionKind kind) { } } -void set_command_flag(Command* command, const Flag* flag, char* value = NULL) { +struct Session { + bool is_requesting_help; + bool is_requesting_version; + string* root_dir; + ActionKind action; + vector diagnostics; + string* programming_language; + + Session() + : is_requesting_help(false) + , is_requesting_version(false) + , action(ActionKind::None) { + } + + void add_diagnostics(Diagnostic* diagnostic) { + diagnostics.push_back(diagnostic); + } + + void write_file(string filename, string content) { + L10ns::write_file(filename, content, *root_dir); + } +}; + +void set_command_flag(Session* session, const Flag* flag, char* value = NULL) { switch (flag->kind) { case FlagKind::Help: - command->is_requesting_help = true; + session->is_requesting_help = true; return; case FlagKind::Version: - command->is_requesting_version = true; + session->is_requesting_version = true; + return; + case FlagKind::RootDir: + session->root_dir = new string(value); return; default: - throw invalid_argument("Unknwon command flag."); + throw invalid_argument("Unknown command flag."); } } -Command* parse_command_args(int argc, char* argv[]) { - Command * command = new Command(); +Session* parse_command_args(int argc, char* argv[]) { + Session* session = new Session(); + session->root_dir = get_cwd(); - // Flag to optimize has action parsing. + // Flag to optimize parsing. bool has_action = false; // The option flag that is pending for a value. @@ -111,14 +140,14 @@ Command* parse_command_args(int argc, char* argv[]) { } for (auto const& a : actions) { if (strcmp(a.name->c_str(), arg) == 0) { - command->action = a.kind; + session->action = a.kind; has_action = true; current_flags = a.flags; goto end_of_loop; } } if (!has_action) { - command->add_diagnostics(create_diagnostic(D::Unknown_command, arg)); + session->add_diagnostics(create_diagnostic(D::Unknown_command, arg)); goto end_of_loop; } @@ -132,23 +161,27 @@ Command* parse_command_args(int argc, char* argv[]) { if (flag.has_value) { flag_which_awaits_value = &flag; } - set_command_flag(command, &flag); + set_command_flag(session, &flag); is_known_flag = true; } } if (!is_known_flag) { - command->add_diagnostics(create_diagnostic(D::Unknown_command_flag, arg)); - return command; + session->add_diagnostics(create_diagnostic(D::Unknown_command_flag, arg)); + return session; } } else { - set_command_flag(command, flag_which_awaits_value, arg); + set_command_flag(session, flag_which_awaits_value, arg); flag_which_awaits_value = NULL; } end_of_loop:; } - return command; + if (!file_exists(*session->root_dir + "l10ns.json")) { + session->add_diagnostics(create_diagnostic(D::You_are_not_inside_a_L10ns_project)); + } + + return session; } } // L10ns diff --git a/Source/Program/Diagnostics.cpp b/Source/Program/Diagnostics.cpp index f8b63f00..bc03b7f0 100644 --- a/Source/Program/Diagnostics.cpp +++ b/Source/Program/Diagnostics.cpp @@ -4,4 +4,5 @@ using namespace std; namespace D { auto Unknown_command = new DiagnosticTemplate("Unknown command '{0}'."); auto Unknown_command_flag = new DiagnosticTemplate("Unknown command flag '{0}'."); + auto You_are_not_inside_a_L10ns_project = new DiagnosticTemplate("You are not inside a L10ns project."); } \ No newline at end of file diff --git a/Source/Program/Diagnostics.json b/Source/Program/Diagnostics.json index 95cf565a..03b65658 100644 --- a/Source/Program/Diagnostics.json +++ b/Source/Program/Diagnostics.json @@ -1,4 +1,5 @@ { "Unknown command flag '{0}'.": {}, - "Unknown command '{0}'.": {} + "Unknown command '{0}'.": {}, + "You are not inside a L10ns project.": {} } diff --git a/Source/Program/Types.cpp b/Source/Program/Types.cpp index 268138f2..1c9b3a09 100644 --- a/Source/Program/Types.cpp +++ b/Source/Program/Types.cpp @@ -21,6 +21,7 @@ enum class FlagKind { Language, Key, Value, + RootDir, }; struct DiagnosticTemplate { @@ -76,22 +77,4 @@ struct Action : Argument { } }; -struct Command { - bool is_requesting_help; - bool is_requesting_version; - ActionKind action; - vector diagnostics; - - Command() - : is_requesting_help(false) - , is_requesting_version(false) - , action(ActionKind::None) { - - } - - void add_diagnostics(Diagnostic* diagnostic) { - diagnostics.push_back(diagnostic); - } -}; - #endif // TYPES_H diff --git a/Source/Program/Utils.cpp b/Source/Program/Utils.cpp index e13be6ab..7f1e8d2b 100644 --- a/Source/Program/Utils.cpp +++ b/Source/Program/Utils.cpp @@ -25,6 +25,11 @@ namespace fs = boost::filesystem; namespace L10ns { +Diagnostic* create_diagnostic(DiagnosticTemplate* d) { + string* message = new string(d->message_template); + return new Diagnostic(message); +} + Diagnostic* create_diagnostic(DiagnosticTemplate* d, string arg1) { string* message = new string(boost::regex_replace(d->message_template, boost::regex("\\{0\\}"), arg1)); return new Diagnostic(message); @@ -151,12 +156,12 @@ class TextWriter { } }; -inline bool file_exists(const string & filename) { +bool file_exists(const string filename) { ifstream f(filename.c_str()); return f.good(); } -inline string read_file(string filename) { +string read_file(string filename) { string line; string result; ifstream f(filename); @@ -172,13 +177,17 @@ inline string read_file(string filename) { } } -inline void write_file(string filename, string content) { +void write_file(string filename, string content) { ofstream f; f.open(filename); f << content; f.close(); } +void write_file(string filename, string content, string cwd) { + write_file(cwd + filename, content); +} + void remove_all(string path) { fs::remove_all(fs::path(path)); } @@ -235,9 +244,9 @@ namespace Debug { } } -void recursively_create_folder(string folder) { - boost::filesystem::path dir(folder); - create_directories(dir); +void recursively_create_dir(string dir) { + boost::filesystem::path d(dir); + boost::filesystem::create_directories(d); } vector find_files(string pattern) { @@ -261,6 +270,11 @@ vector find_files(string pattern, string cwd) { return find_files(cwd + pattern); } +string* get_cwd() { + boost::filesystem::path full_path(boost::filesystem::current_path()); + return new string(full_path.string() + "/"); +} + } // L10ns #endif // UTILS_H diff --git a/Source/TestFramework/ProjectTestRunner.cpp b/Source/TestFramework/ProjectTestRunner.cpp index 55bb7b22..26176e69 100644 --- a/Source/TestFramework/ProjectTestRunner.cpp +++ b/Source/TestFramework/ProjectTestRunner.cpp @@ -17,15 +17,15 @@ void addProjectTests() { for (auto const &p : paths) { auto command = read_file(p + "/Command.cmd"); - command = string(PROJECT_DIR) + "/Executables/l10ns " + command; + string current_dir = replace_string(p, "/Cases/", "/Current/"); + recursively_create_dir(current_dir); + command = string(PROJECT_DIR) + "/Executables/l10ns --rootDir " + current_dir + " " + command; string result = execute_command(command); - string current_folder = replace_string(p, "/Cases/", "/Current/"); - recursively_create_folder(current_folder); - write_file(current_folder + "/stdout.out", result); + write_file(current_dir + "/Output.txt", result); string test_name = p.substr(p.find_last_of("/") + 1); test(test_name, [result, p](Test* t) { string reference_file = replace_string(p, "/Cases/", "/Reference/"); - string reference = read_file(reference_file + "/stdout.out"); + string reference = read_file(reference_file + "/Output.txt"); if (result != reference) { throw runtime_error("Assertion Error!"); }