tern
tern copied to clipboard
Problem with load of cutom tern plugin
@marijnh I would like to share with you, a problem that many people told me with my custom tern plugin :
- https://github.com/angelozerr/tern-lint/issues/64
- https://github.com/angelozerr/tern-jasmine/issues/3
- https://github.com/angelozerr/tern-node-express/issues/16
The issue is that if a tern plugin declares in the package.json a tern version (ex : 0.15.0) < available tern version (ex : 0.17.0) and you have the following case after installing tern + custom tern plugin (ex: tern-lint) :
- node_modules
- tern (0.17.0)
- tern-lint
- node_modules
- tern (0.15.0)
- node_modules
It doesn't work. For instance in this case, tern-lint which provides a custom query 'lint' is not loaded by tern 0.17.0 (see issue at https://github.com/angelozerr/tern-lint/issues/64)
If user remove at hand folder tern (0.15.0), it works again. I have found a solution to fix that. The custom tern plugin must do require to the parent tern folder:
(function(root, mod) {
if (typeof exports == "object" && typeof module == "object") {// CommonJS
function _require(mod) {try {
return require("../" + mod);
}
catch(e) {
return require(mod);
}
}
return mod(exports, _require("tern/lib/infer"), _require("tern/lib/tern"), _require("acorn/dist/walk"));
}
if (typeof define == "function" && define.amd) // AMD
return define(["exports", "tern/lib/infer", "tern/lib/tern", "acorn/dist/walk"], mod);
mod(root.tern || (root.tern = {}), tern, tern, acorn.walk);
})(this, function(exports, infer, tern, walk) {
This code is very uggly, but today I have not found other solution. Perhaps this problem could be fixed with tern, I don't know?
I think there is something in the docs about this, particularly peer dependencies. http://ternjs.net/doc/manual.html#plugin_third_party Does that work?
I just ran into this myself, because when I went looking for examples, I examined the built-in plugins, and coincidentally referred to @angelozerr's modules on NPM as well.
Perhaps the built-in plugins should implement an initialize method too, so that we have uniform way of doing things.
I think the most important part is that with multiple versions of the tern server in the path, the globals go wrong, in particular the registrations. I had to change the architecture in ycmd to work around this, but I don't think it is actually solved. For example, i have tern 0.17.0 and tern-lint "requires" tern "^0.16.0", which isn't "compatible" which means that i get this:
/Users/ben/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/tern_runtime
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └── [email protected]
└─┬ [email protected]
└── [email protected]
FWIW changing the package.json of @angelozerr's tern-lint from:
"dependencies": {
"tern": "^0.16.0",
"acorn": "^2.6.4",
"glob": "3",
"minimatch": "0.2"
},
to
"peerdependencies": {
"tern": "^0.16.0"
},
Solves the issue, leaving this:
(tests)Bens-MBP:tern_runtime ben$ npm install --production
npm WARN prefer global [email protected] should be installed with -g
/Users/ben/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/tern_runtime
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └── [email protected]
└── [email protected]
This might be less of a problem with NPM 3, which installs only a single version of a package whenever possible. In general, the way NPM treats loading multiple versions of a library as completely expected is a bit of a pain, and I don't know a good way for a package to work around it.