如何为此类定义 Google Closure Compiler externs

如何解决如何为此类定义 Google Closure Compiler externs

我有以下 JavaScript 类定义,它可以正常工作,并且我使用 Google Closure Compiler 进行编译:

class State {
  constructor(x,y,z,rotationX,rotationY) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.rotationX = rotationX;
    this.rotationY = rotationY;
  }

  set matrix(value) {
    // Magic
  }

  get matrix() {
    // More magic
  }

  set red(value) {
    this.setAttribute(attributeRed,value)
  }

  get red() {
    return this.getAttribute(attributeRed);;
  }

  static fromUrlSearchParams(searchParams) {
    return new State(parseInt  (searchParams.get("x"),10),parseInt  (searchParams.get("y"),parseInt  (searchParams.get("z"),parseFloat(searchParams.get("rotationX")),parseFloat(searchParams.get("rotationY")));
  }

  toUrlSearchParams() {
    let searchParams = new URLSearchParams();
    searchParams.set("x",this.red);
    searchParams.set("y",this.green);
    searchParams.set("z",this.blue);
    searchParams.set("rotationX",this.pitch);
    searchParams.set("rotationY",this.yaw);
    return searchParams;
  }
}

这个类型是我代码的公共接口的一部分,这意味着我必须阻止闭包编译器重命名它的符号。我正在编写一个 externs 文件,我使用 --externs 开关将其传递给闭包编译器。这是我到目前为止所拥有的:

State = class {
  /**
   * @constructor
   * @param {number} x
   * @param {number} y
   * @param {number} z
   * @param {number} rotationX
   * @param {number} rotationY
   */
  constructor(x,rotationY) {
    /** @type {number} */
    this.x = x;
    /** @type {number} */
    this.y = y;
    /** @type {number} */
    this.z = z;
    /** @type {number} */
    this.rotationX = rotationX;
    /** @type {number} */
    this.rotationY = rotationY;
  }

  // Insert property export here. If you just knew how...

  /** @return {State} */
  static fromUrlSearchParams(searchParams) {}

  /** @return {URLSearchParams} */
  toUrlSearchParams() {}
};

我在完成那个 externs 文件时遇到了三个问题:

  1. 构造函数的参数(xyzrotationXrotationY)被重命名。我需要做些什么来防止这种情况发生?
  2. static 方法 fromUrlSearchParams(searchParams) 被编译器删除,因为它得出的结论是它是死代码,因为它没有在已编译的代码内部使用。如何导出该 static 方法
  3. 如何将 matrix 属性标记为公共接口的一部分?

编辑:

在这个问题上花费了几个小时后,阅读了我能找到的所有文档,在 GitHub 上抓取文件,测试各种在线 externs 生成器,并获得了《Closure - The Definitive Guide》一书的副本"问题还是没有解决

Closure Compiler 文档已经存在十多年了,除了最基本的示例之外,它对所有内容仍然毫无用处。你一定是在逗我。

这是我目前尝试过的:

class State {
  /**
   * @constructor
   * @param {number} x
   * @param {number} y
   * @param {number} z
   * @param {number} rotationX
   * @param {number} rotationY
   */
  constructor(x,rotationY) {
    /** @type {number} */
    this.x = x;
    /** @type {number} */
    this.y = y;
    /** @type {number} */
    this.z = z;
    /** @type {number} */
    this.rotationX = rotationX;
    /** @type {number} */
    this.rotationY = rotationY;
  }

  /**
   * @nocollapse
   * @param {URLSearchParams} searchParams
   * @return {State}
   */
  static fromUrlSearchParams(searchParams) {}

  /** @return {URLSearchParams} */
  toUrlSearchParams() {}
};

与原始文件的不同之处在于使用 class State { 而不是 State = class {。有趣的是,这会导致以下错误消息:

ERROR - [JSC_BLOCK_ScopED_DECL_MULTIPLY_DECLARED_ERROR] Duplicate let / const / class / function declaration in the same scope is not allowed.

不知道为什么这会有所作为,但无论如何,让我们继续前进。下一次尝试:

/**
 * @constructor
 * @param {number} x
 * @param {number} y
 * @param {number} z
 * @param {number} rotationX
 * @param {number} rotationX
 */
var State = {};

/** @type {number} */
State.prototype.x;

/** @type {number} */
State.prototype.y;

/** @type {number} */
State.prototype.z;

/** @type {number} */
State.prototype.rotationX;

/** @type {number} */
State.prototype.rotationX;

/**
 * @nocollapse
 * @param {URLSearchParams} searchParams
 * @return {State}
 */
State.fromUrlSearchParams = function(searchParams) {};

/** @return {URLSearchParams} */
State.prototype.toUrlSearchParams = function() {};

使用该代码运行它会导致

ERROR - [JSC_VAR_MULTIPLY_DECLARED_ERROR] Variable ColorCubeState declared more than once. First occurrence: blabla.js

class State {
      ^^^^^

好吧,我们又来了。如果我传递源文件和外部文件,为什么编译器会声明它已经定义,这对我来说是个谜。一个定义它,另一个注释它,或者你会这么认为。

没有任何尝试可以避免静态方法被编译器删除

在使用我的代码构建和调试编译器之后,我看不到任何其他可以尝试的东西。幸运的是,这个问题有一个有保证的解决方案:只需不使用 Google Closure Compiler。

解决方法

我不是这方面的专家,但这里有一些事情可以尝试。也可以看看 https://github.com/google/closure-compiler/wiki/JS-Modules

在文件末尾,您可以尝试添加

出口 = 状态。

您可能还需要在顶部添加:

goog.module('State');

  1. 为什么需要防止构造函数的参数被重命名?这些在构造函数之外是不可见的,所以应该没有问题。

  2. 试试这个:

goog.exportSymbol('fromUrlSearchParams',fromUrlSearchParams);

  1. 编译器可能不支持 JavaScript getter 和 setter 属性。看到这个 https://google.github.io/styleguide/jsguide.html#features-classes-getters-and-setters
,

以下有效:

输入文件:

"use strict";

const attributeX         = "x";
const attributeY         = "y";
const attributeZ         = "z";
const attributeRotationX = "rotationX"
const attributeRotationY = "rotationY";

/** @implements {StateInterface} */
globalThis["State"] = class {
  constructor(x,y,z,rotationX,rotationY) {
    this.x         = x;
    this.y         = y;
    this.z         = z;
    this.rotationX = rotationX;
    this.rotationY = rotationY;
  }

  /**
   * @nocollapse
   * @suppress {checkTypes}
   */
  static "fromUrlSearchParams"(searchParams) {
    return new globalThis["State"](parseInt  (searchParams.get(attributeX),10),parseInt  (searchParams.get(attributeY),parseInt  (searchParams.get(attributeZ),parseFloat(searchParams.get(attributeRotationX)),parseFloat(searchParams.get(attributeRotationY)));
  }

  toUrlSearchParams() {
    let searchParams = new URLSearchParams();
    searchParams.set(attributeX,this.x        .toString(10));
    searchParams.set(attributeY,this.y        .toString(10));
    searchParams.set(attributeZ,this.z        .toString(10));
    searchParams.set(attributeRotationX,this.rotationX.toString(10));
    searchParams.set(attributeRotationY,this.rotationY.toString(10));
    return searchParams;
  }
}

外部文件:

/**
 * @fileoverview
 * @externs
 */

/** @interface */
class StateInterface {
  /**
   * @param {number} x
   * @param {number} y
   * @param {number} z
   * @param {number} rotationX
   * @param {number} rotationY
   */
  constructor(x,rotationY) {
    /** @type {number} */
    this.x = x;
    /** @type {number} */
    this.y = y;
    /** @type {number} */
    this.z = z;
    /** @type {number} */
    this.rotationX = rotationX;
    /** @type {number} */
    this.rotationY = rotationY;
  }

  /**
   * @param {URLSearchParams} searchParams
   * @return {StateInterface}
   */
  static fromUrlSearchParams(searchParams) {}

  /** @return {URLSearchParams} */
  toUrlSearchParams() {}
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?