Typechecker特殊情况

2018-10-31 11:22 更新

有时你可能想要告诉Typechecker是没报错的,继续运行。最常见的情况是当你知道有一个typechecker错误,你不会因为任何原因修复它,但你仍然希望你的代码在运行时清除typechecker错误hh_client...,你想No errors!输出。

有几种方法可以使typechecker沉默。有些人比其他人更注重行动。

HH_FIXME

HH_FIXME是您通常使用的消声器。这意味着临时缓解从typechecker错误的愤怒,所以您可以从类型检查器的角度维护一个无错误的代码库。

语法HH_FIXME是:

/ * HH_FIXME [error#] string comment * / 
<code of code>

从运行时收到的实际错误消息中检索错误代码hh_client。字符串注释可以是任何您想要的,但通常会解释为什么您正在使用HH_FIXME开始。

<?hh // strict

namespace Hack\UserDocumentation\TypeChecker\Special\Examples\HHFixMe;

// This was the function before we went to strict mode and added annotations to
// to the annotating function. It was fine from the typechecker perspective.
/*

function annotating($x) {
  return $x > 5 ? "Hello" : $x;
}

*/

function annotating(?string $x): string {
  return $x === null ? "Hello" : "Bye";
}

function call_annotating(): void {
  /* HH_FIXME[4110] Will make 6 to "6" later */
  annotating(6);
}

function also_call_annotating(): void {
  /* HH_FIXME[4110] Will make true to "true" later */
  annotating(true);
}

/* HH_FIXME[1002] Will move this call to a partial file later */
call_annotating();

Output

Catchable fatal error: Argument 1 to Hack\UserDocumentation\TypeChecker\Special\Examples\HHFixMe\annotating() must be of type ?string, int given in /data/users/joelm/user-documentation/guides/hack/25-typechecker/07-special-examples/hhfixme.php on line 17

假设我们处于部分模式,现在我们要使这个文件严格,但是我们知道,调用站点将受到函数注释的影响,因为我们做了一些可疑的类型转换。我们不想修复它,或者我们不知道如何解决它(尽管你应该在运行时之前修复,因为它现在将是一个运行时错误)。因此,我们适用HH_FIXME于所有受到变更影响的电话网站,以便您或其他人知道他们需要修复。

没有HH_FIXME,你会看到像:

hhfixme.php:21:14,14: Invalid argument (Typing[4110])
  hhfixme.php:15:22,27: This is a string
  hhfixme.php:21:14,14: It is incompatible with an int
hhfixme.php:26:14,17: Invalid argument (Typing[4110])
  hhfixme.php:15:22,27: This is a string
  hhfixme.php:26:14,17: It is incompatible with a bool
hhfixme.php:29:1,15: Remove all toplevel statements except for requires (Parsing[1002])

在这个例子中,你也可以把HH_FIXME注释放在函数本身上,效果相同。但通常最好HH_FIXME放在最具体的块上。

注意:您可以HH_FIXME在单行代码上有多个注释,表示多个Hack错误的沉默。

HH_IGNORE_ERROR

HH_IGNORE_ERROR在技​​术上是一个别名HH_FIXME,但可以用来为任何看你的代码的人提供更好的环境。虽然,HH_FIXME表示将采取一些行动来解决Hack错误,您正在沉默(由于Hack类型检查程序或您的Hack代码中HH_IGNORE_ERROR的错误),指定您故意忽略该错误,并且不打算采取任何行动修复错误。

语法HH_IGNORE_ERROR是:

/* HH_IGNORE_ERROR[error #] string comment */
<block of code>

一个典型的用例HH_IGNORE_ERROR是用于卷起。hh_client --lint例如,如果您正在使用,则可以按照下面所示的方法来抑制短路错误。

<?hh

namespace Hack\UserDocumentation\Typechecker\Special\Examples\HHIE;

class A {
  // Normally if you use hh_client --lint hh_ignore_error.php without
  // the below HH_IGNORE_ERROR suppression comment, you will get a lint
  // error about using the uppercase TRUE.

  /* HH_IGNORE_ERROR[5001] We want to use uppercase TRUE */
  private bool $a = TRUE;
}

UNSAFE

UNSAFE(或同义UNSAFE_BLOCK)也会使Typechecker沉默。但这不是一个被动作的沉默机制。当使用UNSAFE的时候,你基本上是说你知道这个代码块是个问题,而你就是这样离开的。

语法UNSAFE是:

// UNSAFE
<some block of code>
<?hh // strict

namespace Hack\UserDocumentation\TypeChecker\Special\Examples\Unsafe;

// This was the function before we went to strict mode and added annotations to
// to the annotating function. It was fine from the typechecker perspective.
/*

function annotating($x) {
  return $x > 5 ? "Hello" : $x;
}

*/

function annotating(?string $x): string {
  return $x === null ? "Hello" : "Bye";
}

function call_annotating(): void {
  // UNSAFE
  annotating(6);
}

function also_call_annotating(): void {
  // UNSAFE
  annotating(true);
}

/* HH_FIXME[1002] Will move this call to a partial file later */
call_annotating();

Output

Catchable fatal error: Argument 1 to Hack\UserDocumentation\TypeChecker\Special\Examples\Unsafe\annotating() must be of type ?string, int given in /data/users/joelm/user-documentation/guides/hack/25-typechecker/07-special-examples/unsafe.php on line 17

使用类似的例子HH_FIXME,我们用三个替换了两个UNSAFE。为什么不是第三个?那么,UNSAFE没有那么强大HH_FIXME。UNSAFE不能在顶级代码上使用。

尽量不要使用UNSAFE,而是选择HH_FIXME。UNSAFE不太详细和详细HH_FIXME,这可能会导致一个问题,任何人可能想尝试在以后解决问题。

注意:UNSAFE将来可能会被废弃或删除。所以所有新的沉默都应该完成HH_FIXME。

UNSAFE_EXPR

UNSAFE_EXPR类似于UNSAFE,除了在单个表达式而不是整个代码块上关闭类型检查器。

其语法UNSAFE_EXPR是:

/ * UNSAFE_EXPR * / <expression>

例如,

$ foo = / * UNSAFE_EXPR * / $ bar :: baz();

这是一个有点复杂的例子,显示了使用UNSAFE_EXPR。你可能不想在现实世界中做到这一点,但是希望能够直接得到希望。

<?hh

namespace Hack\UserDocumentation\Typechecker\Special\Examples\UnsafeExpr;

function foo(string $num): int {
  // Without UNSAFE_EXPR, couldn't add stringy number to a number and then
  // return that result later.
  $x = /* UNSAFE_EXPR */ $num + 2;
  echo "More statements here...\n";
  return $x;
}

function run(): void {
  var_dump(foo("1"));
}

run();

Output

More statements here...
int(3)

注意/* */风格评论而UNSAFE_EXPR不是//for UNSAFE。这是很重要的,因为// UNSAFE_EXPR将会被解析为// UNSAFE,并可能给您带来意想不到的结果。

这是一个关于动态属性访问的更真实的示例。在Hack的严格模式下,不允许动态访问属性。你可以UNSAFE_EXPR用来解决这个问题。

<?hh //strict

namespace Hack\UserDocumentation\Typechecker\Special\Examples\UnsafeDP;

class Ranking {
  public function __construct(
    protected int $first,
    protected int $second,
    protected int $third,
  ) {}

  public function copyFields(Ranking $from): Ranking {
    foreach (['first', 'second', 'third'] as $field) {
      /* UNSAFE_EXPR */ $this->$field = $from->$field;
    }
    return $this;
  }
}

/*
Without the UNSAFE_EXPR, you would get an error like this from the typechecker.

unsafe_expr_dynamic_prop.php:14:14,19: Dynamic method call (Naming[2011])
*/


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号