diff --git a/Changelog.md b/Changelog.md index 05bbba4..66b72ed 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,9 @@ syntax consistency. This is the first major release under the new language name (NilScript); as such, runtime APIs and generated code use "ns"/"NS"/"nilscript" rather than "oj"/"OJ". +API Changes: + - All API functions are expected to use Promises (#167). + Major Language Changes: - `@implementation` is now `@class` (#140). - JavaScript functions and variables may no longer be used inside of a `@class` (#166). diff --git a/README.md b/README.md index fc83715..c4aec1b 100644 --- a/README.md +++ b/README.md @@ -360,9 +360,9 @@ This allows Number instance variables to be used in math operations without the Unlike other parts of the NilScript runtime, properties and instance variables aren't intended to be accessed from non-NilScript JavaScript (they should be private to the subclass which defines them). However, they may need to be accessed in the debugger. -By default, the compiler uses a JavaScript property on the instance object with the follow name: +The compiler uses a JavaScript property on the instance object with an underscore prefix: - N$_i_{{IVAR NAME}} + _{{IVAR NAME}} Hence, the following NilScript code: @@ -387,24 +387,6 @@ nilscript.makeClass(…, function(…) { … // Compiler generates -setCounter: and -counter here -….incrementCounter = function() { - this.N$_i__counter++; -} - -}); -``` - -### Simple Ivars - -To make debugging easier, the `--simple-ivars` compiler flag may be used. This uses the exact ivar name as the JavaScript property. - -Hence, the previous example would compile into: - -``` -nilscript.makeClass(…, function(…) { - -… // Compiler generates -setCounter: and -counter here - ….incrementCounter = function() { this._counter++; } @@ -412,10 +394,6 @@ nilscript.makeClass(…, function(…) { }); ``` -As long as ivars are prefixed (either the default `_theIvarName` or the non-standard prefixes such as `m_theIvarName` or `mTheIvarName`), this should be safe. You may run into issues if you use this flag and also use an ivar name which conflicts with an `Object.prototype` property. Examples include: `constructor`, `hasOwnProperty`, `toString`, `valueOf`, etc. - -`--simple-ivars` has no effect when the squeezer is enabled. - --- ## Property Observers @@ -861,10 +839,12 @@ Traditionally, NilScript's API consisted of a single `compile` method: ```javascript let nsc = require("nilscript"); let options = { … }; - -nsc.compile(options, function(err, results) { - -}); + +async function doCompile() { + let results = await nsc.compile(options); + + … // Do something with results +} ``` To allow for fast incremental compiles, NilScript 2.x adds a `Compiler` constructor: @@ -878,10 +858,10 @@ let compiler = new nsc.Compiler(); let options = { … }; // Call doCompile() each time one of the files specified by options.files changes -function doCompile(callback) { - compiler.compile(options, function(err, results) { - callback(err, results); - }); +async function doCompile() { + let results = compiler.compile(options); + + … // Do something with results } ``` @@ -944,7 +924,7 @@ The callback must return a Promise. When this callback is invoked, a file's cont ```javascript // Simple preprocessor example. Strips out #pragma lines and logs to console -options["before-compile"] = async (file) => { +options["before-compile"] = async file => { let inLines = file.getContents().split("\n"); let outLines = [ ]; @@ -964,7 +944,7 @@ options["before-compile"] = async (file) => { }; // ESLint example -options["after-compile"] = async (file) => { +options["after-compile"] = async file => { if (!linter) linter = require("eslint").linter; // file.getContents() returns the generated source as a String @@ -975,7 +955,7 @@ options["after-compile"] = async (file) => { }; // Babel example -options["after-compile"] = async (file) => { +options["after-compile"] = async file => { if (!babel) babel = require("babel-core"); // retainLines must be true or NilScript's output source map will be useless diff --git a/bin/nsc b/bin/nsc index 648006f..47c1cdc 100755 --- a/bin/nsc +++ b/bin/nsc @@ -172,8 +172,16 @@ if (outputSymbolsFile) { } +function compile(options, callback) +{ + nilscript.compile(options) + .then(result => callback(null, result)) + .catch(err => callback(err)); +} + + try { - nilscript.compile(options, function(err, result) { + compile(options, function(err, result) { if (err) { print_error(err); process.exit(1); diff --git a/lib/api.js b/lib/api.js index ab7e1a3..e7113b9 100644 --- a/lib/api.js +++ b/lib/api.js @@ -8,20 +8,6 @@ const CompilerImpl = require("../src/Compiler"); const NSSymbolTyper = require("../src/model/NSSymbolTyper"); -function _logInternalErrors(errors) -{ - _.each(errors, error => { - if (error.name.indexOf("NilScript") !== 0) { - console.error("Internal NilScript error!") - console.error("------------------------------------------------------------"); - console.error(error); - console.error(error.stack); - console.error("------------------------------------------------------------"); - } - }); -} - - class Compiler { constructor() @@ -36,28 +22,9 @@ uses(compiler) } -compile(options, callback) +async compile(options) { - try { - this._impl.compile(options, (err, results) => { - if (err) { - if (!results) results = { errors: [ err ] }; - if (!results.errors) results.errors = [ err ]; - if (!results.errors.length) results.errors = [ err ]; - - } else if (!err && results.errors && results.errors.length) { - err = results.errors[0]; - } - - _logInternalErrors(results.errors); - - callback(err, results); - }); - - } catch (err) { - _logInternalErrors([ err ]); - callback(err, { errors: [ err ] }); - } + return this._impl.compile(options); } @@ -67,8 +34,8 @@ compile(options, callback) module.exports = { Compiler: Compiler, - compile: function(options, callback) { - (new Compiler()).compile(options, callback); + compile: async function(options) { + return (new Compiler()).compile(options); }, getRuntimePath: function() { diff --git a/package.json b/package.json index 93b9106..1880710 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "bin": { "nsc": "./bin/nsc" }, - "version": "2.1.0", - "engines": { "node": ">=6.0" }, + "version": "3.0.0", + "engines": { "node": ">=18.0" }, "maintainers": [{ "name": "Ricci Adams", "email": "npm@ricciadams.com", @@ -22,10 +22,8 @@ "mocha": "*" }, "dependencies": { - "async": "1.x", "estraverse": "4.x", "lodash": "4.x", - "mkdirp": "0.5.x", "node-getopt": "0.2.x", "source-map": "0.5.x", "typescript": "3.9.x" diff --git a/src/Compiler.js b/src/Compiler.js index f1941d4..89f6c83 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -9,7 +9,6 @@ const _ = require("lodash"); const fs = require("fs"); const path = require("path"); -const async = require("async"); const esprima = require("../ext/esprima"); @@ -22,7 +21,6 @@ const Utils = require("./Utils"); const Log = Utils.log; const NSError = require("./Errors").NSError; -const NSWarning = require("./Errors").NSWarning; const NSModel = require("./model").NSModel; const NSFile = require("./model").NSFile; @@ -134,7 +132,7 @@ _extractFilesFromOptions(optionsFiles, previousFiles) }); if (!_.isArray(optionsFiles)) { - Utils.throwError(NSError.APIMisuse, "options.files must be an array"); + throw new Error("options.files must be an array"); } // The 'files' option can either be an Array of String file paths, or @@ -155,11 +153,11 @@ _extractFilesFromOptions(optionsFiles, previousFiles) time = f.time || Date.now() } else { - Utils.throwError(NSError.APIMisuse, "Each member of options.files must be a string or object"); + throw new Error("Each member of options.files must be a string or object"); } if (!path) { - Utils.throwError(NSError.APIMisuse, "No 'path' key in " + f); + throw new Error("No 'path' key in " + f); } nsFile = existingMap[path] || new NSFile(path); @@ -177,65 +175,55 @@ _extractFilesFromOptions(optionsFiles, previousFiles) } -_runBeforeCompileCallback(beforeCompileCallback, nsFile, doneCallback) +_throwErrorInFiles(files) { - let lines = nsFile.contents.split("\n"); - let warnings = [ ]; + _.each(files, nsFile => { + if (nsFile.error) { + throw nsFile.error; + } + }); +} - let callbackFile = new NSCompileCallbackFile(nsFile.path, lines, warnings) - beforeCompileCallback(callbackFile, (error) => { - if (error) { - Utils.addFilePathToError(nsFile.path, error); +async _preprocessFiles(files, options) +{ + let beforeCompileCallback = options["before-compile"]; - Log(`${nsFile.path} needsPreprocess due to error: '${error}'`); - nsFile.needsPreprocess = true; + files = _.filter(files, nsFile => nsFile.needsPreprocess); - } else { - nsFile.contents = callbackFile._lines.join("\n"); + if (!beforeCompileCallback) { + _.map(files, nsFile => { nsFile.needsPreprocess = false; - } + }); - doneCallback(error); - }); -} + return; + } + await Promise.all(_.map(files, async nsFile => { + let lines = nsFile.contents.split("\n"); + let warnings = [ ]; -_preprocessFiles(files, options, callback) -{ - let err = null; - let beforeCompileCallback = options["before-compile"]; + let callbackFile = new NSCompileCallbackFile(nsFile.path, lines, warnings); - async.each(files, (nsFile, callback) => { - if (nsFile.needsPreprocess) { - if (beforeCompileCallback) { - try { - this._runBeforeCompileCallback(beforeCompileCallback, nsFile, callback); - } catch (e) { - if (!err) err = e; - callback(); - } + try { + await beforeCompileCallback(callbackFile); + nsFile.contents = callbackFile._lines.join("\n"); - } else { - nsFile.needsPreprocess = false; - callback(); - } + nsFile.needsPreprocess = false; - } else { - callback(); + } catch (err) { + Log(`${nsFile.path} needsPreprocess due to error: '${err}'`); + nsFile.error = err; } + })); - }, (e) => { - callback(err || e); - }); + this._throwErrorInFiles(files); } -_parseFiles(files, options, callback) +async _parseFiles(files, options) { - let err = null; - - async.each(files, (nsFile, callback) => { + return Promise.all(_.map(files, async nsFile => { if (!nsFile.ast) { Log(`Parsing ${nsFile.path}`); @@ -243,7 +231,6 @@ _parseFiles(files, options, callback) let sourceType = options["parser-source-type"] || "script"; nsFile.ast = esprima.parse(nsFile.contents, { loc: true, sourceType: sourceType }); - nsFile.parseError = null; nsFile.needsGenerate(); nsFile.needsTypecheck(); @@ -260,177 +247,97 @@ _parseFiles(files, options, callback) outError.reason = message; nsFile.needsParse(); - nsFile.parseError = outError; - if (!err) err = outError; + nsFile.error = outError; } } + })); - callback(); - - }, () => { - callback(err); - }); + this._throwErrorInFiles(files); } -_buildFiles(files, model, options, callback) +async _buildFiles(files, model, options) { - let err = null; - - async.each(files, (nsFile, callback) => { + await Promise.all(_.map(files, async nsFile => { try { let builder = new Builder(nsFile, model, options); builder.build(); - nsFile.buildError = null; - } catch (e) { - Utils.addFilePathToError(nsFile.path, e); + } catch (err) { nsFile.needsParse(); - nsFile.buildError = e; - if (!err) err = e; + nsFile.error = err; } + })); - callback(); - - }, () => { - if (err) { - callback(err); - } else { - try { - model.prepare(); - } catch (e) { - callback(e); - } + this._throwErrorInFiles(files); - callback(); - } - }); + model.prepare(); } -_runAfterCompileCallback(afterCompileCallback, nsFile, doneCallback) +async _generateJavaScript(files, model, options) { - let callbackFile = new NSCompileCallbackFile(nsFile.path, nsFile.generatorLines, nsFile.generatorWarnings); - - afterCompileCallback(callbackFile, (error) => { - if (error) { - Utils.addFilePathToError(nsFile.path, error); - - Log(`${nsFile.path} needsGenerate due to error: '${error}'`); - nsFile.needsGenerate(); - nsFile.generatorError = error; + let afterCompileCallback = options["after-compile"]; - } else { - nsFile.generatorError = null; - nsFile.generatorLines = callbackFile._lines; - nsFile.generatorWarnings = callbackFile._warnings; - } + await Promise.all(_.map(files, async nsFile => { + try { + if (!nsFile.generatorLines) { + Log(`Generating ${nsFile.path}`); - doneCallback(error); - }); -} + let generator = new Generator(nsFile, model, false, options); + let result = generator.generate(); + nsFile.generatorLines = result.lines; + nsFile.generatorWarnings = result.warnings || [ ]; + } -_generateJavaScript(files, model, options, callback) -{ - let err = null; + if (afterCompileCallback) { + let callbackFile = new NSCompileCallbackFile(nsFile.path, nsFile.generatorLines, nsFile.generatorWarnings); - let afterCompileCallback = options["after-compile"]; + await afterCompileCallback(callbackFile); - async.each(files, (nsFile, callback) => { - if (!nsFile.generatorLines) { - async.series([ - callback => { - try { - Log(`Generating ${nsFile.path}`); - - let generator = new Generator(nsFile, model, false, options); - let result = generator.generate(); - - nsFile.generatorError = null; - nsFile.generatorLines = result.lines; - nsFile.generatorWarnings = result.warnings || [ ]; - - } catch (e) { - Utils.addFilePathToError(nsFile.path, e); - - Log(`${nsFile.path} needsGenerate due to error: '${e}'`); - nsFile.needsGenerate(); - nsFile.generatorError = e; - - if (!err) err = e; - } - - callback(); - }, - - callback => { - if (afterCompileCallback) { - try { - this._runAfterCompileCallback(afterCompileCallback, nsFile, callback); - } catch (e) { - if (!err) err = e; - callback(); - } - - } else { - callback(); - } - } + nsFile.generatorLines = callbackFile._lines; + nsFile.generatorWarnings = callbackFile._warnings; + } - ], callback); + } catch (err) { + Log(`${nsFile.path} needsGenerate due to error: '${err}'`); - } else { - callback(); + nsFile.needsGenerate(); + nsFile.error = err; } + })); - }, () => { - callback(err); - }); + this._throwErrorInFiles(files); } -_runTypechecker(typechecker, defs, files, model, options, callback) +async _runTypechecker(typechecker, defs, files, model, options) { let err = null; - async.each(files, (nsFile, callback) => { + await Promise.all(_.map(files, async nsFile => { if (!nsFile.typecheckerCode) { try { let generator = new Generator(nsFile, model, true, options); let result = generator.generate(); - nsFile.typecheckerError = null; nsFile.typecheckerCode = result.lines.join("\n"); } catch (e) { - Utils.addFilePathToError(nsFile.path, e); nsFile.needsTypecheck(); - nsFile.typecheckerError = e; - if (!err) err = e; + nsFile.error = e; } } + })); - callback(); - - }, () => { - if (err) { - callback(err) - } else { - try { - typechecker.check(model, defs, files, (err, warnings, defs, code) => { - callback(null, warnings); - }); + this._throwErrorInFiles(files); - } catch (e) { - callback(e, null); - } - } - }); + return typechecker.check(model, defs, files); } -_finish(files, options, callback) +async _finish(files, options) { function getLines(arrayOrString) { if (_.isArray(arrayOrString)) { @@ -442,60 +349,55 @@ _finish(files, options, callback) } } - try { - let prependLines = getLines( options["prepend"] ); - let appendLines = getLines( options["append"] ); - - let outputSourceMap = null; - let outputFunctionMap = null; - - if (options["include-map"]) { - let mapper = new SourceMapper(options["source-map-file"], options["source-map-root"]); + let prependLines = getLines( options["prepend"] ); + let appendLines = getLines( options["append"] ); - mapper.add(null, prependLines); + let outputSourceMap = null; + let outputFunctionMap = null; - _.each(files, nsFile => { - mapper.add(nsFile.path, nsFile.generatorLines); - }); - - mapper.add(null, appendLines); + if (options["include-map"]) { + let mapper = new SourceMapper(options["source-map-file"], options["source-map-root"]); - outputSourceMap = mapper.getSourceMap(); - } + mapper.add(null, prependLines); - if (options["include-function-map"]) { - let functionMaps = { }; + _.each(files, nsFile => { + mapper.add(nsFile.path, nsFile.generatorLines); + }); + + mapper.add(null, appendLines); - _.each(files, nsFile => { - let mapper = new FunctionMapper(nsFile); - functionMaps[nsFile.path] = mapper.map(); - }); + outputSourceMap = mapper.getSourceMap(); + } - outputFunctionMap = functionMaps; - } + if (options["include-function-map"]) { + let functionMaps = { }; - let outputCode = null; - { - let linesArray = [ ]; // Array> + _.each(files, nsFile => { + let mapper = new FunctionMapper(nsFile); + functionMaps[nsFile.path] = mapper.map(); + }); - linesArray.push(prependLines); - _.each(files, nsFile => { - linesArray.push(nsFile.generatorLines); - }); - linesArray.push(appendLines); + outputFunctionMap = functionMaps; + } - outputCode = Array.prototype.concat.apply([ ], linesArray).join("\n"); - } + let outputCode = null; + { + let linesArray = [ ]; // Array> - callback(null, { - code: outputCode, - map: outputSourceMap, - functionMap: outputFunctionMap + linesArray.push(prependLines); + _.each(files, nsFile => { + linesArray.push(nsFile.generatorLines); }); + linesArray.push(appendLines); - } catch (err) { - callback(err); + outputCode = Array.prototype.concat.apply([ ], linesArray).join("\n"); } + + return { + code: outputCode, + map: outputSourceMap, + functionMap: outputFunctionMap + }; } @@ -506,7 +408,7 @@ uses(compiler) } -compile(options, callback) +async compile(options) { let previousFiles = this._files; let previousDefs = this._defs; @@ -610,143 +512,120 @@ compile(options, callback) let outputFunctionMap = null; let typecheckerWarnings = null; - async.waterfall([ + let caughtError = null; + + try { + // Clear errors from last compile + _.each(files, nsFile => { + nsFile.error = null; + }); + // Preprocess files - callback => { - this._preprocessFiles(files, options, callback); - }, + await this._preprocessFiles(files, options); // Parse files - callback => { - this._parseFiles(files, options, callback); - }, + await this._parseFiles(files, options); // Build model - callback => { - this._buildFiles(files, model, options, callback); - }, + await this._buildFiles(files, model, options); // Perform model diff - callback => { - if (!previousModel || previousModel.hasGlobalChanges(model)) { - if (!previousModel) { - Log("No previous model, all files need generate"); - } else { - Log("Model has global changes, all files need generate"); - } + if (!previousModel || previousModel.hasGlobalChanges(model)) { + if (!previousModel) { + Log("No previous model, all files need generate"); + } else { + Log("Model has global changes, all files need generate"); + } - _.each(files, nsFile => { - nsFile.needsGenerate(); - nsFile.needsTypecheck(); - }); + _.each(files, nsFile => { + nsFile.needsGenerate(); + nsFile.needsTypecheck(); + }); - } else { - if (options["warn-unknown-selectors"]) { - let changedSelectors = previousModel.getChangedSelectorMap(model); - - if (changedSelectors) { - _.each(files, nsFile => { - _.each(nsFile.uses.selectors, selectorName => { - if (changedSelectors[selectorName]) { - Log(`${nsFile.path} needsGenerate due to selector: '${selectorName}'`); - nsFile.needsGenerate(); - } - }); + } else { + if (options["warn-unknown-selectors"]) { + let changedSelectors = previousModel.getChangedSelectorMap(model); + + if (changedSelectors) { + _.each(files, nsFile => { + _.each(nsFile.uses.selectors, selectorName => { + if (changedSelectors[selectorName]) { + Log(`${nsFile.path} needsGenerate due to selector: '${selectorName}'`); + nsFile.needsGenerate(); + } }); - } + }); } } + } - - // If we get here, our current model is valid. Save it for next time - this._model = model; - - callback(); - }, + // If we get here, our current model is valid. Save it for next time + this._model = model; // Run generator - callback => { - if (optionsOutputLanguage != "none") { - this._generateJavaScript(files, model, options, callback); - } else { - callback(); - } - }, + if (optionsOutputLanguage != "none") { + await this._generateJavaScript(files, model, options); + } // Run typechecker - callback => { - if (optionsCheckTypes) { - this._runTypechecker(this._checker, defs, files, model, options, (err, warnings) => { - typecheckerWarnings = warnings; - callback(err); - }); - - } else { - callback(); - } - }, + if (optionsCheckTypes) { + typecheckerWarnings = await this._runTypechecker(this._checker, defs, files, model, options); + } // Concatenate and map output - callback => { - if (optionsOutputLanguage != "none") { - this._finish(files, finishOptions, (err, results) => { - if (results) { - outputCode = results.code; - outputSourceMap = results.map; - outputFunctionMap = results.functionMap; - } - - callback(err); - }); - } else { - callback(); + if (optionsOutputLanguage != "none") { + let results = await this._finish(files, finishOptions); + + if (results) { + outputCode = results.code; + outputSourceMap = results.map; + outputFunctionMap = results.functionMap; } - }, + } - ], err => { - let errors = _.compact(_.map(files, nsFile => nsFile.getError())); + } catch (err) { + caughtError = err; + } - // If we have an internal error, throw it now - { - if (err && err.name && !err.name.startsWith("NilScript")) { - throw err; - } + let errors = _.compact(_.map(files, nsFile => nsFile.error)); - _.each(errors, error => { - if (!error.name || !error.name.startsWith("NilScript")) { - throw error; - } - }); + if (caughtError && !errors.includes(caughtError)) { + errors.unshift(caughtError); + } + + _.each(errors, error => { + if (!error.name || !error.name.startsWith("NilScript")) { + throw error; } + }); - let warnings = _.map(files, nsFile => [ - nsFile.generatorWarnings, - ]); + let warnings = _.map(files, nsFile => [ + nsFile.generatorWarnings, + ]); - warnings.push(typecheckerWarnings); + warnings.push(typecheckerWarnings); - let result = { - code: outputCode, - map: outputSourceMap, - functionMap: outputFunctionMap, - errors: errors, - warnings: _.compact(_.flattenDeep(warnings)) - }; + let result = { + code: outputCode, + map: outputSourceMap, + functionMap: outputFunctionMap, + errors: errors, + warnings: _.compact(_.flattenDeep(warnings)) + }; - if (optionsIncludeState) { - result.state = model.saveState(); - } + if (optionsIncludeState) { + result.state = model.saveState(); + } - if (options["squeeze"]) { - result.squeeze = model.getSqueezeMap(); - } + if (options["squeeze"]) { + result.squeeze = model.getSqueezeMap(); + } - if (optionsIncludeBridged) { - result.bridged = model.saveBridged(); - } + if (optionsIncludeBridged) { + result.bridged = model.saveBridged(); + } - callback(err, result); - }); + return result; } } diff --git a/src/Errors.js b/src/Errors.js index ce6715b..92c7313 100644 --- a/src/Errors.js +++ b/src/Errors.js @@ -36,7 +36,6 @@ const NSError = { VariableAlreadyDeclared: "NilScriptVariableAlreadyDeclaredError", VariableNotYetDeclared: "NilScriptVariableNotYetDeclaredError", RestrictedUsage: "NilScriptRestrictedUsageError", - APIMisuse: "NilScriptAPIMisuseError", CircularClassHierarchy: "NilScriptCircularClassHierarchyError", InheritanceError: "NilScriptInheritanceError" }; diff --git a/src/Utils.js b/src/Utils.js index c9298e1..5255d61 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -150,23 +150,23 @@ function rmrf(dir) function mkdirAndWriteFile(file, contents) { - mkdirp.sync(path.dirname(file)); + fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, contents); } module.exports = { - isReservedSelectorName: isReservedSelectorName, - isBaseObjectSelectorName: isBaseObjectSelectorName, - getBaseObjectSelectorNames: getBaseObjectSelectorNames, - makeError: makeError, - throwError: throwError, - addNodeToError: addNodeToError, - addFilePathToError: addFilePathToError, - - enableLog: enableLog, - log: log, - - rmrf: rmrf, - mkdirAndWriteFile: mkdirAndWriteFile + isReservedSelectorName, + isBaseObjectSelectorName, + getBaseObjectSelectorNames, + makeError, + throwError, + addNodeToError, + addFilePathToError, + + enableLog, + log, + + rmrf, + mkdirAndWriteFile }; diff --git a/src/model/NSFile.js b/src/model/NSFile.js index 4b426d7..304f9bc 100644 --- a/src/model/NSFile.js +++ b/src/model/NSFile.js @@ -7,12 +7,14 @@ "use strict"; -const fs = require("fs"); +const fs = require("fs"); +const Utils = require("../Utils"); module.exports = class NSFile { + constructor(path) { this.path = path; @@ -56,9 +58,7 @@ needsAll() needsParse() { - this.ast = null; - this.parseError = null; - + this.ast = null; this.needsBuild(); } @@ -67,7 +67,6 @@ needsBuild() { this.usage = null; this.declarations = null; - this.buildError = null; this.needsGenerate(); this.needsTypecheck(); @@ -78,7 +77,6 @@ needsGenerate() { this.generatorLines = null; this.generatorWarnings = null; - this.generatorError = null; } @@ -86,16 +84,19 @@ needsTypecheck() { this.typecheckerCode = null; this.typecheckerDefs = null; - this.typecheckerError = null; } -getError() +set error(err) +{ + if (err) Utils.addFilePathToError(this.path, err); + this._error = err; +} + + +get error() { - return this.parseError || - this.buildError || - this.generatorError || - this.typecheckerError; + return this._error; } diff --git a/src/typechecker/Typechecker.js b/src/typechecker/Typechecker.js index aa1d81f..cebfc85 100644 --- a/src/typechecker/Typechecker.js +++ b/src/typechecker/Typechecker.js @@ -97,7 +97,7 @@ _getLibraryFilePaths(libString) } -check(model, defs, files, callback) +async check(model, defs, files) { let options = this._options; let development = options["dev-dump-tmp"]; @@ -228,7 +228,7 @@ check(model, defs, files, callback) this._program = program; - callback(null, warnings); + return warnings; } } diff --git a/test/tests.js b/test/tests.js index 9baf634..fc12200 100644 --- a/test/tests.js +++ b/test/tests.js @@ -56,7 +56,7 @@ _parseLines() } -_checkResults(err, result) +_checkResults(result) { function checkMaps(expectedMap, actualMap, noun) { let lineNumbers = _.uniq([].concat( @@ -136,19 +136,8 @@ run() let name = this.name; if (options.squeeze) name += " +squeeze"; - test(name, done => { - try { - nsc.compile(options, (err, result) => { - try { - this._checkResults(err, result); - done(); - } catch (e) { - done(e); - } - }); - } catch (e) { - done(e); - } + test(name, async () => { + this._checkResults(await nsc.compile(options)); }); }