Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add single form code generation for Internal/Debug use #1392

Merged
merged 3 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/generate/gen_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ struct GenData
};
};

static void GenCppForm(GenData& gen_data, Node* form);

// clang-format off

inline constexpr const auto txt_wxueImageFunction = R"===(
Expand Down Expand Up @@ -125,6 +127,76 @@ R"===(//////////////////////////////////////////////////////////////////////////

// clang-format on

#if defined(_DEBUG) || defined(INTERNAL_TESTING)

void MainFrame::OnGenSingleCpp(wxCommandEvent& WXUNUSED(event))
{
auto form = wxGetMainFrame()->getSelectedNode();
if (form && !form->isForm())
{
form = form->getForm();
}
if (!form)
{
wxMessageBox("You must select a form before you can generate code.", "Code Generation");
return;
}

GenResults results;
GenData gen_data(results, nullptr);

if (auto& extProp = Project.as_string(prop_source_ext); extProp.size())
{
gen_data.source_ext = extProp;
}
else
{
gen_data.source_ext = ".cpp";
}

if (auto& extProp = Project.as_string(prop_header_ext); extProp.size())
{
gen_data.header_ext = extProp;
}
else
{
gen_data.header_ext = ".h";
}

std::vector<Node*> forms;
Project.CollectForms(forms);
Project.FindWxueFunctions(forms);

GenCppForm(gen_data, form);

tt_string msg;
if (results.updated_files.size())
{
if (results.updated_files.size() == 1)
msg << "1 file was updated";
else
msg << results.updated_files.size() << " files were updated";
msg << '\n';
}
else
{
msg << "All " << results.file_count << " generated files are current";
}

if (results.msgs.size())
{
for (auto& iter: results.msgs)
{
msg << '\n';
msg << iter;
}
}

wxMessageBox(msg, "C++ Code Generation", wxOK | wxICON_INFORMATION);
}

#endif

static void GenCppForm(GenData& gen_data, Node* form)
{
// These are just defined for convenience.
Expand Down
44 changes: 44 additions & 0 deletions src/generate/gen_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
using namespace code;
using namespace GenEnum;

static bool GeneratePythonForm(Node* form, GenResults& results, std::vector<tt_string>* pClassList = nullptr);

// clang-format off

inline constexpr const auto txt_PyPerlRubyCmtBlock =
Expand All @@ -54,6 +56,48 @@ int GenXrcObject(Node* node, pugi::xml_node& object, size_t xrc_flags);

#if defined(_DEBUG) || defined(INTERNAL_TESTING)

void MainFrame::OnGenSinglePython(wxCommandEvent& WXUNUSED(event))
{
auto form = wxGetMainFrame()->getSelectedNode();
if (form && !form->isForm())
{
form = form->getForm();
}
if (!form)
{
wxMessageBox("You must select a form before you can generate code.", "Code Generation");
return;
}

GenResults results;
GeneratePythonForm(form, results);

tt_string msg;
if (results.updated_files.size())
{
if (results.updated_files.size() == 1)
msg << "1 file was updated";
else
msg << results.updated_files.size() << " files were updated";
msg << '\n';
}
else
{
msg << "Generated file is current";
}

if (results.msgs.size())
{
for (auto& iter: results.msgs)
{
msg << '\n';
msg << iter;
}
}

wxMessageBox(msg, "Python Code Generation", wxOK | wxICON_INFORMATION);
}

void MainFrame::OnGeneratePython(wxCommandEvent& WXUNUSED(event))
{
GenResults results;
Expand Down
46 changes: 45 additions & 1 deletion src/generate/gen_ruby.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
using namespace code;
using namespace GenEnum;

static bool GenerateRubyForm(Node* form, GenResults& results, std::vector<tt_string>* pClassList = nullptr);

// clang-format off

inline constexpr const auto txt_PyPerlRubyCmtBlock =
Expand Down Expand Up @@ -100,6 +102,48 @@ static const std::vector<tt_string> disable_list = {

#if defined(_DEBUG) || defined(INTERNAL_TESTING)

void MainFrame::OnGenSingleRuby(wxCommandEvent& WXUNUSED(event))
{
auto form = wxGetMainFrame()->getSelectedNode();
if (form && !form->isForm())
{
form = form->getForm();
}
if (!form)
{
wxMessageBox("You must select a form before you can generate code.", "Code Generation");
return;
}

GenResults results;
GenerateRubyForm(form, results);

tt_string msg;
if (results.updated_files.size())
{
if (results.updated_files.size() == 1)
msg << "1 file was updated";
else
msg << results.updated_files.size() << " files were updated";
msg << '\n';
}
else
{
msg << "Generated file is current";
}

if (results.msgs.size())
{
for (auto& iter: results.msgs)
{
msg << '\n';
msg << iter;
}
}

wxMessageBox(msg, "Ruby Code Generation", wxOK | wxICON_INFORMATION);
}

void MainFrame::OnGenerateRuby(wxCommandEvent& WXUNUSED(event))
{
GenResults results;
Expand Down Expand Up @@ -417,7 +461,7 @@ void BaseCodeGenerator::GenerateRubyClass(PANEL_PAGE panel_type)
{
if (!images_file_imported)
{
tt_string import_name = iter->form->as_string(prop_python_file).filename();
tt_string import_name = iter->form->as_string(prop_ruby_file).filename();
import_name.remove_extension();
code.Str("require_relative '").Str(import_name) << "'";
m_source->writeLine(code);
Expand Down
148 changes: 145 additions & 3 deletions src/generate/gen_rust.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
// Purpose: Generate Rust code files
// Author: Ralph Walden
// Copyright: Copyright (c) 2023 KeyWorks Software (Ralph Walden)
// Copyright: Copyright (c) 2023-2024 KeyWorks Software (Ralph Walden)
// License: Apache License -- see ../../LICENSE
/////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -29,6 +29,8 @@
using namespace code;
using namespace GenEnum;

static bool GenerateRustForm(Node* form, GenResults& results, std::vector<tt_string>* pClassList = nullptr);

// clang-format off

inline constexpr const auto txt_RustCmtBlock =
Expand All @@ -45,6 +47,48 @@ R"===(//////////////////////////////////////////////////////////////////////////

#if defined(_DEBUG) || defined(INTERNAL_TESTING)

void MainFrame::OnGenSingleRust(wxCommandEvent& WXUNUSED(event))
{
auto form = wxGetMainFrame()->getSelectedNode();
if (form && !form->isForm())
{
form = form->getForm();
}
if (!form)
{
wxMessageBox("You must select a form before you can generate code.", "Code Generation");
return;
}

GenResults results;
GenerateRustForm(form, results);

tt_string msg;
if (results.updated_files.size())
{
if (results.updated_files.size() == 1)
msg << "1 file was updated";
else
msg << results.updated_files.size() << " files were updated";
msg << '\n';
}
else
{
msg << "Generated file is current";
}

if (results.msgs.size())
{
for (auto& iter: results.msgs)
{
msg << '\n';
msg << iter;
}
}

wxMessageBox(msg, "Rust Code Generation", wxOK | wxICON_INFORMATION);
}

void MainFrame::OnGenerateRust(wxCommandEvent& WXUNUSED(event))
{
GenResults results;
Expand Down Expand Up @@ -78,9 +122,107 @@ void MainFrame::OnGenerateRust(wxCommandEvent& WXUNUSED(event))

#endif

bool GenerateRustFiles(GenResults& /* results */, std::vector<tt_string>* /* pClassList */)
static bool GenerateRustForm(Node* form, GenResults& results, std::vector<tt_string>* pClassList)
{
return false;
auto [path, has_base_file] = Project.GetOutputPath(form, GEN_LANG_RUST);
if (!has_base_file)
{
#if !defined(_DEBUG)
// For a lot of wxRuby testing of projects with multiple dialogs, there may
// only be a few forms where wxRuby generation is being tested, so don't nag in
// Debug builds. :-)
results.msgs.emplace_back() << "No Ruby filename specified for " << form->as_string(prop_class_name) << '\n';
#endif // _DEBUG
return false;
}

BaseCodeGenerator codegen(GEN_LANG_RUBY, form);

auto h_cw = std::make_unique<FileCodeWriter>(path);
codegen.SetHdrWriteCode(h_cw.get());

path.replace_extension(".rst");
auto cpp_cw = std::make_unique<FileCodeWriter>(path);
codegen.SetSrcWriteCode(cpp_cw.get());

codegen.GenerateRustClass();

int flags = flag_no_ui;
if (pClassList)
flags |= flag_test_only;
auto retval = cpp_cw->WriteFile(GEN_LANG_PYTHON, flags);

if (auto warning_msgs = codegen.getWarnings(); warning_msgs.size())
{
for (auto& iter: warning_msgs)
{
results.msgs.emplace_back() << iter << '\n';
}
}

if (retval > 0)
{
if (!pClassList)
{
results.updated_files.emplace_back(path);
}
else
{
if (form->isGen(gen_Images))
pClassList->emplace_back(GenEnum::map_GenNames[gen_Images]);
if (form->isGen(gen_Data))
pClassList->emplace_back(GenEnum::map_GenNames[gen_Data]);
else
pClassList->emplace_back(form->as_string(prop_class_name));
return true;
}
}

else if (retval < 0)
{
results.msgs.emplace_back() << "Cannot create or write to the file " << path << '\n';
}
else // retval == result::exists
{
++results.file_count;
}
return true;
}

bool GenerateRustFiles(GenResults& results, std::vector<tt_string>* pClassList)
{
if (Project.getChildCount() == 0)
{
results.msgs.emplace_back("You cannot generate any code until you have added a top level form.") << '\n';
wxMessageBox("You cannot generate any code until you have added a top level form.", "Code Generation");
return false;
}
tt_cwd cwd(true);
Project.ChangeDir();

bool generate_result = true;
std::vector<Node*> forms;
Project.CollectForms(forms);

#if defined(_DEBUG) || defined(INTERNAL_TESTING)
results.StartClock();
#endif

for (const auto& form: forms)
{
GenerateRustForm(form, results, pClassList);
}

if (results.msgs.size())
{
results.msgs.emplace_back() << '\n';
}

#if defined(_DEBUG) || defined(INTERNAL_TESTING)
results.EndClock();
#endif

return generate_result;
}

void BaseCodeGenerator::GenerateRustClass(PANEL_PAGE panel_type)
Expand Down
Loading