简体   繁体   English

为什么Closure Compiler不识别自执行匿名函数中的类型声明?

[英]Why doesn't Closure Compiler recognize type declarations inside a self-executing anonymous function?

I'm getting a lot of "Unknown type" warnings when running a fairly large library through Closure Compiler, and they seem to occur when my types are declared in self-executing anonymous functions. 当通过Closure Compiler运行一个相当大的库时,我收到了很多"Unknown type"警告,并且当我的类型在自执行匿名函数中声明时,它们似乎发生了。 There's nothing exotic about this, but if I strip the self-executing functions out, the type declarations seem to work (at least in this simple test). 这没有什么奇特之处,但是如果我将自执行函数剥离出来,类型声明似乎起作用(至少在这个简单的测试中)。

I'm not sure if there's something wrong with my code annotations or if there's anything illegal in the code, but I think this is all kosher and the standard way to modularize an API. 我不确定我的代码注释是否有问题,或者代码中是否存在任何违法行为,但我认为这都是犹太教和模块化API的标准方法。

The following test code creates a namespace (just a plain old JS object) and attaches an enum (an object literal) and a function to it. 以下测试代码创建一个命名空间(只是一个普通的旧JS对象)并附加一个枚举(一个对象文字)和一个函数。

var mynamespace = {};
(function (mynamespace) {
    /**
     * Some enum.
     * @enum {number}
     */
    mynamespace.SomeEnum = {
        FOO: 1,
        BAR: 2
    };

    /**
     * Frazzle some type.
     * @param {mynamespace.SomeEnum} qux The type to frazzle.
     * @return {boolean} whether the operation succeeded.
     */
    mynamespace.frazzle = function(qux) {
        return true;
    }
}(mynamespace));

// call it
mynamespace.frazzle(mynamespace.SomeEnum.FOO);

Looks fine, right? 看起来很好,对吗? The closure compiler errors: 闭包编译错误:

[jscomp] Compiling 1 file(s) with 37 extern(s)
[jscomp] X:\dev\solclientjs\sdk\tools\jscomptest.js:14: WARNING - Parse error. Unknown type mynamespace.SomeEnum

[jscomp]      * @param {mynamespace.SomeEnum} qux The type to frazzle.

Edit: 编辑:

Original answer was totally off. 原来的答案完全没了。

This definitely appears to be a bug in the compiler. 这肯定是编译器中的一个错误。 I haven't found a bug report with this exact issue, but I found two bug reports that appear to address the inverse of this issue (compiler should be throwing a warning, but it won't unless you unwrap the anonymous function). 我没有找到有关这个问题的错误报告,但是我发现了两个错误报告似乎解决了这个问题的反面(编译器应该抛出警告,但除非你打开匿名函数,否则它不会发出警告)。

http://code.google.com/p/closure-compiler/issues/detail?id=134 http://code.google.com/p/closure-compiler/issues/detail?id=134

http://code.google.com/p/closure-compiler/issues/detail?id=61 http://code.google.com/p/closure-compiler/issues/detail?id=61

In any case it looks like anonymous functions are wonky when used with type expressions. 在任何情况下,当与类型表达式一起使用时,它看起来像匿名函数。

In your example, the argument "mynamespace" is being passed an "alias" to the global mynamespace object. 在您的示例中,参数“mynamespace”正在向全局 mynamespace对象传递“别名”。 Having an alias (local mynamespace) to your global object (global mynamespace) prevents optimizations on the entire tree under the global object. 在全局对象(全局mynamespace)中使用别名(本地mynamespace)可防止对全局对象下的整个树进行优化。 This is a BAD BAD idea for the Closure Compiler in Advanced mode. 对于高级模式下的Closure Compiler,这是一个不好的想法。

Any function defined under a local variable is volatile. 在局部变量下定义的任何函数都是volatile。 The compiler has no idea (without deep code flow analysis) the local "mynamespace" is an alias to the global "mynamespace". 编译器不知道(没有深度代码流分析)本地“mynamespace”是全局“mynamespace”的别名。 Therefore, it won't automatically associate anything you define under the local variable to the object that it aliases. 因此,它不会自动将您在局部变量下定义的任何内容与其别名的对象相关联。

The proper ways to do this are: 正确的方法是:

Option #1, using the global object directly: 选项#1,直接使用全局对象:

(function() {
    mynamespace.someEnum = ...
})();

Option #2, use a goog.scope alias (assuming you are using Advanced mode): 选项#2,使用goog.scope别名(假设您使用的是高级模式):

goog.scope(function() {
    var somevar = mynamespace;

    (function() {
        somevar.someEnum = ...
    })();
});

Both options should get you your desired result. 这两个选项都可以为您提供所需的结果。 However, there is currently no way to do what you want via an argument into a wrapper closure. 但是,目前没有办法通过参数进入包装器闭包。

The Closure Compiler has improved here. Closure Compiler在这里有所改进。 The only thing that you need to do to correct the code above so that it is recognized is to declare the namespace as @const: 要纠正上面的代码以使其被识别,您唯一需要做的就是将名称空间声明为@const:

/** @const */ var mynamespace = {}; / ** @const * / var mynamespace = {};

The type is then recognized. 然后识别该类型。

The Closure Compiler doesn't support local type names. Closure编译器不支持本地类型名称。 The names must be global and within the function "mynamespace" is a local name. 名称必须是全局的,并且在函数“mynamespace”中是本地名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM