0

I read somewhere that orion uses tern for code completion for JavaScript but after running the server, creating a js file and then creating another file the other file is unaware of any code in the first file.

It seems that completion only works for symbols defined in the currently open file.

Is there a way to configure tern in orion so it will produce some helpful completion instead of a working demo without any real value?

HMR
  • 37,593
  • 24
  • 91
  • 160
  • Code assist is only useful to you with completions being brought in from other files? That is a powerful feature, but I would argue in-file expression completions along with the keyword and template proposals already provide a lot of real value. – CWindatt May 04 '15 at 15:06

2 Answers2

1

Orion has only moved to Tern for content assist proposals a couple weeks ago (mid-April 2015).

https://bugs.eclipse.org/bugs/show_bug.cgi?id=432940

We are working on enabling multi-file support.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=464821

CWindatt
  • 124
  • 8
  • I've added an answer explaining how to have it add files to the tern server on a per project base. It's kind of a dirty hack but works for me for the moment. Keep up the good work, I am excited to see this project and hope to see it grow to an excellent IDE. How would I get involved in this project? Maybe there is something I can help with? As for the code assist being useful; sorry but yes, if it only works on the current file I'm editing it's not much use for me.But for IDE's to add all the files in my project would be a bit too much as well because that causes most IDEs to be slow. – HMR May 04 '15 at 23:54
0

I have implemented a hack to load files for a particular project using a .tern-config file.

It does not work with values containing * because that would require changing the server.

This is just a simple hack and would easily break but does the job for me at the moment.

Here is how I changed the code for version 9 build S20150504-1254:

in org.eclipse.orion.client.javascript_1.0.0.v20150504-1644.jar

the file: /web/javascript/handlers/ternOccurrencesHandler.js

function sortProposals the if statement checks if file is the current open file just check if it is a value starting with /file/

replace:

            if(_o === args.meta.location) {

with:

            if(/^\/file\//.test(_o)) {

look for the function computeProposals and add the following code before that function:

function getFile(url){
    return new Promise(function(resolve,reject){
        var xhr = new XMLHttpRequest();
        xhr.open('GET',url);
        xhr.addEventListener("load", function(e){
            //@todo: have to check something I dont think this should be called on a 404 but it is
                console.log('ok, done:',xhr.responseURL);
                if(xhr.status!==200){
                    reject('file not found:',xhr.responseURL);
                    return;
                }
                resolve(xhr.responseText);
            }, false);
        xhr.addEventListener("error", function(e){
                console.log('an error:',e);
                reject(e);
            }, false);
        xhr.send();
    });
}
var loadFilesInTern = (function(){
    var loadedConfigs = [];
    var currentConfig = '';
    function loadJsFileIntoTernServer(fileName,ternserver){
        return getFile(fileName)
        .then(function resolve(val){
            ternserver.addFile(fileName,val);
        },function reject(err){
            console.log('an error:',fileName);
            return true;
        });
    }
    return function(location,ternserver){
        var p = new Promise(function(resolve){resolve(true);});
          rootPath = location.split('/').slice(0,4).join('/');
        console.log('got rootpath, trying to get tern-config from:',rootPath+'/.tern-config');
        return p
        .then(function(){
            if(!loadedConfigs[rootPath]){
                return getFile(rootPath+'/.tern-config');
            }else {
                return loadedConfigs[rootPath];
            }
        })
        .then(function(config){
            loadedConfigs[rootPath]=config;
            if(config===currentConfig){
                return;
            };
            currentConfig = config;
            var settings = JSON.parse(config);
            var promises = [];
            settings.loadEagerly.forEach(function(fileName){
                promises.push(loadJsFileIntoTernServer(rootPath + '/' + fileName,ternserver));
            });
            return Promise.all(promises);
        })
        .then(null,function reject(e){
            console.log('an error:',e);
            return true;
        });
        p.resolve('start');
    };
}());

Load the config before computing proposals (the first time)

function computeProposals(ternserver, args, callback) {
    if(ternserver) {
        loadFilesInTern(args.meta.location,ternserver)
        .then(function(){
            console.log('ternserver is now:',ternserver);
           ternserver.request({
           //... rest of the computeProposals code
        });//close the then 
    } else {//original code from computeProposals
        callback({request: 'completions', proposals:[]});
    }

You can create a a .tern-config in the project directory and add loadEagerly files:

{
  "libs": [
    "browser",
    "ecma5",
    "jquery"
  ],
  "loadEagerly": [
    "goog/base.js",
    "somefile.js",
    "another file.js"
  ],
  "plugins": {
    "requirejs": {
      "baseURL": "./",
      "paths": {}
    }
  }
}

libs and plugins are ignored at the moment but other files are loaded (note that this is a simple hack that probably breaks under certain circumstances)

HMR
  • 37,593
  • 24
  • 91
  • 160