diff --git a/test-app/app/build.gradle b/test-app/app/build.gradle index 3edb21dde..388cb7041 100644 --- a/test-app/app/build.gradle +++ b/test-app/app/build.gradle @@ -29,7 +29,8 @@ def PACKAGE_JSON = "package.json" //static binding generator def SBG_JAVA_DEPENDENCIES = "sbg-java-dependencies.txt" -def SBG_INPUT_OUTPUT_DIRS = "sbg-input-output-dirs.txt" +def SBG_INPUT_FILE = "sbg-input-file.txt" +def SBG_OUTPUT_FILE = "sbg-output-file.txt" def SBG_JS_PARCED_FILES = "sbg-js-parced-files.txt" def SBG_BINDINGS_NAME = "sbg-bindings.txt" def SBG_INTERFACE_NAMES = "sbg-interface-names.txt" @@ -333,8 +334,11 @@ task collectAllJars { } } } - new File("$BUILD_TOOLS_PATH/$SBG_INPUT_OUTPUT_DIRS").withWriter { out -> + + new File("$BUILD_TOOLS_PATH/$SBG_INPUT_FILE").withWriter { out -> out.println INPUT_JS_DIR + } + new File("$BUILD_TOOLS_PATH/$SBG_OUTPUT_FILE").withWriter { out -> out.println OUTPUT_JAVA_DIR } } @@ -464,7 +468,8 @@ task cleanSbg(type: Delete) { "$BUILD_TOOLS_PATH/$SBG_JAVA_DEPENDENCIES", "$BUILD_TOOLS_PATH/$SBG_INTERFACE_NAMES", "$BUILD_TOOLS_PATH/$SBG_BINDINGS_NAME", - "$BUILD_TOOLS_PATH/$SBG_INPUT_OUTPUT_DIRS", + "$BUILD_TOOLS_PATH/$SBG_INPUT_FILE", + "$BUILD_TOOLS_PATH/$SBG_OUTPUT_FILE", "$OUTPUT_JAVA_DIR/com/tns/gen" } diff --git a/test-app/build-tools/.gitignore b/test-app/build-tools/.gitignore index 85ac1669d..d83ea296d 100644 --- a/test-app/build-tools/.gitignore +++ b/test-app/build-tools/.gitignore @@ -2,7 +2,8 @@ static-binding-generator.jar sbg-bindings.txt sbg-interfaces-names.txt sbg-js-parced-files.txt -sbg-input-output-dirs.txt +sbg-input-file.txt +sbg-output-file.txt sbg-java-dependencies.txt android-metadata-generator.jar mdg-output-dir.txt diff --git a/test-app/build-tools/jsparser/js_parser.js b/test-app/build-tools/jsparser/js_parser.js index e8f006699..6aaaedb5e 100644 --- a/test-app/build-tools/jsparser/js_parser.js +++ b/test-app/build-tools/jsparser/js_parser.js @@ -10,9 +10,9 @@ if (process.env.AST_PARSER_DISABLE_LOGGING && process.env.AST_PARSER_DISABLE_LOG disableLogger = false; } -var arguments = process.argv; +var arguments = process.argv; if (arguments && arguments.length) { - if(arguments[arguments.length - 1] == "enableVerboseLogging") { + if (arguments[arguments.length - 1] == "enableVerboseLogging") { disableLogger = false } } @@ -35,17 +35,21 @@ var fs = require("fs"), lazy = require("lazy"), eol = require('os').EOL, + BUILD_TOOLS_DIR = `${__dirname}/../`, appDir = path.dirname(require.main.filename), extendDecoratorName = "JavaProxy", interfacesDecoratorName = "Interfaces", outFile = "out/out_parsed_typescript.txt", // default out file inputDir = "input_parced_typescript", // default input folder SBG_INTERFACE_NAMES = "sbg-interface-names.txt", - interfacesNamesFilePath = "../" + SBG_INTERFACE_NAMES, //default interace_names file path + interfacesNamesFilePath = getRelativeToBuildTools(SBG_INTERFACE_NAMES), //default interace_names file path + SBG_INPUT_FILE = "sbg-input-file.txt", + SBG_BINDINGS_NAME = "sbg-bindings.txt", + SBG_INTERFACE_NAMES = "sbg-interfaces-names.txt", + SBG_JS_PARCED_FILES = "sbg-js-parced-files.txt", interfaceNames = [], inputFiles = []; - //env variables if (process.env.AST_PARSER_OUT_FILE) { outFile = process.env.AST_PARSER_OUT_FILE.trim(); @@ -57,24 +61,17 @@ if (process.env.AST_PARSER_INTERFACE_FILE_PATH) { interfacesNamesFilePath = process.env.AST_PARSER_INTERFACE_FILE_PATH.trim(); } +inputDir = fs.readFileSync(getRelativeToBuildTools(SBG_INPUT_FILE), "UTF-8").trim(); +try { + fs.unlinkSync(getRelativeToBuildTools(SBG_BINDINGS_NAME)); //delete before each run +} catch (e) { } +outFile = getRelativeToBuildTools(SBG_BINDINGS_NAME) +interfacesNamesFilePath = getRelativeToBuildTools(SBG_INTERFACE_NAMES) +inputFilesPath = getRelativeToBuildTools(SBG_JS_PARCED_FILES) -//console variables have priority -if (arguments && arguments.length >= 3) { - inputDir = arguments[2] - // console.log("inputDir: " + inputDir) -} -if (arguments && arguments.length >= 4) { - outFile = arguments[3] - // console.log("outFile: " + outFile) -} -if (arguments && arguments.length >= 5) { - interfacesNamesFilePath = arguments[4] - // console.log("interfacesNamesFilePath: " + interfacesNamesFilePath) +function getRelativeToBuildTools(relativePath) { + return path.resolve(`${BUILD_TOOLS_DIR}/${relativePath}`) } -if (arguments && arguments.length >= 6) { - inputFilesPath = arguments[5] -} - /////////////// PREPARATION //////////////// // fileHelpers.createFile(outFile) @@ -113,10 +110,10 @@ function readLinesFromFile(filePath, outArr, resolveParameter) { /* * Get line and column of the __extends function from ts_helpers file */ -function getFileAst(tsHelpersFilePath) { +function getFileAst(tsHelpersFilePath) { return new Promise(function (resolve, reject) { - fs.readFile(tsHelpersFilePath, 'utf8', function(err, fileContent) { - if (err) { + fs.readFile(tsHelpersFilePath, 'utf8', function (err, fileContent) { + if (err) { logger.warn("+DIDN'T parse ast from file " + tsHelpersFilePath); return reject(err); } @@ -126,7 +123,7 @@ function getFileAst(tsHelpersFilePath) { var ast = babelParser.parse(fileContent, { minify: false, plugins: ["decorators"] - }); + }); return resolve(ast); }); @@ -142,15 +139,15 @@ function getExtendsLineColumn(ast) { var tsHelpersInfo = {}; traverse.default(ast, { - enter: function(path) { + enter: function (path) { - if(t.isAssignmentExpression(path.parent) && + if (t.isAssignmentExpression(path.parent) && t.isCallExpression(path) && - path.node.callee.property && - path.node.callee.property.name === "extend" && - path.node.callee.object.name === "parent") { - tsHelpersInfo.line = path.node.callee.property.loc.start.line - tsHelpersInfo.column = path.node.callee.property.loc.start.column + 1 + path.node.callee.property && + path.node.callee.property.name === "extend" && + path.node.callee.object.name === "parent") { + tsHelpersInfo.line = path.node.callee.property.loc.start.line + tsHelpersInfo.column = path.node.callee.property.loc.start.column + 1 } } }) @@ -197,15 +194,15 @@ function traverseAndAnalyseFilesDir(inputDir, err) { function traverseFiles(filesToTraverse) { var filesLength = filesToTraverse.length; - for(var i = 0; i < filesLength; i += 1) { + for (var i = 0; i < filesLength; i += 1) { var fp = filesToTraverse[i]; logger.info("Visiting JavaScript file: " + fp); readFile(fp) - .then(astFromFileContent) - .then(visitAst) - .then(writeToFile) - .catch(exceptionHandler) + .then(astFromFileContent) + .then(visitAst) + .then(writeToFile) + .catch(exceptionHandler) } } @@ -213,7 +210,7 @@ function traverseFiles(filesToTraverse) { * Gets the file content as text and passes it down the line. */ var readFile = function (filePath, err) { - + return new Promise(function (resolve, reject) { fs.readFile(filePath, function (err, data) { if (err) { @@ -234,7 +231,7 @@ var readFile = function (filePath, err) { * Get's the AST (https://en.wikipedia.org/wiki/Abstract_syntax_tree) from the file content and passes it down the line. */ var astFromFileContent = function (data, err) { - return new Promise(function (resolve, reject) { + return new Promise(function (resolve, reject) { if (err) { logger.warn("+DIDN'T parse ast from file!"); return reject(err); @@ -288,7 +285,7 @@ var visitAst = function (data, err) { }); } -var writeToFile = function (data, err) { +var writeToFile = function (data, err) { return new Promise(function (resolve, reject) { if (data.trim() != "") { // fs.appendFile(outFile, stringify(data), function (writeFileError) { diff --git a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java index 80a412ca8..8ada185ae 100644 --- a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java +++ b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java @@ -16,6 +16,9 @@ public class GetInterfaceNames { private static String currentDir; + /* + * generate interfaceNames.txt file, needed for js analyzer + * */ public static void generateInterfaceFile(List rows) throws IOException, ClassNotFoundException { currentDir = System.getProperty("user.dir"); diff --git a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java index f29fa94fa..447a305e6 100644 --- a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java +++ b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; +import java.io.InterruptedIOException; import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.file.Paths; @@ -13,87 +14,88 @@ import java.util.List; public class Main { - public static final String SBG_INPUT_OUTPUT_DIRS = "sbg-input-output-dirs.txt"; + public static final String SBG_INPUT_FILE = "sbg-input-file.txt"; + public static final String SBG_OUTPUT_FILE = "sbg-output-file.txt"; public static final String SBG_BINDINGS_NAME = "sbg-bindings.txt"; public static final String SBG_JS_PARCED_FILES = "sbg-js-parced-files.txt"; public static final String SBG_INTERFACE_NAMES = "sbg-interfaces-names.txt"; + private static String jsCodeAbsolutePath; - private static List inputJsFiles = new ArrayList<>(); + private static List inputJsFiles; private static File outputDir; private static File inputDir; private static String dependenciesFile; + static { + inputJsFiles = new ArrayList<>(); + } + public static void main(String[] args) throws IOException, ClassNotFoundException { validateInput(); - //webpack specific excluded files getWorkerExcludeFile(); List rows = Generator.getRows(dependenciesFile); - - //generate interfaceNames.txt needed for js parser GetInterfaceNames.generateInterfaceFile(rows); - - //run static js analysis - String inputBindingFilename = Paths.get(System.getProperty("user.dir"), SBG_BINDINGS_NAME).toString(); - try { - new File(inputBindingFilename).delete(); - } catch (Exception e) {} - runJsParser(inputDir); + generateJsInputFile(); + runJsParser(); // generate java bindings + String inputBindingFilename = Paths.get(System.getProperty("user.dir"), SBG_BINDINGS_NAME).toString(); new Generator(outputDir, rows).writeBindings(inputBindingFilename); } + /* + * Method should traverse all js files from input folder and put the ones that need traversing in another file + * */ + private static void generateJsInputFile() throws IOException { + try { + traverseDirectory(inputDir, false/*traverse explicitly*/); + } catch (JSONException e) { + e.printStackTrace(); + } + String pathToJsFileParams = SBG_JS_PARCED_FILES; + PrintWriter pw = GetInterfaceNames.ensureOutputFile(pathToJsFileParams); + for (String f : inputJsFiles) { + pw.write(f); + pw.write("\n"); + } + pw.flush(); + pw.close(); + } + private static void validateInput() throws IOException { dependenciesFile = "sbg-java-dependencies.txt"; if (!(new File(dependenciesFile).exists())) { throw new IllegalArgumentException(String.format("Couldn't find input dependenciesFile file. Make sure the file %s is present.", dependenciesFile)); } - List inputOutput = Generator.getRows(SBG_INPUT_OUTPUT_DIRS); - inputDir = new File(inputOutput.get(0).getRow()); + List inputFile = Generator.getRows(SBG_INPUT_FILE); + inputDir = new File(inputFile.get(0).getRow()); if (!inputDir.exists() || !inputDir.isDirectory()) { throw new IllegalArgumentException(String.format("Couldn't find the output dir %s or it wasn't a directory", inputDir.getAbsolutePath())); } jsCodeAbsolutePath = inputDir.getAbsolutePath(); - //asd - outputDir = new File(inputOutput.get(1).getRow()); + List outputFile = Generator.getRows(SBG_OUTPUT_FILE); + outputDir = new File(outputFile.get(0).getRow()); if (!outputDir.exists() || !outputDir.isDirectory()) { System.out.println(String.format("Couldn't find the output dir %s or it wasn't a directory so it will be created!", outputDir.getAbsolutePath())); outputDir.mkdirs(); } } - private static void runJsParser(File inputDir) throws IOException { + /* + * Run the javascript static analysis [js_parser] and generate an output file. + * This output file should contain all the information needed to generate java counterparts to the traversed js classes. + * */ + private static void runJsParser() throws IOException { String parserPath = Paths.get(System.getProperty("user.dir"), "jsparser", "js_parser.js").toString(); - String inputPath = inputDir.getAbsolutePath(); - String bindingsFilePath = Paths.get(System.getProperty("user.dir"), SBG_BINDINGS_NAME).toString(); - String interfaceNamesFilePath = Paths.get(System.getProperty("user.dir"), SBG_INTERFACE_NAMES).toString(); - try { - traverseDirectory(inputDir, false/*traverse explicitly*/); - } catch (JSONException e) { - e.printStackTrace(); - } - String pathToJsFileParams = SBG_JS_PARCED_FILES; - PrintWriter pw = GetInterfaceNames.ensureOutputFile(pathToJsFileParams); - pathToJsFileParams = Paths.get(System.getProperty("user.dir"), pathToJsFileParams).toString(); - for (String f : inputJsFiles) { - pw.write(f); - pw.write("\n"); - } - pw.flush(); - pw.close(); List l = new ArrayList(); l.add("node"); l.add(parserPath); - l.add(inputPath); - l.add(bindingsFilePath); - l.add(interfaceNamesFilePath); - l.add(pathToJsFileParams); ProcessBuilder pb = new ProcessBuilder(l); pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); @@ -103,6 +105,7 @@ private static void runJsParser(File inputDir) throws IOException { p.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); + throw new InterruptedIOException("A problem occured while waiting for the jsparser to finish."); } } @@ -159,6 +162,9 @@ private static void traverseDirectory(File currentDir, boolean traverseExplicitl private static String webpackWorkersExcludePath = System.getProperty("user.dir") + "/app/src/main/assets/app/__worker-chunks.json"; private static List webpackWorkersExcludesList; + /* + * Should provide the webpack specific files that need to be excluded from the js analysis + * */ private static void getWorkerExcludeFile() { webpackWorkersExcludesList = new ArrayList();