Fix missing export files for extensions (#4773)

This commit is contained in:
D8H
2023-01-02 19:11:11 +01:00
committed by GitHub
parent 9b199d5aa0
commit c62f9c5c65
11 changed files with 129 additions and 251 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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']);

View File

@@ -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;
}; };

View File

@@ -0,0 +1,6 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdUsedExtensionsResult {
getUsedExtensions(): gdSetString;
delete(): void;
ptr: number;
};

View File

@@ -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>;

View File

@@ -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();