Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSDoc should do more to interpret IIFEs #456

Open
rvernica opened this issue Jul 16, 2013 · 12 comments
Open

JSDoc should do more to interpret IIFEs #456

rvernica opened this issue Jul 16, 2013 · 12 comments
Labels
Milestone

Comments

@rvernica
Copy link

JSDoc does not detect functions created by compiling CoffeeScript functions with proper JSDoc comments. Here is a simple example:

x = 1

###*
   * Funtion to ...
###
a = () ->
  1

x = 1 or some other code had to be before the comment, otherwise CoffeeScript assigns the comment to the file outer anonymous function and not the inner function.

After compilation CoffeeScript generates the following JavaScript code:

// Generated by CoffeeScript 1.6.3
(function() {
  var a, x;

  x = 1;

  /**
     * Funtion to ...
  */


  a = function() {
    return 1;
  };

}).call(this);

On this code, JSDoc does not detect the a function.

If the var a, x; line is removed, JSDoc works fine.

@hegemonic
Copy link
Contributor

CoffeeScript, and most other compile-to-JS languages, can slice and dice your code in a variety of ways. Inevitably, some of that slicing and dicing will defeat JSDoc's static-analysis tools.

That said, if JSDoc did a better job of interpreting immediately invoked function expressions, such as the (function() {}).call(this) wrapper, it would be able to handle this situation correctly. I'll use this issue as a feature request for that change (and update the summary accordingly).

Removing the var a, x; line is not a good solution here, since it just turns a and x into globals.

@rvernica
Copy link
Author

That makes sense. Thanks!

@KyleJSummers
Copy link

Is there currently any way to effectively document apps with JSDoc that use IIFE's to encapsulate code?

@hegemonic
Copy link
Contributor

Yes, you can document code that uses IIFEs--it just requires a bit more markup. Our documentation website has some examples for documenting AMD modules that should help you get started.

We could use some non-module examples in the docs as well; I filed jsdoc/jsdoc.github.io#41 to address that at some point.

@hegemonic
Copy link
Contributor

Another common use case, from #442: (function() {})(window);

Before resolving this issue, we may need to tackle the more general issue that JSDoc doesn't recognize when two symbols are effectively sharing a pointer. For example, if you're documenting namespace X, and your code says var Y = X, JSDoc won't recognize that the method Y.getFoo can be documented as X.getFoo. (We don't do this because it's hard and creates a lot of edge cases, but at some point we could.)

@boba1l0s2k9
Copy link

I created a hackaround using part of the JSDoc plugin framework to filter out IIFE's before JSDoc sees the code, see jsdoc-plugin-strip-outer-iife. You can see the source code is pretty straight-forward. I believe it handles all the cases mentioned in this thread. But most importantly it handles my cases perfectly. :) This isn't the right solution for this problem, but since it works for me I thought I'd share.

@hegemonic
Copy link
Contributor

Another common use case that I allude to in a previous comment: Adding properties to window, or some other symbol that's defined outside of the IIFE's scope. (This came up again in #614. I don't think we currently infer @global when a property is added to window, although that would be useful. We might want to make this opt-in or implement it as a plugin.)

@ejfrancis
Copy link

I was going to create a separate issue but since my problem is related to IIFEs and this issue is titled "do more to interpret IIFEs" I guess my comment fits here. I'm using an IIFE in a CommonJS module to be able assign the public interface to either "module.exports" or the "window" object, so that a node.js module can be included in a <script> tag in a browser environment and it works there as well. Here is the example code

/**
 * This is a description
 *
 *  @module someModule
 */

(function (exports) {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    exports.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

This works as expected because the exports object is passed into the IIFE.

This example doesn't work, however. It looks like the exports object passed into the IIFE will only be recognized by JSDoc if it's actually named "exports". JSDoc doesn't document the public interface if it's attached to the object passed into the IIFE and that object is NOT named "exports", even the the "ex" argument is just the module.exports object being passed in. I'll show that in this example, which doesn't work

/**
 * This is a description
 *
 *  @module someModule
 */

(function (ex) {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    ex.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

This example does work though, when the exports object isn't passed into the IIFE at all

/**
 * This is a description
 *
 *  @module someModule
 */

(function () {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    exports.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

@hegemonic
Copy link
Contributor

@ejfrancis This example in the docs shows how to document your second example.

@ejfrancis
Copy link

@hegemonic I've tried that and can't get it to work. Those docs are for AMD and I'm using it within CommonJs. I couldn't tell if using the @exports tag still required the @module tag so I tried these three permutations and none worked

A with @module and @exports using different names

/**
 * This is a description
 *
 *  @module someModule
 */

(function (
    /**
     * Utility functions for jackets.
     * @exports someModuleExports
     */
    ex) {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    ex.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

B with @module and @exports using the same name

/**
 * This is a description
 *
 *  @module someModule
 */

(function (
    /**
     * Utility functions for jackets.
     * @exports someModule
     */
    ex) {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    ex.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

C with no @module tag

(function (
    /**
     * Utility functions for jackets.
     * @exports someModule
     */
    ex) {

    /**
     *  A method
     * @returns {Boolean}
     * @static
     */
    ex.isSomething = function() {
        return true;
    };


})(
    typeof exports === 'undefined'? window: exports
);

@hegemonic
Copy link
Contributor

C with no @module tag looks perfect to me. What part of the output are you unhappy with?

@ejfrancis
Copy link

@hegemonic the docs aren't even generated for the CommonJS module at all with C. without the @module tag it's just the README file that's generated into the index.html file. With A and B it generates the page for the module, but only lists the module name and description, doesn't have docs for any public methods/properties. I just tried each again in an empty project with only the module file and a README and confirm this behavior

@hegemonic hegemonic modified the milestones: Future, 3.4.0 Oct 22, 2015
openstack-gerrit pushed a commit to openstack-infra/js-generator-openstack that referenced this issue Jul 12, 2016
It is not required by node.js, but introduce troubles while
generating documents with jsdoc3.

Refer to jsdoc/jsdoc#456

Change-Id: I6664f1be0fc3e86f3a7e3843d557786c37df1c5e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants