Typechecker特殊情況

2018-10-31 11:22 更新

有時(shí)你可能想要告訴Typechecker是沒(méi)報(bào)錯(cuò)的,繼續(xù)運(yùn)行。最常見(jiàn)的情況是當(dāng)你知道有一個(gè)typechecker錯(cuò)誤,你不會(huì)因?yàn)槿魏卧蛐迯?fù)它,但你仍然希望你的代碼在運(yùn)行時(shí)清除typechecker錯(cuò)誤hh_client...,你想No errors!輸出。

有幾種方法可以使typechecker沉默。有些人比其他人更注重行動(dòng)。

HH_FIXME

HH_FIXME是您通常使用的消聲器。這意味著臨時(shí)緩解從typechecker錯(cuò)誤的憤怒,所以您可以從類型檢查器的角度維護(hù)一個(gè)無(wú)錯(cuò)誤的代碼庫(kù)。

語(yǔ)法HH_FIXME是:

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

從運(yùn)行時(shí)收到的實(shí)際錯(cuò)誤消息中檢索錯(cuò)誤代碼hh_client。字符串注釋可以是任何您想要的,但通常會(huì)解釋為什么您正在使用HH_FIXME開(kāi)始。

<?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

假設(shè)我們處于部分模式,現(xiàn)在我們要使這個(gè)文件嚴(yán)格,但是我們知道,調(diào)用站點(diǎn)將受到函數(shù)注釋的影響,因?yàn)槲覀冏隽艘恍┛梢傻念愋娃D(zhuǎn)換。我們不想修復(fù)它,或者我們不知道如何解決它(盡管你應(yīng)該在運(yùn)行時(shí)之前修復(fù),因?yàn)樗F(xiàn)在將是一個(gè)運(yùn)行時(shí)錯(cuò)誤)。因此,我們適用HH_FIXME于所有受到變更影響的電話網(wǎng)站,以便您或其他人知道他們需要修復(fù)。

沒(méi)有HH_FIXME,你會(huì)看到像:

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

在這個(gè)例子中,你也可以把HH_FIXME注釋放在函數(shù)本身上,效果相同。但通常最好HH_FIXME放在最具體的塊上。

注意:您可以HH_FIXME在單行代碼上有多個(gè)注釋,表示多個(gè)Hack錯(cuò)誤的沉默。

HH_IGNORE_ERROR

HH_IGNORE_ERROR在技??術(shù)上是一個(gè)別名HH_FIXME,但可以用來(lái)為任何看你的代碼的人提供更好的環(huán)境。雖然,HH_FIXME表示將采取一些行動(dòng)來(lái)解決Hack錯(cuò)誤,您正在沉默(由于Hack類型檢查程序或您的Hack代碼中HH_IGNORE_ERROR的錯(cuò)誤),指定您故意忽略該錯(cuò)誤,并且不打算采取任何行動(dòng)修復(fù)錯(cuò)誤。

語(yǔ)法HH_IGNORE_ERROR是:

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

一個(gè)典型的用例HH_IGNORE_ERROR是用于卷起。hh_client --lint例如,如果您正在使用,則可以按照下面所示的方法來(lái)抑制短路錯(cuò)誤。

<?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)也會(huì)使Typechecker沉默。但這不是一個(gè)被動(dòng)作的沉默機(jī)制。當(dāng)使用UNSAFE的時(shí)候,你基本上是說(shuō)你知道這個(gè)代碼塊是個(gè)問(wèn)題,而你就是這樣離開(kāi)的。

語(yǔ)法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,我們用三個(gè)替換了兩個(gè)UNSAFE。為什么不是第三個(gè)?那么,UNSAFE沒(méi)有那么強(qiáng)大HH_FIXME。UNSAFE不能在頂級(jí)代碼上使用。

盡量不要使用UNSAFE,而是選擇HH_FIXME。UNSAFE不太詳細(xì)和詳細(xì)HH_FIXME,這可能會(huì)導(dǎo)致一個(gè)問(wèn)題,任何人可能想嘗試在以后解決問(wèn)題。

注意:UNSAFE將來(lái)可能會(huì)被廢棄或刪除。所以所有新的沉默都應(yīng)該完成HH_FIXME。

UNSAFE_EXPR

UNSAFE_EXPR類似于UNSAFE,除了在單個(gè)表達(dá)式而不是整個(gè)代碼塊上關(guān)閉類型檢查器。

其語(yǔ)法UNSAFE_EXPR是:

/ * UNSAFE_EXPR * / <expression>

例如,

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

這是一個(gè)有點(diǎn)復(fù)雜的例子,顯示了使用UNSAFE_EXPR。你可能不想在現(xiàn)實(shí)世界中做到這一點(diǎn),但是希望能夠直接得到希望。

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

注意/* */風(fēng)格評(píng)論而UNSAFE_EXPR不是//for UNSAFE。這是很重要的,因?yàn)?/ UNSAFE_EXPR將會(huì)被解析為// UNSAFE,并可能給您帶來(lái)意想不到的結(jié)果。

這是一個(gè)關(guān)于動(dòng)態(tài)屬性訪問(wèn)的更真實(shí)的示例。在Hack的嚴(yán)格模式下,不允許動(dòng)態(tài)訪問(wèn)屬性。你可以UNSAFE_EXPR用來(lái)解決這個(gè)問(wèn)題。

<?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])
*/


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)