2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
10 /** Module consisting of the special names known to the typechecker */
14 pub const PARENT: &str = "parent";
16 pub const STATIC: &str = "static";
18 pub const SELF: &str = "self";
20 pub const UNKNOWN: &str = "\\*Unknown*";
22 /* Used for dynamic classnames, e.g. new $foo(); */
24 pub const AWAITABLE: &str = "\\HH\\Awaitable";
26 pub const GENERATOR: &str = "\\Generator";
28 pub const ASYNC_GENERATOR: &str = "\\HH\\AsyncGenerator";
30 pub const FORMAT_STRING: &str = "\\FormatString";
32 pub const HH_FORMAT_STRING: &str = "\\HH\\FormatString";
34 pub fn is_format_string(x: &str) -> bool {
36 FORMAT_STRING | HH_FORMAT_STRING => true,
41 pub const HH_BUILTIN_ENUM: &str = "\\HH\\BuiltinEnum";
43 pub const THROWABLE: &str = "\\Throwable";
45 pub const STD_CLASS: &str = "\\stdClass";
47 pub const DATE_TIME: &str = "\\DateTime";
49 pub const DATE_TIME_IMMUTABLE: &str = "\\DateTimeImmutable";
51 pub const ASYNC_ITERATOR: &str = "\\HH\\AsyncIterator";
53 pub const ASYNC_KEYED_ITERATOR: &str = "\\HH\\AsyncKeyedIterator";
55 pub const STRINGISH: &str = "\\Stringish";
57 pub const XHP_CHILD: &str = "\\XHPChild";
59 pub const IMEMOIZE_PARAM: &str = "\\HH\\IMemoizeParam";
61 pub const CLASS_NAME: &str = "\\HH\\classname";
63 pub const TYPE_NAME: &str = "\\HH\\typename";
65 pub const IDISPOSABLE: &str = "\\IDisposable";
67 pub const IASYNC_DISPOSABLE: &str = "\\IAsyncDisposable";
71 /* concrete classes */
72 pub const VECTOR: &str = "\\HH\\Vector";
74 pub const IMM_VECTOR: &str = "\\HH\\ImmVector";
76 pub const SET: &str = "\\HH\\Set";
78 pub const IMM_SET: &str = "\\HH\\ImmSet";
80 pub const MAP: &str = "\\HH\\Map";
82 pub const IMM_MAP: &str = "\\HH\\ImmMap";
84 pub const PAIR: &str = "\\HH\\Pair";
87 pub const CONTAINER: &str = "\\HH\\Container";
89 pub const KEYED_CONTAINER: &str = "\\HH\\KeyedContainer";
91 pub const TRAVERSABLE: &str = "\\HH\\Traversable";
93 pub const KEYED_TRAVERSABLE: &str = "\\HH\\KeyedTraversable";
95 pub const COLLECTION: &str = "\\Collection";
97 pub const CONST_VECTOR: &str = "\\ConstVector";
99 pub const CONST_MAP: &str = "\\ConstMap";
101 pub const CONST_COLLECTION: &str = "\\ConstCollection";
103 pub const DICT: &str = "\\HH\\dict";
105 pub const VEC: &str = "\\HH\\vec";
107 pub const KEYSET: &str = "\\HH\\keyset";
112 use lazy_static::lazy_static;
113 use std::collections::HashSet;
115 pub const M_CLASS: &str = "class";
117 pub const __CONSTRUCT: &str = "__construct";
119 pub const __DESTRUCT: &str = "__destruct";
121 pub const __CALL: &str = "__call";
123 pub const __CALL_STATIC: &str = "__callStatic";
125 pub const __CLONE: &str = "__clone";
127 pub const __DEBUG_INFO: &str = "__debugInfo";
129 pub const __DISPOSE: &str = "__dispose";
131 pub const __DISPOSE_ASYNC: &str = "__disposeAsync";
133 pub const __GET: &str = "__get";
135 pub const __INVOKE: &str = "__invoke";
137 pub const __ISSET: &str = "__isset";
139 pub const __SET: &str = "__set";
141 pub const __SET_STATE: &str = "__set_state";
143 pub const __SLEEP: &str = "__sleep";
145 pub const __TO_STRING: &str = "__toString";
147 pub const __UNSET: &str = "__unset";
149 pub const __WAKEUP: &str = "__wakeup";
152 static ref AS_SET: HashSet<&'static str> = vec![
174 pub static ref AS_LOWERCASE_SET: HashSet<String> = {
177 .fold(HashSet::<String>::new(), |mut set, special_name| {
178 set.insert(special_name.to_ascii_lowercase());
184 /* Any data- or aria- attribute is always valid, even if it is not declared
185 * for a given XHP element */
186 pub fn is_special_xhp_attribute(s: &str) -> bool {
189 ":data-" | ":aria-" => true,
195 pub mod user_attributes {
197 use lazy_static::lazy_static;
198 use std::collections::HashSet;
200 pub const OVERRIDE: &str = "__Override";
202 pub const CONSISTENT_CONSTRUCT: &str = "__ConsistentConstruct";
204 pub const CONST: &str = "__Const";
206 pub const DEPRECATED: &str = "__Deprecated";
208 pub const ENTRY_POINT: &str = "__EntryPoint";
210 pub const MEMOIZE: &str = "__Memoize";
212 pub const MEMOIZE_LSB: &str = "__MemoizeLSB";
214 pub const PHP_STD_LIB: &str = "__PHPStdLib";
216 pub const HIPHOP_SPECIFIC: &str = "__HipHopSpecific";
218 pub const ACCEPT_DISPOSABLE: &str = "__AcceptDisposable";
220 pub const RETURN_DISPOSABLE: &str = "__ReturnDisposable";
222 pub const REACTIVE: &str = "__Rx";
224 pub const LOCAL_REACTIVE: &str = "__RxLocal";
226 pub const SHALLOW_REACTIVE: &str = "__RxShallow";
228 pub const MUTABLE: &str = "__Mutable";
230 pub const MUTABLE_RETURN: &str = "__MutableReturn";
232 pub const ONLY_RX_IF_IMPL: &str = "__OnlyRxIfImpl";
234 pub const PROBABILISTIC_MODEL: &str = "__PPL";
236 pub const LSB: &str = "__LSB";
238 pub const AT_MOST_RX_AS_FUNC: &str = "__AtMostRxAsFunc";
240 pub const AT_MOST_RX_AS_ARGS: &str = "__AtMostRxAsArgs";
242 pub const SEALED: &str = "__Sealed";
244 pub const RETURNS_VOID_TO_RX: &str = "__ReturnsVoidToRx";
246 pub const MAYBE_MUTABLE: &str = "__MaybeMutable";
248 pub const LATE_INIT: &str = "__LateInit";
250 pub const OWNED_MUTABLE: &str = "__OwnedMutable";
252 pub const NON_RX: &str = "__NonRx";
254 pub const NEWABLE: &str = "__Newable";
256 pub const ENFORCEABLE: &str = "__Enforceable";
258 pub const EXPLICIT: &str = "__Explicit";
260 pub const SOFT: &str = "__Soft";
262 pub const WARN: &str = "__Warn";
264 pub const MOCK_CLASS: &str = "__MockClass";
266 pub const PROVENANCE_SKIP_FRAME: &str = "__ProvenanceSkipFrame";
268 pub const DYNAMICALLY_CALLABLE: &str = "__DynamicallyCallable";
270 pub const DYNAMICALLY_CONSTRUCTIBLE: &str = "__DynamicallyConstructible";
272 pub const REIFIABLE: &str = "__Reifiable";
274 pub const NEVER_INLINE: &str = "__NEVER_INLINE";
277 static ref AS_SET: HashSet<&'static str> = vec![
279 CONSISTENT_CONSTRUCT,
311 PROVENANCE_SKIP_FRAME,
312 DYNAMICALLY_CALLABLE,
313 DYNAMICALLY_CONSTRUCTIBLE,
322 pub fn is_memoized(name: &str) -> bool {
323 name == MEMOIZE || name == MEMOIZE_LSB
326 // TODO(hrust) these should probably be added to the above map/fields, too
328 pub fn is_native(name: &str) -> bool {
332 pub fn is_foldable(name: &str) -> bool {
333 name == "__IsFoldable"
336 pub fn is_meth_caller(name: &str) -> bool {
337 name == "__MethCaller"
341 pub mod attribute_kinds {
342 use lazy_static::lazy_static;
343 use std::collections::HashMap;
345 pub const CLS: &str = "\\HH\\ClassAttribute";
347 pub const ENUM: &str = "\\HH\\EnumAttribute";
349 pub const TYPE_ALIAS: &str = "\\HH\\TypeAliasAttribute";
351 pub const FN: &str = "\\HH\\FunctionAttribute";
353 pub const MTHD: &str = "\\HH\\MethodAttribute";
355 pub const INST_PROPERTY: &str = "\\HH\\InstancePropertyAttribute";
357 pub const STATIC_PROPERTY: &str = "\\HH\\StaticPropertyAttribute";
359 pub const PARAMETER: &str = "\\HH\\ParameterAttribute";
361 pub const TYPE_PARAM: &str = "\\HH\\TypeParameterAttribute";
363 pub const FILE: &str = "\\HH\\FileAttribute";
365 pub const TYPE_CONST: &str = "\\HH\\TypeConstantAttribute";
368 pub static ref PLAIN_ENGLISH_MAP: HashMap<&'static str, &'static str> = [
371 (TYPE_ALIAS, "a typealias"),
374 (INST_PROPERTY, "an instance property"),
375 (STATIC_PROPERTY, "a static property"),
376 (PARAMETER, "a parameter"),
377 (TYPE_PARAM, "a type parameter"),
379 (TYPE_CONST, "a type pub constant")
387 /* Tested before \\-prepending name-canonicalization */
388 pub mod special_functions {
389 pub const TUPLE: &str = "tuple"; /* pseudo-function */
391 pub const ECHO: &str = "echo"; /* pseudo-function */
393 pub const ASSERT_: &str = "assert";
395 pub const INVARIANT: &str = "invariant";
397 pub const INVARIANT_VIOLATION: &str = "invariant_violation";
399 pub const FUN_: &str = "fun";
401 pub const INST_METH: &str = "inst_meth";
403 pub const CLASS_METH: &str = "class_meth";
405 pub const METH_CALLER: &str = "meth_caller";
407 pub const CALL_USER_FUNC: &str = "call_user_func";
409 pub const AUTOLOAD: &str = "__autoload";
411 pub const CLONE: &str = "__clone";
414 pub mod special_idents {
415 pub const THIS: &str = "$this";
417 pub const PLACEHOLDER: &str = "$_";
419 pub const DOLLAR_DOLLAR: &str = "$$";
421 /* Intentionally using an invalid variable name to ensure it's translated */
422 pub const TMP_VAR_PREFIX: &str = "__tmp$";
424 pub fn is_tmp_var(name: &str) -> bool {
425 name.len() > 6 && &name[..6] == TMP_VAR_PREFIX
428 pub fn assert_tmp_var(name: &str) {
429 assert!(is_tmp_var(name))
433 pub mod pseudo_functions {
434 use lazy_static::lazy_static;
436 pub const ISSET: &str = "\\isset";
438 pub const UNSET: &str = "\\unset";
440 pub const HH_SHOW: &str = "\\hh_show";
442 pub const HH_SHOW_ENV: &str = "\\hh_show_env";
444 pub const HH_LOG_LEVEL: &str = "\\hh_log_level";
446 pub const HH_FORCE_SOLVE: &str = "\\hh_force_solve";
448 pub const HH_LOOP_FOREVER: &str = "\\hh_loop_forever";
450 pub const ASSERT: &str = "\\assert";
452 pub const ECHO: &str = "\\echo";
454 pub const EXIT: &str = "\\exit";
456 pub const DIE: &str = "\\die";
459 pub static ref ALL_PSEUDO_FUNCTIONS: Vec<&'static str> = vec![
475 pub mod std_lib_functions {
476 pub const IS_ARRAY: &str = "\\is_array";
478 pub const IS_NULL: &str = "\\is_null";
480 pub const GET_CLASS: &str = "\\get_class";
482 pub const ARRAY_FILTER: &str = "\\array_filter";
484 pub const ARRAY_MAP: &str = "\\array_map";
486 pub const TYPE_STRUCTURE: &str = "\\HH\\type_structure";
488 pub const MARK_LEGACY_HACK_ARRAY: &str = "\\HH\\mark_legacy_hack_array";
492 use lazy_static::lazy_static;
493 use std::collections::HashSet;
495 pub const NULL: &str = "null";
497 pub const VOID: &str = "void";
499 pub const RESOURCE: &str = "resource";
501 pub const NUM: &str = "num";
503 pub const ARRAYKEY: &str = "arraykey";
505 pub const NORETURN: &str = "noreturn";
507 pub const MIXED: &str = "mixed";
509 pub const NONNULL: &str = "nonnull";
511 pub const THIS: &str = "this";
513 pub const DYNAMIC: &str = "dynamic";
515 pub const NOTHING: &str = "nothing";
517 pub const INT: &str = "int";
519 pub const BOOL: &str = "bool";
521 pub const FLOAT: &str = "float";
523 pub const STRING: &str = "string";
525 pub const ARRAY: &str = "array";
527 pub const DARRAY: &str = "darray";
529 pub const VARRAY: &str = "varray";
531 pub const VARRAY_OR_DARRAY: &str = "varray_or_darray";
533 pub const CALLABLE: &str = "callable";
535 pub const OBJECT_CAST: &str = "object";
537 pub const WILDCARD: &str = "_";
540 static ref RESERVED_GLOBAL_NAMES: HashSet<&'static str> = vec![
543 crate::classes::SELF,
544 crate::classes::PARENT
550 pub fn is_reserved_global_name(x: &str) -> bool {
551 RESERVED_GLOBAL_NAMES.contains(x)
555 static ref RESERVED_HH_NAMES: HashSet<&'static str> = vec![
556 VOID, NORETURN, INT, BOOL, FLOAT, NUM, STRING, RESOURCE, MIXED, ARRAY, ARRAYKEY,
557 DYNAMIC, WILDCARD, NONNULL, NOTHING, THIS
563 pub fn is_reserved_hh_name(x: &str) -> bool {
564 RESERVED_HH_NAMES.contains(x)
567 // This function checks if this is a namespace of the "(not HH)\\(...)*\\(reserved_name)"
568 pub fn is_namespace_with_reserved_hh_name(x: &str) -> bool {
569 // This splits the string into its namespaces
570 fn unqualify(x: &str) -> (Vec<&str>, &str) {
571 let mut as_list = x.split("\\").collect::<Vec<&str>>();
572 // Retain if not empty
573 as_list.retain(|&split| match split {
577 let last_split = match as_list.pop() {
582 (as_list, last_split)
585 // This returns a bool whether or not the list is just the string "HH"
586 fn is_hh(qualifier: &Vec<&str>) -> bool {
587 match qualifier.len() {
588 1 => qualifier[0] == "HH",
592 let (qualifier, name) = unqualify(x);
593 !is_hh(&qualifier) && !qualifier.is_empty() && is_reserved_hh_name(name)
597 pub mod pseudo_consts {
598 use lazy_static::lazy_static;
599 use std::collections::HashSet;
601 pub const G__LINE__: &str = "\\__LINE__";
603 pub const G__CLASS__: &str = "\\__CLASS__";
605 pub const G__TRAIT__: &str = "\\__TRAIT__";
607 pub const G__FILE__: &str = "\\__FILE__";
609 pub const G__DIR__: &str = "\\__DIR__";
611 pub const G__FUNCTION__: &str = "\\__FUNCTION__";
613 pub const G__METHOD__: &str = "\\__METHOD__";
615 pub const G__NAMESPACE__: &str = "\\__NAMESPACE__";
617 pub const G__COMPILER_FRONTEND__: &str = "\\__COMPILER_FRONTEND__";
619 pub const G__FUNCTION_CREDENTIAL__: &str = "\\__FUNCTION_CREDENTIAL__";
622 static ref ALL_PSEUDO_CONSTS: Vec<&'static str> = vec![
631 G__COMPILER_FRONTEND__,
632 G__FUNCTION_CREDENTIAL__
634 static ref PSEUDO_SET: HashSet<&'static str> =
635 { ALL_PSEUDO_CONSTS.iter().cloned().collect() };
638 pub fn is_pseudo_const(x: &str) -> bool {
639 PSEUDO_SET.contains(x)
644 pub const ENUM: &str = "\\Enum";
646 pub const UNCHECKED_ENUM: &str = "\\UncheckedEnum";
648 pub const IDX: &str = "\\HH\\idx";
650 pub const TYPE_STRUCTURE: &str = "\\HH\\TypeStructure";
652 pub const INCORRECT_TYPE: &str = "\\HH\\INCORRECT_TYPE";
656 pub const ASIO_VA: &str = "\\HH\\Asio\\va";
658 pub const LIB_TUPLE_FROM_ASYNC: &str = "\\HH\\Lib\\Tuple\\from_async";
660 pub const LIB_TUPLE_GEN: &str = "\\HH\\Lib\\Tuple\\gen";
662 pub const CONTAINS: &str = "\\HH\\Lib\\C\\contains";
664 pub const CONTAINS_KEY: &str = "\\HH\\Lib\\C\\contains_key";
668 pub const FREEZE: &str = "\\HH\\Rx\\freeze";
670 pub const MUTABLE_: &str = "\\HH\\Rx\\mutable";
672 pub const TRAVERSABLE: &str = "\\HH\\Rx\\Traversable";
674 pub const IS_ENABLED: &str = "\\HH\\Rx\\IS_ENABLED";
676 pub const KEYED_TRAVERSABLE: &str = "\\HH\\Rx\\KeyedTraversable";
678 pub const ASYNC_ITERATOR: &str = "\\HH\\Rx\\AsyncIterator";
680 pub const MOVE: &str = "\\HH\\Rx\\move";
684 pub const SHAPES: &str = "\\HH\\Shapes";
686 pub const IDX: &str = "idx";
688 pub const AT: &str = "at";
690 pub const KEY_EXISTS: &str = "keyExists";
692 pub const REMOVE_KEY: &str = "removeKey";
694 pub const TO_ARRAY: &str = "toArray";
696 pub const TO_DICT: &str = "toDict";
699 pub mod superglobals {
700 use lazy_static::lazy_static;
701 use std::collections::HashSet;
702 pub const GLOBALS: &str = "$GLOBALS";
705 static ref SUPERGLOBALS: Vec<&'static str> = vec![
714 static ref SUPERGLOBALS_SET: HashSet<&'static str> = SUPERGLOBALS.iter().cloned().collect();
716 pub fn is_superglobal(x: &str) -> bool {
717 SUPERGLOBALS_SET.contains(x)
719 pub fn is_any_global(x: &str) -> bool {
720 is_superglobal(x) || x == GLOBALS
724 pub mod ppl_functions {
725 use lazy_static::lazy_static;
726 use std::collections::HashSet;
728 static ref ALL_RESERVED: Vec<&'static str> = vec!(
740 static ref ALL_RESERVED_SET: HashSet<&'static str> = ALL_RESERVED.iter().cloned().collect();
742 pub fn is_reserved(x: &str) -> bool {
743 ALL_RESERVED_SET.contains(x)
748 pub const T_PATTERN: &str = "\\HH\\Lib\\Regex\\Pattern";
753 use crate::members::is_special_xhp_attribute;
754 use crate::members::AS_LOWERCASE_SET;
755 use crate::special_idents::is_tmp_var;
756 use crate::typehints::is_namespace_with_reserved_hh_name;
759 fn test_special_idents_is_tmp_var() {
760 assert!(!is_tmp_var("_tmp$Blah"));
761 assert!(!is_tmp_var("__tmp$"));
763 assert!(is_tmp_var("__tmp$Blah"));
767 fn test_members_as_lowercase_set() {
768 assert!(AS_LOWERCASE_SET.contains("__tostring"));
769 assert!(!AS_LOWERCASE_SET.contains("__toString"));
773 fn test_members_is_special_xhp_attribute() {
774 assert!(is_special_xhp_attribute(":data-blahblah"));
775 assert!(is_special_xhp_attribute(":aria-blahblah"));
777 assert!(!is_special_xhp_attribute(":arla-blahblah"));
778 assert!(!is_special_xhp_attribute(":aria"));
782 fn test_typehint_is_namespace_with_reserved_hh_name() {
783 assert!(!is_namespace_with_reserved_hh_name("HH\\void"));
784 assert!(!is_namespace_with_reserved_hh_name("void"));
785 assert!(!is_namespace_with_reserved_hh_name("ReturnType\\Lloyd"));
786 assert!(!is_namespace_with_reserved_hh_name("Lloyd"));
788 assert!(is_namespace_with_reserved_hh_name("Anything\\Else\\void"));