javascripteclipsejsdt

Buggy code completion in eclipse JavaScript Development Tools


I open a project with file => new => static web project. Name it MyProject and web content folder name is WebContent.

Right click the WebContent directory and add a js directory. Right click the js directory and choose new => other => JavaScript source file and call it DomStuff.js with the following content:

var MyApp={};
MyApp.DomStuff={};
MyApp.DomStuff.someFunction=function(){
  return true;
}
MyApp.do<== here it auto completes to DomStuff

Right click the js directory again and choose new => other => JavaScript source file and call it WorkFlow.js

When I type MyApp. then press control + space I get a box saying No Default Proposals. It's like auto complete only works when all the code is in one file.

Right click JavaScript Resources under the Source tab MyProject/WebContent is listed as included all and excluded none.

This is in Eclipse Version: 4.2.1 with Eclipse Web Developer Tools 3.4.1 and JavaScript Development Tools 1.4.1.

For as long as I remember I never got the auto complete to work on code outside the file I am currently working on. Is this normal or am I missing some setting here?


Solution

  • [update] Basically Eclipse with JSDT can't do the job. Tried to define all my namespaces with constructor functions but it's all too much trouble.

    Trying netbeans now and it'll assist most of the closure library and all of my code. Some things like goog.array won't complete because goog.array is never defined. When adding goog.array=new Object() to the array.js it'll complete goog.array and goog.array.ArrayLike. These modded js file go in your js/libs directory of your project.

    If you want the troublesome way to get it to work in Eclipse then keep reading.

    It seems that Eclipse has problems with objects declared as object literals. Declaring my complex types with a constructor function seems to do the trick. An instance of the root object has to be created on Window (capital W).

    // this would be the way I would define
    // a complex property that doesn't need
    // more than one instance and is not complex
    // enough to put in a separate file
    myapp.workflow.objectLiteral={
      thisDoesNotCodeAssist:function(){},
      neitherDoesThis:22
    };
    
    /** if you define the complex property as
     *  a constructor it will auto complete
     *  in other files and closure compiler will 
     *  recognize it's type
     */
    /** @constructor organizes flow 
     * used for Eclipse code assist */
    var WorkFlow=function(){};
    ProwpWithSubs=function(){};
    PropWithSubs.prototype.subProp=22;
    PropWithSubs.prototype.subFunction=function(){
      this.subsub=44;
    };
    WorkFlow.prototype.propwithsubs=new PropWithSubs();
    if(ALLWAYSFALSE){
      /**needed for Eclipse code assist
       * @constructor
       */
      var MyApp=function(){};
      MyApp.prototype.workflow=new WorkFlow();
      MyApp.prototype.dom=new DOM();
      Window.prototype.myapp=new MyApp();
    }else{
      myapp.workflow=new WorkFlow();
    }
    

    [update]

    Here are 3 files I use to split up the definition and the implementation a little so it's easier with google closure.

    Setting up the main types in types.js

    // source: js/mmyapp/types.js
    goog.provide("myapp.types");
    /** @constructor */
    var gooblediegoog=function(){};
    /** @constructor */
    gooblediegoog.prototype.WorkFlow=function(){};
    /** @constructor */
    gooblediegoog.prototype.Dom=function(){};
    myapp.types=new gooblediegoog();
    

    A file that isn't used at all in my code but tells Eclipse how to auto complete:

    // source: js/myapp/forCodeAssist.js
    /** @const {boolean} */
    var ALLWAYSFALSE=false;
    
    if(ALLWAYSFALSE){
        /**needed for Eclipse autocomplete
         * @constructor
         */
        var MyApp=function(){};
        MyApp.prototype.types=new gooblediegoog();
        Window.prototype.myapp=new MyApp();
        MyApp.prototype.workflow=new myapp.types.WorkFlow();
        MyApp.prototype.dom=new myapp.types.Dom();
    }
    

    An implementation of workflow:

    // source: js/myapp/workflow.js
    goog.provide("myapp.workflow");
    goog.require("myapp.types");
    goog.require("myapp.dom");
    
    /** @returns number|undefined */
    myapp.types.WorkFlow.prototype.createOrder=function(){
        return myapp.dom.getArticleAmout();
    };
    myapp.workflow=new myapp.types.WorkFlow();
    window['console'].log(myapp.workflow.createOrder());
    

    This can be converted to a myapp.workflow.createOrder=... syntax by replacing myapp.types.WorkFlow.prototype with myapp.workflow, removing myapp.workflow=new myapp.types.WorkFlow() and removing the goog.require("myapp.types"). Maybe this can be automated in the build/compile process if needed.

    I am not sure if creating a single object with the help from a constructor function is much more expensive than just having goog.require create myapp.workflow and adding properties to it as I used to do (and as it's done in closure library).