diff --git a/.gitmodules b/.gitmodules index 0fdbcddffb1..99f7ae246b7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,12 +7,6 @@ [submodule "src/thirdparty/mustache"] path = src/thirdparty/mustache url = https://github.com/janl/mustache.js.git -[submodule "src/extensions/default/JavaScriptCodeHints/thirdparty/tern"] - path = src/extensions/default/JavaScriptCodeHints/thirdparty/tern - url = https://github.com/ternjs/tern.git -[submodule "src/extensions/default/JavaScriptCodeHints/thirdparty/acorn"] - path = src/extensions/default/JavaScriptCodeHints/thirdparty/acorn - url = https://github.com/marijnh/acorn.git [submodule "src/thirdparty/requirejs"] path = src/thirdparty/requirejs url = https://github.com/jrburke/requirejs.git diff --git a/Gruntfile.js b/Gruntfile.js index 835eb3dbb5c..62278c7110e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -323,7 +323,7 @@ module.exports = function (grunt) { }); // task: install - grunt.registerTask('install', ['write-config', 'less']); + grunt.registerTask('install', ['write-config', 'less', 'npm-install-extensions']); // task: test grunt.registerTask('test', ['eslint', 'jasmine', 'nls-check']); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1949ba7a559..23f1f90405c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4,7 +4,7 @@ "dependencies": { "anymatch": { "version": "1.3.0", - "from": "anymatch@>=1.3.0 <2.0.0", + "from": "anymatch@1.3.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz" }, "arr-diff": { @@ -28,9 +28,9 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" }, "async-each": { - "version": "1.0.0", + "version": "1.0.1", "from": "async-each@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz" }, "balanced-match": { "version": "0.4.2", @@ -159,7 +159,7 @@ }, "is-glob": { "version": "2.0.1", - "from": "is-glob@>=2.0.0 <3.0.0", + "from": "is-glob@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" }, "is-number": { @@ -192,6 +192,11 @@ "from": "kind-of@>=3.0.2 <4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz" }, + "lodash": { + "version": "4.15.0", + "from": "lodash@4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz" + }, "micromatch": { "version": "2.3.11", "from": "micromatch@>=2.1.5 <3.0.0", @@ -199,7 +204,7 @@ }, "minimatch": { "version": "3.0.3", - "from": "minimatch@3.0.3", + "from": "minimatch@>=3.0.2 <4.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" }, "normalize-path": { diff --git a/package.json b/package.json index a33211f7915..950b6ba98fe 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ }, "dependencies": { "anymatch": "1.3.0", - "chokidar": "1.6.0" + "chokidar": "1.6.0", + "lodash": "4.15.0" }, "devDependencies": { + "glob": "7.0.6", "grunt": "0.4.5", "jasmine-node": "1.11.0", "grunt-jasmine-node": "0.1.0", diff --git a/src/config.json b/src/config.json index 1d84d0ef8b8..e769d723bcd 100644 --- a/src/config.json +++ b/src/config.json @@ -37,9 +37,11 @@ }, "dependencies": { "anymatch": "1.3.0", - "chokidar": "1.6.0" + "chokidar": "1.6.0", + "lodash": "4.15.0" }, "devDependencies": { + "glob": "7.0.6", "grunt": "0.4.5", "jasmine-node": "1.11.0", "grunt-jasmine-node": "0.1.0", diff --git a/src/extensions/default/JavaScriptCodeHints/.gitignore b/src/extensions/default/JavaScriptCodeHints/.gitignore new file mode 100644 index 00000000000..2ccbe4656c6 --- /dev/null +++ b/src/extensions/default/JavaScriptCodeHints/.gitignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/src/extensions/default/JavaScriptCodeHints/HintUtils.js b/src/extensions/default/JavaScriptCodeHints/HintUtils.js index 3ce858f9ee0..6da315be7bb 100644 --- a/src/extensions/default/JavaScriptCodeHints/HintUtils.js +++ b/src/extensions/default/JavaScriptCodeHints/HintUtils.js @@ -26,7 +26,7 @@ define(function (require, exports, module) { "use strict"; - var Acorn = require("thirdparty/acorn/acorn"); + var Acorn = require("node_modules/acorn/dist/acorn"); var LANGUAGE_ID = "javascript", HTML_LANGUAGE_ID = "html", diff --git a/src/extensions/default/JavaScriptCodeHints/ScopeManager.js b/src/extensions/default/JavaScriptCodeHints/ScopeManager.js index 3601c673d64..008ca169566 100644 --- a/src/extensions/default/JavaScriptCodeHints/ScopeManager.js +++ b/src/extensions/default/JavaScriptCodeHints/ScopeManager.js @@ -55,7 +55,7 @@ define(function (require, exports, module) { var ternEnvironment = [], pendingTernRequests = {}, - builtinFiles = ["ecma5.json", "browser.json", "jquery.json"], + builtinFiles = ["ecmascript.json", "browser.json", "jquery.json"], builtinLibraryNames = [], isDocumentDirty = false, _hintCount = 0, @@ -84,7 +84,7 @@ define(function (require, exports, module) { * Read in the json files that have type information for the builtins, dom,etc */ function initTernEnv() { - var path = ExtensionUtils.getModulePath(module, "thirdparty/tern/defs/"), + var path = ExtensionUtils.getModulePath(module, "node_modules/tern/defs/"), files = builtinFiles, library; diff --git a/src/extensions/default/JavaScriptCodeHints/Session.js b/src/extensions/default/JavaScriptCodeHints/Session.js index 35474d944a4..f264cf8b3b8 100644 --- a/src/extensions/default/JavaScriptCodeHints/Session.js +++ b/src/extensions/default/JavaScriptCodeHints/Session.js @@ -32,8 +32,8 @@ define(function (require, exports, module) { HTMLUtils = brackets.getModule("language/HTMLUtils"), HintUtils = require("HintUtils"), ScopeManager = require("ScopeManager"), - Acorn = require("thirdparty/acorn/acorn"), - Acorn_Loose = require("thirdparty/acorn/acorn_loose"); + Acorn = require("node_modules/acorn/dist/acorn"), + Acorn_Loose = require("node_modules/acorn/dist/acorn_loose"); /** * Session objects encapsulate state associated with a hinting session @@ -669,7 +669,9 @@ define(function (require, exports, module) { var ast; try { ast = Acorn.parse(fragment); - } catch (e) { ast = Acorn_Loose.parse_dammit(fragment); } + } catch (e) { + ast = Acorn_Loose.parse_dammit(fragment, {}); + } // find argument as cursor location and bold it. var startOffset = this.getOffsetFromCursor(start), diff --git a/src/extensions/default/JavaScriptCodeHints/fix-acorn.js b/src/extensions/default/JavaScriptCodeHints/fix-acorn.js new file mode 100644 index 00000000000..a13e550fd4c --- /dev/null +++ b/src/extensions/default/JavaScriptCodeHints/fix-acorn.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/*eslint-env node */ +/*jslint node: true */ + +"use strict"; + +var fs = require("fs"); +var path = require("path"); +var fpath = path.resolve(__dirname, "node_modules", "acorn", "dist", "acorn_loose.js"); +var content = fs.readFileSync(fpath, "utf8"); +content = content.replace(/'\.\/acorn\.js'/g, "'./acorn'"); +fs.writeFileSync(fpath, content, "utf8"); diff --git a/src/extensions/default/JavaScriptCodeHints/main.js b/src/extensions/default/JavaScriptCodeHints/main.js index 4783dc0b9f1..9482bcd1b0b 100644 --- a/src/extensions/default/JavaScriptCodeHints/main.js +++ b/src/extensions/default/JavaScriptCodeHints/main.js @@ -41,7 +41,7 @@ define(function (require, exports, module) { HintUtils = require("HintUtils"), ScopeManager = require("ScopeManager"), Session = require("Session"), - Acorn = require("thirdparty/acorn/acorn"); + Acorn = require("node_modules/acorn/dist/acorn"); var session = null, // object that encapsulates the current session state cachedCursor = null, // last cursor of the current hinting session @@ -590,8 +590,8 @@ define(function (require, exports, module) { // to check this, run the hint through Acorns tokenizer // it should result in one token, and that token should either be // a 'name' or a 'keyword', as javascript allows keywords as property names - var tokenizer = Acorn.tokenize(completion); - var currentToken = tokenizer(); + var tokenizer = Acorn.tokenizer(completion); + var currentToken = tokenizer.getToken(); // the name is invalid if the hint is not a 'name' or 'keyword' token if (currentToken.type !== Acorn.tokTypes.name && !currentToken.type.keyword) { @@ -599,7 +599,7 @@ define(function (require, exports, module) { } else { // check for a second token - if there is one (other than 'eof') // then the hint isn't a valid property name either - currentToken = tokenizer(); + currentToken = tokenizer.getToken(); if (currentToken.type !== Acorn.tokTypes.eof) { invalidPropertyName = true; } diff --git a/src/extensions/default/JavaScriptCodeHints/npm-shrinkwrap.json b/src/extensions/default/JavaScriptCodeHints/npm-shrinkwrap.json new file mode 100644 index 00000000000..1108b36c220 --- /dev/null +++ b/src/extensions/default/JavaScriptCodeHints/npm-shrinkwrap.json @@ -0,0 +1,122 @@ +{ + "name": "brackets-javascript-code-hints", + "dependencies": { + "acorn": { + "version": "3.3.0", + "from": "acorn@3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "enhanced-resolve": { + "version": "2.2.2", + "from": "enhanced-resolve@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.2.2.tgz" + }, + "errno": { + "version": "0.1.4", + "from": "errno@>=0.1.3 <0.2.0", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz" + }, + "glob": { + "version": "3.2.11", + "from": "glob@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "dependencies": { + "minimatch": { + "version": "0.3.0", + "from": "minimatch@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz" + } + } + }, + "graceful-fs": { + "version": "4.1.6", + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "memory-fs": { + "version": "0.3.0", + "from": "memory-fs@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz" + }, + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + }, + "object-assign": { + "version": "4.1.0", + "from": "object-assign@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "prr": { + "version": "0.0.0", + "from": "prr@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz" + }, + "readable-stream": { + "version": "2.1.5", + "from": "readable-stream@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz" + }, + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "tapable": { + "version": "0.2.4", + "from": "tapable@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.4.tgz" + }, + "tern": { + "version": "0.20.0", + "from": "tern@0.20.0", + "resolved": "https://registry.npmjs.org/tern/-/tern-0.20.0.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } +} diff --git a/src/extensions/default/JavaScriptCodeHints/package.json b/src/extensions/default/JavaScriptCodeHints/package.json new file mode 100644 index 00000000000..3f665e0693a --- /dev/null +++ b/src/extensions/default/JavaScriptCodeHints/package.json @@ -0,0 +1,10 @@ +{ + "name": "brackets-javascript-code-hints", + "dependencies": { + "acorn": "3.3.0", + "tern": "0.20.0" + }, + "scripts": { + "postinstall": "node ./fix-acorn" + } +} diff --git a/src/extensions/default/JavaScriptCodeHints/tern-worker.js b/src/extensions/default/JavaScriptCodeHints/tern-worker.js index c7af67de0b4..50079d5729e 100644 --- a/src/extensions/default/JavaScriptCodeHints/tern-worker.js +++ b/src/extensions/default/JavaScriptCodeHints/tern-worker.js @@ -35,7 +35,7 @@ var config = {}; require(["./MessageIds", "./HintUtils2"], function (messageIds, hintUtils2) { MessageIds = messageIds; HintUtils2 = hintUtils2; - var ternRequire = require.config({baseUrl: "./thirdparty"}); + var ternRequire = require.config({baseUrl: "./node_modules"}); ternRequire(["tern/lib/tern", "tern/lib/infer", "tern/plugin/requirejs", "tern/plugin/doc_comment", "tern/plugin/angular"], function (tern, infer, requirejs, docComment) { Tern = tern; Infer = infer; @@ -110,7 +110,7 @@ var config = {}; * Create a new tern server. * * @param {Object} env - an Object with the environment, as read in from - * the json files in thirdparty/tern/defs + * the json files in node_modules/tern/defs * @param {Array.} files - a list of filenames tern should be aware of */ function initTernServer(env, files) { diff --git a/src/extensions/default/JavaScriptCodeHints/thirdparty/acorn b/src/extensions/default/JavaScriptCodeHints/thirdparty/acorn deleted file mode 160000 index 78e1d7ada68..00000000000 --- a/src/extensions/default/JavaScriptCodeHints/thirdparty/acorn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 78e1d7ada684868d92d09555408ae2df1812b5ae diff --git a/src/extensions/default/JavaScriptCodeHints/thirdparty/tern b/src/extensions/default/JavaScriptCodeHints/thirdparty/tern deleted file mode 160000 index 7606a6448a8..00000000000 --- a/src/extensions/default/JavaScriptCodeHints/thirdparty/tern +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7606a6448a8f7a2aacd50d10d9752440689803e8 diff --git a/src/extensions/default/JavaScriptCodeHints/unittests.js b/src/extensions/default/JavaScriptCodeHints/unittests.js index da179e00063..9c93ac879e9 100644 --- a/src/extensions/default/JavaScriptCodeHints/unittests.js +++ b/src/extensions/default/JavaScriptCodeHints/unittests.js @@ -1152,8 +1152,8 @@ define(function (require, exports, module) { testDoc.replaceRange("help.", start, start); testEditor.setCursorPos(end); var hintObj = expectHints(JSCodeHints.jsHintProvider); - // check we have a properties from "Function", "Array", and "Date" - hintsPresentOrdered(hintObj, ["apply", "concat", "getSeconds"]); + // check we have a properties from "Function", "String", and "Array" + hintsPresentOrdered(hintObj, ["apply", "charCodeAt", "concat"]); }); it("should switch to guesses after typing a query that does not match any hints", function () { diff --git a/tasks/npm-install.js b/tasks/npm-install.js index a0eff2bb07d..4020822fe13 100644 --- a/tasks/npm-install.js +++ b/tasks/npm-install.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved. + * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,9 +26,25 @@ "use strict"; module.exports = function (grunt) { - var exec = require("child_process").exec, + + var _ = require("lodash"), common = require("./lib/common")(grunt), - build = require("./build")(grunt); + build = require("./build")(grunt), + glob = require("glob"), + path = require("path"), + exec = require("child_process").exec; + + function runNpmInstall(where, callback) { + grunt.log.writeln("running npm install --production in " + where); + exec('npm install --production', { cwd: './' + where }, function (err, stdout, stderr) { + if (err) { + grunt.log.error(stderr); + } else { + grunt.log.writeln(stdout || "finished npm install in " + where); + } + return err ? callback(stderr) : callback(null, stdout); + }); + } grunt.registerTask("npm-install", "Install node_modules to the dist folder so it gets bundled with release", function () { var npmShrinkwrapJSON = grunt.file.readJSON("npm-shrinkwrap.json"); @@ -40,14 +56,27 @@ module.exports = function (grunt) { common.writeJSON(grunt, "dist/package.json", packageJSON); var done = this.async(); - exec("npm install --production", { cwd: "./dist" }, function (err, stdout, stderr) { + runNpmInstall("dist", function (err) { + return err ? done(false) : done(); + }); + }); + + grunt.registerTask("npm-install-extensions", "Install node_modules for default extensions which have package.json defined", function () { + var _done = this.async(); + glob("src/extensions/**/package.json", function (err, files) { if (err) { - grunt.log.error(stderr); - done(false); - } else { - grunt.log.writeln(stdout); - done(); + grunt.log.error(err); + return _done(false); } + files = files.filter(function (path) { + return path.indexOf("node_modules") === -1; + }); + var done = _.after(files.length, _done); + files.forEach(function (file) { + runNpmInstall(path.dirname(file), function (err) { + return err ? _done(false) : done(); + }); + }); }); });