有時(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是您通常使用的消聲器。這意味著臨時(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在技??術(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_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,除了在單個(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])
*/
更多建議: