Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 02.09.2013, 22:10
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Разметка для Google closure compiler
/** @namespace foo */
def ('foo') ({
	/**
	 * @constructor
	 */
	__init__: function() {

              // WARNING - Property method never defined
              this.method();
	},
    /** @this {foo} */
	method: function() {
               // WARNING - Bad type annotation. Unknown type namespace
       }
});

 // WARNING - foo never defined
new foo;



Кто-нибудь знает как размечать такие конструкторы для GCC?

Последний раз редактировалось monolithed, 02.09.2013 в 22:30.
Ответить с цитированием
  #2 (permalink)  
Старый 02.09.2013, 23:32
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Он их ломает?

упс. Вижу, ломает.
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.

Последний раз редактировалось Gozar, 02.09.2013 в 23:36.
Ответить с цитированием
  #3 (permalink)  
Старый 03.09.2013, 00:25
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Да много там сюрпризов:

/**
 * @param {Object} object
 * @param {(string|number)} name
 * @param {*} value
 */
var fabric = function(object, name, value) {
    object[name] = value;
};


fabric(Number, 'MAX_INTEGER', 9007199254740991);
// ...

console.log(Number.MAX_INTEGER); // 9007199254740991

// WARNING: JSC_INEXISTENT_PROPERTY: Property MAX_INTEGER never defined on Number at line 14 character 12


Без предварительного экспорта переменных через через опцию --externs=... сыпит ворнингами
Ответить с цитированием
  #4 (permalink)  
Старый 03.09.2013, 09:35
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от monolithed
Разметка для Google closure compiler
боролся я как то с этим, хотя мне больше волновал вопрос с автокомплитом. В итоге вышло примерно так, GCC при этом не плачет и автокомплит работает хорошо:
/**
 * Component является общим предком всех классов компонентов.
 *
 * @author <a href="mailto:spb.piksel@gmail.com">Dmitrii Pakhtinov</a>
 * @requires Class
 * @version 1.0 - 12/20/2012
 */
Class("SP.Component", function() {
  /**
   * Ссылка на родительский компонент
   *
   * @type {SP.Component|null}
   * @private
   */
  var owner = null;
  /**
   * Список дочерних компонентов
   *
   * @type {Array}
   * @private
   */
  var components = [];
  /**
   * @class SP.Component
   */
  return {
    /**
     * Общий предок всех компонентов, каждый компонент обязан наследоватся от этого класса
     *
     * @namespace SP
     * @constructs
     * @constructor
     */
    Component: function() {
        // dummy
    },
    /**
     * Устанавливает или возвращает родительский компонент
     * Для удаления родительского компонента установите значение <b>null</b>
     *
     * Родительский компонент является владельцем компонента и может оперировать
     * свойствами дочернего компонента. Присвоеный компонент является владельцем
     * компонента которому его присвоили и в случае удаления владельца, будут
     * удалены все его подчиненные компоненты, если вы не хотите потерять подчиненные
     * копоненты, позаботьтесь об этом заранее
     *
     * @type {SP.Component|null}
     * @property
     * @public
     * @final
     */
    owner: {
      /**
       * @param {SP.Component|null} component
       */
      set: function(component) {

        // пропускаем только если текущая ссылка на владельца иная и это наследник компонента
        if (component !== owner && (component === null || Class.instanceOf(component, this.__class__))) {

          // удаляем у текущего владельца данный компонент
          if (owner) {
            // если владелец не позволит удалить компонет
            if (owner.onremovecomponent(this) === false) {
              return;
            }
            owner.removeComponent.call(false, this, owner);
          }

          // добавляем владельцу текущий компонент
          if (component) {
            // если компонент не позволит его добавить
            if (component.oninsertcomponent(this) === false) {
              return;
            }
            component.insertComponent.call(false, this, component);
          }

          // меняем ссылку на владельца
          owner = component;
        }
      },

      get: function() {
        return owner;
      }
    },

    /**
     * Добавляет в список дочерний компонент
     *
     * @param {SP.Component} component компонент который будет дочерним
     * @return {Boolean} возвращает <b>true</b> при успешном выполнении, в противном случае <b>false</b>
     * @public
     * @final
     * @see {@link get.components}
     */
    insertComponent: function(component) {

      // Условие для внутреннего использования
      if (this instanceof Boolean && arguments.length > 1) {

        // Добавляем компонент в список
        components[components.length] = component;

        // информируем компонент о том что его добавли владельцу
        component.oninsert(arguments[1]);

      } else if (Class.instanceOf(component, this.__class__)) {
        // Если объект является компонентом пробуем добавить его
        return components.length < (component.owner = this, components.length);
      }

      return false;
    },

    /**
     * Удаляет из списка дочерний компонент
     *
     * @param {SP.Component} component компонент который является дочерним этого компонента
     * @return {Boolean} возвращает <b>true</b> при успешном выполнении, в противном случае <b>false</b>
     * @public
     * @final
     * @see {@link get.components}
     */
    removeComponent: function(component) {

      // Условие для внутреннего использования
      if (this instanceof Boolean && arguments.length > 1) {

        var index = -1;

        if ("indexOf" in components) {
          // новая версия ECMAScript имеет поддержку метода indexOf для массивов
          index = components.indexOf(component);
        } else {
          // для более старой версии ECMAScript
          for(var i = components.length; i--;) {
            if (components[i] === component) {
              index = i;
              break;
            }
          }
        }

        if (index >= 0) {

          // удаляем компонент из стека
          components.splice(index, 1);

          // информируем компонент о том что его удалили из родительского компонента
          component.onremove(arguments[1]);
        }

      } else if (Class.instanceOf(component, this.__class__)) {
        // Если объект является компонентом удаляем у него родителя
        return components.length > (component.owner = null, components.length);
      }

      return false;
    },

    /**
     * Содержит список всех дочерних компонентов
     *
     * @type {Array}
     * @property
     * @public
     * @see {@link insertComponent}
     * @see {@link removeComponent}
     */
    components: {
      get:function() {
        // не будем возвращать ссылку на оригинальный список компонентов, отдаем копию
        return components.slice(0);
      }
    },

    /**
     * Устанавливает или возвращает позицию компонента
     *
     * Если параметр component не задан, то в случае если задан position установит
     * текущий компонент у его владельца на новую позицию, если же параметр position
     * так же не задан, то вернет текущую позицию у владельца.
     *
     * Если компонент не имеет владельца, вернет значение -1
     *
     * @param {SP.Component} [component]
     * @param {Integer} [position]
     * @return {Integer}
     * @public
     */
    componentPosition: function(component, position) {

      // ищем компонент у владельца
      if (typeof component === "number" || !component) {
        return owner ? owner.componentPosition(this, component) : -1;
      }

      var index = -1, length = components.length;

      if ("indexOf" in components) {
        // новая версия ECMAScript имеет поддержку метода indexOf для массивов
        index = components.indexOf(component);
      } else {
        // для более старой версии ECMAScript
        for(var i = components.length; i--;) {
          if (components[i] === component) {
            index = i;
            break;
          }
        }
      }

      // если позиция или компонент не определены, возвращаем текущуюю позицию
      if (typeof position !== "number" || index < 0) {
        return index;
      }

      // попытаемся нормализовать позицию
      while(position < 0 || position >= length) {
        position = position < 0 ? length + position : position >= length ? position - length : position;
      }

      // если текущая позиция не равна новой позиции
      if (index !== position) {

        // удаляем компонент из текущей позиции
        components.splice(index, 1);

        if (position === 0) {
          // вставляем в начало
          components.unshift(component);
        } else if (position === components.length) {
          // вставляем в конец
          components.push(component);
        } else {
          // вставляем где то в середине
          components = components.slice(0, position).concat(component, components.slice(position));
        }

        length = index < position ? position : index;
        index = index < position ? index : position;

        for( ; index <= length; index++ ) {
          components[index].onchangeposition(index);
        }
      }

      // возвращаем позицию компонента
      return position;
    },

    /**
     * Событие страбатывает у владельца в случае если добавляют в него новый компонент
     * Верните <b>false</b> если не хотите что бы в ваш компонент что-то добавляли.
     *
     * @protected
     * @param {SP.Component} component
     */
    oninsertcomponent: function(component) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает у владельца при удалении из него компонента
     * Верните <b>false</b> если не хотите что бы из владельца что-то удаляли
     *
     * @protected
     * @param {SP.Component} component
     */
    onremovecomponent: function(component) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает у компонента в том случае если он был успешно принят владельцем
     *
     * @protected
     * @param {SP.Component} owner
     */
    oninsert: function(owner) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает если компонент успешно был удален владельцем
     *
     * @protected
     * @param {SP.Component} owner
     */
    onremove: function(owner) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает если сменили позицию компонента
     *
     * @protected
     * @param {Integer} position
     */
    onchangeposition: function(position) {
      /* virtual protected */
    }
  }
});
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #5 (permalink)  
Старый 03.09.2013, 09:47
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Может у тебя такие ошибки игнорировались?

Потому что сразу же будет предупреждение:

JSC_TYPE_PARSE_ERROR: Bad type annotation. Unknown type SP.Component at line 12 character 9
* @type {SP.Component|null}


Больше всего меня конечно бесит это:

var global = function() {
    return this;
}();

void function(global) {

    global.foo = 1;

}(global);


Приходится выносить определение глобальной перменной в экстерны.

PS: мой конфиг:

#! /usr/bin/env sh

# Google closure compiler
# [url]http://code.google.com/p/closure-compiler/wiki/Warnings[/url]

timestamp=`date +%s`

compiler=../tools/closure-compiler/build/compiler.jar
output=../cache/static/__init__

java -jar ${compiler} \
	--js=${output}.js \
	--externs=../model/__slot__.js \
	--js_output_file="${output}.${timestamp}.js" \
	--create_source_map="${output}.${timestamp}.json" \
	--summary_detail_level=3 \
	--charset=UTF-8 \
	--language_in=ECMASCRIPT5_STRICT \
	--warning_level=VERBOSE \
	--compilation_level=SIMPLE_OPTIMIZATIONS \
	--formatting=SINGLE_QUOTES \
	--jscomp_error=ambiguousFunctionDecl \
	--jscomp_error=checkDebuggerStatement \
	--jscomp_error=checkRegExp \
	--jscomp_error=checkVars \
	--jscomp_error=const \
	--jscomp_error=constantProperty \
	--jscomp_error=es5Strict \
	--jscomp_error=internetExplorerChecks \
	--jscomp_error=invalidCasts \
	--jscomp_error=missingProperties \
	--jscomp_error=suspiciousCode \
	--jscomp_error=undefinedNames \
	--jscomp_error=undefinedVars \
	--jscomp_warning=uselessCode \
	--jscomp_warning=globalThis \
	--jscomp_warning=externsValidation \
	--jscomp_warning=duplicate \
	--jscomp_warning=deprecated \
	--jscomp_warning=accessControls \
	--jscomp_warning=visibility \
	--jscomp_warning=checkTypes \
	--jscomp_warning=fileoverviewTags \
	--jscomp_warning=nonStandardJsDocs \
	--jscomp_warning=strictModuleDepCheck \
	--jscomp_warning=unknownDefines \
#	--output_wrapper='void function(window){ %output %}(window);' \
#	--source_map_format=DEFAULT \
#	--use_types_for_optimization \
#	--create_name_map_files=true \
#	--print_ast \
#	--print_pass_graph \
#	--print_tree \
Ответить с цитированием
  #6 (permalink)  
Старый 03.09.2013, 10:11
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Если я правильно понял, то тебе нужно продекларировать принадлежность методов к прототипу класса, а это можно сделать с помощью директивы lends, но нужно учесть 2 моменты при работе с ней:
1) В директиве указывается ссылка, а не название конструктора или тип, как в type или param
2) Директива применима только для литералов объекта.

Использование:

/** @constructor */
var MyClass = new Class(function init() {

    this.myMethod();

},  /** @lends {MyClass.prototype} */ {

    myMethod: function () { },
    myMethod2: function () { }
});

new MyClass().myMethod();
__________________
kobezzza
code monkey
Ответить с цитированием
  #7 (permalink)  
Старый 03.09.2013, 10:17
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от monolithed
Потому что сразу же будет предупреждение:
хм.. а что не так я могу настраивать в GCC? Обычно компилю такой командой:
java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js=Component.class.js --js_output_file=Component.class.min.js


Сообщение от monolithed
мой конфиг:
ужс
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #8 (permalink)  
Старый 03.09.2013, 11:23
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Сообщение от devote
жс
Статический анализ, что тут ужасного?
Ответить с цитированием
  #9 (permalink)  
Старый 03.09.2013, 11:45
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Сообщение от kobezzza
сли я правильно понял, то тебе нужно продекларировать принадлежность методов к прототипу класса, а это можно сделать с помощью директивы lends, но нужно учесть 2 моменты при работе с ней
Не совсем так, у меня конструктор создается динамически:

void function() {
     var global = function() {
         return this;
     }();

     var fabric = function(name, value) {
        global[name] = value;
     };

     global.fabric = fabric;
}();

// Как тут сказать что создается конструктор window.foo, а this это ссылка на него ?
fabric('foo', function(name) {
    this[name] = 1;
});

(new foo).prop; // 1



PS: правда такой код успешно компилится, а вот если сделать фабрику конструкторов чуть по сложней, то gcc валит ошибками, что ничего не понимат (


Проблема частично решена, если свойство определено через скобочную нотацию, значит доступ к нему должен быть таким же:

(new foo)['prop']; // 1


Либо экпортировать все переменные заранее, через опцию --externs

Последний раз редактировалось monolithed, 03.09.2013 в 12:17.
Ответить с цитированием
  #10 (permalink)  
Старый 03.09.2013, 22:16
Особый гость
Посмотреть профиль Найти все сообщения от monolithed
 
Регистрация: 02.04.2010
Сообщений: 4,260

Object.defineProperty(Object, 'isObject', {
	value: function(object) {
		return Object.prototype.toString.call(object) === '[object Object]';
	},
	configurable: true,
	enumerable:   false,
	writable:     true
});

Object.isObject({});

// JSC_INEXISTENT_PROPERTY: Property isObject never defined on Object at line 19 character 0
Object.isObject({});
^



Вот как такое победить чтобы не писать Object['isObject']({});?

Последний раз редактировалось monolithed, 03.09.2013 в 22:24.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Решение проблемы кодировок для AJAX и PHP без iconv (cp1251 в AJAX) Serge Ageyev AJAX и COMET 10 24.04.2013 19:48
Что использует google для настройки личной страницы?? m00 Общие вопросы Javascript 3 04.05.2010 17:06
Модуль для работы с модулями JSprog Ваши сайты и скрипты 29 02.09.2009 12:31