mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Fix missing export files for extensions (#4773)
This commit is contained in:
@@ -11,30 +11,36 @@
|
|||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
|
|
||||||
std::set<gd::String> UsedExtensionsFinder::ScanProject(gd::Project& project) {
|
const UsedExtensionsResult UsedExtensionsFinder::ScanProject(gd::Project& project) {
|
||||||
UsedExtensionsFinder worker(project);
|
UsedExtensionsFinder worker(project);
|
||||||
gd::WholeProjectRefactorer::ExposeProjectObjects(project, worker);
|
gd::WholeProjectRefactorer::ExposeProjectObjects(project, worker);
|
||||||
gd::WholeProjectRefactorer::ExposeProjectEvents(project, worker);
|
gd::WholeProjectRefactorer::ExposeProjectEvents(project, worker);
|
||||||
return worker.usedExtensions;
|
return worker.result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Objects scanner
|
// Objects scanner
|
||||||
|
|
||||||
void UsedExtensionsFinder::DoVisitObject(gd::Object& object) {
|
void UsedExtensionsFinder::DoVisitObject(gd::Object &object) {
|
||||||
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||||
project.GetCurrentPlatform(), object.GetType())
|
project.GetCurrentPlatform(), object.GetType());
|
||||||
.GetExtension()
|
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||||
.GetName());
|
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||||
|
result.GetUsedIncludeFiles().insert(includeFile);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Behaviors scanner
|
// Behaviors scanner
|
||||||
|
|
||||||
void UsedExtensionsFinder::DoVisitBehavior(gd::Behavior& behavior) {
|
void UsedExtensionsFinder::DoVisitBehavior(gd::Behavior &behavior) {
|
||||||
usedExtensions.insert(
|
auto metadata = gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
|
||||||
gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
|
project.GetCurrentPlatform(), behavior.GetTypeName());
|
||||||
project.GetCurrentPlatform(), behavior.GetTypeName())
|
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||||
.GetExtension()
|
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||||
.GetName());
|
result.GetUsedIncludeFiles().insert(includeFile);
|
||||||
|
}
|
||||||
|
for (auto &&includeFile : metadata.GetMetadata().requiredFiles) {
|
||||||
|
result.GetUsedRequiredFiles().insert(includeFile);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instructions scanner
|
// Instructions scanner
|
||||||
@@ -46,7 +52,10 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
project.GetCurrentPlatform(), instruction.GetType())
|
project.GetCurrentPlatform(), instruction.GetType())
|
||||||
: gd::MetadataProvider::GetExtensionAndActionMetadata(
|
: gd::MetadataProvider::GetExtensionAndActionMetadata(
|
||||||
project.GetCurrentPlatform(), instruction.GetType());
|
project.GetCurrentPlatform(), instruction.GetType());
|
||||||
usedExtensions.insert(metadata.GetExtension().GetName());
|
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||||
|
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
|
||||||
|
result.GetUsedIncludeFiles().insert(includeFile);
|
||||||
|
}
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto expression : instruction.GetParameters()) {
|
for (auto expression : instruction.GetParameters()) {
|
||||||
@@ -61,7 +70,7 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
rootType = "number";
|
rootType = "number";
|
||||||
expression.GetRootNode()->Visit(*this);
|
expression.GetRootNode()->Visit(*this);
|
||||||
} else if (gd::ParameterMetadata::IsExpression("variable", parameterType))
|
} else if (gd::ParameterMetadata::IsExpression("variable", parameterType))
|
||||||
usedExtensions.insert("BuiltinVariables");
|
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -93,31 +102,35 @@ void UsedExtensionsFinder::OnVisitUnaryOperatorNode(UnaryOperatorNode& node) {
|
|||||||
|
|
||||||
// Add variable extension and visit sub-expressions on variable nodes
|
// Add variable extension and visit sub-expressions on variable nodes
|
||||||
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||||
usedExtensions.insert("BuiltinVariables");
|
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||||
if (node.child) node.child->Visit(*this);
|
if (node.child) node.child->Visit(*this);
|
||||||
};
|
};
|
||||||
|
|
||||||
void UsedExtensionsFinder::OnVisitVariableAccessorNode(
|
void UsedExtensionsFinder::OnVisitVariableAccessorNode(
|
||||||
VariableAccessorNode& node) {
|
VariableAccessorNode& node) {
|
||||||
usedExtensions.insert("BuiltinVariables");
|
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||||
if (node.child) node.child->Visit(*this);
|
if (node.child) node.child->Visit(*this);
|
||||||
};
|
};
|
||||||
|
|
||||||
void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
|
void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
|
||||||
VariableBracketAccessorNode& node) {
|
VariableBracketAccessorNode& node) {
|
||||||
usedExtensions.insert("BuiltinVariables");
|
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||||
node.expression->Visit(*this);
|
node.expression->Visit(*this);
|
||||||
if (node.child) node.child->Visit(*this);
|
if (node.child) node.child->Visit(*this);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add extensions bound to Objects/Behaviors/Functions
|
// Add extensions bound to Objects/Behaviors/Functions
|
||||||
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode& node) {
|
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode &node) {
|
||||||
auto type = gd::ExpressionTypeFinder::GetType(project.GetCurrentPlatform(), GetGlobalObjectsContainer(), GetObjectsContainer(), rootType, node);
|
auto type = gd::ExpressionTypeFinder::GetType(
|
||||||
|
project.GetCurrentPlatform(), GetGlobalObjectsContainer(),
|
||||||
|
GetObjectsContainer(), rootType, node);
|
||||||
if (gd::ParameterMetadata::IsObject(type)) {
|
if (gd::ParameterMetadata::IsObject(type)) {
|
||||||
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||||
project.GetCurrentPlatform(), node.identifierName)
|
project.GetCurrentPlatform(), node.identifierName);
|
||||||
.GetExtension()
|
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||||
.GetName());
|
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||||
|
result.GetUsedIncludeFiles().insert(includeFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,7 +151,10 @@ void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usedExtensions.insert(metadata.GetExtension().GetName());
|
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||||
|
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
|
||||||
|
result.GetUsedIncludeFiles().insert(includeFile);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -21,18 +21,62 @@ class Behavior;
|
|||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
|
|
||||||
|
class GD_CORE_API UsedExtensionsResult {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The extensions used by the project (or part of it).
|
||||||
|
*/
|
||||||
|
const std::set<gd::String> &GetUsedExtensions() const {
|
||||||
|
return usedExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The include files used at runtime by the project (or part of it).
|
||||||
|
*/
|
||||||
|
const std::set<gd::String> &GetUsedIncludeFiles() const {
|
||||||
|
return usedIncludeFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The additional files required at runtime by the project (or part of it).
|
||||||
|
*/
|
||||||
|
const std::set<gd::String> &GetUsedRequiredFiles() const {
|
||||||
|
return usedRequiredFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extensions used by the project (or part of it).
|
||||||
|
*/
|
||||||
|
std::set<gd::String> &GetUsedExtensions() { return usedExtensions; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The include files used at runtime by the project (or part of it).
|
||||||
|
*/
|
||||||
|
std::set<gd::String> &GetUsedIncludeFiles() { return usedIncludeFiles; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The additional files required at runtime by the project (or part of it).
|
||||||
|
*/
|
||||||
|
std::set<gd::String> &GetUsedRequiredFiles() { return usedRequiredFiles; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<gd::String> usedExtensions;
|
||||||
|
std::set<gd::String> usedIncludeFiles;
|
||||||
|
std::set<gd::String> usedRequiredFiles;
|
||||||
|
};
|
||||||
|
|
||||||
class GD_CORE_API UsedExtensionsFinder
|
class GD_CORE_API UsedExtensionsFinder
|
||||||
: public ArbitraryObjectsWorker,
|
: public ArbitraryObjectsWorker,
|
||||||
public ArbitraryEventsWorkerWithContext,
|
public ArbitraryEventsWorkerWithContext,
|
||||||
public ExpressionParser2NodeWorker {
|
public ExpressionParser2NodeWorker {
|
||||||
public:
|
public:
|
||||||
static std::set<gd::String> ScanProject(gd::Project& project);
|
static const UsedExtensionsResult ScanProject(gd::Project& project);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UsedExtensionsFinder(gd::Project& project_) : project(project_){};
|
UsedExtensionsFinder(gd::Project& project_) : project(project_){};
|
||||||
gd::Project& project;
|
gd::Project& project;
|
||||||
gd::String rootType;
|
gd::String rootType;
|
||||||
std::set<gd::String> usedExtensions;
|
UsedExtensionsResult result;
|
||||||
|
|
||||||
// Object Visitor
|
// Object Visitor
|
||||||
void DoVisitObject(gd::Object& object) override;
|
void DoVisitObject(gd::Object& object) override;
|
||||||
|
@@ -32,6 +32,11 @@
|
|||||||
|
|
||||||
namespace gdjs {
|
namespace gdjs {
|
||||||
|
|
||||||
|
static void InsertUnique(std::vector<gd::String> &container, gd::String str) {
|
||||||
|
if (std::find(container.begin(), container.end(), str) == container.end())
|
||||||
|
container.push_back(str);
|
||||||
|
}
|
||||||
|
|
||||||
Exporter::Exporter(gd::AbstractFileSystem &fileSystem, gd::String gdjsRoot_)
|
Exporter::Exporter(gd::AbstractFileSystem &fileSystem, gd::String gdjsRoot_)
|
||||||
: fs(fileSystem), gdjsRoot(gdjsRoot_) {
|
: fs(fileSystem), gdjsRoot(gdjsRoot_) {
|
||||||
SetCodeOutputDirectory(fs.GetTempDir() + "/GDTemporaries/JSCodeTemp");
|
SetCodeOutputDirectory(fs.GetTempDir() + "/GDTemporaries/JSCodeTemp");
|
||||||
@@ -52,10 +57,11 @@ bool Exporter::ExportWholePixiProject(
|
|||||||
ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
|
ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
|
||||||
gd::Project exportedProject = project;
|
gd::Project exportedProject = project;
|
||||||
|
|
||||||
auto usedExtensions = gd::UsedExtensionsFinder::ScanProject(project);
|
auto usedExtensionsResult = gd::UsedExtensionsFinder::ScanProject(project);
|
||||||
|
auto& usedExtensions = usedExtensionsResult.GetUsedExtensions();
|
||||||
|
|
||||||
auto exportProject = [this, &exportedProject, &exportOptions, &helper](
|
auto exportProject = [this, &exportedProject, &exportOptions, &helper,
|
||||||
gd::String exportDir) {
|
&usedExtensionsResult](gd::String exportDir) {
|
||||||
bool exportForCordova = exportOptions["exportForCordova"];
|
bool exportForCordova = exportOptions["exportForCordova"];
|
||||||
bool exportForFacebookInstantGames =
|
bool exportForFacebookInstantGames =
|
||||||
exportOptions["exportForFacebookInstantGames"];
|
exportOptions["exportForFacebookInstantGames"];
|
||||||
@@ -88,9 +94,14 @@ bool Exporter::ExportWholePixiProject(
|
|||||||
exportedProject.GetLoadingScreen().GetGDevelopLogoStyle(),
|
exportedProject.GetLoadingScreen().GetGDevelopLogoStyle(),
|
||||||
includesFiles);
|
includesFiles);
|
||||||
|
|
||||||
// Export files for object and behaviors
|
// Export files for free function, object and behaviors
|
||||||
helper.ExportObjectAndBehaviorsIncludes(exportedProject, includesFiles);
|
for (const auto &includeFile : usedExtensionsResult.GetUsedIncludeFiles()) {
|
||||||
helper.ExportObjectAndBehaviorsRequiredFiles(exportedProject, resourcesFiles);
|
InsertUnique(includesFiles, includeFile);
|
||||||
|
}
|
||||||
|
for (const auto &requiredFile :
|
||||||
|
usedExtensionsResult.GetUsedRequiredFiles()) {
|
||||||
|
InsertUnique(resourcesFiles, requiredFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Export effects (after engine libraries as they auto-register themselves
|
// Export effects (after engine libraries as they auto-register themselves
|
||||||
// to the engine)
|
// to the engine)
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
#include "GDCore/Tools/Log.h"
|
#include "GDCore/Tools/Log.h"
|
||||||
#include "GDJS/Events/CodeGeneration/LayoutCodeGenerator.h"
|
#include "GDJS/Events/CodeGeneration/LayoutCodeGenerator.h"
|
||||||
#include "GDJS/Extensions/JsPlatform.h"
|
#include "GDJS/Extensions/JsPlatform.h"
|
||||||
|
#include "GDCore/IDE/Events/UsedExtensionsFinder.h"
|
||||||
#undef CopyFile // Disable an annoying macro
|
#undef CopyFile // Disable an annoying macro
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -115,9 +116,15 @@ bool ExporterHelper::ExportProjectForPixiPreview(
|
|||||||
immutableProject.GetLoadingScreen().GetGDevelopLogoStyle(),
|
immutableProject.GetLoadingScreen().GetGDevelopLogoStyle(),
|
||||||
includesFiles);
|
includesFiles);
|
||||||
|
|
||||||
// Export files for object and behaviors
|
// Export files for free function, object and behaviors
|
||||||
ExportObjectAndBehaviorsIncludes(immutableProject, includesFiles);
|
auto usedExtensionsResult =
|
||||||
ExportObjectAndBehaviorsRequiredFiles(immutableProject, resourcesFiles);
|
gd::UsedExtensionsFinder::ScanProject(exportedProject);
|
||||||
|
for (const auto &includeFile : usedExtensionsResult.GetUsedIncludeFiles()) {
|
||||||
|
InsertUnique(includesFiles, includeFile);
|
||||||
|
}
|
||||||
|
for (const auto &requiredFile : usedExtensionsResult.GetUsedRequiredFiles()) {
|
||||||
|
InsertUnique(resourcesFiles, requiredFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Export effects (after engine libraries as they auto-register themselves to
|
// Export effects (after engine libraries as they auto-register themselves to
|
||||||
// the engine)
|
// the engine)
|
||||||
@@ -797,98 +804,6 @@ bool ExporterHelper::ExportIncludesAndLibs(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExporterHelper::ExportObjectAndBehaviorsIncludes(
|
|
||||||
const gd::Project &project, std::vector<gd::String> &includesFiles) {
|
|
||||||
auto addIncludeFiles = [&](const std::vector<gd::String> &newIncludeFiles) {
|
|
||||||
for (const auto &includeFile : newIncludeFiles) {
|
|
||||||
InsertUnique(includesFiles, includeFile);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addObjectIncludeFiles = [&](const gd::Object &object) {
|
|
||||||
// Ensure needed files are included for the object type and its behaviors.
|
|
||||||
const gd::ObjectMetadata &metadata =
|
|
||||||
gd::MetadataProvider::GetObjectMetadata(JsPlatform::Get(),
|
|
||||||
object.GetType());
|
|
||||||
addIncludeFiles(metadata.includeFiles);
|
|
||||||
|
|
||||||
std::vector<gd::String> behaviors = object.GetAllBehaviorNames();
|
|
||||||
for (std::size_t j = 0; j < behaviors.size(); ++j) {
|
|
||||||
const gd::BehaviorMetadata &metadata =
|
|
||||||
gd::MetadataProvider::GetBehaviorMetadata(
|
|
||||||
JsPlatform::Get(),
|
|
||||||
object.GetBehavior(behaviors[j]).GetTypeName());
|
|
||||||
addIncludeFiles(metadata.includeFiles);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addObjectsIncludeFiles =
|
|
||||||
[&](const gd::ObjectsContainer &objectsContainer) {
|
|
||||||
for (std::size_t i = 0; i < objectsContainer.GetObjectsCount(); ++i) {
|
|
||||||
addObjectIncludeFiles(objectsContainer.GetObject(i));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO UsedExtensionsFinder should be used instead to find the file to include.
|
|
||||||
// The Exporter class already use it.
|
|
||||||
addObjectsIncludeFiles(project);
|
|
||||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
|
||||||
const gd::Layout &layout = project.GetLayout(i);
|
|
||||||
addObjectsIncludeFiles(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event based objects children
|
|
||||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount(); e++) {
|
|
||||||
auto& eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
||||||
for (auto&& eventsBasedObjectUniquePtr :
|
|
||||||
eventsFunctionsExtension.GetEventsBasedObjects()
|
|
||||||
.GetInternalVector()) {
|
|
||||||
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
|
|
||||||
|
|
||||||
addObjectsIncludeFiles(*eventsBasedObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExporterHelper::ExportObjectAndBehaviorsRequiredFiles(
|
|
||||||
const gd::Project &project, std::vector<gd::String> &requiredFiles) {
|
|
||||||
auto addRequiredFiles = [&](const std::vector<gd::String> &newRequiredFiles) {
|
|
||||||
for (const auto &requiredFile : newRequiredFiles) {
|
|
||||||
InsertUnique(requiredFiles, requiredFile);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addObjectRequiredFiles = [&](const gd::Object &object) {
|
|
||||||
// Ensure needed files are included for the object type and its behaviors.
|
|
||||||
|
|
||||||
// TODO: Handle required files declared by objects. For now, no objects has
|
|
||||||
// a need for additional required files, so the object metadata do not even
|
|
||||||
// have `requiredFiles`.
|
|
||||||
|
|
||||||
std::vector<gd::String> behaviors = object.GetAllBehaviorNames();
|
|
||||||
for (std::size_t j = 0; j < behaviors.size(); ++j) {
|
|
||||||
const gd::BehaviorMetadata &metadata =
|
|
||||||
gd::MetadataProvider::GetBehaviorMetadata(
|
|
||||||
JsPlatform::Get(),
|
|
||||||
object.GetBehavior(behaviors[j]).GetTypeName());
|
|
||||||
addRequiredFiles(metadata.requiredFiles);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addObjectsRequiredFiles =
|
|
||||||
[&](const gd::ObjectsContainer &objectsContainer) {
|
|
||||||
for (std::size_t i = 0; i < objectsContainer.GetObjectsCount(); ++i) {
|
|
||||||
addObjectRequiredFiles(objectsContainer.GetObject(i));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
addObjectsRequiredFiles(project);
|
|
||||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
|
||||||
const gd::Layout &layout = project.GetLayout(i);
|
|
||||||
addObjectsRequiredFiles(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExporterHelper::ExportResources(gd::AbstractFileSystem &fs,
|
void ExporterHelper::ExportResources(gd::AbstractFileSystem &fs,
|
||||||
gd::Project &project,
|
gd::Project &project,
|
||||||
gd::String exportDir) {
|
gd::String exportDir) {
|
||||||
|
@@ -247,19 +247,6 @@ class ExporterHelper {
|
|||||||
bool ExportEffectIncludes(const gd::Project &project,
|
bool ExportEffectIncludes(const gd::Project &project,
|
||||||
std::vector<gd::String> &includesFiles);
|
std::vector<gd::String> &includesFiles);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Add the include files for all the objects of the project
|
|
||||||
* and their behaviors.
|
|
||||||
*/
|
|
||||||
void ExportObjectAndBehaviorsIncludes(const gd::Project &project,
|
|
||||||
std::vector<gd::String> &includesFiles);
|
|
||||||
/**
|
|
||||||
* \brief Add the required files for all the objects of the project
|
|
||||||
* and their behaviors.
|
|
||||||
*/
|
|
||||||
void ExportObjectAndBehaviorsRequiredFiles(const gd::Project &project,
|
|
||||||
std::vector<gd::String> &includesFiles);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copy the external source files used by the game into the export
|
* \brief Copy the external source files used by the game into the export
|
||||||
* directory, and add them into files to be included.
|
* directory, and add them into files to be included.
|
||||||
|
@@ -2221,8 +2221,12 @@ interface PropertyFunctionGenerator {
|
|||||||
boolean STATIC_CanGenerateGetterAndSetter([Const, Ref] AbstractEventsBasedEntity eventsBasedBehavior, [Const, Ref] NamedPropertyDescriptor property);
|
boolean STATIC_CanGenerateGetterAndSetter([Const, Ref] AbstractEventsBasedEntity eventsBasedBehavior, [Const, Ref] NamedPropertyDescriptor property);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface UsedExtensionsResult {
|
||||||
|
[Const, Ref] SetString GetUsedExtensions();
|
||||||
|
};
|
||||||
|
|
||||||
interface UsedExtensionsFinder {
|
interface UsedExtensionsFinder {
|
||||||
[Value] SetString STATIC_ScanProject([Ref] Project project);
|
[Value] UsedExtensionsResult STATIC_ScanProject([Ref] Project project);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ExtensionAndBehaviorMetadata {
|
interface ExtensionAndBehaviorMetadata {
|
||||||
|
@@ -108,6 +108,7 @@ describe('libGD.js', function () {
|
|||||||
it('should have a list of extensions', function () {
|
it('should have a list of extensions', function () {
|
||||||
expect(
|
expect(
|
||||||
gd.UsedExtensionsFinder.scanProject(project)
|
gd.UsedExtensionsFinder.scanProject(project)
|
||||||
|
.getUsedExtensions()
|
||||||
.toNewVectorString()
|
.toNewVectorString()
|
||||||
.toJSArray()
|
.toJSArray()
|
||||||
).toEqual([]);
|
).toEqual([]);
|
||||||
@@ -116,6 +117,7 @@ describe('libGD.js', function () {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
gd.UsedExtensionsFinder.scanProject(project)
|
gd.UsedExtensionsFinder.scanProject(project)
|
||||||
|
.getUsedExtensions()
|
||||||
.toNewVectorString()
|
.toNewVectorString()
|
||||||
.toJSArray()
|
.toJSArray()
|
||||||
).toEqual(['Sprite']);
|
).toEqual(['Sprite']);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||||
declare class gdUsedExtensionsFinder {
|
declare class gdUsedExtensionsFinder {
|
||||||
static scanProject(project: gdProject): gdSetString;
|
static scanProject(project: gdProject): gdUsedExtensionsResult;
|
||||||
delete(): void;
|
delete(): void;
|
||||||
ptr: number;
|
ptr: number;
|
||||||
};
|
};
|
6
GDevelop.js/types/gdusedextensionsresult.js
Normal file
6
GDevelop.js/types/gdusedextensionsresult.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||||
|
declare class gdUsedExtensionsResult {
|
||||||
|
getUsedExtensions(): gdSetString;
|
||||||
|
delete(): void;
|
||||||
|
ptr: number;
|
||||||
|
};
|
@@ -152,6 +152,7 @@ declare class libGDevelop {
|
|||||||
VectorUnfilledRequiredBehaviorPropertyProblem: Class<gdVectorUnfilledRequiredBehaviorPropertyProblem>;
|
VectorUnfilledRequiredBehaviorPropertyProblem: Class<gdVectorUnfilledRequiredBehaviorPropertyProblem>;
|
||||||
WholeProjectRefactorer: Class<gdWholeProjectRefactorer>;
|
WholeProjectRefactorer: Class<gdWholeProjectRefactorer>;
|
||||||
PropertyFunctionGenerator: Class<gdPropertyFunctionGenerator>;
|
PropertyFunctionGenerator: Class<gdPropertyFunctionGenerator>;
|
||||||
|
UsedExtensionsResult: Class<gdUsedExtensionsResult>;
|
||||||
UsedExtensionsFinder: Class<gdUsedExtensionsFinder>;
|
UsedExtensionsFinder: Class<gdUsedExtensionsFinder>;
|
||||||
ExtensionAndBehaviorMetadata: Class<gdExtensionAndBehaviorMetadata>;
|
ExtensionAndBehaviorMetadata: Class<gdExtensionAndBehaviorMetadata>;
|
||||||
ExtensionAndObjectMetadata: Class<gdExtensionAndObjectMetadata>;
|
ExtensionAndObjectMetadata: Class<gdExtensionAndObjectMetadata>;
|
||||||
|
@@ -43,7 +43,6 @@ type Options = {|
|
|||||||
|
|
||||||
type CodeGenerationContext = {|
|
type CodeGenerationContext = {|
|
||||||
codeNamespacePrefix: string,
|
codeNamespacePrefix: string,
|
||||||
extensionIncludeFiles: Array<string>,
|
|
||||||
|};
|
|};
|
||||||
|
|
||||||
const mangleName = (name: string) => {
|
const mangleName = (name: string) => {
|
||||||
@@ -145,29 +144,6 @@ const loadProjectEventsFunctionsExtension = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of mandatory include files when using the
|
|
||||||
* extension.
|
|
||||||
*/
|
|
||||||
const getExtensionIncludeFiles = (
|
|
||||||
project: gdProject,
|
|
||||||
eventsFunctionsExtension: gdEventsFunctionsExtension,
|
|
||||||
options: Options,
|
|
||||||
codeNamespacePrefix: string
|
|
||||||
): Array<string> => {
|
|
||||||
return mapFor(0, eventsFunctionsExtension.getEventsFunctionsCount(), i => {
|
|
||||||
const eventsFunction = eventsFunctionsExtension.getEventsFunctionAt(i);
|
|
||||||
|
|
||||||
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
||||||
eventsFunction,
|
|
||||||
codeNamespacePrefix
|
|
||||||
);
|
|
||||||
const functionName = codeNamespace + '.func'; // TODO
|
|
||||||
|
|
||||||
return options.eventsFunctionCodeWriter.getIncludeFileFor(functionName);
|
|
||||||
}).filter(Boolean);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the code for the events based extension
|
* Generate the code for the events based extension
|
||||||
*/
|
*/
|
||||||
@@ -182,15 +158,8 @@ const generateEventsFunctionExtension = (
|
|||||||
const codeNamespacePrefix =
|
const codeNamespacePrefix =
|
||||||
'gdjs.evtsExt__' + mangleName(eventsFunctionsExtension.getName());
|
'gdjs.evtsExt__' + mangleName(eventsFunctionsExtension.getName());
|
||||||
|
|
||||||
const extensionIncludeFiles = getExtensionIncludeFiles(
|
|
||||||
project,
|
|
||||||
eventsFunctionsExtension,
|
|
||||||
options,
|
|
||||||
codeNamespacePrefix
|
|
||||||
);
|
|
||||||
const codeGenerationContext = {
|
const codeGenerationContext = {
|
||||||
codeNamespacePrefix,
|
codeNamespacePrefix,
|
||||||
extensionIncludeFiles,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
@@ -246,9 +215,6 @@ const generateEventsFunctionExtension = (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then(functionInfos => {
|
.then(functionInfos => {
|
||||||
if (!options.skipCodeGeneration) {
|
|
||||||
applyFunctionIncludeFilesDependencyTransitivity(functionInfos);
|
|
||||||
}
|
|
||||||
return extension;
|
return extension;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -301,11 +267,6 @@ const generateFreeFunction = (
|
|||||||
.setIncludeFile(functionFile)
|
.setIncludeFile(functionFile)
|
||||||
.setFunctionName(functionName);
|
.setFunctionName(functionName);
|
||||||
|
|
||||||
// Always include the extension include files when using a free function.
|
|
||||||
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
|
|
||||||
instructionOrExpression.addIncludeFile(includeFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!options.skipCodeGeneration) {
|
if (!options.skipCodeGeneration) {
|
||||||
const includeFiles = new gd.SetString();
|
const includeFiles = new gd.SetString();
|
||||||
const eventsFunctionsExtensionCodeGenerator = new gd.EventsFunctionsExtensionCodeGenerator(
|
const eventsFunctionsExtensionCodeGenerator = new gd.EventsFunctionsExtensionCodeGenerator(
|
||||||
@@ -353,65 +314,6 @@ const generateFreeFunction = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Add dependencies between functions according to transitivity.
|
|
||||||
* @param functionInfos free function metadatas
|
|
||||||
*/
|
|
||||||
const applyFunctionIncludeFilesDependencyTransitivity = (
|
|
||||||
functionInfos: Array<{
|
|
||||||
functionFile: string,
|
|
||||||
functionMetadata:
|
|
||||||
| gdInstructionMetadata
|
|
||||||
| gdExpressionMetadata
|
|
||||||
| gdMultipleInstructionMetadata,
|
|
||||||
}>
|
|
||||||
): void => {
|
|
||||||
// Note that the iteration order doesn't matter, for instance for:
|
|
||||||
// a -> b
|
|
||||||
// b -> c
|
|
||||||
// c -> d
|
|
||||||
//
|
|
||||||
// going from a to c:
|
|
||||||
// a -> (b -> c)
|
|
||||||
// b -> c
|
|
||||||
// c -> d
|
|
||||||
//
|
|
||||||
// or from c to a:
|
|
||||||
// a -> b
|
|
||||||
// b -> (c -> d)
|
|
||||||
// c -> d
|
|
||||||
//
|
|
||||||
// give the same result:
|
|
||||||
// a -> (b -> (c -> d))
|
|
||||||
// b -> (c -> d)
|
|
||||||
// c -> d
|
|
||||||
const includeFileSets = functionInfos.map(
|
|
||||||
functionInfo =>
|
|
||||||
new Set(functionInfo.functionMetadata.getIncludeFiles().toJSArray())
|
|
||||||
);
|
|
||||||
// For any function A of the extension...
|
|
||||||
for (let index = 0; index < functionInfos.length; index++) {
|
|
||||||
const includeFiles = includeFileSets[index];
|
|
||||||
const functionIncludeFile = functionInfos[index].functionFile;
|
|
||||||
|
|
||||||
// ...and any function B of the extension...
|
|
||||||
for (let otherIndex = 0; otherIndex < functionInfos.length; otherIndex++) {
|
|
||||||
const otherFunctionMetadata = functionInfos[otherIndex].functionMetadata;
|
|
||||||
const otherIncludeFileSet = includeFileSets[otherIndex];
|
|
||||||
// ...where function B depends on function A...
|
|
||||||
if (otherIncludeFileSet.has(functionIncludeFile)) {
|
|
||||||
// ...add function A dependencies to the function B ones.
|
|
||||||
includeFiles.forEach(includeFile => {
|
|
||||||
if (!otherIncludeFileSet.has(includeFile)) {
|
|
||||||
otherIncludeFileSet.add(includeFile);
|
|
||||||
otherFunctionMetadata.addIncludeFile(includeFile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function generateBehavior(
|
function generateBehavior(
|
||||||
project: gdProject,
|
project: gdProject,
|
||||||
extension: gdPlatformExtension,
|
extension: gdPlatformExtension,
|
||||||
@@ -436,11 +338,6 @@ function generateBehavior(
|
|||||||
|
|
||||||
behaviorMetadata.setIncludeFile(includeFile);
|
behaviorMetadata.setIncludeFile(includeFile);
|
||||||
|
|
||||||
// Always include the extension include files when using a behavior.
|
|
||||||
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
|
|
||||||
behaviorMetadata.addIncludeFile(includeFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
const behaviorMethodMangledNames = new gd.MapStringString();
|
const behaviorMethodMangledNames = new gd.MapStringString();
|
||||||
|
|
||||||
@@ -557,11 +454,6 @@ function generateObject(
|
|||||||
|
|
||||||
objectMetadata.setIncludeFile(includeFile);
|
objectMetadata.setIncludeFile(includeFile);
|
||||||
|
|
||||||
// Always include the extension include files when using an object.
|
|
||||||
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
|
|
||||||
objectMetadata.addIncludeFile(includeFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
const objectMethodMangledNames = new gd.MapStringString();
|
const objectMethodMangledNames = new gd.MapStringString();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user