Browse Source

calculate exact dependencies and update the d.ts files.
Next step will be - generate one module per file, apart from core

Raanan Weber 7 years ago
parent
commit
2ca4ebf365
3 changed files with 145 additions and 12 deletions
  1. 71 0
      Tools/Gulp/gulp-calculateDependencies.js
  2. 38 4
      Tools/Gulp/gulp-dtsModuleSupport.js
  3. 36 8
      Tools/Gulp/gulpfile.js

+ 71 - 0
Tools/Gulp/gulp-calculateDependencies.js

@@ -0,0 +1,71 @@
+var gutil = require('gulp-util');
+var through = require('through2');
+var path = require('path');
+
+module.exports = function (moduleName, perFile, declared, depTree) {
+    return through.obj(function (file, enc, cb) {
+        let basename = (path.basename(file.path, ".ts"));
+        depTree[basename] = depTree[basename] || [];
+        // detect dependencies
+        let depReg1 = /[:,][ ]{0,1}([_A-Za-z]\w*)/g;
+        let depReg2 = /<([A-Z]\w*)(\[\]){0,1}>/g;
+        let depReg3 = /[\s(]([A-Z]\w*)\./g;
+        let depReg4 = /[new|extends|implements] ([A-Z]\w*)/g;
+
+        let dependencies = [];
+        fileContent = file.contents.toString();
+        function findWhereDeclared(objectName) {
+            let fileLocator;
+            Object.keys(perFile).some((filename => {
+                filedec = perFile[filename];
+                if (filedec.declarations.indexOf(objectName) !== -1) {
+                    fileLocator = filename;
+                    return true;
+                }
+                return false;
+            }))
+            return fileLocator;
+        }
+
+        //if (basename === "babylon.webVRCamera") {
+        [depReg1, depReg2, depReg3, depReg4].forEach(reg => {
+            var match = reg.exec(fileContent);
+            while (match != null) {
+                if (match[1]) {
+                    let dep = match[1];
+                    //find if it is declared internally
+                    if (perFile[basename].declarations.indexOf(dep) === -1) {
+                        // not internally? maybe it is in core?
+                        //if (declared.core.indexOf(dep) === -1) {
+                        // seems like a legit dependency! was it already added?
+                        if (perFile[basename].dependencies.indexOf(dep) === -1) {
+                            //no! add it.
+                            let whereDeclared = (findWhereDeclared(dep));
+                            if (whereDeclared) {
+                                perFile[basename].dependencies.push(dep);
+                                depTree[basename].push({
+                                    name: dep,
+                                    file: whereDeclared,
+                                    module: perFile[whereDeclared].module
+                                });
+                            }
+                        }
+                        //}
+                    }
+                }
+                match = reg.exec(fileContent);
+            }
+        });
+        //}
+
+
+        try {
+            this.push(file);
+
+        } catch (err) {
+            this.emit('error', new gutil.PluginError('gulp-calculateDependencies', err, { fileName: file.path }));
+        }
+        cb();
+    });
+};
+

+ 38 - 4
Tools/Gulp/gulp-dtsModuleSupport.js

@@ -1,14 +1,23 @@
 var gutil = require('gulp-util');
 var through = require('through2');
+var path = require('path');
 
 // inject - if set to true, it will add all declarations as imports.
-module.exports = function (moduleName, inject, declarations) {
+module.exports = function (moduleName, inject, declarations, perFile, dependencyTree) {
     return through.obj(function (file, enc, cb) {
-
+        let basename = (path.basename(file.path, ".d.ts"));
         let fileContent = file.contents.toString();
         let importsString = '';
 
         if (!inject) {
+            perFile[basename] = perFile[basename] || {
+                module: [moduleName],
+                dependencies: [],
+                declarations: []
+            };
+            if (perFile[basename].module.indexOf(moduleName) === -1) {
+                perFile[basename].module.push(moduleName);
+            }
             declarations[moduleName] = declarations[moduleName] || [];
             let regexp = /    (abstract class|function|class|interface|type|const|enum|var) ([\w]*)/g;
 
@@ -17,13 +26,15 @@ module.exports = function (moduleName, inject, declarations) {
                 if (match[2]) {
                     // check it is not SIMD:
                     let simdMatch = /    interface (\w*\dx\d{1,2}\w*)/.exec(match[0]);
-                    if (!simdMatch && match[2] !== 'earcut' && match[2] !== 'deviation' && match[2] !== 'flatten')
+                    if (!simdMatch && match[2] !== 'earcut' && match[2] !== 'deviation' && match[2] !== 'flatten') {
                         declarations[moduleName].push(match[2]);
+                        perFile[basename].declarations.push(match[2]);
+                    }
                 }
                 match = regexp.exec(fileContent);
             }
         } else {
-            let declared = [];
+            /*let declared = [];
             Object.keys(declarations).forEach(name => {
                 if (name === moduleName) return;
                 let imports = declarations[name].filter(obj => {
@@ -36,6 +47,29 @@ module.exports = function (moduleName, inject, declarations) {
                 if (imports.length)
                     importsString += `import {${imports.join(',')}} from 'babylonjs/${name}';
 `;
+            });*/
+
+            // find all of the related files for the dependency tree integration
+            let basenames = Object.keys(perFile).filter(basefilename => {
+                return perFile[basefilename].module.indexOf(moduleName) !== -1;
+            });
+
+            let classesForImports = {} // key : module name, content - array of objects
+            basenames.forEach(bname => {
+                dependencyTree[bname].forEach(dep => {
+                    if (dep.module.indexOf(moduleName) !== -1) return;
+                    let depModule = dep.module.indexOf("core") === -1 ? dep.module[0] : "core";
+                    classesForImports[depModule] = classesForImports[depModule] || [];
+                    if (classesForImports[depModule].indexOf(dep.name) === -1) {
+                        //babylon.imageProcessingPostProcess
+                        classesForImports[depModule].push(dep.name);
+                    }
+                });
+            });
+
+            Object.keys(classesForImports).forEach(modName => {
+                importsString += `import {${classesForImports[modName].join(',')}} from 'babylonjs/${modName}';
+`;
             });
         }
 

+ 36 - 8
Tools/Gulp/gulpfile.js

@@ -9,6 +9,7 @@ var addModuleExports = require("./gulp-addModuleExports");
 var babylonModuleExports = require("./gulp-babylonModule");
 var babylonES6ModuleExports = require("./gulp-es6ModuleExports");
 var dtsModuleSupport = require("./gulp-dtsModuleSupport");
+let calculateDependencies = require("./gulp-calculateDependencies");
 var merge2 = require("merge2");
 var concat = require("gulp-concat");
 var rename = require("gulp-rename");
@@ -631,23 +632,49 @@ gulp.task("modules-compile", function () {
 
 // this holds the declared objects in each module
 let declared = {}
+let perFile = {};
+let dependencyTree = {};
 
-gulp.task('prepare-for-modules', ["modules-compile"], function () {
+gulp.task('prepare-for-modules', /*["modules-compile"],*/ function () {
     let tasks = [];
     Object.keys(config.workloads).forEach((moduleName) => {
         let dtsFiles = config.workloads[moduleName].files.map(f => f.replace(".js", ".d.ts"))
         let dtsTask = gulp.src(dtsFiles)
-            .pipe(dtsModuleSupport(moduleName, false, declared));
+            .pipe(dtsModuleSupport(moduleName, false, declared, perFile));
 
         tasks.push(dtsTask);
     });
 
+    // now calculate internal dependencies in the .ts files!
+    /*Object.keys(config.workloads).forEach((moduleName) => {
+        let tsFiles = config.workloads[moduleName].files.map(f => f.replace(".js", ".ts"))
+        let depTask = gulp.src(tsFiles)
+            .pipe(calculateDependencies(moduleName, perFile, dependencyTree));
+
+        tasks.push(depTask);
+    });*/
+
+    return merge2(tasks);
+});
+
+gulp.task('prepare-dependency-tree', ["prepare-for-modules"], function () {
+    let tasks = [];
+
+    // now calculate internal dependencies in the .ts files!
+    Object.keys(config.workloads).forEach((moduleName) => {
+        let tsFiles = config.workloads[moduleName].files.map(f => f.replace(".js", ".ts"))
+        let depTask = gulp.src(tsFiles)
+            .pipe(calculateDependencies(moduleName, perFile, declared, dependencyTree));
+
+        tasks.push(depTask);
+    });
+
     return merge2(tasks);
 });
 
 // generate the modules directory, along with commonjs modules and es6 modules
 // Note - the generated modules are UNMINIFIED! The user will choose whether they want to minify or not.
-gulp.task("modules", ["prepare-for-modules"], function () {
+gulp.task("modules", ["prepare-dependency-tree"], function () {
     let tasks = [];
 
     Object.keys(config.workloads)
@@ -668,11 +695,11 @@ gulp.task("modules", ["prepare-for-modules"], function () {
             let jsTask = merge2([
                 gulp.src(config.workloads[moduleName].files),
                 gulp.src(shadersFiles).
-                    pipe(expect.real({ errorOnFailure: true }, shadersFiles)).
+                    //pipe(expect.real({ errorOnFailure: true }, shadersFiles)).
                     pipe(uncommentShader()).
                     pipe(appendSrcToVariable("BABYLON.Effect.ShadersStore", shadersName, config.build.outputDirectory + '/commonjs/' + moduleName + ".fx", true)),
                 gulp.src(shaderIncludeFiles).
-                    pipe(expect.real({ errorOnFailure: true }, shaderIncludeFiles)).
+                    //pipe(expect.real({ errorOnFailure: true }, shaderIncludeFiles)).
                     pipe(uncommentShader()).
                     pipe(appendSrcToVariable("BABYLON.Effect.IncludesShadersStore", includeShadersName, config.build.outputDirectory + '/commonjs/' + moduleName + ".include.fx", true))
             ]).pipe(concat('index.js'))
@@ -686,17 +713,18 @@ gulp.task("modules", ["prepare-for-modules"], function () {
             let es6Task = merge2([
                 gulp.src(config.workloads[moduleName].files),
                 gulp.src(shadersFiles).
-                    pipe(expect.real({ errorOnFailure: true }, shadersFiles)).
+                    //pipe(expect.real({ errorOnFailure: true }, shadersFiles)).
                     pipe(uncommentShader()).
                     pipe(appendSrcToVariable("BABYLON.Effect.ShadersStore", shadersName, config.build.outputDirectory + '/commonjs/' + moduleName + ".fx", true)),
                 gulp.src(shaderIncludeFiles).
-                    pipe(expect.real({ errorOnFailure: true }, shaderIncludeFiles)).
+                    //pipe(expect.real({ errorOnFailure: true }, shaderIncludeFiles)).
                     pipe(uncommentShader()).
                     pipe(appendSrcToVariable("BABYLON.Effect.IncludesShadersStore", includeShadersName, config.build.outputDirectory + '/commonjs/' + moduleName + ".include.fx", true))
             ]).pipe(concat('es6.js'))
                 .pipe(replace(extendsSearchRegex, ""))
                 .pipe(replace(decorateSearchRegex, ""))
                 .pipe(replace(referenceSearchRegex, ""))
+                .pipe(replace(/var BABYLON;/g, ""))
                 .pipe(babylonES6ModuleExports(moduleName, config.workloads[moduleName].dependUpon))
                 .pipe(gulp.dest(config.build.outputDirectory + '/modules/' + moduleName + '/'));
 
@@ -706,7 +734,7 @@ gulp.task("modules", ["prepare-for-modules"], function () {
                 .pipe(concat("index.d.ts"))
                 .pipe(replace(/declare module BABYLON {/g, `declare module 'babylonjs/${moduleName}' {`))
                 .pipe(replace(/\ninterface /g, `\nexport interface `))
-                .pipe(dtsModuleSupport(moduleName, true, declared))
+                .pipe(dtsModuleSupport(moduleName, true, declared, perFile, dependencyTree))
                 .pipe(gulp.dest(config.build.outputDirectory + '/modules/' + moduleName + '/'));
 
             tasks.push(jsTask, es6Task, dtsTask);