Typechecker特殊情況

2018-10-31 11:22 更新

有時你可能想要告訴Typechecker是沒報錯的,繼續(xù)運行。最常見的情況是當你知道有一個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

假設我們處于部分模式,現(xiàn)在我們要使這個文件嚴格,但是我們知道,調用站點將受到函數(shù)注釋的影響,因為我們做了一些可疑的類型轉換。我們不想修復它,或者我們不知道如何解決它(盡管你應該在運行時之前修復,因為它現(xiàn)在將是一個運行時錯誤)。因此,我們適用HH_FIXME于所有受到變更影響的電話網(wǎng)站,以便您或其他人知道他們需要修復。

沒有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注釋放在函數(shù)本身上,效果相同。但通常最好HH_FIXME放在最具體的塊上。

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

HH_IGNORE_ERROR

HH_IGNORE_ERROR在技??術上是一個別名HH_FIXME,但可以用來為任何看你的代碼的人提供更好的環(huán)境。雖然,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。你可能不想在現(xià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)

注意/* */風格評論而UNSAFE_EXPR不是//for UNSAFE。這是很重要的,因為// UNSAFE_EXPR將會被解析為// UNSAFE,并可能給您帶來意想不到的結果。

這是一個關于動態(tài)屬性訪問的更真實的示例。在Hack的嚴格模式下,不允許動態(tài)訪問屬性。你可以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

公眾號
微信公眾號

編程獅公眾號