Почему Closure Compiler не распознает объявления типов внутри самоисполняющейся анонимной функции? - PullRequest
13 голосов
/ 03 марта 2011

Я получаю много "Unknown type" предупреждений при запуске довольно большой библиотеки через Closure Compiler, и они, кажется, появляются, когда мои типы объявляются в самозапускающихся анонимных функциях.В этом нет ничего экзотического, но если я уберу самовыполняющиеся функции, объявления типов, похоже, будут работать (по крайней мере, в этом простом тесте).

Я не уверен, что с моим кодом что-то не таканнотации или если в коде есть что-то недопустимое, но я думаю, что это все кошерный и стандартный способ модуляции API.

Следующий тестовый код создает пространство имен (просто старый старый объект JS) и присоединяетenum (литерал объекта) и функция к нему.

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

Выглядит хорошо, верно?Ошибки компиляции закрытия:

[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.

Ответы [ 4 ]

3 голосов
/ 09 марта 2011

В вашем примере аргументу "mynamespace" передается "псевдоним" объекту global mynamespace.Наличие псевдонима (локального пространства имен) для вашего глобального объекта (глобального пространства имен) предотвращает оптимизацию всего дерева под глобальным объектом.Это ПЛОХАЯ идея для Компилятора Закрытия в Расширенном режиме.

Любая функция, определенная в локальной переменной, является изменчивой.Компилятор понятия не имеет (без глубокого анализа потока кода), что локальное «пространство имен» является псевдонимом глобального «пространства имен».Поэтому он не будет автоматически связывать что-либо, что вы определяете в локальной переменной, с псевдонимом объекта.

Надлежащие способы сделать это:

Опция # 1, используя глобальный объектнапрямую:

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

Вариант № 2, используйте псевдоним goog.scope (при условии, что вы используете расширенный режим):

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

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

Обе опции должны дать вам желаемый результат.Однако в настоящее время нет способа сделать то, что вы хотите, через аргумент в закрытии оболочки.

3 голосов
/ 03 марта 2011

Редактировать:

Исходный ответ был полностью отключен.

Это определенно является ошибкой в ​​компиляторе.Я не нашел отчет об ошибке с этой конкретной проблемой, но я нашел два отчета об ошибках, которые, по-видимому, решают проблему, обратную этой проблеме (компилятор должен выдавать предупреждение, но этого не произойдет, если вы не развернете анонимную функцию).

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

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

В любом случае похоже, что анонимные функции бесполезны при использовании с выражениями типов.

1 голос
/ 04 февраля 2013

Компилятор Closure улучшился здесь.Единственное, что вам нужно сделать, чтобы исправить приведенный выше код и распознать его, - объявить пространство имен как @const:

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

Тип распознается.

0 голосов
/ 04 марта 2011

Компилятор Closure не поддерживает локальные имена типов.Имена должны быть глобальными, и внутри функции «mynamespace» есть локальное имя.

...