ternjs / tern

A JavaScript code analyzer for deep, cross-editor language support
https://ternjs.net/
MIT License
4.25k stars 378 forks source link

Problem with load of cutom tern plugin #709

Open angelozerr opened 8 years ago

angelozerr commented 8 years ago

@marijnh I would like to share with you, a problem that many people told me with my custom tern plugin :

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) :

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?

puremourning commented 8 years ago

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?

jacksonrayhamilton commented 8 years ago

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.

puremourning commented 8 years ago

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
├─┬ tern@0.17.0 
│ ├── acorn@2.7.0 
│ ├─┬ enhanced-resolve@0.9.1 
│ │ ├── graceful-fs@4.1.3 
│ │ ├── memory-fs@0.2.0 
│ │ └── tapable@0.1.10 
│ ├─┬ glob@3.2.11 
│ │ ├── inherits@2.0.1 
│ │ └── minimatch@0.3.0 
│ ├─┬ minimatch@0.2.14 
│ │ ├── lru-cache@2.7.3 
│ │ └── sigmund@1.0.1 
│ └── typescript@1.0.1 
└─┬ tern-lint@0.6.0 
  └── tern@0.16.0 

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 typescript@1.0.1 should be installed with -g
/Users/ben/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/tern_runtime
├─┬ tern@0.17.0 
│ ├── acorn@2.7.0 
│ ├─┬ enhanced-resolve@0.9.1 
│ │ ├── graceful-fs@4.1.3 
│ │ ├── memory-fs@0.2.0 
│ │ └── tapable@0.1.10 
│ ├─┬ glob@3.2.11 
│ │ ├── inherits@2.0.1 
│ │ └── minimatch@0.3.0 
│ ├─┬ minimatch@0.2.14 
│ │ ├── lru-cache@2.7.3 
│ │ └── sigmund@1.0.1 
│ └── typescript@1.0.1 
└── tern-lint@0.7.0 
marijnh commented 8 years ago

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.