remove coroutine keyword
[hiphop-php.git] / hphp / hack / src / parser / rust_parser_errors.rs
blob3741a51dcf7f326fb4cf2d4dbf7f375b1df1717a
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 use itertools::Itertools;
7 use lazy_static::lazy_static;
8 use regex::Regex;
9 use std::collections::{BTreeMap, HashMap, HashSet};
10 use std::str::FromStr;
11 use strum;
12 use strum::IntoEnumIterator;
13 use strum_macros::{Display, EnumIter, EnumString, IntoStaticStr};
15 use naming_special_names_rust as sn;
17 use oxidized::parser_options::ParserOptions;
18 use parser_core_types::{
19     indexed_source_text::IndexedSourceText,
20     lexable_token::LexableToken,
21     positioned_syntax::PositionedSyntax,
22     syntax::{ListItemChildren, Syntax, SyntaxValueType, SyntaxVariant, SyntaxVariant::*},
23     syntax_error::{self as errors, Error, ErrorType, SyntaxError},
24     syntax_trait::SyntaxTrait,
25     syntax_tree::SyntaxTree,
26     token_kind::TokenKind,
29 use hh_autoimport_rust as hh_autoimport;
31 #[derive(Clone, PartialEq, Debug)]
32 struct Location {
33     start_offset: usize,
34     end_offset: usize,
37 #[derive(Clone, PartialEq, Debug)]
38 enum NameKind {
39     NameUse,         // `use` construct
40     NameDef,         // definition e.g. `class` or `trait`
41     NameImplicitUse, // implicit `use` e.g. HH type in type hint
44 enum LvalType {
45     LvalTypeNone,
46     LvalTypeNonFinal,
47     LvalTypeFinal,
48     LvalTypeNonFinalInout,
51 use LvalType::*;
53 enum BinopAllowsAwaitInPositions {
54     BinopAllowAwaitBoth,
55     BinopAllowAwaitLeft,
56     BinopAllowAwaitRight,
57     BinopAllowAwaitNone,
60 #[derive(
61     Clone,
62     Copy,
63     EnumIter,
64     EnumString,
65     Eq,
66     Display,
67     Hash,
68     IntoStaticStr,
69     PartialEq
71 #[strum(serialize_all = "snake_case")]
72 enum UnstableFeatures {
73     UnionIntersectionTypeHints,
74     ClassLevelWhere,
77 use BinopAllowsAwaitInPositions::*;
78 use NameKind::*;
80 #[derive(Clone, Debug)]
81 struct FirstUseOrDef {
82     location: Location,
83     kind: NameKind,
84     name: String,
85     global: bool,
88 #[derive(PartialEq)]
89 enum NamespaceType {
90     Unspecified,
91     Bracketed(Location),
92     Unbracketed(Location),
95 use NamespaceType::*;
97 // TODO: is there a more Rust idiomatic way to write this?
98 #[derive(Clone, Debug)]
99 enum Strmap<X> {
100     YesCase(HashMap<String, X>),
101     NoCase(HashMap<String, X>),
104 impl<X> Strmap<X> {
105     fn mem(&self, k: &str) -> bool {
106         match &self {
107             NoCase(m) => m.contains_key(&k.to_ascii_lowercase()),
108             YesCase(m) => m.contains_key(k),
109         }
110     }
112     fn add(&mut self, k: &str, v: X) {
113         match self {
114             NoCase(m) => m.insert(k.to_ascii_lowercase(), v),
115             YesCase(m) => m.insert(k.to_string(), v),
116         };
117     }
119     fn get(&self, k: &str) -> Option<&X> {
120         match &self {
121             NoCase(m) => m.get(&k.to_ascii_lowercase()),
122             YesCase(m) => m.get(k),
123         }
124     }
126     fn filter<F>(self, f: F) -> Self
127     where
128         F: Fn(&X) -> bool,
129     {
130         match self {
131             NoCase(m) => NoCase(m.into_iter().filter(|(_, x)| f(x)).collect()),
132             YesCase(m) => YesCase(m.into_iter().filter(|(_, x)| f(x)).collect()),
133         }
134     }
136     fn into_iter(self) -> std::collections::hash_map::IntoIter<String, X> {
137         match self {
138             NoCase(m) => m.into_iter(),
139             YesCase(m) => m.into_iter(),
140         }
141     }
144 use crate::Strmap::*;
146 fn empty_trait_require_clauses() -> Strmap<TokenKind> {
147     NoCase(HashMap::new())
150 #[derive(Clone, Debug)]
151 struct UsedNames {
152     classes: Strmap<FirstUseOrDef>,    // NoCase
153     namespaces: Strmap<FirstUseOrDef>, // NoCase
154     functions: Strmap<FirstUseOrDef>,  // NoCase
155     constants: Strmap<FirstUseOrDef>,  // YesCase
156     attributes: Strmap<FirstUseOrDef>, // YesCase
159 impl UsedNames {
160     fn empty() -> Self {
161         Self {
162             classes: NoCase(HashMap::new()),
163             namespaces: NoCase(HashMap::new()),
164             functions: NoCase(HashMap::new()),
165             constants: YesCase(HashMap::new()),
166             attributes: YesCase(HashMap::new()),
167         }
168     }
171 struct Context<'a, Syntax> {
172     pub active_classish: Option<&'a Syntax>,
173     pub active_methodish: Option<&'a Syntax>,
174     pub active_callable: Option<&'a Syntax>,
175     pub active_callable_attr_spec: Option<&'a Syntax>,
176     // true if active callable is reactive if it is a function or method, or there is a reactive
177     // proper ancestor (including lambdas) but not beyond the enclosing function or method
178     pub active_is_rx_or_enclosing_for_lambdas: bool,
179     pub active_const: Option<&'a Syntax>,
180     pub active_unstable_features: HashSet<UnstableFeatures>,
183 // TODO: why can't this be auto-derived?
184 impl<'a, Syntax> std::clone::Clone for Context<'a, Syntax> {
185     fn clone(&self) -> Self {
186         Self {
187             active_classish: self.active_classish,
188             active_methodish: self.active_methodish,
189             active_callable: self.active_callable,
190             active_callable_attr_spec: self.active_callable_attr_spec,
191             active_is_rx_or_enclosing_for_lambdas: self.active_is_rx_or_enclosing_for_lambdas,
192             active_const: self.active_const,
193             active_unstable_features: self.active_unstable_features.clone(),
194         }
195     }
198 struct Env<'a, Syntax, SyntaxTree> {
199     parser_options: ParserOptions,
200     syntax_tree: &'a SyntaxTree,
201     text: IndexedSourceText<'a>,
202     context: Context<'a, Syntax>,
203     hhvm_compat_mode: bool,
204     hhi_mode: bool,
205     codegen: bool,
208 impl<'a, Syntax, SyntaxTree> Env<'a, Syntax, SyntaxTree> {
209     fn is_hhvm_compat(&self) -> bool {
210         self.hhvm_compat_mode
211     }
213     fn is_typechecker(&self) -> bool {
214         !self.codegen
215     }
217     fn is_hhi_mode(&self) -> bool {
218         self.hhi_mode
219     }
222 const GLOBAL_NAMESPACE_NAME: &str = "\\";
224 fn combine_names(n1: &str, n2: &str) -> String {
225     let has_leading_slash = n2.starts_with('\\');
226     let has_trailing_slash = n1.ends_with('\\');
227     match (has_leading_slash, has_trailing_slash) {
228         (true, true) => n1.to_string() + &n2[1..],
229         (false, false) => n1.to_string() + "\\" + n2,
230         _ => n1.to_string() + n2,
231     }
234 fn make_first_use_or_def(
235     is_method: bool,
236     kind: NameKind,
237     location: Location,
238     namespace_name: &str,
239     name: &str,
240 ) -> FirstUseOrDef {
241     let res = FirstUseOrDef {
242         location,
243         kind,
244         name: combine_names(namespace_name, name),
245         global: !is_method && namespace_name == GLOBAL_NAMESPACE_NAME,
246     };
248     res
250 struct ParserErrors<'a, Token, Value, State> {
251     phantom: std::marker::PhantomData<(*const Token, *const Value, *const State)>,
253     env: Env<'a, Syntax<Token, Value>, SyntaxTree<'a, Syntax<Token, Value>, State>>,
254     errors: Vec<SyntaxError>,
255     parents: Vec<&'a Syntax<Token, Value>>,
257     trait_require_clauses: Strmap<TokenKind>,
258     is_in_concurrent_block: bool,
259     names: UsedNames,
260     // Named (not anonymous) namespaces that the current expression is enclosed within.
261     nested_namespaces: Vec<&'a Syntax<Token, Value>>,
262     namespace_type: NamespaceType,
263     namespace_name: String,
266 // TODO: why do we need :'a everywhere?
267 impl<'a, Token: 'a, Value: 'a, State: 'a> ParserErrors<'a, Token, Value, State>
268 where
269     Syntax<Token, Value>: SyntaxTrait,
270     Token: LexableToken<'a> + std::fmt::Debug,
271     Value: SyntaxValueType<Token> + std::fmt::Debug,
272     State: Clone,
274     fn new(
275         env: Env<'a, Syntax<Token, Value>, SyntaxTree<'a, Syntax<Token, Value>, State>>,
276     ) -> Self {
277         Self {
278             env,
279             errors: vec![],
280             parents: vec![],
281             names: UsedNames::empty(),
282             trait_require_clauses: empty_trait_require_clauses(),
283             namespace_name: GLOBAL_NAMESPACE_NAME.to_string(),
284             namespace_type: Unspecified,
285             is_in_concurrent_block: false,
286             nested_namespaces: vec![],
287             phantom: std::marker::PhantomData,
288         }
289     }
291     fn text(&self, node: &'a Syntax<Token, Value>) -> &'a str {
292         node.extract_text(self.env.syntax_tree.text())
293             .expect("<text_extraction_failure>")
294     }
296     fn make_location(s: &'a Syntax<Token, Value>, e: &'a Syntax<Token, Value>) -> Location {
297         let start_offset = Self::start_offset(s);
298         let end_offset = Self::end_offset(e);
299         Location {
300             start_offset,
301             end_offset,
302         }
303     }
305     fn make_location_of_node(n: &'a Syntax<Token, Value>) -> Location {
306         Self::make_location(n, n)
307     }
309     fn start_offset(n: &'a Syntax<Token, Value>) -> usize {
310         // TODO: this logic should be moved to SyntaxTrait::position, when implemented
311         n.leading_start_offset() + n.leading_width()
312     }
314     fn end_offset(n: &'a Syntax<Token, Value>) -> usize {
315         // TODO: this logic should be moved to SyntaxTrait::position, when implemented
316         let w = n.width();
317         n.leading_start_offset() + n.leading_width() + w
318     }
320     fn get_short_name_from_qualified_name<'b>(name: &'b str, alias: &'b str) -> &'b str {
321         if !alias.is_empty() {
322             return alias;
323         }
324         match name.rfind('\\') {
325             Some(i) => &name[i + 1..],
326             None => name,
327         }
328     }
330     // Turns a syntax node into a list of nodes; if it is a separated syntax
331     // list then the separators are filtered from the resulting list.
332     fn syntax_to_list(
333         include_separators: bool,
334         node: &'a Syntax<Token, Value>,
335     ) -> impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>> {
336         use itertools::Either::{Left, Right};
337         use std::iter::{empty, once};
338         let on_list_item = move |x: &'a ListItemChildren<Token, Value>| {
339             if include_separators {
340                 vec![&x.list_item, &x.list_separator].into_iter()
341             } else {
342                 vec![&x.list_item].into_iter()
343             }
344         };
345         match &node.syntax {
346             Missing => Left(Left(empty())),
347             SyntaxList(s) => Left(Right(
348                 s.iter()
349                     .map(move |x| match &x.syntax {
350                         ListItem(x) => Left(on_list_item(x)),
351                         _ => Right(once(x)),
352                     })
353                     .flatten(),
354             )),
355             ListItem(x) => Right(Left(on_list_item(x))),
356             _ => Right(Right(once(node))),
357         }
358     }
360     fn syntax_to_list_no_separators(
361         node: &'a Syntax<Token, Value>,
362     ) -> impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>> {
363         Self::syntax_to_list(false, node)
364     }
366     fn syntax_to_list_with_separators(
367         node: &'a Syntax<Token, Value>,
368     ) -> impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>> {
369         Self::syntax_to_list(true, node)
370     }
372     fn assert_last_in_list<F>(
373         assert_fun: F,
374         node: &'a Syntax<Token, Value>,
375     ) -> Option<&'a Syntax<Token, Value>>
376     where
377         F: Fn(&'a Syntax<Token, Value>) -> bool,
378     {
379         let mut iter = Self::syntax_to_list_no_separators(node);
380         iter.next_back();
381         iter.find(|x| assert_fun(*x))
382     }
384     fn enable_unstable_feature(
385         &mut self,
386         _node: &'a Syntax<Token, Value>,
387         arg: &'a Syntax<Token, Value>,
388     ) {
389         let error_invalid_argument = |self_: &mut Self, message| {
390             self_.errors.push(Self::make_error_from_node(
391                 arg,
392                 errors::invalid_use_of_enable_unstable_feature(message),
393             ))
394         };
396         match &arg.syntax {
397             LiteralExpression(x) => {
398                 let text = self.text(&x.literal_expression);
399                 match UnstableFeatures::from_str(escaper::unquote_str(text)) {
400                     Ok(feature) => {
401                         self.env.context.active_unstable_features.insert(feature);
402                     }
403                     Err(_) => error_invalid_argument(
404                         self,
405                         format!(
406                             "there is no feature named {}.\nAvailable features are:\n\t{}",
407                             text,
408                             UnstableFeatures::iter().join("\n\t")
409                         )
410                         .as_str(),
411                     ),
412                 }
413             }
414             _ => error_invalid_argument(self, "this is not a literal string expression"),
415         };
416     }
418     fn check_can_use_feature(
419         &mut self,
420         node: &'a Syntax<Token, Value>,
421         feature: &UnstableFeatures,
422     ) {
423         let parser_options = &self.env.parser_options;
424         let enabled = match feature {
425             UnstableFeatures::UnionIntersectionTypeHints => {
426                 parser_options.tco_union_intersection_type_hints
427             }
428             UnstableFeatures::ClassLevelWhere => parser_options.po_enable_class_level_where_clauses,
429         } || self.env.context.active_unstable_features.contains(feature);
430         if !enabled {
431             self.errors.push(Self::make_error_from_node(
432                 node,
433                 errors::cannot_use_feature(feature.into()),
434             ))
435         }
436     }
438     fn attr_spec_to_node_list(
439         node: &'a Syntax<Token, Value>,
440     ) -> impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>> {
441         use itertools::Either::{Left, Right};
442         let f = |attrs| Left(Self::syntax_to_list_no_separators(attrs));
443         match &node.syntax {
444             AttributeSpecification(x) => f(&x.attribute_specification_attributes),
445             OldAttributeSpecification(x) => f(&x.old_attribute_specification_attributes),
446             FileAttributeSpecification(x) => f(&x.file_attribute_specification_attributes),
447             _ => Right(std::iter::empty()),
448         }
449     }
451     fn attr_constructor_call(node: &'a Syntax<Token, Value>) -> &'a SyntaxVariant<Token, Value> {
452         match &node.syntax {
453             ConstructorCall(_) => &node.syntax,
454             Attribute(x) => &x.attribute_attribute_name.syntax,
455             _ => &Missing,
456         }
457     }
459     fn attr_name(&self, node: &'a Syntax<Token, Value>) -> Option<&'a str> {
460         if let ConstructorCall(x) = Self::attr_constructor_call(node) {
461             Some(self.text(&x.constructor_call_type))
462         } else {
463             None
464         }
465     }
467     fn attr_args(
468         &self,
469         node: &'a Syntax<Token, Value>,
470     ) -> Option<impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>>> {
471         if let ConstructorCall(x) = Self::attr_constructor_call(node) {
472             Some(Self::syntax_to_list_no_separators(
473                 &x.constructor_call_argument_list,
474             ))
475         } else {
476             None
477         }
478     }
480     fn attribute_specification_contains(&self, node: &'a Syntax<Token, Value>, name: &str) -> bool {
481         match &node.syntax {
482             AttributeSpecification(_)
483             | OldAttributeSpecification(_)
484             | FileAttributeSpecification(_) => {
485                 Self::attr_spec_to_node_list(node).any(|node| self.attr_name(node) == Some(name))
486             }
487             _ => false,
488         }
489     }
491     fn methodish_contains_attribute(
492         &self,
493         node: &'a Syntax<Token, Value>,
494         attribute: &str,
495     ) -> bool {
496         match &node.syntax {
497             MethodishDeclaration(x) => {
498                 self.attribute_specification_contains(&x.methodish_attribute, attribute)
499             }
500             _ => false,
501         }
502     }
504     fn is_decorated_expression<F>(node: &'a Syntax<Token, Value>, f: F) -> bool
505     where
506         F: Fn(&'a Syntax<Token, Value>) -> bool,
507     {
508         match &node.syntax {
509             DecoratedExpression(x) => f(&x.decorated_expression_decorator),
510             _ => false,
511         }
512     }
514     fn test_decorated_expression_child<F>(node: &'a Syntax<Token, Value>, f: F) -> bool
515     where
516         F: Fn(&'a Syntax<Token, Value>) -> bool,
517     {
518         match &node.syntax {
519             DecoratedExpression(x) => f(&x.decorated_expression_expression),
520             _ => false,
521         }
522     }
524     fn is_variadic_expression(node: &'a Syntax<Token, Value>) -> bool {
525         Self::is_decorated_expression(node, |x| x.is_ellipsis())
526             || Self::test_decorated_expression_child(node, &Self::is_variadic_expression)
527     }
529     fn is_double_variadic(node: &'a Syntax<Token, Value>) -> bool {
530         Self::is_decorated_expression(node, |x| x.is_ellipsis())
531             && Self::test_decorated_expression_child(node, &Self::is_variadic_expression)
532     }
534     fn is_variadic_parameter_variable(node: &'a Syntax<Token, Value>) -> bool {
535         // TODO: This shouldn't be a decorated *expression* because we are not
536         // expecting an expression at all. We're expecting a declaration.
537         Self::is_variadic_expression(node)
538     }
540     fn is_variadic_parameter_declaration(node: &'a Syntax<Token, Value>) -> bool {
541         match &node.syntax {
542             VariadicParameter(_) => true,
543             ParameterDeclaration(x) => Self::is_variadic_parameter_variable(&x.parameter_name),
544             _ => false,
545         }
546     }
547     fn misplaced_variadic_param(
548         param: &'a Syntax<Token, Value>,
549     ) -> Option<&'a Syntax<Token, Value>> {
550         Self::assert_last_in_list(&Self::is_variadic_parameter_declaration, param)
551     }
552     fn misplaced_variadic_arg(args: &'a Syntax<Token, Value>) -> Option<&'a Syntax<Token, Value>> {
553         Self::assert_last_in_list(&Self::is_variadic_expression, args)
554     }
555     // If a list ends with a variadic parameter followed by a comma, return it
556     fn ends_with_variadic_comma(
557         params: &'a Syntax<Token, Value>,
558     ) -> Option<&'a Syntax<Token, Value>> {
559         let mut iter = Self::syntax_to_list_with_separators(params).rev();
560         let y = iter.next();
561         let x = iter.next();
562         match (x, y) {
563             (Some(x), Some(y)) if Self::is_variadic_parameter_declaration(x) && y.is_comma() => {
564                 Some(y)
565             }
566             _ => None,
567         }
568     }
570     // Extract variadic parameter from a parameter list
571     fn variadic_param(params: &'a Syntax<Token, Value>) -> Option<&'a Syntax<Token, Value>> {
572         Self::syntax_to_list_with_separators(params)
573             .find(|&x| Self::is_variadic_parameter_declaration(x))
574     }
576     fn is_parameter_with_default_value(param: &'a Syntax<Token, Value>) -> bool {
577         match &param.syntax {
578             ParameterDeclaration(x) => !x.parameter_default_value.is_missing(),
579             _ => false,
580         }
581     }
583     // test a node is a syntaxlist and that the list contains an element
584     // satisfying a given predicate
585     fn list_contains_predicate<P>(p: P, node: &'a Syntax<Token, Value>) -> bool
586     where
587         P: Fn(&'a Syntax<Token, Value>) -> bool,
588     {
589         if let SyntaxList(lst) = &node.syntax {
590             lst.iter().any(p)
591         } else {
592             false
593         }
594     }
596     fn list_first_duplicate_token(
597         node: &'a Syntax<Token, Value>,
598     ) -> Option<&'a Syntax<Token, Value>> {
599         if let SyntaxList(lst) = &node.syntax {
600             let mut seen = BTreeMap::new();
601             for node in lst.iter().rev() {
602                 if let Token(t) = &node.syntax {
603                     if let Some(dup) = seen.insert(t.kind(), node) {
604                         return Some(dup);
605                     }
606                 }
607             }
608         }
609         None
610     }
612     fn is_empty_list_or_missing(node: &'a Syntax<Token, Value>) -> bool {
613         match &node.syntax {
614             SyntaxList(x) if x.is_empty() => true,
615             Missing => true,
616             _ => false,
617         }
618     }
620     fn token_kind(node: &'a Syntax<Token, Value>) -> Option<TokenKind> {
621         if let Token(t) = &node.syntax {
622             return Some(t.kind());
623         }
624         None
625     }
627     // Helper function for common code pattern
628     fn is_token_kind(node: &'a Syntax<Token, Value>, kind: TokenKind) -> bool {
629         Self::token_kind(node) == Some(kind)
630     }
632     fn active_classish_kind(&self) -> Option<TokenKind> {
633         self.env
634             .context
635             .active_classish
636             .and_then(|x| match &x.syntax {
637                 ClassishDeclaration(cd) => Self::token_kind(&cd.classish_keyword),
638                 _ => None,
639             })
640     }
642     fn modifiers_of_function_decl_header_exn(
643         node: &'a Syntax<Token, Value>,
644     ) -> &'a Syntax<Token, Value> {
645         match &node.syntax {
646             FunctionDeclarationHeader(x) => &x.function_modifiers,
647             _ => panic!("expected to get FunctionDeclarationHeader"),
648         }
649     }
651     fn get_modifiers_of_declaration(
652         node: &'a Syntax<Token, Value>,
653     ) -> Option<&'a Syntax<Token, Value>> {
654         match &node.syntax {
655             MethodishDeclaration(x) => Some(Self::modifiers_of_function_decl_header_exn(
656                 &x.methodish_function_decl_header,
657             )),
658             FunctionDeclaration(x) => Some(Self::modifiers_of_function_decl_header_exn(
659                 &x.function_declaration_header,
660             )),
661             PropertyDeclaration(x) => Some(&x.property_modifiers),
662             ConstDeclaration(x) => Some(&x.const_modifiers),
663             TypeConstDeclaration(x) => Some(&x.type_const_modifiers),
664             ClassishDeclaration(x) => Some(&x.classish_modifiers),
665             TraitUseAliasItem(x) => Some(&x.trait_use_alias_item_modifiers),
666             _ => None,
667         }
668     }
670     // tests whether the node's modifiers contain one that satisfies [p]
671     fn has_modifier_helper<P>(p: P, node: &'a Syntax<Token, Value>) -> bool
672     where
673         P: Fn(&'a Syntax<Token, Value>) -> bool,
674     {
675         match Self::get_modifiers_of_declaration(node) {
676             Some(x) => Self::list_contains_predicate(p, x),
677             None => false,
678         }
679     }
681     // does the node contain the Abstract keyword in its modifiers
682     fn has_modifier_abstract(node: &'a Syntax<Token, Value>) -> bool {
683         Self::has_modifier_helper(|x| x.is_abstract(), node)
684     }
686     // does the node contain the Static keyword in its modifiers
687     fn has_modifier_static(node: &'a Syntax<Token, Value>) -> bool {
688         Self::has_modifier_helper(|x| x.is_static(), node)
689     }
691     // does the node contain the Private keyword in its modifiers
692     fn has_modifier_private(node: &'a Syntax<Token, Value>) -> bool {
693         Self::has_modifier_helper(|x| x.is_private(), node)
694     }
696     fn get_modifier_final(modifiers: &'a Syntax<Token, Value>) -> Option<&'a Syntax<Token, Value>> {
697         Self::syntax_to_list_no_separators(modifiers).find(|x| x.is_final())
698     }
700     fn is_visibility(x: &'a Syntax<Token, Value>) -> bool {
701         x.is_public() || x.is_private() || x.is_protected()
702     }
704     fn contains_async_not_last(mods: &'a Syntax<Token, Value>) -> bool {
705         let mut mod_list = Self::syntax_to_list_no_separators(mods);
706         match mod_list.next_back() {
707             Some(x) if x.is_async() => false,
708             _ => mod_list.any(|x| x.is_async()),
709         }
710     }
712     fn has_static<F>(&self, node: &'a Syntax<Token, Value>, f: F) -> bool
713     where
714         F: Fn(&'a Syntax<Token, Value>) -> bool,
715     {
716         match &node.syntax {
717             FunctionDeclarationHeader(node) => {
718                 let label = &node.function_name;
719                 f(label)
720                     && self
721                         .env
722                         .context
723                         .active_methodish
724                         .iter()
725                         .any(|&x| Self::has_modifier_static(x))
726             }
727             _ => false,
728         }
729     }
731     fn is_clone(&self, label: &'a Syntax<Token, Value>) -> bool {
732         self.text(label).eq_ignore_ascii_case(sn::members::__CLONE)
733     }
735     fn class_constructor_has_static(&self, node: &'a Syntax<Token, Value>) -> bool {
736         self.has_static(node, |x| x.is_construct())
737     }
739     fn clone_cannot_be_static(&self, node: &'a Syntax<Token, Value>) -> bool {
740         self.has_static(node, |x| self.is_clone(x))
741     }
743     fn promoted_params(
744         params: impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>>,
745     ) -> impl DoubleEndedIterator<Item = &'a Syntax<Token, Value>> {
746         params.filter(|node| match &node.syntax {
747             ParameterDeclaration(x) => !x.parameter_visibility.is_missing(),
748             _ => false,
749         })
750     }
752     // Given a function declaration header, confirm that it is NOT a constructor
753     // and that the header containing it has visibility modifiers in parameters
754     fn class_non_constructor_has_visibility_param(node: &'a Syntax<Token, Value>) -> bool {
755         match &node.syntax {
756             FunctionDeclarationHeader(node) => {
757                 let params = Self::syntax_to_list_no_separators(&node.function_parameter_list);
758                 (!&node.function_name.is_construct())
759                     && Self::promoted_params(params).next().is_some()
760             }
761             _ => false,
762         }
763     }
765     // Don't allow a promoted parameter in a constructor if the class
766     // already has a property with the same name. Return the clashing name found.
767     fn class_constructor_param_promotion_clash(
768         &self,
769         node: &'a Syntax<Token, Value>,
770     ) -> Option<&str> {
771         use itertools::Either::{Left, Right};
772         let class_elts = |node: Option<&'a Syntax<Token, Value>>| match node.map(|x| &x.syntax) {
773             Some(ClassishDeclaration(cd)) => match &cd.classish_body.syntax {
774                 ClassishBody(cb) => Left(Self::syntax_to_list_no_separators(
775                     &cb.classish_body_elements,
776                 )),
777                 _ => Right(std::iter::empty()),
778             },
779             _ => Right(std::iter::empty()),
780         };
782         // A property declaration may include multiple property names:
783         // public int $x, $y;
784         let prop_names = |elt: &'a Syntax<Token, Value>| match &elt.syntax {
785             PropertyDeclaration(x) => Left(
786                 Self::syntax_to_list_no_separators(&x.property_declarators).filter_map(|decl| {
787                     match &decl.syntax {
788                         PropertyDeclarator(x) => Some(self.text(&x.property_name)),
789                         _ => None,
790                     }
791                 }),
792             ),
793             _ => Right(std::iter::empty()),
794         };
796         let param_name = |p: &'a Syntax<Token, Value>| match &p.syntax {
797             ParameterDeclaration(x) => Some(self.text(&x.parameter_name)),
798             _ => None,
799         };
801         match &node.syntax {
802             FunctionDeclarationHeader(node) if node.function_name.is_construct() => {
803                 let class_var_names: Vec<_> = class_elts(self.env.context.active_classish)
804                     .map(|x| prop_names(x))
805                     .flatten()
806                     .collect();
807                 let params = Self::syntax_to_list_no_separators(&node.function_parameter_list);
808                 let mut promoted_param_names = Self::promoted_params(params).filter_map(param_name);
809                 promoted_param_names.find(|name| class_var_names.contains(name))
810             }
811             _ => None,
812         }
813     }
815     // Ban parameter promotion in abstract constructors.
816     fn abstract_class_constructor_has_visibility_param(node: &'a Syntax<Token, Value>) -> bool {
817         match &node.syntax {
818             FunctionDeclarationHeader(node) => {
819                 let label = &node.function_name;
820                 let params = Self::syntax_to_list_no_separators(&node.function_parameter_list);
821                 label.is_construct()
822                     && Self::list_contains_predicate(|x| x.is_abstract(), &node.function_modifiers)
823                     && Self::promoted_params(params).next().is_some()
824             }
825             _ => false,
826         }
827     }
829     // Ban parameter promotion in interfaces and traits.
830     fn interface_or_trait_has_visibility_param(&self, node: &'a Syntax<Token, Value>) -> bool {
831         match &node.syntax {
832             FunctionDeclarationHeader(node) => {
833                 let is_interface_or_trait =
834                     self.env
835                         .context
836                         .active_classish
837                         .map_or(false, |parent_classish| match &parent_classish.syntax {
838                             ClassishDeclaration(cd) => {
839                                 let kind = Self::token_kind(&cd.classish_keyword);
840                                 kind == Some(TokenKind::Interface) || kind == Some(TokenKind::Trait)
841                             }
842                             _ => false,
843                         });
845                 let params = Self::syntax_to_list_no_separators(&node.function_parameter_list);
846                 Self::promoted_params(params).next().is_some() && is_interface_or_trait
847             }
848             _ => false,
849         }
850     }
852     // check that a constructor is type annotated
853     fn class_constructor_has_non_void_type(&self, node: &'a Syntax<Token, Value>) -> bool {
854         if !self.env.is_typechecker() {
855             false
856         } else {
857             match &node.syntax {
858                 FunctionDeclarationHeader(node) => {
859                     let label = &node.function_name;
860                     let type_ano = &node.function_type;
861                     let function_colon = &node.function_colon;
862                     let is_missing = type_ano.is_missing() && function_colon.is_missing();
863                     let is_void = match &type_ano.syntax {
864                         SimpleTypeSpecifier(spec) => spec.simple_type_specifier.is_void(),
865                         _ => false,
866                     };
867                     label.is_construct() && !(is_missing || is_void)
868                 }
869                 _ => false,
870             }
871         }
872     }
874     fn unsupported_magic_method_errors(&mut self, node: &'a Syntax<Token, Value>) {
875         if let FunctionDeclarationHeader(x) = &node.syntax {
876             let name = self.text(&x.function_name).to_ascii_lowercase();
877             let unsupported = sn::members::UNSUPPORTED_MAP.get(&name);
879             if let Some(unsupported) = unsupported {
880                 self.errors.push(Self::make_error_from_node(
881                     node,
882                     errors::unsupported_magic_method(unsupported),
883                 ));
884             }
885         }
886     }
888     fn async_magic_method(&self, node: &'a Syntax<Token, Value>) -> bool {
889         match &node.syntax {
890             FunctionDeclarationHeader(node) => {
891                 let name = self.text(&node.function_name).to_ascii_lowercase();
892                 match name {
893                     _ if name.eq_ignore_ascii_case(sn::members::__DISPOSE_ASYNC) => false,
894                     _ if sn::members::AS_LOWERCASE_SET.contains(&name) => {
895                         Self::list_contains_predicate(|x| x.is_async(), &node.function_modifiers)
896                     }
897                     _ => false,
898                 }
899             }
900             _ => false,
901         }
902     }
904     fn clone_takes_no_arguments(&self, node: &'a Syntax<Token, Value>) -> bool {
905         match &node.syntax {
906             FunctionDeclarationHeader(x) => {
907                 let mut params = Self::syntax_to_list_no_separators(&x.function_parameter_list);
908                 self.is_clone(&x.function_name) && params.next().is_some()
909             }
910             _ => false,
911         }
912     }
914     // whether a methodish decl has body
915     fn methodish_has_body(node: &'a Syntax<Token, Value>) -> bool {
916         match &node.syntax {
917             MethodishDeclaration(syntax) => !syntax.methodish_function_body.is_missing(),
918             _ => false,
919         }
920     }
922     // whether a methodish decl is native
923     fn methodish_is_native(&self, node: &'a Syntax<Token, Value>) -> bool {
924         self.methodish_contains_attribute(node, "__Native")
925     }
927     // By checking the third parent of a methodish node, tests whether the methodish
928     // node is inside an interface.
929     fn methodish_inside_interface(&self) -> bool {
930         self.env
931             .context
932             .active_classish
933             .iter()
934             .any(|parent_classish| match &parent_classish.syntax {
935                 ClassishDeclaration(cd) => {
936                     Self::token_kind(&cd.classish_keyword) == Some(TokenKind::Interface)
937                 }
938                 _ => false,
939             })
940     }
942     // Test whether node is a non-abstract method without a body and not native.
943     // Here node is the methodish node
944     // And methods inside interfaces are inherently considered abstract *)
945     fn methodish_non_abstract_without_body_not_native(
946         &self,
947         node: &'a Syntax<Token, Value>,
948     ) -> bool {
949         let non_abstract =
950             !(Self::has_modifier_abstract(node) || self.methodish_inside_interface());
951         let not_has_body = !Self::methodish_has_body(node);
952         let not_native = !self.methodish_is_native(node);
953         let not_hhi = !self.env.is_hhi_mode();
955         not_hhi && non_abstract && not_has_body && not_native
956     }
958     // Test whether node is a method that is both abstract and private
959     fn methodish_abstract_conflict_with_private(node: &'a Syntax<Token, Value>) -> bool {
960         let is_abstract = Self::has_modifier_abstract(node);
961         let has_private = Self::has_modifier_private(node);
962         is_abstract && has_private
963     }
965     fn methodish_abstract_inside_interface(&self, node: &'a Syntax<Token, Value>) -> bool {
966         let is_abstract = Self::has_modifier_abstract(node);
967         let is_in_interface = self.methodish_inside_interface();
968         is_abstract && is_in_interface
969     }
971     fn using_statement_function_scoped_is_legal(&self) -> bool {
972         // using is allowed in the toplevel, and also in toplevel async blocks
973         let len = self.parents.len();
974         if len < 3 {
975             return false;
976         }
977         match (self.parents.get(len - 2), self.parents.get(len - 3)) {
978             (
979                 Some(Syntax {
980                     syntax: CompoundStatement(_),
981                     ..
982                 }),
983                 Some(x),
984             ) => match &x.syntax {
985                 FunctionDeclaration(_)
986                 | MethodishDeclaration(_)
987                 | AnonymousFunction(_)
988                 | LambdaExpression(_)
989                 | AwaitableCreationExpression(_) => true,
990                 _ => false,
991             },
992             _ => false,
993         }
994     }
996     fn make_error_from_nodes(
997         child: Option<SyntaxError>,
998         start_node: &'a Syntax<Token, Value>,
999         end_node: &'a Syntax<Token, Value>,
1000         error_type: ErrorType,
1001         error: errors::Error,
1002     ) -> SyntaxError {
1003         let s = Self::start_offset(start_node);
1004         let e = Self::end_offset(end_node);
1005         SyntaxError::make_with_child_and_type(child, s, e, error_type, error)
1006     }
1008     fn make_error_from_node(node: &'a Syntax<Token, Value>, error: errors::Error) -> SyntaxError {
1009         Self::make_error_from_nodes(None, node, node, ErrorType::ParseError, error)
1010     }
1012     fn make_error_from_node_with_type(
1013         node: &'a Syntax<Token, Value>,
1014         error: errors::Error,
1015         error_type: ErrorType,
1016     ) -> SyntaxError {
1017         Self::make_error_from_nodes(None, node, node, error_type, error)
1018     }
1020     fn is_invalid_xhp_attr_enum_item_literal(literal_expression: &'a Syntax<Token, Value>) -> bool {
1021         if let Token(t) = &literal_expression.syntax {
1022             match t.kind() {
1023                 TokenKind::DecimalLiteral
1024                 | TokenKind::SingleQuotedStringLiteral
1025                 | TokenKind::DoubleQuotedStringLiteral => false,
1026                 _ => true,
1027             }
1028         } else {
1029             true
1030         }
1031     }
1033     fn is_invalid_xhp_attr_enum_item(node: &'a Syntax<Token, Value>) -> bool {
1034         if let LiteralExpression(x) = &node.syntax {
1035             Self::is_invalid_xhp_attr_enum_item_literal(&x.literal_expression)
1036         } else {
1037             true
1038         }
1039     }
1041     fn xhp_errors(&mut self, node: &'a Syntax<Token, Value>) {
1042         match &node.syntax {
1043             XHPEnumType(enum_type) => {
1044                 if self.env.is_typechecker() && enum_type.xhp_enum_values.is_missing() {
1045                     self.errors.push(Self::make_error_from_node(
1046                         &enum_type.xhp_enum_values,
1047                         errors::error2055,
1048                     ))
1049                 } else if self.env.is_typechecker() {
1050                     Self::syntax_to_list_no_separators(&enum_type.xhp_enum_values)
1051                         .filter(|&x| Self::is_invalid_xhp_attr_enum_item(x))
1052                         .for_each(|item| {
1053                             self.errors
1054                                 .push(Self::make_error_from_node(item, errors::error2063))
1055                         })
1056                 }
1057             }
1058             XHPExpression(x) => {
1059                 if let XHPOpen(xhp_open) = &x.xhp_open.syntax {
1060                     if let XHPClose(xhp_close) = &x.xhp_close.syntax {
1061                         let open_tag = self.text(&xhp_open.xhp_open_name);
1062                         let close_tag = self.text(&xhp_close.xhp_close_name);
1063                         if open_tag != close_tag {
1064                             self.errors.push(Self::make_error_from_node(
1065                                 node,
1066                                 errors::error2070(&open_tag, &close_tag),
1067                             ))
1068                         }
1069                     }
1070                 }
1071             }
1072             _ => {}
1073         }
1074     }
1076     fn invalid_modifier_errors<F>(&mut self, decl_name: &str, node: &'a Syntax<Token, Value>, ok: F)
1077     where
1078         F: Fn(TokenKind) -> bool,
1079     {
1080         if let Some(modifiers) = Self::get_modifiers_of_declaration(node) {
1081             for modifier in Self::syntax_to_list_no_separators(modifiers) {
1082                 if let Some(kind) = Self::token_kind(modifier) {
1083                     if !ok(kind) {
1084                         self.errors.push(Self::make_error_from_node(
1085                             modifier,
1086                             errors::invalid_modifier_for_declaration(
1087                                 decl_name,
1088                                 self.text(modifier),
1089                             ),
1090                         ));
1091                     }
1092                 }
1093             }
1094             if let Some(duplicate) = Self::list_first_duplicate_token(modifiers) {
1095                 self.errors.push(Self::make_error_from_node(
1096                     duplicate,
1097                     errors::duplicate_modifiers_for_declaration(decl_name),
1098                 ))
1099             }
1100             if let SyntaxList(modifiers) = &modifiers.syntax {
1101                 let modifiers: Vec<&'a Syntax<Token, Value>> = modifiers
1102                     .iter()
1103                     .filter(|x: &&'a Syntax<Token, Value>| Self::is_visibility(*x))
1104                     .collect();
1105                 if modifiers.len() > 1 {
1106                     self.errors.push(Self::make_error_from_node(
1107                         modifiers.last().unwrap(),
1108                         errors::multiple_visibility_modifiers_for_declaration(decl_name),
1109                     ));
1110                 }
1111             }
1112         }
1113     }
1115     // helper since there are so many kinds of errors
1116     fn produce_error<'b, F, E, X>(
1117         &mut self,
1118         check: F,
1119         node: &'b X,
1120         error: E, // closure to avoid constant premature concatenation of error strings
1121         error_node: &'a Syntax<Token, Value>,
1122     ) where
1123         F: Fn(&mut Self, &'b X) -> bool,
1124         E: Fn() -> Error,
1125     {
1126         if check(self, node) {
1127             self.errors
1128                 .push(Self::make_error_from_node(error_node, error()))
1129         }
1130     }
1132     // helper since there are so many kinds of errors
1133     fn produce_error_from_check<'b, F, E, X>(&mut self, check: F, node: &'b X, error: E)
1134     where
1135         F: Fn(&'b X) -> Option<&'a Syntax<Token, Value>>,
1136         E: Fn() -> Error,
1137     {
1138         if let Some(error_node) = check(node) {
1139             self.errors
1140                 .push(Self::make_error_from_node(error_node, error()))
1141         }
1142     }
1144     fn cant_be_classish_name(name: &str) -> bool {
1145         match name.to_ascii_lowercase().as_ref() {
1146             "callable" | "classname" | "darray" | "false" | "null" | "parent" | "self" | "this"
1147             | "true" | "varray" => true,
1148             _ => false,
1149         }
1150     }
1152     // Given a function_declaration_header node, returns its function_name
1153     // as a string opt.
1154     fn extract_function_name(&self, header_node: &'a Syntax<Token, Value>) -> Option<&'a str> {
1155         // The '_' arm of this match will never be reached, but the type checker
1156         // doesn't allow a direct extraction of function_name from
1157         // function_declaration_header. *)
1158         match &header_node.syntax {
1159             FunctionDeclarationHeader(fdh) => Some(self.text(&fdh.function_name)),
1160             _ => None,
1161         }
1162     }
1164     // Return, as a string opt, the name of the function or method given the context *)
1165     fn first_parent_function_name(&self) -> Option<&str> {
1166         // Note: matching on either is sound because functions and/or methods cannot be nested
1168         match self.env.context.active_methodish {
1169             Some(Syntax {
1170                 syntax: FunctionDeclaration(x),
1171                 ..
1172             }) => self.extract_function_name(&x.function_declaration_header),
1173             Some(Syntax {
1174                 syntax: MethodishDeclaration(x),
1175                 ..
1176             }) => self.extract_function_name(&x.methodish_function_decl_header),
1177             _ => None,
1178         }
1179     }
1181     // Given a particular TokenKind::(Trait/Interface), tests if a given
1182     // classish_declaration node is both of that kind and declared abstract.
1183     fn is_classish_kind_declared_abstract(&self, cd_node: &'a Syntax<Token, Value>) -> bool {
1184         match &cd_node.syntax {
1185             ClassishDeclaration(x)
1186                 if Self::is_token_kind(&x.classish_keyword, TokenKind::Trait)
1187                     || Self::is_token_kind(&x.classish_keyword, TokenKind::Interface) =>
1188             {
1189                 Self::list_contains_predicate(|x| x.is_abstract(), &x.classish_modifiers)
1190             }
1191             _ => false,
1192         }
1193     }
1195     fn is_immediately_in_lambda(&self) -> bool {
1196         self.env
1197             .context
1198             .active_callable
1199             .map_or(false, |node| match &node.syntax {
1200                 AnonymousFunction(_) | LambdaExpression(_) | AwaitableCreationExpression(_) => true,
1201                 _ => false,
1202             })
1203     }
1205     // Returns the whether the current context is in an active class scope
1206     fn is_in_active_class_scope(&self) -> bool {
1207         self.env.context.active_classish.is_some()
1208     }
1210     // Returns the first ClassishDeclaration node or
1211     // None if there isn't one or classish_kind does not match. *)
1212     fn first_parent_classish_node(
1213         &self,
1214         classish_kind: TokenKind,
1215     ) -> Option<&'a Syntax<Token, Value>> {
1216         self.env
1217             .context
1218             .active_classish
1219             .and_then(|node| match &node.syntax {
1220                 ClassishDeclaration(cd)
1221                     if Self::is_token_kind(&cd.classish_keyword, classish_kind) =>
1222                 {
1223                     Some(node)
1224                 }
1225                 _ => None,
1226             })
1227     }
1229     // Return, as a string opt, the name of the closest enclosing classish entity in
1230     // the given context (not just Classes )
1231     fn active_classish_name(&self) -> Option<&'a str> {
1232         self.env.context.active_classish.and_then(|node| {
1233             if let ClassishDeclaration(cd) = &node.syntax {
1234                 cd.classish_name.extract_text(self.env.syntax_tree.text())
1235             } else {
1236                 None
1237             }
1238         })
1239     }
1241     // Return, as a string opt, the name of the Class in the given context
1242     fn first_parent_class_name(&self) -> Option<&'a str> {
1243         return self
1244             .env
1245             .context
1246             .active_classish
1247             .and_then(|parent_classish| {
1248                 if let ClassishDeclaration(cd) = &parent_classish.syntax {
1249                     if Self::token_kind(&cd.classish_keyword) == Some(TokenKind::Class) {
1250                         return self.active_classish_name();
1251                     } else {
1252                         return None; // This arm is never reached
1253                     }
1254                 }
1255                 return None;
1256             });
1257     }
1259     // Given a declaration node, returns the modifier node matching the given
1260     // predicate from its list of modifiers, or None if there isn't one.
1261     fn extract_keyword<F>(
1262         modifier: F,
1263         declaration_node: &'a Syntax<Token, Value>,
1264     ) -> Option<&'a Syntax<Token, Value>>
1265     where
1266         F: Fn(&'a Syntax<Token, Value>) -> bool,
1267     {
1268         Self::get_modifiers_of_declaration(declaration_node).and_then(|modifiers_list| {
1269             Self::syntax_to_list_no_separators(modifiers_list)
1270                 .find(|x: &&'a Syntax<Token, Value>| modifier(*x))
1271         })
1272     }
1274     // Wrapper function that uses above extract_keyword function to test if node
1275     // contains is_abstract keyword
1276     fn is_abstract_declaration(declaration_node: &'a Syntax<Token, Value>) -> bool {
1277         Self::extract_keyword(|x| x.is_abstract(), declaration_node).is_some()
1278     }
1280     // Tests if the immediate classish parent is an interface.
1281     fn is_inside_interface(&self) -> bool {
1282         self.first_parent_classish_node(TokenKind::Interface)
1283             .is_some()
1284     }
1286     // Tests if the immediate classish parent is a trait.
1287     fn is_inside_trait(&self) -> bool {
1288         self.first_parent_classish_node(TokenKind::Trait).is_some()
1289     }
1291     fn is_abstract_and_async_method(md_node: &'a Syntax<Token, Value>) -> bool {
1292         Self::is_abstract_declaration(md_node)
1293             && Self::extract_keyword(|x| x.is_async(), md_node).is_some()
1294     }
1296     fn is_interface_and_async_method(&self, md_node: &'a Syntax<Token, Value>) -> bool {
1297         self.is_inside_interface() && Self::extract_keyword(|x| x.is_async(), md_node).is_some()
1298     }
1300     fn get_params_for_enclosing_callable(&self) -> Option<&'a Syntax<Token, Value>> {
1301         let from_header = |header: &'a Syntax<Token, Value>| match &header.syntax {
1302             FunctionDeclarationHeader(fdh) => Some(&fdh.function_parameter_list),
1303             _ => None,
1304         };
1305         self.env
1306             .context
1307             .active_callable
1308             .and_then(|callable| match &callable.syntax {
1309                 FunctionDeclaration(x) => from_header(&x.function_declaration_header),
1310                 MethodishDeclaration(x) => from_header(&x.methodish_function_decl_header),
1311                 LambdaExpression(x) => match &x.lambda_signature.syntax {
1312                     LambdaSignature(x) => Some(&x.lambda_parameters),
1313                     _ => None,
1314                 },
1315                 _ => None,
1316             })
1317     }
1319     fn first_parent_function_attributes_contains(&self, name: &str) -> bool {
1320         let from_attr_spec = |attr_spec| {
1321             Self::attr_spec_to_node_list(attr_spec).any(|node| self.attr_name(node) == Some(name))
1322         };
1323         match self.env.context.active_methodish {
1324             Some(Syntax {
1325                 syntax: FunctionDeclaration(x),
1326                 ..
1327             }) => from_attr_spec(&x.function_attribute_spec),
1328             Some(Syntax {
1329                 syntax: MethodishDeclaration(x),
1330                 ..
1331             }) => from_attr_spec(&x.methodish_attribute),
1332             _ => false,
1333         }
1334     }
1336     fn parameter_callconv(param: &'a Syntax<Token, Value>) -> Option<&'a Syntax<Token, Value>> {
1337         (match &param.syntax {
1338             ParameterDeclaration(x) => Some(&x.parameter_call_convention),
1339             ClosureParameterTypeSpecifier(x) => Some(&x.closure_parameter_call_convention),
1340             VariadicParameter(x) => Some(&x.variadic_parameter_call_convention),
1341             _ => None,
1342         })
1343         .filter(|node| !node.is_missing())
1344     }
1346     fn is_parameter_with_callconv(param: &'a Syntax<Token, Value>) -> bool {
1347         Self::parameter_callconv(param).is_some()
1348     }
1350     fn has_inout_params(&self) -> bool {
1351         self.get_params_for_enclosing_callable()
1352             .map_or(false, |function_parameter_list| {
1353                 Self::syntax_to_list_no_separators(function_parameter_list)
1354                     .any(|x| Self::is_parameter_with_callconv(x))
1355             })
1356     }
1358     fn is_inside_async_method(&self) -> bool {
1359         let from_header = |header: &'a Syntax<Token, Value>| match &header.syntax {
1360             FunctionDeclarationHeader(fdh) => {
1361                 Self::syntax_to_list_no_separators(&fdh.function_modifiers).any(|x| x.is_async())
1362             }
1363             _ => false,
1364         };
1365         self.env
1366             .context
1367             .active_callable
1368             .map_or(false, |node| match &node.syntax {
1369                 FunctionDeclaration(x) => from_header(&x.function_declaration_header),
1370                 MethodishDeclaration(x) => from_header(&x.methodish_function_decl_header),
1371                 AnonymousFunction(x) => !x.anonymous_async_keyword.is_missing(),
1372                 LambdaExpression(x) => !x.lambda_async.is_missing(),
1373                 AwaitableCreationExpression(_) => true,
1374                 _ => false,
1375             })
1376     }
1378     fn make_name_already_used_error(
1379         node: &'a Syntax<Token, Value>,
1380         name: &str,
1381         short_name: &str,
1382         original_location: &Location,
1383         report_error: &dyn Fn(&str, &str) -> Error,
1384     ) -> SyntaxError {
1385         let name = Self::strip_ns(name);
1386         let original_location_error = SyntaxError::make(
1387             original_location.start_offset,
1388             original_location.end_offset,
1389             errors::original_definition,
1390         );
1392         let s = Self::start_offset(node);
1393         let e = Self::end_offset(node);
1394         SyntaxError::make_with_child_and_type(
1395             Some(original_location_error),
1396             s,
1397             e,
1398             ErrorType::ParseError,
1399             report_error(&name, short_name),
1400         )
1401     }
1403     fn check_type_name_reference(&mut self, name_text: &str, location: Location) {
1404         if hh_autoimport::is_hh_autoimport(name_text) && !self.names.classes.mem(name_text) {
1405             let def = make_first_use_or_def(false, NameImplicitUse, location, "HH", name_text);
1406             self.names.classes.add(name_text, def)
1407         }
1408     }
1410     fn check_type_hint(&mut self, node: &'a Syntax<Token, Value>) {
1411         for x in node.iter_children() {
1412             self.check_type_hint(x)
1413         }
1414         let check_type_name = |self_: &mut Self, s| {
1415             self_.check_type_name_reference(self_.text(s), Self::make_location_of_node(node))
1416         };
1417         match &node.syntax {
1418             SimpleTypeSpecifier(x) => check_type_name(self, &x.simple_type_specifier),
1419             GenericTypeSpecifier(x) => check_type_name(self, &x.generic_class_type),
1420             _ => (),
1421         }
1422     }
1424     fn extract_callconv_node(node: &'a Syntax<Token, Value>) -> Option<&'a Syntax<Token, Value>> {
1425         match &node.syntax {
1426             ParameterDeclaration(x) => Some(&x.parameter_call_convention),
1427             ClosureParameterTypeSpecifier(x) => Some(&x.closure_parameter_call_convention),
1428             VariadicParameter(x) => Some(&x.variadic_parameter_call_convention),
1429             _ => None,
1430         }
1431     }
1433     // Given a node, checks if it is a abstract ConstDeclaration
1434     fn is_abstract_const(declaration: &'a Syntax<Token, Value>) -> bool {
1435         match &declaration.syntax {
1436             ConstDeclaration(_) => Self::has_modifier_abstract(declaration),
1437             _ => false,
1438         }
1439     }
1441     // Given a ConstDeclarator node, test whether it is abstract, but has an
1442     // initializer.
1443     fn constant_abstract_with_initializer(&self, init: &'a Syntax<Token, Value>) -> bool {
1444         let is_abstract = match self.env.context.active_const {
1445             Some(p_const_declaration) if Self::is_abstract_const(p_const_declaration) => true,
1446             _ => false,
1447         };
1448         let has_initializer = !init.is_missing();
1449         is_abstract && has_initializer
1450     }
1452     // Given a node, checks if it is a concrete ConstDeclaration *)
1453     fn is_concrete_const(declaration: &'a Syntax<Token, Value>) -> bool {
1454         match &declaration.syntax {
1455             ConstDeclaration(_) => !Self::has_modifier_abstract(declaration),
1456             _ => false,
1457         }
1458     }
1460     // Given a ConstDeclarator node, test whether it is concrete, but has no
1461     // initializer.
1462     fn constant_concrete_without_initializer(&self, init: &'a Syntax<Token, Value>) -> bool {
1463         let is_concrete = match self.env.context.active_const {
1464             Some(p_const_declaration) if Self::is_concrete_const(p_const_declaration) => true,
1465             _ => false,
1466         };
1467         is_concrete && init.is_missing()
1468     }
1470     fn methodish_memoize_lsb_on_non_static(&mut self, node: &'a Syntax<Token, Value>) {
1471         if self.methodish_contains_attribute(node, sn::user_attributes::MEMOIZE_LSB)
1472             && !Self::has_modifier_static(node)
1473         {
1474             self.errors.push(Self::make_error_from_node(
1475                 node,
1476                 errors::memoize_lsb_on_non_static,
1477             ));
1478         }
1479     }
1481     fn function_declaration_contains_attribute(
1482         &self,
1483         node: &'a Syntax<Token, Value>,
1484         attribute: &str,
1485     ) -> bool {
1486         match &node.syntax {
1487             FunctionDeclaration(x) => {
1488                 self.attribute_specification_contains(&x.function_attribute_spec, attribute)
1489             }
1490             _ => false,
1491         }
1492     }
1494     fn methodish_contains_memoize(&self, node: &'a Syntax<Token, Value>) -> bool {
1495         self.env.is_typechecker()
1496             && self.is_inside_interface()
1497             && self.methodish_contains_attribute(node, sn::user_attributes::MEMOIZE)
1498     }
1500     fn is_some_reactivity_attribute_name(name: &str) -> bool {
1501         name == sn::user_attributes::REACTIVE
1502             || name == sn::user_attributes::SHALLOW_REACTIVE
1503             || name == sn::user_attributes::LOCAL_REACTIVE
1504             || name == sn::user_attributes::NON_RX
1505             || name == sn::user_attributes::PURE
1506     }
1508     fn is_some_reactivity_attribute(&self, node: &'a Syntax<Token, Value>) -> bool {
1509         match self.attr_name(node) {
1510             None => false,
1511             Some(name) => Self::is_some_reactivity_attribute_name(name),
1512         }
1513     }
1515     fn attribute_first_reactivity_annotation(
1516         &self,
1517         node: &'a Syntax<Token, Value>,
1518     ) -> Option<&'a Syntax<Token, Value>> {
1519         match &node.syntax {
1520             AttributeSpecification(_) | OldAttributeSpecification(_) => {
1521                 Self::attr_spec_to_node_list(node).find(|x| self.is_some_reactivity_attribute(x))
1522             }
1523             _ => None,
1524         }
1525     }
1527     fn attribute_has_reactivity_annotation(&self, attr_spec: &'a Syntax<Token, Value>) -> bool {
1528         self.attribute_first_reactivity_annotation(attr_spec)
1529             .is_some()
1530     }
1532     fn attribute_missing_reactivity_for_condition(
1533         &self,
1534         attr_spec: &'a Syntax<Token, Value>,
1535     ) -> bool {
1536         let has_attr = |attr| self.attribute_specification_contains(attr_spec, attr);
1537         !(self.attribute_has_reactivity_annotation(attr_spec))
1538             && (has_attr(sn::user_attributes::ONLY_RX_IF_IMPL)
1539                 || has_attr(sn::user_attributes::AT_MOST_RX_AS_ARGS))
1540     }
1542     fn error_if_memoize_function_returns_mutable(&mut self, attrs: &'a Syntax<Token, Value>) {
1543         let mut has_memoize = false;
1544         let mut mutable_node = None;
1545         let mut mut_return_node = None;
1546         for node in Self::attr_spec_to_node_list(attrs) {
1547             match self.attr_name(node) {
1548                 Some(n) if n == sn::user_attributes::MUTABLE_RETURN => mut_return_node = Some(node),
1549                 Some(n)
1550                     if n == sn::user_attributes::MEMOIZE
1551                         || n == sn::user_attributes::MEMOIZE_LSB =>
1552                 {
1553                     has_memoize = true
1554                 }
1555                 Some(n) if n == sn::user_attributes::MUTABLE => mutable_node = Some(node),
1556                 _ => (),
1557             }
1558         }
1560         if has_memoize {
1561             if let Some(n) = mutable_node {
1562                 self.errors.push(Self::make_error_from_node(
1563                     n,
1564                     errors::mutable_parameter_in_memoize_function(true),
1565                 ))
1566             }
1567             if let Some(n) = mut_return_node {
1568                 self.errors.push(Self::make_error_from_node(
1569                     n,
1570                     errors::mutable_return_in_memoize_function,
1571                 ))
1572             }
1573         }
1574     }
1576     fn methodish_missing_reactivity_for_condition(&self, node: &'a Syntax<Token, Value>) -> bool {
1577         match &node.syntax {
1578             MethodishDeclaration(x) => {
1579                 self.attribute_missing_reactivity_for_condition(&x.methodish_attribute)
1580             }
1581             _ => false,
1582         }
1583     }
1585     fn methodish_contains_owned_mutable_attribute(&self, node: &'a Syntax<Token, Value>) -> bool {
1586         self.methodish_contains_attribute(node, sn::user_attributes::OWNED_MUTABLE)
1587     }
1589     fn check_nonrx_annotation(&mut self, node: &'a Syntax<Token, Value>) {
1590         let err_decl = |self_: &mut Self| {
1591             self_.errors.push(Self::make_error_from_node(
1592                 node,
1593                 errors::invalid_non_rx_argument_for_declaration,
1594             ))
1595         };
1596         let err_lambda = |self_: &mut Self| {
1597             self_.errors.push(Self::make_error_from_node(
1598                 node,
1599                 errors::invalid_non_rx_argument_for_lambda,
1600             ))
1601         };
1602         let attr_spec = match &node.syntax {
1603             MethodishDeclaration(x) => Some((&x.methodish_attribute, true)),
1604             FunctionDeclaration(x) => Some((&x.function_attribute_spec, true)),
1605             AnonymousFunction(x) => Some((&x.anonymous_attribute_spec, false)),
1606             LambdaExpression(x) => Some((&x.lambda_attribute_spec, false)),
1607             AwaitableCreationExpression(x) => Some((&x.awaitable_attribute_spec, false)),
1608             _ => None,
1609         };
1611         if let Some((node, is_decl)) = attr_spec {
1612             // try find argument list
1613             let args_opt = Self::attr_spec_to_node_list(node)
1614                 .find(|node| self.attr_name(node) == Some(sn::user_attributes::NON_RX))
1615                 .and_then(|x| self.attr_args(x));
1617             let is_string_argument = |x: &'a Syntax<Token, Value>| match &x.syntax {
1618                 LiteralExpression(x) => match &x.literal_expression.syntax {
1619                     Token(token) => {
1620                         token.kind() == TokenKind::DoubleQuotedStringLiteral
1621                             || token.kind() == TokenKind::SingleQuotedStringLiteral
1622                     }
1623                     _ => false,
1624                 },
1625                 _ => false,
1626             };
1628             if let Some(mut args_opt) = args_opt {
1629                 let first_arg = args_opt.next();
1630                 let second_arg = args_opt.next();
1631                 match (first_arg, second_arg) {
1632                     // __NonRx attribute is found and argument list is empty.
1633                     // This is ok for lambdas but error for declarations
1634                     (None, _) => {
1635                         if is_decl {
1636                             err_decl(self)
1637                         }
1638                     }
1639                     // __NonRx attribute is found with single string argument.
1640                     // This is ok for declarations for not allowed for lambdas *)
1641                     (Some(arg), None) if is_string_argument(arg) => {
1642                         if !is_decl {
1643                             err_lambda(self)
1644                         }
1645                     }
1646                     // __NonRx attribute is found but argument list is not suitable
1647                     // nor for declarations, neither for lambdas
1648                     _ => {
1649                         if is_decl {
1650                             err_decl(self)
1651                         } else {
1652                             err_lambda(self)
1653                         }
1654                     }
1655                 }
1656             }
1657         } else {
1658             // __NonRx attribute not found
1659         }
1660     }
1662     fn function_missing_reactivity_for_condition(&self, node: &'a Syntax<Token, Value>) -> bool {
1663         match &node.syntax {
1664             FunctionDeclaration(x) => {
1665                 self.attribute_missing_reactivity_for_condition(&x.function_attribute_spec)
1666             }
1667             _ => false,
1668         }
1669     }
1671     fn function_declaration_contains_only_rx_if_impl_attribute(
1672         &self,
1673         node: &'a Syntax<Token, Value>,
1674     ) -> bool {
1675         self.function_declaration_contains_attribute(node, sn::user_attributes::ONLY_RX_IF_IMPL)
1676     }
1678     fn function_declaration_contains_owned_mutable_attribute(
1679         &self,
1680         node: &'a Syntax<Token, Value>,
1681     ) -> bool {
1682         self.function_declaration_contains_attribute(node, sn::user_attributes::OWNED_MUTABLE)
1683     }
1685     fn attribute_multiple_reactivity_annotations(
1686         &self,
1687         attr_spec: &'a Syntax<Token, Value>,
1688     ) -> bool {
1689         match &attr_spec.syntax {
1690             OldAttributeSpecification(_) | AttributeSpecification(_) => {
1691                 Self::attr_spec_to_node_list(attr_spec)
1692                     .filter(|x| self.is_some_reactivity_attribute(x))
1693                     .take(2)
1694                     .count()
1695                     > 1
1696             }
1697             _ => false,
1698         }
1699     }
1701     fn methodish_multiple_reactivity_annotations(&self, node: &'a Syntax<Token, Value>) -> bool {
1702         match &node.syntax {
1703             MethodishDeclaration(x) => {
1704                 self.attribute_multiple_reactivity_annotations(&x.methodish_attribute)
1705             }
1706             _ => false,
1707         }
1708     }
1710     fn function_multiple_reactivity_annotations(&self, node: &'a Syntax<Token, Value>) -> bool {
1711         match &node.syntax {
1712             FunctionDeclaration(x) => {
1713                 self.attribute_multiple_reactivity_annotations(&x.function_attribute_spec)
1714             }
1715             _ => false,
1716         }
1717     }
1719     fn function_declaration_header_memoize_lsb(&mut self) {
1720         if let (Some(node), None) = (
1721             self.env.context.active_methodish,
1722             self.env.context.active_classish,
1723         ) {
1724             // a function, not a method
1725             if self.function_declaration_contains_attribute(node, sn::user_attributes::MEMOIZE_LSB)
1726             {
1727                 self.errors.push(Self::make_error_from_node(
1728                     node,
1729                     errors::memoize_lsb_on_non_method,
1730                 ))
1731             }
1732         }
1733     }
1735     fn is_in_reified_class(&self) -> bool {
1736         let active_classish = match self.env.context.active_classish {
1737             Some(x) => x,
1738             _ => return false,
1739         };
1740         if let ClassishDeclaration(x) = &active_classish.syntax {
1741             if let TypeParameters(x) = &x.classish_type_parameters.syntax {
1742                 return Self::syntax_to_list_no_separators(&x.type_parameters_parameters).any(
1743                     |p| match &p.syntax {
1744                         TypeParameter(x) => !x.type_reified.is_missing(),
1745                         _ => false,
1746                     },
1747                 );
1748             }
1749         };
1750         false
1751     }
1753     fn methodish_errors(&mut self, node: &'a Syntax<Token, Value>) {
1754         match &node.syntax {
1755             FunctionDeclarationHeader(x) => {
1756                 let function_parameter_list = &x.function_parameter_list;
1757                 let function_type = &x.function_type;
1759                 self.produce_error(
1760                     |self_, x| Self::class_constructor_has_non_void_type(self_, x),
1761                     node,
1762                     || errors::error2018,
1763                     function_type,
1764                 );
1766                 self.produce_error(
1767                     |_, x| Self::class_non_constructor_has_visibility_param(x),
1768                     node,
1769                     || errors::error2010,
1770                     function_parameter_list,
1771                 );
1773                 if let Some(clashing_name) = self.class_constructor_param_promotion_clash(node) {
1774                     let class_name = self.active_classish_name().unwrap_or("");
1775                     let error_msg = errors::error2025(class_name, &clashing_name);
1776                     self.errors.push(Self::make_error_from_node(
1777                         function_parameter_list,
1778                         error_msg,
1779                     ))
1780                 }
1782                 self.produce_error(
1783                     |_, x| Self::abstract_class_constructor_has_visibility_param(x),
1784                     node,
1785                     || errors::error2023,
1786                     function_parameter_list,
1787                 );
1789                 self.produce_error(
1790                     |self_, x| Self::interface_or_trait_has_visibility_param(self_, x),
1791                     node,
1792                     || errors::error2024,
1793                     function_parameter_list,
1794                 );
1795                 self.function_declaration_header_memoize_lsb();
1796             }
1797             FunctionDeclaration(fd) => {
1798                 let function_attrs = &fd.function_attribute_spec;
1799                 self.produce_error(
1800                     |self_, x| Self::function_multiple_reactivity_annotations(self_, x),
1801                     node,
1802                     || errors::multiple_reactivity_annotations,
1803                     function_attrs,
1804                 );
1805                 self.error_if_memoize_function_returns_mutable(function_attrs);
1807                 self.produce_error(
1808                     |self_, x| {
1809                         Self::function_declaration_contains_only_rx_if_impl_attribute(self_, x)
1810                     },
1811                     node,
1812                     || errors::functions_cannot_implement_reactive,
1813                     function_attrs,
1814                 );
1815                 self.check_nonrx_annotation(node);
1817                 self.produce_error(
1818                     |self_, x| Self::function_missing_reactivity_for_condition(self_, x),
1819                     node,
1820                     || errors::missing_reactivity_for_condition,
1821                     function_attrs,
1822                 );
1824                 self.produce_error(
1825                     |self_, x| {
1826                         Self::function_declaration_contains_owned_mutable_attribute(self_, x)
1827                     },
1828                     node,
1829                     || errors::misplaced_owned_mutable,
1830                     function_attrs,
1831                 );
1833                 self.invalid_modifier_errors("Top-level functions", node, |kind| {
1834                     kind == TokenKind::Async || kind == TokenKind::Coroutine
1835                 });
1836             }
1837             MethodishDeclaration(md) => {
1838                 let header_node = &md.methodish_function_decl_header;
1839                 let modifiers = Self::modifiers_of_function_decl_header_exn(header_node);
1840                 let class_name = self.active_classish_name().unwrap_or("");
1841                 let method_name = self
1842                     .extract_function_name(&md.methodish_function_decl_header)
1843                     .unwrap_or("");
1844                 let method_attrs = &md.methodish_attribute;
1845                 self.error_if_memoize_function_returns_mutable(method_attrs);
1846                 self.produce_error(
1847                     |self_, x| self_.methodish_contains_memoize(x),
1848                     node,
1849                     || errors::interface_with_memoize,
1850                     header_node,
1851                 );
1852                 self.produce_error(
1853                     |self_, x| self_.class_constructor_has_static(x),
1854                     header_node,
1855                     || errors::error2009(class_name, method_name),
1856                     modifiers,
1857                 );
1858                 self.unsupported_magic_method_errors(header_node);
1859                 self.produce_error(
1860                     |self_, x| self_.async_magic_method(x),
1861                     header_node,
1862                     || errors::async_magic_method(method_name),
1863                     modifiers,
1864                 );
1865                 self.produce_error(
1866                     |self_, x| self_.clone_takes_no_arguments(x),
1867                     header_node,
1868                     || errors::clone_takes_no_arguments(class_name, method_name),
1869                     modifiers,
1870                 );
1871                 self.produce_error(
1872                     |self_, x| self_.clone_cannot_be_static(x),
1873                     header_node,
1874                     || errors::clone_cannot_be_static(class_name, method_name),
1875                     modifiers,
1876                 );
1877                 self.invalid_modifier_errors("Methods", node, |kind| {
1878                     kind == TokenKind::Abstract
1879                         || kind == TokenKind::Final
1880                         || kind == TokenKind::Static
1881                         || kind == TokenKind::Private
1882                         || kind == TokenKind::Protected
1883                         || kind == TokenKind::Public
1884                         || kind == TokenKind::Async
1885                         || kind == TokenKind::Coroutine
1886                 });
1888                 if self.is_inside_interface() {
1889                     self.invalid_modifier_errors("Interface methods", node, |kind| {
1890                         kind != TokenKind::Final
1891                     });
1892                 };
1894                 if Self::has_modifier_static(node)
1895                     && (self.attribute_specification_contains(
1896                         method_attrs,
1897                         sn::user_attributes::MUTABLE,
1898                     ) || self.attribute_specification_contains(
1899                         method_attrs,
1900                         sn::user_attributes::MAYBE_MUTABLE,
1901                     ))
1902                 {
1903                     self.errors.push(Self::make_error_from_node(
1904                         node,
1905                         errors::mutability_annotation_on_static_method,
1906                     ))
1907                 };
1909                 if method_name.eq_ignore_ascii_case(sn::members::__CONSTRUCT)
1910                     && (self.attribute_specification_contains(
1911                         method_attrs,
1912                         sn::user_attributes::MUTABLE,
1913                     ) || self.attribute_specification_contains(
1914                         method_attrs,
1915                         sn::user_attributes::MAYBE_MUTABLE,
1916                     ) || self.attribute_specification_contains(
1917                         method_attrs,
1918                         sn::user_attributes::MUTABLE_RETURN,
1919                     ))
1920                 {
1921                     self.errors.push(Self::make_error_from_node(
1922                         node,
1923                         errors::mutability_annotation_on_constructor,
1924                     ))
1925                 };
1927                 let fun_semicolon = &md.methodish_semicolon;
1929                 self.produce_error(
1930                     |self_, x| self_.methodish_non_abstract_without_body_not_native(x),
1931                     node,
1932                     || errors::error2015(class_name, method_name),
1933                     fun_semicolon,
1934                 );
1935                 self.produce_error(
1936                     |_, x| Self::methodish_abstract_conflict_with_private(x),
1937                     node,
1938                     || errors::error2016(class_name, method_name),
1939                     modifiers,
1940                 );
1942                 if let Some(modifier) = Self::get_modifier_final(modifiers) {
1943                     self.produce_error(
1944                         |_, x| Self::has_modifier_abstract(x),
1945                         node,
1946                         || errors::error2019(class_name, method_name),
1947                         modifier,
1948                     );
1949                 }
1951                 self.produce_error(
1952                     |self_, x| self_.methodish_abstract_inside_interface(x),
1953                     node,
1954                     || errors::error2045,
1955                     modifiers,
1956                 );
1957                 self.methodish_memoize_lsb_on_non_static(node);
1958                 let async_annotation =
1959                     Self::extract_keyword(|x| x.is_async(), node).unwrap_or(node);
1961                 self.produce_error(
1962                     |self_, x| self_.is_interface_and_async_method(x),
1963                     node,
1964                     || errors::error2046("a method in an interface"),
1965                     async_annotation,
1966                 );
1968                 self.produce_error(
1969                     |_, x| Self::is_abstract_and_async_method(x),
1970                     node,
1971                     || errors::error2046("an abstract method"),
1972                     async_annotation,
1973                 );
1975                 if self.env.is_typechecker() {
1976                     self.produce_error(
1977                         |_, x| Self::contains_async_not_last(x),
1978                         modifiers,
1979                         || errors::async_not_last,
1980                         modifiers,
1981                     );
1982                 }
1983                 self.produce_error(
1984                     |self_, x| self_.methodish_multiple_reactivity_annotations(x),
1985                     node,
1986                     || errors::multiple_reactivity_annotations,
1987                     method_attrs,
1988                 );
1989                 self.check_nonrx_annotation(node);
1990                 self.produce_error(
1991                     |self_, x| self_.methodish_missing_reactivity_for_condition(x),
1992                     node,
1993                     || errors::missing_reactivity_for_condition,
1994                     method_attrs,
1995                 );
1996                 self.produce_error(
1997                     |self_, x| self_.methodish_contains_owned_mutable_attribute(x),
1998                     node,
1999                     || errors::misplaced_owned_mutable,
2000                     method_attrs,
2001                 );
2002             }
2003             _ => (),
2004         }
2005     }
2007     fn is_hashbang(&self, node: &'a Syntax<Token, Value>) -> bool {
2008         let text = self.text(node);
2009         lazy_static! {
2010             static ref RE: Regex = Regex::new("^#!.*\n").unwrap();
2011         }
2012         text.lines().nth(1).is_none() && // only one line
2013         RE.is_match(text)
2014     }
2016     fn is_in_construct_method(&self) -> bool {
2017         if self.is_immediately_in_lambda() {
2018             false
2019         } else {
2020             self.first_parent_function_name()
2021                 .map_or(false, |s| s.eq_ignore_ascii_case(sn::members::__CONSTRUCT))
2022         }
2023     }
2025     // If a variadic parameter has a default value, return it
2026     fn variadic_param_with_default_value(
2027         params: &'a Syntax<Token, Value>,
2028     ) -> Option<&'a Syntax<Token, Value>> {
2029         Self::variadic_param(params).filter(|x| Self::is_parameter_with_default_value(x))
2030     }
2032     // If a variadic parameter is marked inout, return it
2033     fn variadic_param_with_callconv(
2034         params: &'a Syntax<Token, Value>,
2035     ) -> Option<&'a Syntax<Token, Value>> {
2036         Self::variadic_param(params).filter(|x| Self::is_parameter_with_callconv(x))
2037     }
2039     // If an inout parameter has a default, return the default
2040     fn param_with_callconv_has_default(
2041         node: &'a Syntax<Token, Value>,
2042     ) -> Option<&'a Syntax<Token, Value>> {
2043         match &node.syntax {
2044             ParameterDeclaration(x)
2045                 if Self::is_parameter_with_callconv(node)
2046                     && Self::is_parameter_with_default_value(&node) =>
2047             {
2048                 Some(&x.parameter_default_value)
2049             }
2050             _ => None,
2051         }
2052     }
2054     fn params_errors(&mut self, params: &'a Syntax<Token, Value>) {
2055         self.produce_error_from_check(&Self::ends_with_variadic_comma, params, || {
2056             errors::error2022
2057         });
2058         self.produce_error_from_check(&Self::misplaced_variadic_param, params, || {
2059             errors::error2021
2060         });
2062         self.produce_error_from_check(&Self::variadic_param_with_default_value, params, || {
2063             errors::error2065
2064         });
2066         self.produce_error_from_check(&Self::variadic_param_with_callconv, params, || {
2067             errors::error2073
2068         });
2069     }
2071     fn decoration_errors(&mut self, node: &'a Syntax<Token, Value>) {
2072         self.produce_error(
2073             |_, x| Self::is_double_variadic(x),
2074             node,
2075             || errors::double_variadic,
2076             node,
2077         );
2078     }
2080     fn parameter_rx_errors(&mut self, node: &'a Syntax<Token, Value>) {
2081         if let ParameterDeclaration(x) = &node.syntax {
2082             let spec = &x.parameter_attribute;
2083             let name = &x.parameter_name;
2084             let has_owned_mutable =
2085                 self.attribute_specification_contains(spec, sn::user_attributes::OWNED_MUTABLE);
2087             let has_mutable =
2088                 self.attribute_specification_contains(spec, sn::user_attributes::MUTABLE);
2090             let has_maybemutable =
2091                 self.attribute_specification_contains(spec, sn::user_attributes::MAYBE_MUTABLE);
2093             match (has_mutable, has_owned_mutable, has_maybemutable) {
2094                 (true, true, _) => self.errors.push(Self::make_error_from_node(
2095                     node,
2096                     errors::conflicting_mutable_and_owned_mutable_attributes,
2097                 )),
2098                 (true, _, true) => self.errors.push(Self::make_error_from_node(
2099                     node,
2100                     errors::conflicting_mutable_and_maybe_mutable_attributes,
2101                 )),
2102                 (_, true, true) => self.errors.push(Self::make_error_from_node(
2103                     node,
2104                     errors::conflicting_owned_mutable_and_maybe_mutable_attributes,
2105                 )),
2106                 _ => (),
2107             }
2108             if (has_mutable || has_owned_mutable || has_maybemutable)
2109                 && Self::is_variadic_expression(name)
2110             {
2111                 self.errors
2112                     .push(Self::make_error_from_node(name, errors::vararg_and_mutable))
2113             }
2114             let is_inout = Self::is_parameter_with_callconv(node);
2115             if is_inout && (has_mutable || has_maybemutable || has_owned_mutable) {
2116                 self.errors.push(Self::make_error_from_node(
2117                     node,
2118                     errors::mutability_annotation_on_inout_parameter,
2119                 ))
2120             }
2121             if has_owned_mutable || has_mutable {
2122                 let attrs = self.env.context.active_callable_attr_spec;
2123                 let active_is_rx = self.env.context.active_is_rx_or_enclosing_for_lambdas;
2125                 let parent_func_is_memoize = attrs
2126                     .map(|spec| {
2127                         self.attribute_specification_contains(spec, sn::user_attributes::MEMOIZE)
2128                             || self.attribute_specification_contains(
2129                                 spec,
2130                                 sn::user_attributes::MEMOIZE,
2131                             )
2132                     })
2133                     .unwrap_or(false);
2135                 if has_owned_mutable && !active_is_rx {
2136                     self.errors.push(Self::make_error_from_node(
2137                         node,
2138                         errors::mutably_owned_attribute_on_non_rx_function,
2139                     ))
2140                 }
2141                 if has_mutable && parent_func_is_memoize {
2142                     self.errors.push(Self::make_error_from_node(
2143                         node,
2144                         errors::mutable_parameter_in_memoize_function(false),
2145                     ))
2146                 }
2147             }
2148         }
2149     }
2151     fn does_unop_create_write(token_kind: Option<TokenKind>) -> bool {
2152         token_kind.map_or(false, |x| match x {
2153             TokenKind::PlusPlus | TokenKind::MinusMinus => true,
2154             _ => false,
2155         })
2156     }
2158     fn does_decorator_create_write(token_kind: Option<TokenKind>) -> bool {
2159         match token_kind {
2160             Some(TokenKind::Inout) => true,
2161             _ => false,
2162         }
2163     }
2165     fn node_lval_type<'b>(
2166         node: &'a Syntax<Token, Value>,
2167         parents: &'b [&'a Syntax<Token, Value>],
2168     ) -> LvalType {
2169         let is_in_final_lval_position = |mut node, parents: &'b [&'a Syntax<Token, Value>]| {
2170             for &parent in parents.iter().rev() {
2171                 match &parent.syntax {
2172                     SyntaxList(_) | ListItem(_) => {
2173                         node = parent;
2174                         continue;
2175                     }
2176                     ExpressionStatement(_) => return true,
2177                     ForStatement(x)
2178                         if node as *const _ == &x.for_initializer as *const _
2179                             || node as *const _ == &x.for_end_of_loop as *const _ =>
2180                     {
2181                         return true
2182                     }
2183                     UsingStatementFunctionScoped(x)
2184                         if node as *const _ == &x.using_function_expression as *const _ =>
2185                     {
2186                         return true
2187                     }
2188                     UsingStatementBlockScoped(x)
2189                         if node as *const _ == &x.using_block_expressions as *const _ =>
2190                     {
2191                         return true
2192                     }
2193                     _ => return false,
2194                 }
2195             }
2196             false
2197         };
2198         let get_arg_call_node_with_parents = |mut node, parents: &'b [&'a Syntax<Token, Value>]| {
2199             for i in (0..parents.len()).rev() {
2200                 let parent = parents[i];
2201                 match &parent.syntax {
2202                     SyntaxList(_) | ListItem(_) => {
2203                         node = parent;
2204                         continue;
2205                     }
2206                     FunctionCallExpression(x)
2207                         if node as *const _ == &x.function_call_argument_list as *const _ =>
2208                     {
2209                         if i == 0 {
2210                             // probably unreachable, but just in case to avoid crashing on 0-1
2211                             return Some((parent, &parents[0..0]));
2212                         }
2213                         let grandparent = parents.get(i - 1).unwrap();
2214                         return match &grandparent.syntax {
2215                             PrefixUnaryExpression(x)
2216                                 if Self::token_kind(&x.prefix_unary_operator)
2217                                     == Some(TokenKind::At) =>
2218                             {
2219                                 Some((grandparent, &parents[..i - 1]))
2220                             }
2221                             _ => Some((parent, &parents[..i])),
2222                         };
2223                     }
2224                     _ => return None,
2225                 }
2226             }
2227             None
2228         };
2230         let lval_ness_of_function_arg_for_inout =
2231             |node, parents| match get_arg_call_node_with_parents(node, parents) {
2232                 None => LvalTypeNone,
2233                 Some((call_node, parents)) => {
2234                     if is_in_final_lval_position(call_node, parents) {
2235                         return LvalTypeFinal;
2236                     }
2237                     match parents.last() {
2238                         None => LvalTypeNonFinalInout,
2239                         Some(parent) => match &parent.syntax {
2240                             BinaryExpression(x)
2241                                 if call_node as *const _ == &x.binary_right_operand as *const _
2242                                     && Self::does_binop_create_write_on_left(Self::token_kind(
2243                                         &x.binary_operator,
2244                                     )) =>
2245                             {
2246                                 if is_in_final_lval_position(parent, &parents[..parents.len() - 1])
2247                                 {
2248                                     LvalTypeFinal
2249                                 } else {
2250                                     LvalTypeNonFinalInout
2251                                 }
2252                             }
2253                             _ => LvalTypeNonFinalInout,
2254                         },
2255                     }
2256                 }
2257             };
2259         let unary_expression_operator = |x: &'a Syntax<Token, Value>| match &x.syntax {
2260             PrefixUnaryExpression(x) => &x.prefix_unary_operator,
2261             PostfixUnaryExpression(x) => &x.postfix_unary_operator,
2262             _ => panic!("expected expression operator"),
2263         };
2265         let unary_expression_operand = |x: &'a Syntax<Token, Value>| match &x.syntax {
2266             PrefixUnaryExpression(x) => &x.prefix_unary_operand,
2267             PostfixUnaryExpression(x) => &x.postfix_unary_operand,
2268             _ => panic!("expected expression operator"),
2269         };
2271         if let Some(next_node) = parents.last() {
2272             let parents = &parents[..parents.len() - 1];
2273             match &next_node.syntax {
2274                 DecoratedExpression(x)
2275                     if node as *const _ == &x.decorated_expression_expression as *const _
2276                         && Self::does_decorator_create_write(Self::token_kind(
2277                             &x.decorated_expression_decorator,
2278                         )) =>
2279                 {
2280                     lval_ness_of_function_arg_for_inout(next_node, parents)
2281                 }
2282                 PrefixUnaryExpression(_) | PostfixUnaryExpression(_)
2283                     if node as *const _ == unary_expression_operand(next_node) as *const _
2284                         && Self::does_unop_create_write(Self::token_kind(
2285                             unary_expression_operator(next_node),
2286                         )) =>
2287                 {
2288                     if is_in_final_lval_position(next_node, parents) {
2289                         LvalTypeFinal
2290                     } else {
2291                         LvalTypeNonFinal
2292                     }
2293                 }
2294                 BinaryExpression(x)
2295                     if node as *const _ == &x.binary_left_operand as *const _
2296                         && Self::does_binop_create_write_on_left(Self::token_kind(
2297                             &x.binary_operator,
2298                         )) =>
2299                 {
2300                     if is_in_final_lval_position(next_node, parents) {
2301                         LvalTypeFinal
2302                     } else {
2303                         LvalTypeNonFinal
2304                     }
2305                 }
2306                 ForeachStatement(x)
2307                     if node as *const _ == &x.foreach_key as *const _
2308                         || node as *const _ == &x.foreach_value as *const _ =>
2309                 {
2310                     LvalTypeFinal
2311                 }
2312                 _ => LvalTypeNone,
2313             }
2314         } else {
2315             LvalTypeNone
2316         }
2317     }
2319     fn lval_errors(&mut self, syntax_node: &'a Syntax<Token, Value>) {
2320         if self.env.parser_options.po_disable_lval_as_an_expression {
2321             if let LvalTypeNonFinal = Self::node_lval_type(syntax_node, &self.parents) {
2322                 self.errors.push(Self::make_error_from_node(
2323                     syntax_node,
2324                     errors::lval_as_expression,
2325                 ))
2326             }
2327         }
2328     }
2330     fn parameter_errors(&mut self, node: &'a Syntax<Token, Value>) {
2331         let param_errors = |self_: &mut Self, params| {
2332             for x in Self::syntax_to_list_no_separators(params) {
2333                 self_.parameter_rx_errors(x)
2334             }
2335             self_.params_errors(params)
2336         };
2337         match &node.syntax {
2338             ParameterDeclaration(p) => {
2339                 let callconv_text = self.text(Self::extract_callconv_node(node).unwrap_or(node));
2340                 self.produce_error_from_check(&Self::param_with_callconv_has_default, node, || {
2341                     errors::error2074(callconv_text)
2342                 });
2343                 self.parameter_rx_errors(node);
2344                 self.check_type_hint(&p.parameter_type);
2346                 if let Some(inout_modifier) = Self::parameter_callconv(node) {
2347                     if self.is_inside_async_method() {
2348                         self.errors.push(Self::make_error_from_node_with_type(
2349                             inout_modifier,
2350                             errors::inout_param_in_async,
2351                             ErrorType::RuntimeError,
2352                         ))
2353                     }
2354                     if self.is_in_construct_method() {
2355                         self.errors.push(Self::make_error_from_node(
2356                             inout_modifier,
2357                             errors::inout_param_in_construct,
2358                         ))
2359                     }
2360                     let in_memoize = self
2361                         .first_parent_function_attributes_contains(sn::user_attributes::MEMOIZE);
2362                     let in_memoize_lsb = self.first_parent_function_attributes_contains(
2363                         sn::user_attributes::MEMOIZE_LSB,
2364                     );
2366                     if (in_memoize || in_memoize_lsb) && !self.is_immediately_in_lambda() {
2367                         self.errors.push(Self::make_error_from_node_with_type(
2368                             inout_modifier,
2369                             errors::memoize_with_inout,
2370                             ErrorType::RuntimeError,
2371                         ))
2372                     }
2373                 }
2374             }
2375             FunctionDeclarationHeader(x) => param_errors(self, &x.function_parameter_list),
2376             AnonymousFunction(x) => param_errors(self, &x.anonymous_parameters),
2377             ClosureTypeSpecifier(x) => param_errors(self, &x.closure_parameter_list),
2378             LambdaExpression(x) => {
2379                 if let LambdaSignature(x) = &x.lambda_signature.syntax {
2380                     param_errors(self, &x.lambda_parameters)
2381                 }
2382             }
2383             DecoratedExpression(_) => self.decoration_errors(node),
2384             _ => (),
2385         }
2386     }
2388     // Only check the functions; invalid attributes on methods (like <<__EntryPoint>>) are caught elsewhere
2389     fn multiple_entrypoint_attribute_errors(&mut self, node: &'a Syntax<Token, Value>) {
2390         match &node.syntax {
2391             FunctionDeclaration(f)
2392                 if self.attribute_specification_contains(
2393                     &f.function_attribute_spec,
2394                     sn::user_attributes::ENTRY_POINT,
2395                 ) =>
2396             {
2397                 // Get the location of the <<...>> annotation
2398                 let location = match &f.function_attribute_spec.syntax {
2399                     AttributeSpecification(x) => {
2400                         Self::make_location_of_node(&x.attribute_specification_attributes)
2401                     }
2402                     OldAttributeSpecification(x) => {
2403                         Self::make_location_of_node(&x.old_attribute_specification_attributes)
2404                     }
2405                     _ => panic!("Expected attribute specification node"),
2406                 };
2407                 let def = make_first_use_or_def(
2408                     false,
2409                     NameDef,
2410                     location,
2411                     &self.namespace_name,
2412                     sn::user_attributes::ENTRY_POINT,
2413                 );
2414                 match self.names.attributes.get(sn::user_attributes::ENTRY_POINT) {
2415                     Some(prev_def) => {
2416                         let (line_num, _) = self
2417                             .env
2418                             .text
2419                             .offset_to_position(prev_def.location.start_offset as isize);
2421                         let path = self.env.text.source_text().file_path().path_str();
2422                         let loc = String::from(path) + ":" + &line_num.to_string();
2423                         let err = errors::multiple_entrypoints(&loc);
2424                         let err_type = ErrorType::ParseError;
2425                         self.errors
2426                             .push(Self::make_error_from_node_with_type(node, err, err_type))
2427                     }
2428                     _ => (),
2429                 };
2430                 self.names
2431                     .attributes
2432                     .add(sn::user_attributes::ENTRY_POINT, def)
2433             }
2434             _ => (),
2435         }
2436     }
2438     fn redeclaration_errors(&mut self, node: &'a Syntax<Token, Value>) {
2439         match &node.syntax {
2440             FunctionDeclarationHeader(f) if !f.function_name.is_missing() => {
2441                 let mut it = self.parents.iter().rev();
2442                 let p1 = it.next();
2443                 let _ = it.next();
2444                 let p3 = it.next();
2445                 let p4 = it.next();
2446                 match (p1, p3, p4) {
2447                     (
2448                         Some(Syntax {
2449                             syntax: FunctionDeclaration(_),
2450                             ..
2451                         }),
2452                         Some(Syntax {
2453                             syntax: NamespaceBody(_),
2454                             ..
2455                         }),
2456                         _,
2457                     )
2458                     | (
2459                         Some(Syntax {
2460                             syntax: FunctionDeclaration(_),
2461                             ..
2462                         }),
2463                         _,
2464                         None,
2465                     )
2466                     | (
2467                         Some(Syntax {
2468                             syntax: MethodishDeclaration(_),
2469                             ..
2470                         }),
2471                         _,
2472                         _,
2473                     )
2474                     | (
2475                         Some(Syntax {
2476                             syntax: MethodishTraitResolution(_),
2477                             ..
2478                         }),
2479                         _,
2480                         _,
2481                     ) => {
2482                         let function_name = self.text(&f.function_name);
2483                         let location = Self::make_location_of_node(&f.function_name);
2484                         let is_method = match p1 {
2485                             Some(Syntax {
2486                                 syntax: MethodishDeclaration(_),
2487                                 ..
2488                             }) => true,
2489                             _ => false,
2490                         };
2491                         let def = make_first_use_or_def(
2492                             is_method,
2493                             NameDef,
2494                             location,
2495                             &self.namespace_name,
2496                             &function_name,
2497                         );
2498                         match self.names.functions.get(function_name) {
2499                             Some(prev_def)
2500                                 if prev_def.global == def.global && prev_def.kind == NameDef =>
2501                             {
2502                                 let (line_num, _) = self
2503                                     .env
2504                                     .text
2505                                     .offset_to_position(prev_def.location.start_offset as isize);
2507                                 let path = self.env.text.source_text().file_path().path_str();
2508                                 let loc = String::from(path) + ":" + &line_num.to_string();
2509                                 let (err, err_type) = match self.first_parent_class_name() {
2510                                     None => (
2511                                         errors::redeclaration_of_function(function_name, &loc),
2512                                         ErrorType::RuntimeError,
2513                                     ),
2514                                     Some(class_name) => {
2515                                         let full_name =
2516                                             String::from(class_name) + "::" + function_name;
2517                                         (
2518                                             errors::redeclaration_of_method(&full_name),
2519                                             ErrorType::ParseError,
2520                                         )
2521                                     }
2522                                 };
2523                                 self.errors
2524                                     .push(Self::make_error_from_node_with_type(node, err, err_type))
2525                             }
2526                             Some(prev_def) if (prev_def.kind != NameDef) => {
2527                                 let (line_num, _) = self
2528                                     .env
2529                                     .text
2530                                     .offset_to_position(prev_def.location.start_offset as isize);
2531                                 let line_num = line_num as usize;
2533                                 self.errors.push(Self::make_name_already_used_error(
2534                                     &f.function_name,
2535                                     &combine_names(&self.namespace_name, &function_name),
2536                                     &function_name,
2537                                     &def.location,
2538                                     &|x, y| errors::declared_name_is_already_in_use(line_num, x, y),
2539                                 ))
2540                             }
2541                             _ => (),
2542                         };
2543                         self.names.functions.add(function_name, def)
2544                     }
2545                     _ if self.env.is_typechecker() => self.errors.push(Self::make_error_from_node(
2546                         node,
2547                         errors::decl_outside_global_scope,
2548                     )),
2549                     _ => (),
2550                 }
2551             }
2552             _ => (),
2553         }
2554     }
2556     fn is_foreach_in_for(for_initializer: &'a Syntax<Token, Value>) -> bool {
2557         if let Some(Syntax {
2558             syntax: ListItem(x),
2559             ..
2560         }) = for_initializer.syntax_node_to_list().next()
2561         {
2562             x.list_item.is_as_expression()
2563         } else {
2564             false
2565         }
2566     }
2568     fn statement_errors(&mut self, node: &'a Syntax<Token, Value>) {
2569         let expect_colon = |colon: &'a Syntax<Token, Value>| match &colon.syntax {
2570             Token(m) if self.env.is_typechecker() && m.kind() != TokenKind::Colon => {
2571                 Some((colon, errors::error1020))
2572             }
2573             _ => None,
2574         };
2575         (match &node.syntax {
2576             TryStatement(x)
2577                 if x.try_catch_clauses.is_missing() && x.try_finally_clause.is_missing() =>
2578             {
2579                 Some((node, errors::error2007))
2580             }
2581             UsingStatementFunctionScoped(_) if !self.using_statement_function_scoped_is_legal() => {
2582                 Some((node, errors::using_st_function_scoped_top_level))
2583             }
2584             ForStatement(x) if Self::is_foreach_in_for(&x.for_initializer) => {
2585                 Some((node, errors::for_with_as_expression))
2586             }
2587             CaseLabel(x) => expect_colon(&x.case_colon),
2589             DefaultLabel(x) => expect_colon(&x.default_colon),
2590             _ => None,
2591         })
2592         .into_iter()
2593         .for_each(|(error_node, error_message)| {
2594             self.errors
2595                 .push(Self::make_error_from_node(error_node, error_message))
2596         })
2597     }
2599     fn invalid_shape_initializer_name(&mut self, node: &'a Syntax<Token, Value>) {
2600         match &node.syntax {
2601             LiteralExpression(x) => {
2602                 let is_str = match Self::token_kind(&x.literal_expression) {
2603                     Some(TokenKind::SingleQuotedStringLiteral) => true,
2605                     // TODO: Double quoted string are only legal
2606                     // if they contain no encapsulated expressions.
2607                     Some(TokenKind::DoubleQuotedStringLiteral) => true,
2608                     _ => false,
2609                 };
2610                 if !is_str {
2611                     self.errors.push(Self::make_error_from_node(
2612                         node,
2613                         errors::invalid_shape_field_name,
2614                     ))
2615                 }
2616             }
2617             ScopeResolutionExpression(_) => (),
2618             QualifiedName(_) => {
2619                 if self.env.is_typechecker() {
2620                     self.errors.push(Self::make_error_from_node(
2621                         node,
2622                         errors::invalid_shape_field_name,
2623                     ))
2624                 }
2625             }
2626             Token(_) if node.is_name() => {
2627                 if self.env.is_typechecker() {
2628                     self.errors.push(Self::make_error_from_node(
2629                         node,
2630                         errors::invalid_shape_field_name,
2631                     ))
2632                 }
2633             }
2634             _ => self.errors.push(Self::make_error_from_node(
2635                 node,
2636                 errors::invalid_shape_field_name,
2637             )),
2638         }
2639     }
2641     fn invalid_shape_field_check(&mut self, node: &'a Syntax<Token, Value>) {
2642         if let FieldInitializer(x) = &node.syntax {
2643             self.invalid_shape_initializer_name(&x.field_initializer_name)
2644         } else {
2645             self.errors.push(Self::make_error_from_node(
2646                 node,
2647                 errors::invalid_shape_field_name,
2648             ))
2649         }
2650     }
2652     fn is_in_unyieldable_magic_method(&self) -> bool {
2653         self.first_parent_function_name().map_or(false, |s| {
2654             let s = s.to_ascii_lowercase();
2655             match s {
2656                 _ if s == sn::members::__INVOKE => false,
2657                 _ => sn::members::AS_LOWERCASE_SET.contains(&s),
2658             }
2659         })
2660     }
2662     fn function_call_argument_errors(
2663         &mut self,
2664         in_constructor_call: bool,
2665         node: &'a Syntax<Token, Value>,
2666     ) {
2667         if let Some(e) = match &node.syntax {
2668             VariableExpression(x)
2669                 if self.text(&x.variable_expression) == sn::superglobals::GLOBALS =>
2670             {
2671                 Some(errors::globals_without_subscript)
2672             }
2673             DecoratedExpression(x) => {
2674                 if let Token(token) = &x.decorated_expression_decorator.syntax {
2675                     if token.kind() == TokenKind::Inout {
2676                         let expression = &x.decorated_expression_expression;
2677                         match &expression.syntax {
2678                             _ if in_constructor_call => Some(errors::inout_param_in_construct),
2679                             VariableExpression(x)
2680                                 if sn::superglobals::is_any_global(
2681                                     self.text(&x.variable_expression),
2682                                 ) =>
2683                             {
2684                                 Some(errors::fun_arg_invalid_arg)
2685                             }
2686                             BinaryExpression(_) => Some(errors::fun_arg_inout_set),
2687                             QualifiedName(_) => Some(errors::fun_arg_inout_const),
2688                             Token(_) if expression.is_name() => Some(errors::fun_arg_inout_const),
2689                             // TODO: Maybe be more descriptive in error messages
2690                             ScopeResolutionExpression(_)
2691                             | FunctionCallExpression(_)
2692                             | MemberSelectionExpression(_)
2693                             | SafeMemberSelectionExpression(_) => Some(errors::fun_arg_invalid_arg),
2694                             SubscriptExpression(x) => match &x.subscript_receiver.syntax {
2695                                 MemberSelectionExpression(_) | ScopeResolutionExpression(_) => {
2696                                     Some(errors::fun_arg_invalid_arg)
2697                                 }
2698                                 _ => {
2699                                     let text = self.text(&x.subscript_receiver);
2700                                     if sn::superglobals::is_any_global(text) {
2701                                         Some(errors::fun_arg_inout_containers)
2702                                     } else {
2703                                         None
2704                                     }
2705                                 }
2706                             },
2707                             _ => None,
2708                         }
2709                     } else {
2710                         None
2711                     }
2712                 } else {
2713                     None
2714                 }
2715             }
2716             _ => None,
2717         } {
2718             self.errors.push(Self::make_error_from_node(node, e))
2719         }
2720     }
2722     fn function_call_on_xhp_name_errors(&mut self, node: &'a Syntax<Token, Value>) {
2723         let check = |self_: &mut Self,
2724                      member_object: &'a Syntax<Token, Value>,
2725                      name: &'a Syntax<Token, Value>| {
2726             if let XHPExpression(_) = &member_object.syntax {
2727                 if self_.env.is_typechecker() {
2728                     self_.errors.push(Self::make_error_from_node(
2729                         node,
2730                         errors::method_calls_on_xhp_expression,
2731                     ))
2732                 }
2733             }
2735             if let Token(token) = &name.syntax {
2736                 if token.kind() == TokenKind::XHPClassName {
2737                     self_.errors.push(Self::make_error_from_node(
2738                         node,
2739                         errors::method_calls_on_xhp_attributes,
2740                     ))
2741                 }
2742             }
2743         };
2744         match &node.syntax {
2745             MemberSelectionExpression(x) => check(self, &x.member_object, &x.member_name),
2746             SafeMemberSelectionExpression(x) => {
2747                 check(self, &x.safe_member_object, &x.safe_member_name)
2748             }
2749             _ => (),
2750         }
2751     }
2753     fn no_async_before_lambda_body(&mut self, body_node: &'a Syntax<Token, Value>) {
2754         if let AwaitableCreationExpression(_) = &body_node.syntax {
2755             if self.env.is_typechecker() {
2756                 self.errors.push(Self::make_error_from_node(
2757                     body_node,
2758                     errors::no_async_before_lambda_body,
2759                 ))
2760             }
2761         }
2762     }
2764     fn no_memoize_attribute_on_lambda(&mut self, node: &'a Syntax<Token, Value>) {
2765         match &node.syntax {
2766             OldAttributeSpecification(_) | AttributeSpecification(_) => {
2767                 for node in Self::attr_spec_to_node_list(node) {
2768                     match self.attr_name(node) {
2769                         Some(n)
2770                             if n == sn::user_attributes::MEMOIZE
2771                                 || n == sn::user_attributes::MEMOIZE_LSB =>
2772                         {
2773                             self.errors
2774                                 .push(Self::make_error_from_node(node, errors::memoize_on_lambda))
2775                         }
2777                         _ => (),
2778                     }
2779                 }
2780             }
2782             _ => (),
2783         }
2784     }
2786     fn is_good_scope_resolution_qualifier(node: &'a Syntax<Token, Value>) -> bool {
2787         match &node.syntax {
2788             QualifiedName(_) => true,
2789             Token(token) => match token.kind() {
2790                 TokenKind::XHPClassName
2791                 | TokenKind::Name
2792                 | TokenKind::SelfToken
2793                 | TokenKind::Parent
2794                 | TokenKind::Static => true,
2795                 _ => false,
2796             },
2797             _ => false,
2798         }
2799     }
2801     fn new_variable_errors_(
2802         &mut self,
2803         node: &'a Syntax<Token, Value>,
2804         inside_scope_resolution: bool,
2805     ) {
2806         match &node.syntax {
2807             SimpleTypeSpecifier(_)
2808             | VariableExpression(_)
2809             | GenericTypeSpecifier(_)
2810             | PipeVariableExpression(_) => (),
2811             SubscriptExpression(x) if x.subscript_index.is_missing() => self.errors.push(
2812                 Self::make_error_from_node(node, errors::instanceof_missing_subscript_index),
2813             ),
2814             SubscriptExpression(x) => {
2815                 self.new_variable_errors_(&x.subscript_receiver, inside_scope_resolution)
2816             }
2817             MemberSelectionExpression(x) => {
2818                 if inside_scope_resolution {
2819                     self.errors.push(Self::make_error_from_node(
2820                         node,
2821                         errors::instanceof_memberselection_inside_scoperesolution,
2822                     ))
2823                 } else {
2824                     self.new_variable_errors_(&x.member_object, inside_scope_resolution)
2825                 }
2826             }
2827             ScopeResolutionExpression(x) => {
2828                 if let Token(name) = &x.scope_resolution_name.syntax {
2829                     if Self::is_good_scope_resolution_qualifier(&x.scope_resolution_qualifier)
2830                         && name.kind() == TokenKind::Variable
2831                     {
2832                         // OK
2833                     } else if name.kind() == TokenKind::Variable {
2834                         self.new_variable_errors_(&x.scope_resolution_qualifier, true)
2835                     } else {
2836                         self.errors.push(Self::make_error_from_node(
2837                             node,
2838                             errors::instanceof_invalid_scope_resolution,
2839                         ))
2840                     }
2841                 } else {
2842                     self.errors.push(Self::make_error_from_node(
2843                         node,
2844                         errors::instanceof_invalid_scope_resolution,
2845                     ))
2846                 }
2847             }
2848             _ => {
2849                 self.errors.push(Self::make_error_from_node(
2850                     node,
2851                     errors::instanceof_new_unknown_node(node.kind().to_string()),
2852                 ));
2853             }
2854         }
2855     }
2857     fn new_variable_errors(&mut self, node: &'a Syntax<Token, Value>) {
2858         self.new_variable_errors_(node, false)
2859     }
2861     fn class_type_designator_errors(&mut self, node: &'a Syntax<Token, Value>) {
2862         if !Self::is_good_scope_resolution_qualifier(node) {
2863             match &node.syntax {
2864                 ParenthesizedExpression(_) => (),
2865                 _ => self.new_variable_errors(node),
2866             }
2867         }
2868     }
2870     fn rec_walk_impl<F, X>(
2871         &self,
2872         parents: &mut Vec<&'a Syntax<Token, Value>>,
2873         f: &F,
2874         node: &'a Syntax<Token, Value>,
2875         mut acc: X,
2876     ) -> X
2877     where
2878         F: Fn(&'a Syntax<Token, Value>, &Vec<&'a Syntax<Token, Value>>, X) -> (bool, X),
2879     {
2880         let (continue_walk, new_acc) = f(node, parents, acc);
2881         acc = new_acc;
2882         if continue_walk {
2883             parents.push(node);
2884             for child in node.iter_children() {
2885                 acc = self.rec_walk_impl(parents, f, child, acc);
2886             }
2887             parents.pop();
2888         }
2889         acc
2890     }
2892     fn rec_walk<F, X>(&self, f: F, node: &'a Syntax<Token, Value>, acc: X) -> X
2893     where
2894         F: Fn(&'a Syntax<Token, Value>, &Vec<&'a Syntax<Token, Value>>, X) -> (bool, X),
2895     {
2896         self.rec_walk_impl(&mut vec![], &f, node, acc)
2897     }
2899     fn find_invalid_lval_usage(&self, node: &'a Syntax<Token, Value>) -> Vec<SyntaxError> {
2900         self.rec_walk(
2901             |node, parents, mut acc| match &node.syntax {
2902                 AnonymousFunction(_) | LambdaExpression(_) | AwaitableCreationExpression(_) => {
2903                     (false, acc)
2904                 }
2905                 _ => {
2906                     match Self::node_lval_type(node, parents) {
2907                         LvalTypeFinal | LvalTypeNone => (),
2908                         LvalTypeNonFinalInout | LvalTypeNonFinal => {
2909                             acc.push(Self::make_error_from_node(node, errors::lval_as_expression))
2910                         }
2911                     };
2912                     (true, acc)
2913                 }
2914             },
2915             node,
2916             vec![],
2917         )
2918     }
2920     fn does_binop_create_write_on_left(token_kind: Option<TokenKind>) -> bool {
2921         token_kind.map_or(false, |x| match x {
2922             TokenKind::Equal
2923             | TokenKind::BarEqual
2924             | TokenKind::PlusEqual
2925             | TokenKind::StarEqual
2926             | TokenKind::StarStarEqual
2927             | TokenKind::SlashEqual
2928             | TokenKind::DotEqual
2929             | TokenKind::MinusEqual
2930             | TokenKind::PercentEqual
2931             | TokenKind::CaratEqual
2932             | TokenKind::AmpersandEqual
2933             | TokenKind::LessThanLessThanEqual
2934             | TokenKind::GreaterThanGreaterThanEqual
2935             | TokenKind::QuestionQuestionEqual => true,
2936             _ => false,
2937         })
2938     }
2940     fn get_positions_binop_allows_await(
2941         t: &'a Syntax<Token, Value>,
2942     ) -> BinopAllowsAwaitInPositions {
2943         use TokenKind::*;
2944         match Self::token_kind(t) {
2945             None => BinopAllowAwaitNone,
2946             Some(t) => match t {
2947                 BarBar | AmpersandAmpersand | QuestionColon | QuestionQuestion | BarGreaterThan => {
2948                     BinopAllowAwaitLeft
2949                 }
2950                 Equal
2951                 | BarEqual
2952                 | PlusEqual
2953                 | StarEqual
2954                 | StarStarEqual
2955                 | SlashEqual
2956                 | DotEqual
2957                 | MinusEqual
2958                 | PercentEqual
2959                 | CaratEqual
2960                 | AmpersandEqual
2961                 | LessThanLessThanEqual
2962                 | GreaterThanGreaterThanEqual => BinopAllowAwaitRight,
2963                 Plus
2964                 | Minus
2965                 | Star
2966                 | Slash
2967                 | StarStar
2968                 | EqualEqualEqual
2969                 | LessThan
2970                 | GreaterThan
2971                 | Percent
2972                 | Dot
2973                 | EqualEqual
2974                 | ExclamationEqual
2975                 | ExclamationEqualEqual
2976                 | LessThanEqual
2977                 | LessThanEqualGreaterThan
2978                 | GreaterThanEqual
2979                 | Ampersand
2980                 | Bar
2981                 | LessThanLessThan
2982                 | GreaterThanGreaterThan
2983                 | Carat => BinopAllowAwaitBoth,
2984                 QuestionQuestionEqual | _ => BinopAllowAwaitNone,
2985             },
2986         }
2987     }
2989     fn unop_allows_await(t: &'a Syntax<Token, Value>) -> bool {
2990         use TokenKind::*;
2991         Self::token_kind(t).map_or(false, |t| match t {
2992             Exclamation | Tilde | Plus | Minus | At | Clone | Print => true,
2993             _ => false,
2994         })
2995     }
2997     fn await_as_an_expression_errors(&mut self, await_node: &'a Syntax<Token, Value>) {
2998         let mut prev = None;
2999         let mut node = await_node;
3000         for n in self.parents.iter().rev() {
3001             if let Some(prev) = prev {
3002                 node = prev;
3003             }
3004             prev = Some(n);
3005             match &n.syntax {
3006                 // statements that root for the concurrently executed await expressions
3007                 ExpressionStatement(_)
3008                 | ReturnStatement(_)
3009                 | UnsetStatement(_)
3010                 | EchoStatement(_)
3011                 | ThrowStatement(_) => break,
3012                 IfStatement(x) if node as *const _ == &x.if_condition as *const _ => break,
3013                 ForStatement(x) if node as *const _ == &x.for_initializer as *const _ => break,
3014                 SwitchStatement(x) if node as *const _ == &x.switch_expression as *const _ => break,
3015                 ForeachStatement(x) if node as *const _ == &x.foreach_collection as *const _ => {
3016                     break
3017                 }
3018                 UsingStatementBlockScoped(x)
3019                     if node as *const _ == &x.using_block_expressions as *const _ =>
3020                 {
3021                     break
3022                 }
3023                 UsingStatementFunctionScoped(x)
3024                     if node as *const _ == &x.using_function_expression as *const _ =>
3025                 {
3026                     break
3027                 }
3028                 LambdaExpression(x) if node as *const _ == &x.lambda_body as *const _ => break,
3029                 // Dependent awaits are not allowed currently
3030                 PrefixUnaryExpression(x)
3031                     if Self::token_kind(&x.prefix_unary_operator) == Some(TokenKind::Await) =>
3032                 {
3033                     self.errors.push(Self::make_error_from_node(
3034                         await_node,
3035                         errors::invalid_await_position_dependent,
3036                     ));
3037                     break;
3038                 }
3039                 // Unary based expressions have their own custom fanout
3040                 PrefixUnaryExpression(x) if Self::unop_allows_await(&x.prefix_unary_operator) => {
3041                     continue
3042                 }
3043                 PostfixUnaryExpression(x) if Self::unop_allows_await(&x.postfix_unary_operator) => {
3044                     continue
3045                 }
3046                 DecoratedExpression(x)
3047                     if Self::unop_allows_await(&x.decorated_expression_decorator) =>
3048                 {
3049                     continue
3050                 }
3051                 // Special case the pipe operator error message
3052                 BinaryExpression(x)
3053                     if node as *const _ == &x.binary_right_operand as *const _
3054                         && Self::token_kind(&x.binary_operator)
3055                             == Some(TokenKind::BarGreaterThan) =>
3056                 {
3057                     self.errors.push(Self::make_error_from_node(
3058                         await_node,
3059                         errors::invalid_await_position_pipe,
3060                     ));
3061                     break;
3062                 }
3063                 // left or right operand of binary expressions are considered legal locations
3064                 // if operator is not short-circuiting and containing expression
3065                 // is in legal location
3066                 BinaryExpression(x)
3067                     if (match Self::get_positions_binop_allows_await(&x.binary_operator) {
3068                         BinopAllowAwaitBoth => true,
3069                         BinopAllowAwaitLeft => {
3070                             node as *const _ == &x.binary_left_operand as *const _
3071                         }
3072                         BinopAllowAwaitRight => {
3073                             node as *const _ == &x.binary_right_operand as *const _
3074                         }
3075                         BinopAllowAwaitNone => false,
3076                     }) =>
3077                 {
3078                     continue
3079                 }
3080                 // test part of conditional expression is considered legal location if
3081                 //  onditional expression itself is in legal location
3082                 ConditionalExpression(x) if node as *const _ == &x.conditional_test as *const _ => {
3083                     continue
3084                 }
3085                 FunctionCallExpression(x)
3086                     if node as *const _ == &x.function_call_receiver as *const _
3087                         || node as *const _ == &x.function_call_argument_list as *const _
3088                             && !x
3089                                 .function_call_receiver
3090                                 .is_safe_member_selection_expression() =>
3091                 {
3092                     continue
3093                 }
3095                 // object of member selection expression or safe member selection expression
3096                 // is in legal position if member selection expression itself is in legal position
3097                 SafeMemberSelectionExpression(x)
3098                     if node as *const _ == &x.safe_member_object as *const _ =>
3099                 {
3100                     continue
3101                 }
3103                 // These are nodes where any position is valid
3104                 CastExpression(_)
3105                 | MemberSelectionExpression(_)
3106                 | ScopeResolutionExpression(_)
3107                 | IsExpression(_)
3108                 | AsExpression(_)
3109                 | NullableAsExpression(_)
3110                 | IssetExpression(_)
3111                 | ParenthesizedExpression(_)
3112                 | BracedExpression(_)
3113                 | EmbeddedBracedExpression(_)
3114                 | CollectionLiteralExpression(_)
3115                 | ObjectCreationExpression(_)
3116                 | ConstructorCall(_)
3117                 | ShapeExpression(_)
3118                 | TupleExpression(_)
3119                 | ArrayIntrinsicExpression(_)
3120                 | DarrayIntrinsicExpression(_)
3121                 | DictionaryIntrinsicExpression(_)
3122                 | KeysetIntrinsicExpression(_)
3123                 | VarrayIntrinsicExpression(_)
3124                 | VectorIntrinsicExpression(_)
3125                 | ElementInitializer(_)
3126                 | FieldInitializer(_)
3127                 | SimpleInitializer(_)
3128                 | SubscriptExpression(_)
3129                 | EmbeddedSubscriptExpression(_)
3130                 | YieldExpression(_)
3131                 | XHPExpression(_)
3132                 | XHPOpen(_)
3133                 | XHPSimpleAttribute(_)
3134                 | XHPSpreadAttribute(_)
3135                 | SyntaxList(_)
3136                 | ListItem(_) => continue,
3137                 // otherwise report error and bail out
3138                 _ => {
3139                     self.errors.push(Self::make_error_from_node(
3140                         await_node,
3141                         errors::invalid_await_position,
3142                     ));
3143                     break;
3144                 }
3145             }
3146         }
3147         let is_in_concurrent = self
3148             .parents
3149             .iter()
3150             .rev()
3151             .any(|parent| match &parent.syntax {
3152                 ConcurrentStatement(_) => true,
3153                 _ => false,
3154             });
3155         if !is_in_concurrent {
3156             let await_node_statement_parent =
3157                 self.parents
3158                     .iter()
3159                     .rev()
3160                     .find(|parent| match &parent.syntax {
3161                         ExpressionStatement(_)
3162                         | ReturnStatement(_)
3163                         | UnsetStatement(_)
3164                         | EchoStatement(_)
3165                         | ThrowStatement(_)
3166                         | IfStatement(_)
3167                         | ForStatement(_)
3168                         | SwitchStatement(_)
3169                         | ForeachStatement(_) => true,
3170                         _ => false,
3171                     });
3172             if let Some(x) = await_node_statement_parent {
3173                 for error in self.find_invalid_lval_usage(x) {
3174                     self.errors.push(error)
3175                 }
3176             } else {
3177                 // We must have already errored in for loop
3178             }
3179         }
3180     }
3182     fn check_prefix_unary_dollar(node: &'a Syntax<Token, Value>) -> bool {
3183         match &node.syntax {
3184             PrefixUnaryExpression(x)
3185                 if Self::token_kind(&x.prefix_unary_operator) == Some(TokenKind::Dollar) =>
3186             {
3187                 Self::check_prefix_unary_dollar(&x.prefix_unary_operand)
3188             }
3189             BracedExpression(_) | SubscriptExpression(_) | VariableExpression(_) => false, // these ones are valid
3190             LiteralExpression(_) | PipeVariableExpression(_) => false, // these ones get caught later
3191             _ => true,
3192         }
3193     }
3195     fn node_has_await_child(&mut self, node: &'a Syntax<Token, Value>) -> bool {
3196         self.rec_walk(
3197             |node, _parents, acc| {
3198                 let is_new_scope = match &node.syntax {
3199                     AnonymousFunction(_) | LambdaExpression(_) | AwaitableCreationExpression(_) => {
3200                         true
3201                     }
3202                     _ => false,
3203                 };
3204                 if is_new_scope {
3205                     (false, false)
3206                 } else {
3207                     let is_await = |n: &'a Syntax<Token, Value>| match &n.syntax {
3208                         PrefixUnaryExpression(x)
3209                             if Self::token_kind(&x.prefix_unary_operator)
3210                                 == Some(TokenKind::Await) =>
3211                         {
3212                             true
3213                         }
3214                         _ => false,
3215                     };
3216                     let found_await = acc || is_await(node);
3217                     (!found_await, found_await)
3218                 }
3219             },
3220             node,
3221             false,
3222         )
3223     }
3225     fn expression_errors(&mut self, node: &'a Syntax<Token, Value>) {
3226         let check_is_as_expression = |self_: &mut Self, hint: &'a Syntax<Token, Value>| {
3227             let n = match &node.syntax {
3228                 IsExpression(_) => "is",
3229                 _ => "as",
3230             };
3231             match &hint.syntax {
3232                 ClosureTypeSpecifier(_) if self_.env.is_hhvm_compat() => {
3233                     self_.errors.push(Self::make_error_from_node(
3234                         hint,
3235                         errors::invalid_is_as_expression_hint(n, "Callable"),
3236                     ));
3237                 }
3238                 SoftTypeSpecifier(_) => {
3239                     self_.errors.push(Self::make_error_from_node(
3240                         hint,
3241                         errors::invalid_is_as_expression_hint(n, "Soft"),
3242                     ));
3243                 }
3244                 AttributizedSpecifier(x)
3245                     if self_.attribute_specification_contains(
3246                         &x.attributized_specifier_attribute_spec,
3247                         "__Soft",
3248                     ) =>
3249                 {
3250                     self_.errors.push(Self::make_error_from_node(
3251                         hint,
3252                         errors::invalid_is_as_expression_hint(n, "Soft"),
3253                     ));
3254                 }
3255                 _ => (),
3256             }
3257         };
3258         match &node.syntax {
3259             // We parse the right hand side of `new` as a generic expression, but PHP
3260             // (and therefore Hack) only allow a certain subset of expressions, so we
3261             // should verify here that the expression we parsed is in that subset.
3262             // Refer: https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#instanceof-operator*)
3263             ConstructorCall(ctr_call) => {
3264                 for p in
3265                     Self::syntax_to_list_no_separators(&ctr_call.constructor_call_argument_list)
3266                 {
3267                     self.function_call_argument_errors(true, p);
3268                 }
3269                 self.class_type_designator_errors(&ctr_call.constructor_call_type);
3270                 if self.env.is_typechecker() {
3271                     // attr or list item -> syntax list -> attribute
3272                     match self.parents.iter().rev().nth(2) {
3273                         Some(a)
3274                             if a.is_attribute_specification()
3275                                 || a.is_old_attribute_specification()
3276                                 || a.is_file_attribute_specification() =>
3277                         {
3278                             ()
3279                         }
3280                         _ => {
3281                             if ctr_call.constructor_call_left_paren.is_missing()
3282                                 || ctr_call.constructor_call_right_paren.is_missing()
3283                             {
3284                                 let node = &ctr_call.constructor_call_type;
3285                                 let constructor_name = self.text(&ctr_call.constructor_call_type);
3286                                 self.errors.push(Self::make_error_from_node(
3287                                     node,
3288                                     errors::error2038(constructor_name),
3289                                 ));
3290                             }
3291                         }
3292                     }
3293                 };
3294             }
3295             LiteralExpression(x) => {
3296                 if let Token(token) = &x.literal_expression.syntax {
3297                     if token.kind() == TokenKind::DecimalLiteral
3298                         || token.kind() == TokenKind::DecimalLiteral
3299                     {
3300                         let text = self.text(&x.literal_expression);
3301                         if text.parse::<i64>().is_err() {
3302                             let error_text = if token.kind() == TokenKind::DecimalLiteral {
3303                                 errors::error2071(text)
3304                             } else {
3305                                 errors::error2072(text)
3306                             };
3307                             self.errors
3308                                 .push(Self::make_error_from_node(node, error_text))
3309                         }
3310                     }
3311                 }
3312             }
3314             SubscriptExpression(x)
3315                 if self.env.is_typechecker() && x.subscript_left_bracket.is_left_brace() =>
3316             {
3317                 self.errors
3318                     .push(Self::make_error_from_node(node, errors::error2020))
3319             }
3321             FunctionCallExpression(x) => {
3322                 let arg_list = &x.function_call_argument_list;
3323                 if let Some(h) = Self::misplaced_variadic_arg(arg_list) {
3324                     self.errors
3325                         .push(Self::make_error_from_node(h, errors::error2033))
3326                 }
3328                 for p in Self::syntax_to_list_no_separators(arg_list) {
3329                     self.function_call_argument_errors(false, p)
3330                 }
3331                 self.function_call_on_xhp_name_errors(&x.function_call_receiver);
3332             }
3333             ListExpression(x) if x.list_members.is_missing() && self.env.is_hhvm_compat() => {
3334                 if let Some(Syntax {
3335                     syntax: ForeachStatement(x),
3336                     ..
3337                 }) = self.parents.last()
3338                 {
3339                     if node as *const _ == &x.foreach_value as *const _ {
3340                         self.errors.push(Self::make_error_from_node_with_type(
3341                             node,
3342                             errors::error2077,
3343                             ErrorType::RuntimeError,
3344                         ))
3345                     }
3346                 }
3347             }
3349             ListExpression(_) => {
3350                 if self
3351                     .parents
3352                     .last()
3353                     .map_or(false, |e| e.is_return_statement())
3354                 {
3355                     self.errors
3356                         .push(Self::make_error_from_node(node, errors::list_must_be_lvar))
3357                 }
3358             }
3359             ShapeExpression(x) => {
3360                 for f in Self::syntax_to_list_no_separators(&x.shape_expression_fields).rev() {
3361                     self.invalid_shape_field_check(f)
3362                 }
3363             }
3364             DecoratedExpression(x) => {
3365                 let decorator = &x.decorated_expression_decorator;
3366                 if Self::token_kind(decorator) == Some(TokenKind::Await) {
3367                     self.await_as_an_expression_errors(node)
3368                 }
3369             }
3370             YieldExpression(_) => {
3371                 if self.is_in_unyieldable_magic_method() {
3372                     self.errors.push(Self::make_error_from_node(
3373                         node,
3374                         errors::yield_in_magic_methods,
3375                     ))
3376                 }
3377                 if self.env.context.active_callable.is_none() {
3378                     self.errors.push(Self::make_error_from_node(
3379                         node,
3380                         errors::yield_outside_function,
3381                     ))
3382                 }
3384                 if self.has_inout_params() {
3385                     let e = if self.is_inside_async_method() {
3386                         errors::inout_param_in_async_generator
3387                     } else {
3388                         errors::inout_param_in_generator
3389                     };
3390                     self.errors.push(Self::make_error_from_node_with_type(
3391                         node,
3392                         e,
3393                         ErrorType::RuntimeError,
3394                     ))
3395                 }
3396             }
3397             ScopeResolutionExpression(x) => {
3398                 let qualifier = &x.scope_resolution_qualifier;
3399                 let name = &x.scope_resolution_name;
3401                 let (is_dynamic_name, is_self_or_parent, is_valid) =
3402                 // PHP langspec allows string literals, variables
3403                 // qualified names, static, self and parent as valid qualifiers
3404                 // We do not allow string literals in hack
3405                 match (&qualifier.syntax , Self::token_kind(qualifier)) {
3406                 | (LiteralExpression (_), _) => (false, false, false),
3407                 | (QualifiedName (_), _) => (false, false, true),
3408                 | (_, Some (TokenKind::Name))
3409                 | (_, Some (TokenKind::XHPClassName))
3410                 | (_, Some (TokenKind::Static)) =>
3411                   (false, false, true),
3412                 | (_, Some (TokenKind::SelfToken))
3413                 | (_, Some (TokenKind::Parent)) =>
3414                   (false, true, true),
3415                 // ${}::class
3416                 | (PrefixUnaryExpression (x), _) if Self::token_kind(&x.prefix_unary_operator) == Some (TokenKind::Dollar) =>
3417                   (true, false, true),
3418                 | (PipeVariableExpression (_), _)
3419                 | (VariableExpression (_), _)
3420                 | (SimpleTypeSpecifier (_), _)
3421                 | (GenericTypeSpecifier (_), _) =>
3422                   (true, false, true),
3423                 | _ => (true, false, false),
3424             };
3425                 if !is_valid && self.env.is_typechecker() {
3426                     self.errors.push(Self::make_error_from_node(
3427                         node,
3428                         errors::invalid_scope_resolution_qualifier,
3429                     ))
3430                 }
3431                 let is_name_class = self.text(name).eq_ignore_ascii_case("class");
3432                 if (is_dynamic_name || !is_valid) && is_name_class {
3433                     self.errors.push(Self::make_error_from_node(
3434                         node,
3435                         errors::coloncolonclass_on_dynamic,
3436                     ))
3437                 }
3438                 let text_name = self.text(qualifier);
3439                 let is_name_namespace = text_name.eq_ignore_ascii_case("namespace");
3440                 if is_name_namespace {
3441                     self.errors.push(Self::make_error_from_node(
3442                         node,
3443                         errors::namespace_not_a_classname,
3444                     ))
3445                 }
3446                 if is_self_or_parent && is_name_class && !self.is_in_active_class_scope() {
3447                     self.errors.push(Self::make_error_from_node_with_type(
3448                         node,
3449                         errors::self_or_parent_colon_colon_class_outside_of_class(text_name),
3450                         ErrorType::RuntimeError,
3451                     ))
3452                 }
3453             }
3455             PrefixUnaryExpression(x)
3456                 if Self::token_kind(&x.prefix_unary_operator) == Some(TokenKind::Dollar) =>
3457             {
3458                 if Self::check_prefix_unary_dollar(node) {
3459                     self.errors
3460                         .push(Self::make_error_from_node(node, errors::dollar_unary))
3461                 }
3462             }
3464             // TODO(T21285960): Remove this bug-port, stemming from T22184312
3465             LambdaExpression(x)
3466                 if self.env.is_hhvm_compat()
3467                     && !x.lambda_async.is_missing()
3468                     && x.lambda_async.trailing_width() == 0
3469                     && x.lambda_signature.leading_width() == 0 =>
3470             {
3471                 self.errors
3472                     .push(Self::make_error_from_node(node, errors::error1057("==>")))
3473             }
3474             // End of bug-port
3475             IsExpression(x) => check_is_as_expression(self, &x.is_right_operand),
3476             AsExpression(x) => check_is_as_expression(self, &x.as_right_operand),
3478             ConditionalExpression(x) => {
3479                 if x.conditional_consequence.is_missing() && self.env.is_typechecker() {
3480                     self.errors.push(Self::make_error_from_node(
3481                         node,
3482                         errors::elvis_operator_space,
3483                     ))
3484                 }
3485                 if x.conditional_test.is_conditional_expression() && self.env.is_typechecker() {
3486                     self.errors
3487                         .push(Self::make_error_from_node(node, errors::nested_ternary))
3488                 }
3489                 match &x.conditional_alternative.syntax {
3490                     LambdaExpression(x)
3491                         if x.lambda_body.is_conditional_expression()
3492                             && self.env.is_typechecker() =>
3493                     {
3494                         self.errors
3495                             .push(Self::make_error_from_node(node, errors::nested_ternary))
3496                     }
3497                     _ => (),
3498                 }
3499             }
3500             LambdaExpression(x) => {
3501                 self.no_memoize_attribute_on_lambda(&x.lambda_attribute_spec);
3502                 self.no_async_before_lambda_body(&x.lambda_body);
3503             }
3504             AnonymousFunction(x) => {
3505                 self.no_memoize_attribute_on_lambda(&x.anonymous_attribute_spec)
3506             }
3507             AwaitableCreationExpression(x) => {
3508                 self.no_memoize_attribute_on_lambda(&x.awaitable_attribute_spec)
3509             }
3511             CollectionLiteralExpression(x) => {
3512                 enum Status {
3513                     ValidClass(String),
3514                     InvalidClass,
3515                     InvalidBraceKind,
3516                 }
3517                 use Status::*;
3519                 let n = &x.collection_literal_name;
3520                 let initializers = &x.collection_literal_initializers;
3522                 let is_standard_collection = |lc_name: &str| {
3523                     lc_name.eq_ignore_ascii_case("pair")
3524                         || lc_name.eq_ignore_ascii_case("vector")
3525                         || lc_name.eq_ignore_ascii_case("map")
3526                         || lc_name.eq_ignore_ascii_case("set")
3527                         || lc_name.eq_ignore_ascii_case("immvector")
3528                         || lc_name.eq_ignore_ascii_case("immmap")
3529                         || lc_name.eq_ignore_ascii_case("immset")
3530                 };
3531                 let use_key_value_initializers = |lc_name: &str| {
3532                     lc_name.eq_ignore_ascii_case("map") || lc_name.eq_ignore_ascii_case("immmap")
3533                 };
3534                 let is_qualified_std_collection = |l, r| {
3535                     Self::token_kind(l) == Some(TokenKind::Name)
3536                         && Self::token_kind(r) == Some(TokenKind::Name)
3537                         && self.text(l).eq_ignore_ascii_case("hh")
3538                         && is_standard_collection(&self.text(r))
3539                 };
3541                 let check_type_specifier = |n, t: &Token| {
3542                     if t.kind() == TokenKind::Name {
3543                         match self.text(n).to_ascii_lowercase().as_ref() {
3544                             "dict" | "vec" | "keyset" => InvalidBraceKind,
3545                             n => {
3546                                 if is_standard_collection(n) {
3547                                     ValidClass(n.to_string())
3548                                 } else {
3549                                     InvalidClass
3550                                 }
3551                             }
3552                         }
3553                     } else {
3554                         InvalidClass
3555                     }
3556                 };
3558                 let check_qualified_name = |parts| {
3559                     let mut parts = Self::syntax_to_list(false, parts);
3560                     let p1 = parts.next();
3561                     let p2 = parts.next();
3562                     let p3 = parts.next();
3563                     let p4 = parts.next();
3564                     match (p1, p2, p3, p4) {
3565                         (Some(l), Some(r), None, None)
3566                             if self.namespace_name == GLOBAL_NAMESPACE_NAME
3567                                 && is_qualified_std_collection(l, r) =>
3568                         {
3569                             // HH\Vector in global namespace
3570                             ValidClass(self.text(r).to_ascii_lowercase())
3571                         }
3572                         (Some(missing), Some(l), Some(r), None)
3573                             if missing.is_missing() && is_qualified_std_collection(l, r) =>
3574                         {
3575                             // \HH\Vector
3576                             ValidClass(self.text(r).to_ascii_lowercase())
3577                         }
3578                         _ => InvalidClass,
3579                     }
3580                 };
3581                 let status = match &n.syntax {
3582                     // non-qualified name
3583                     SimpleTypeSpecifier(x) => match &x.simple_type_specifier.syntax {
3584                         Token(t) => check_type_specifier(&x.simple_type_specifier, t),
3585                         QualifiedName(x) => check_qualified_name(&x.qualified_name_parts),
3586                         _ => InvalidClass,
3587                     },
3588                     GenericTypeSpecifier(x) => match &x.generic_class_type.syntax {
3589                         Token(t) => check_type_specifier(&x.generic_class_type, t),
3590                         QualifiedName(x) => check_qualified_name(&x.qualified_name_parts),
3591                         _ => InvalidClass,
3592                     },
3593                     _ => InvalidClass,
3594                 };
3596                 let is_key_value = |s: &Syntax<Token, Value>| {
3597                     if let ElementInitializer(_) = s.syntax {
3598                         true
3599                     } else {
3600                         false
3601                     }
3602                 };
3603                 let initializer_list = || Self::syntax_to_list_no_separators(initializers);
3604                 let num_initializers = initializer_list().count();
3605                 match &status {
3606                     ValidClass(name)
3607                         if use_key_value_initializers(name)
3608                             && initializer_list().any(|i| !is_key_value(i)) =>
3609                     {
3610                         self.errors.push(Self::make_error_from_node(
3611                             node,
3612                             errors::invalid_value_initializer(self.text(n)),
3613                         ));
3614                     }
3616                     ValidClass(name)
3617                         if !use_key_value_initializers(name)
3618                             && initializer_list().any(|i| is_key_value(i)) =>
3619                     {
3620                         self.errors.push(Self::make_error_from_node(
3621                             node,
3622                             errors::invalid_key_value_initializer(self.text(n)),
3623                         ));
3624                     }
3626                     ValidClass(pair) if pair == "pair" && num_initializers != 2 => {
3627                         let msg = if num_initializers == 0 {
3628                             errors::pair_initializer_needed
3629                         } else {
3630                             errors::pair_initializer_arity
3631                         };
3632                         self.errors.push(Self::make_error_from_node_with_type(
3633                             node,
3634                             msg,
3635                             ErrorType::RuntimeError,
3636                         ));
3637                     }
3639                     ValidClass(_) => (),
3640                     InvalidBraceKind => self.errors.push(Self::make_error_from_node(
3641                         node,
3642                         errors::invalid_brace_kind_in_collection_initializer,
3643                     )),
3644                     InvalidClass => self.errors.push(Self::make_error_from_node(
3645                         node,
3646                         errors::invalid_class_in_collection_initializer,
3647                     )),
3648                 }
3649             }
3650             PrefixUnaryExpression(x)
3651                 if Self::token_kind(&x.prefix_unary_operator) == Some(TokenKind::Await) =>
3652             {
3653                 self.await_as_an_expression_errors(node)
3654             }
3655             // Other kinds of expressions currently produce no expr errors.
3656             _ => (),
3657         }
3658     }
3660     fn check_repeated_properties_tconst_const(
3661         &mut self,
3662         full_name: &str,
3663         prop: &'a Syntax<Token, Value>,
3664         p_names: &mut HashSet<String>,
3665         c_names: &mut HashSet<String>,
3666     ) {
3667         let mut check = |sname, names: &mut HashSet<String>| {
3668             let name = self.text(sname);
3669             // If the name is empty, then there was an earlier
3670             // parsing error that should supercede this one.
3671             if name == "" {
3672             } else if names.contains(name) {
3673                 self.errors.push(Self::make_error_from_node(
3674                     prop,
3675                     errors::redeclaration_error(
3676                         &(Self::strip_ns(&full_name).to_string() + "::" + name),
3677                     ),
3678                 ))
3679             } else {
3680                 names.insert(name.to_owned());
3681             }
3682         };
3684         match &prop.syntax {
3685             PropertyDeclaration(x) => {
3686                 for prop in Self::syntax_to_list_no_separators(&x.property_declarators) {
3687                     if let PropertyDeclarator(x) = &prop.syntax {
3688                         check(&x.property_name, p_names)
3689                     }
3690                 }
3691             }
3692             ConstDeclaration(x) => {
3693                 for prop in Self::syntax_to_list_no_separators(&x.const_declarators) {
3694                     if let ConstantDeclarator(x) = &prop.syntax {
3695                         check(&x.constant_declarator_name, c_names)
3696                     }
3697                 }
3698             }
3699             TypeConstDeclaration(x) => check(&x.type_const_name, c_names),
3700             _ => (),
3701         }
3702     }
3704     fn require_errors(&mut self, node: &'a Syntax<Token, Value>) {
3705         if let RequireClause(p) = &node.syntax {
3706             let name = self.text(&p.require_name);
3707             let req_kind = Self::token_kind(&p.require_kind);
3708             match (self.trait_require_clauses.get(name), req_kind) {
3709                 (None, Some(tk)) => self.trait_require_clauses.add(name, tk),
3710                 (Some(tk1), Some(tk2)) if *tk1 == tk2 =>
3711                     // duplicate, it is okay
3712                     {}
3713                 _ => {
3714                     // Conflicting entry
3715                     self.errors.push(Self::make_error_from_node(
3716                         node,
3717                         errors::conflicting_trait_require_clauses(name),
3718                     ))
3719                 }
3720             };
3721             match (self.active_classish_kind(), req_kind) {
3722                 (Some(TokenKind::Interface), Some(TokenKind::Implements))
3723                 | (Some(TokenKind::Class), Some(TokenKind::Implements)) => self
3724                     .errors
3725                     .push(Self::make_error_from_node(node, errors::error2030)),
3726                 _ => (),
3727             }
3728         }
3729     }
3731     fn check_type_name(
3732         &mut self,
3733         name: &'a Syntax<Token, Value>,
3734         name_text: &str,
3735         location: Location,
3736     ) {
3737         match self.names.classes.get(name_text) {
3738             Some(FirstUseOrDef {
3739                 location,
3740                 kind,
3741                 name: def_name,
3742                 ..
3743             }) if &combine_names(&self.namespace_name, name_text) != def_name
3744                 && *kind != NameDef =>
3745             {
3746                 let (line_num, _) = self
3747                     .env
3748                     .text
3749                     .offset_to_position(location.start_offset as isize);
3750                 let line_num = line_num as usize;
3751                 let long_name_text = combine_names(&self.namespace_name, name_text);
3752                 self.errors.push(Self::make_name_already_used_error(
3753                     &name,
3754                     &long_name_text,
3755                     name_text,
3756                     location,
3757                     &|x, y| match kind {
3758                         NameImplicitUse => {
3759                             errors::declared_name_is_already_in_use_implicit_hh(line_num, x, y)
3760                         }
3761                         NameUse => errors::declared_name_is_already_in_use(line_num, x, y),
3762                         NameDef => errors::type_name_is_already_in_use(x, y),
3763                     },
3764                 ))
3765             }
3766             _ => {
3767                 let def = make_first_use_or_def(
3768                     false,
3769                     NameDef,
3770                     location,
3771                     &self.namespace_name,
3772                     name_text,
3773                 );
3774                 self.names.classes.add(&name_text, def)
3775             }
3776         }
3777     }
3779     fn get_type_params_and_emit_shadowing_errors(
3780         &mut self,
3781         l: &'a Syntax<Token, Value>,
3782     ) -> (HashSet<&'a str>, HashSet<&'a str>) {
3783         let mut res: HashSet<&'a str> = HashSet::new();
3784         let mut notreified: HashSet<&'a str> = HashSet::new();
3785         for p in Self::syntax_to_list_no_separators(l).rev() {
3786             match &p.syntax {
3787                 TypeParameter(x) => {
3788                     let name = self.text(&x.type_name);
3789                     if !x.type_reified.is_missing() {
3790                         if res.contains(&name) {
3791                             self.errors
3792                                 .push(Self::make_error_from_node(p, errors::shadowing_reified))
3793                         } else {
3794                             res.insert(name);
3795                         }
3796                     } else {
3797                         notreified.insert(name);
3798                     }
3799                 }
3800                 _ => (),
3801             }
3802         }
3803         (res, notreified)
3804     }
3806     fn reified_parameter_errors(&mut self, node: &'a Syntax<Token, Value>) {
3807         if let FunctionDeclarationHeader(x) = &node.syntax {
3808             if let TypeParameters(x) = &x.function_type_parameter_list.syntax {
3809                 self.get_type_params_and_emit_shadowing_errors(&x.type_parameters_parameters)
3810                     .0;
3811             }
3812         }
3813     }
3815     fn is_method_declaration(node: &'a Syntax<Token, Value>) -> bool {
3816         if let MethodishDeclaration(_) = &node.syntax {
3817             true
3818         } else {
3819             false
3820         }
3821     }
3823     fn class_reified_param_errors(&mut self, node: &'a Syntax<Token, Value>) {
3824         match &node.syntax {
3825             ClassishDeclaration(cd) => {
3826                 let (reified, non_reified) = match &cd.classish_type_parameters.syntax {
3827                     TypeParameters(x) => self
3828                         .get_type_params_and_emit_shadowing_errors(&x.type_parameters_parameters),
3829                     _ => (HashSet::new(), HashSet::new()),
3830                 };
3832                 let tparams: HashSet<&'a str> = reified
3833                     .union(&non_reified)
3834                     .cloned()
3835                     .collect::<HashSet<&'a str>>();
3837                 let add_error = |self_: &mut Self, e: &'a Syntax<Token, Value>| {
3838                     if let TypeParameter(x) = &e.syntax {
3839                         if !x.type_reified.is_missing()
3840                             && tparams.contains(&self_.text(&x.type_name))
3841                         {
3842                             self_
3843                                 .errors
3844                                 .push(Self::make_error_from_node(e, errors::shadowing_reified))
3845                         }
3846                     }
3847                 };
3848                 let check_method = |e: &'a Syntax<Token, Value>| {
3849                     if let MethodishDeclaration(x) = &e.syntax {
3850                         if let FunctionDeclarationHeader(x) =
3851                             &x.methodish_function_decl_header.syntax
3852                         {
3853                             if let TypeParameters(x) = &x.function_type_parameter_list.syntax {
3854                                 Self::syntax_to_list_no_separators(&x.type_parameters_parameters)
3855                                     .rev()
3856                                     .for_each(|x| add_error(self, x))
3857                             }
3858                         }
3859                     }
3860                 };
3861                 if let ClassishBody(x) = &cd.classish_body.syntax {
3862                     Self::syntax_to_list_no_separators(&x.classish_body_elements)
3863                         .rev()
3864                         .for_each(check_method)
3865                 }
3867                 if !reified.is_empty() {
3868                     if Self::is_token_kind(&cd.classish_keyword, TokenKind::Interface) {
3869                         self.errors.push(Self::make_error_from_node(
3870                             node,
3871                             errors::reified_in_invalid_classish("an interface"),
3872                         ))
3873                     } else if Self::is_token_kind(&cd.classish_keyword, TokenKind::Trait) {
3874                         self.errors.push(Self::make_error_from_node(
3875                             node,
3876                             errors::reified_in_invalid_classish("a trait"),
3877                         ))
3878                     }
3879                 }
3880             }
3881             PropertyDeclaration(_) => {
3882                 if Self::has_modifier_static(node) && self.is_in_reified_class() {
3883                     self.errors.push(Self::make_error_from_node(
3884                         node,
3885                         errors::static_property_in_reified_class,
3886                     ));
3887                 }
3888             }
3889             _ => {}
3890         }
3891     }
3893     fn attr_spec_contains_sealed(&self, node: &'a Syntax<Token, Value>) -> bool {
3894         self.attribute_specification_contains(node, sn::user_attributes::SEALED)
3895     }
3897     fn attr_spec_contains_const(&self, node: &'a Syntax<Token, Value>) -> bool {
3898         self.attribute_specification_contains(node, sn::user_attributes::CONST)
3899     }
3901     // If there's more than one XHP category, report an error on the last one.
3902     fn duplicate_xhp_category_errors<I>(&mut self, elts: I)
3903     where
3904         I: Iterator<Item = &'a Syntax<Token, Value>>,
3905     {
3906         let mut iter = elts.filter(|x| match &x.syntax {
3907             XHPCategoryDeclaration(_) => true,
3908             _ => false,
3909         });
3910         iter.next();
3911         if let Some(node) = iter.last() {
3912             self.errors.push(Self::make_error_from_node(
3913                 node,
3914                 errors::xhp_class_multiple_category_decls,
3915             ))
3916         }
3917     }
3919     // If there's more than one XHP children declaration, report an error
3920     // on the last one.
3921     fn duplicate_xhp_children_errors<I>(&mut self, elts: I)
3922     where
3923         I: Iterator<Item = &'a Syntax<Token, Value>>,
3924     {
3925         let mut iter = elts.filter(|x| match &x.syntax {
3926             XHPChildrenDeclaration(_) => true,
3927             _ => false,
3928         });
3929         iter.next();
3930         if let Some(node) = iter.last() {
3931             self.errors.push(Self::make_error_from_node(
3932                 node,
3933                 errors::xhp_class_multiple_children_decls,
3934             ))
3935         }
3936     }
3938     fn interface_private_method_errors<I>(&mut self, elts: I)
3939     where
3940         I: Iterator<Item = &'a Syntax<Token, Value>>,
3941     {
3942         for elt in elts {
3943             if let Some(modifiers) = Self::get_modifiers_of_declaration(elt) {
3944                 for modifier in Self::syntax_to_list_no_separators(modifiers) {
3945                     if modifier.is_private() {
3946                         self.errors.push(Self::make_error_from_node(
3947                             modifier,
3948                             errors::interface_has_private_method,
3949                         ))
3950                     }
3951                 }
3952             }
3953         }
3954     }
3956     fn classish_errors(&mut self, node: &'a Syntax<Token, Value>) {
3957         if let ClassishDeclaration(cd) = &node.syntax {
3958             // Given a ClassishDeclaration node, test whether or not it's a trait
3959             // invoking the 'extends' keyword.
3960             let classish_invalid_extends_keyword = |_|
3961               // Invalid if uses 'extends' and is a trait.
3962               Self::token_kind(&cd.classish_extends_keyword) == Some(TokenKind::Extends)
3963               && Self::token_kind(&cd.classish_keyword) == Some(TokenKind::Trait);
3965             let abstract_keyword = Self::extract_keyword(|x| x.is_abstract(), node).unwrap_or(node);
3967             self.produce_error(
3968                 |self_, x| self_.is_classish_kind_declared_abstract(x),
3969                 node,
3970                 || errors::error2042,
3971                 abstract_keyword,
3972             );
3974             // Given a sealed ClassishDeclaration node, test whether all the params
3975             // are classnames.
3976             let classish_sealed_arg_not_classname = |self_: &mut Self| {
3977                 Self::attr_spec_to_node_list(&cd.classish_attribute).any(|node| {
3978                     self_.attr_name(node) == Some(sn::user_attributes::SEALED)
3979                         && self_.attr_args(node).map_or(false, |mut args| {
3980                             args.any(|arg_node| match &arg_node.syntax {
3981                                 ScopeResolutionExpression(x) => {
3982                                     self_.text(&x.scope_resolution_name) != "class"
3983                                 }
3984                                 _ => true,
3985                             })
3986                         })
3987                 })
3988             };
3990             let classish_is_sealed = self.attr_spec_contains_sealed(&cd.classish_attribute);
3992             // Given a ClassishDeclaration node, test whether or not length of
3993             // extends_list is appropriate for the classish_keyword. *)
3994             let classish_invalid_extends_list = |self_: &mut Self| {
3995                 // Invalid if is a class and has list of length greater than one.
3996                 self_.env.is_typechecker()
3997                     && Self::token_kind(&cd.classish_keyword) == Some(TokenKind::Class)
3998                     && Self::token_kind(&cd.classish_extends_keyword) == Some(TokenKind::Extends)
3999                     && Self::syntax_to_list_no_separators(&cd.classish_extends_list).count() != 1
4000             };
4002             // Given a ClassishDeclaration node, test whether it is sealed and final.
4003             let classish_sealed_final = |_| {
4004                 Self::list_contains_predicate(|x| x.is_final(), &cd.classish_modifiers)
4005                     && classish_is_sealed
4006             };
4008             self.produce_error(
4009                 |self_, _| classish_invalid_extends_list(self_),
4010                 &(),
4011                 || errors::error2037,
4012                 &cd.classish_extends_list,
4013             );
4015             if let Some(n) = self.attribute_first_reactivity_annotation(&cd.classish_attribute) {
4016                 self.errors.push(Self::make_error_from_node(
4017                     n,
4018                     errors::misplaced_reactivity_annotation,
4019                 ))
4020             };
4022             self.invalid_modifier_errors("Classes, interfaces, and traits", node, |kind| {
4023                 kind == TokenKind::Abstract || kind == TokenKind::Final || kind == TokenKind::XHP
4024             });
4026             self.produce_error(
4027                 |self_, _| classish_sealed_arg_not_classname(self_),
4028                 &(),
4029                 || errors::sealed_val_not_classname,
4030                 &cd.classish_attribute,
4031             );
4033             self.produce_error(
4034                 |_, x| classish_invalid_extends_keyword(x),
4035                 &(),
4036                 || errors::error2036,
4037                 &cd.classish_extends_keyword,
4038             );
4040             self.produce_error(
4041                 |_, x| classish_sealed_final(x),
4042                 &(),
4043                 || errors::sealed_final,
4044                 &cd.classish_attribute,
4045             );
4047             let classish_name = self.text(&cd.classish_name);
4048             self.produce_error(
4049                 |_, x| Self::cant_be_classish_name(x),
4050                 &classish_name,
4051                 || errors::reserved_keyword_as_class_name(&classish_name),
4052                 &cd.classish_name,
4053             );
4054             if Self::is_token_kind(&cd.classish_keyword, TokenKind::Interface)
4055                 && !cd.classish_implements_keyword.is_missing()
4056             {
4057                 self.errors.push(Self::make_error_from_node(
4058                     node,
4059                     errors::interface_implements,
4060                 ))
4061             };
4062             if self.attr_spec_contains_const(&cd.classish_attribute)
4063                 && (Self::is_token_kind(&cd.classish_keyword, TokenKind::Interface)
4064                     || Self::is_token_kind(&cd.classish_keyword, TokenKind::Trait))
4065             {
4066                 self.errors.push(Self::make_error_from_node(
4067                     node,
4068                     errors::no_const_interfaces_traits_enums,
4069                 ))
4070             }
4071             if self.attr_spec_contains_const(&cd.classish_attribute)
4072                 && Self::is_token_kind(&cd.classish_keyword, TokenKind::Class)
4073                 && Self::list_contains_predicate(|x| x.is_abstract(), &cd.classish_modifiers)
4074                 && Self::list_contains_predicate(|x| x.is_final(), &cd.classish_modifiers)
4075             {
4076                 self.errors.push(Self::make_error_from_node(
4077                     node,
4078                     errors::no_const_abstract_final_class,
4079                 ))
4080             }
4082             if Self::list_contains_predicate(|x| x.is_final(), &cd.classish_modifiers) {
4083                 match Self::token_kind(&cd.classish_keyword) {
4084                     Some(TokenKind::Interface) => self.errors.push(Self::make_error_from_node(
4085                         node,
4086                         errors::declared_final("Interfaces"),
4087                     )),
4088                     Some(TokenKind::Trait) => self.errors.push(Self::make_error_from_node(
4089                         node,
4090                         errors::declared_final("Traits"),
4091                     )),
4092                     _ => (),
4093                 }
4094             }
4096             if Self::token_kind(&cd.classish_xhp) == Some(TokenKind::XHP) {
4097                 match Self::token_kind(&cd.classish_keyword) {
4098                     Some(TokenKind::Interface) => self.errors.push(Self::make_error_from_node(
4099                         node,
4100                         errors::invalid_xhp_classish("Interfaces"),
4101                     )),
4102                     Some(TokenKind::Trait) => self.errors.push(Self::make_error_from_node(
4103                         node,
4104                         errors::invalid_xhp_classish("Traits"),
4105                     )),
4106                     Some(TokenKind::Enum) => self.errors.push(Self::make_error_from_node(
4107                         node,
4108                         errors::invalid_xhp_classish("Enums"),
4109                     )),
4110                     _ => (),
4111                 }
4112             }
4114             let name = self.text(&cd.classish_name);
4115             if let ClassishBody(cb) = &cd.classish_body.syntax {
4116                 let declared_name_str = self.text(&cd.classish_name);
4117                 let full_name = combine_names(&self.namespace_name, declared_name_str);
4119                 let class_body_elts =
4120                     || Self::syntax_to_list_no_separators(&cb.classish_body_elements);
4121                 let class_body_methods =
4122                     || class_body_elts().filter(|x| Self::is_method_declaration(x));
4124                 let mut p_names = HashSet::<String>::new();
4125                 let mut c_names = HashSet::<String>::new();
4126                 for elt in class_body_elts() {
4127                     self.check_repeated_properties_tconst_const(
4128                         &full_name,
4129                         elt,
4130                         &mut p_names,
4131                         &mut c_names,
4132                     );
4133                 }
4134                 let has_abstract_fn = class_body_methods().any(&Self::has_modifier_abstract);
4135                 if has_abstract_fn
4136                     && Self::is_token_kind(&cd.classish_keyword, TokenKind::Class)
4137                     && !Self::list_contains_predicate(|x| x.is_abstract(), &cd.classish_modifiers)
4138                 {
4139                     self.errors.push(Self::make_error_from_node(
4140                         &cd.classish_name,
4141                         errors::class_with_abstract_method(name),
4142                     ))
4143                 }
4145                 if Self::is_token_kind(&cd.classish_keyword, TokenKind::Interface) {
4146                     self.interface_private_method_errors(class_body_elts());
4147                 }
4149                 self.duplicate_xhp_category_errors(class_body_elts());
4150                 self.duplicate_xhp_children_errors(class_body_elts());
4151             }
4153             match Self::token_kind(&cd.classish_keyword) {
4154                 Some(TokenKind::Class) | Some(TokenKind::Trait)
4155                     if !cd.classish_name.is_missing() =>
4156                 {
4157                     let location = Self::make_location_of_node(&cd.classish_name);
4158                     self.check_type_name(&cd.classish_name, name, location)
4159                 }
4160                 _ => (),
4161             }
4162         }
4163     }
4165     // Checks for modifiers on class constants
4166     fn class_constant_modifier_errors(&mut self, node: &'a Syntax<Token, Value>) {
4167         if self.is_inside_trait() {
4168             self.errors
4169                 .push(Self::make_error_from_node(node, errors::const_in_trait))
4170         }
4171         self.invalid_modifier_errors("Constants", node, |kind| kind == TokenKind::Abstract);
4172     }
4174     fn type_const_modifier_errors(&mut self, node: &'a Syntax<Token, Value>) {
4175         self.invalid_modifier_errors("Type constants", node, |kind| kind == TokenKind::Abstract);
4176     }
4178     fn alias_errors(&mut self, node: &'a Syntax<Token, Value>) {
4179         if let AliasDeclaration(ad) = &node.syntax {
4180             if Self::token_kind(&ad.alias_keyword) == Some(TokenKind::Type)
4181                 && !ad.alias_constraint.is_missing()
4182             {
4183                 self.errors.push(Self::make_error_from_node(
4184                     &ad.alias_keyword,
4185                     errors::error2034,
4186                 ))
4187             }
4188             if !ad.alias_name.is_missing() {
4189                 let name = self.text(&ad.alias_name);
4190                 let location = Self::make_location_of_node(&ad.alias_name);
4191                 if let TypeConstant(_) = &ad.alias_type.syntax {
4192                     if self.env.is_typechecker() {
4193                         self.errors.push(Self::make_error_from_node(
4194                             &ad.alias_type,
4195                             errors::type_alias_to_type_constant,
4196                         ))
4197                     }
4198                 }
4200                 self.check_type_name(&ad.alias_name, name, location)
4201             }
4202         }
4203     }
4205     fn is_invalid_group_use_clause(
4206         kind: &'a Syntax<Token, Value>,
4207         clause: &'a Syntax<Token, Value>,
4208     ) -> bool {
4209         if let NamespaceUseClause(x) = &clause.syntax {
4210             let clause_kind = &x.namespace_use_clause_kind;
4211             if kind.is_missing() {
4212                 match &clause_kind.syntax {
4213                     Missing => false,
4214                     Token(token)
4215                         if token.kind() == TokenKind::Function
4216                             || token.kind() == TokenKind::Const =>
4217                     {
4218                         false
4219                     }
4220                     _ => true,
4221                 }
4222             } else {
4223                 !clause_kind.is_missing()
4224             }
4225         } else {
4226             false
4227         }
4228     }
4230     fn is_invalid_group_use_prefix(prefix: &'a Syntax<Token, Value>) -> bool {
4231         !prefix.is_namespace_prefix()
4232     }
4234     fn group_use_errors(&mut self, node: &'a Syntax<Token, Value>) {
4235         if let NamespaceGroupUseDeclaration(x) = &node.syntax {
4236             let prefix = &x.namespace_group_use_prefix;
4237             let clauses = &x.namespace_group_use_clauses;
4238             let kind = &x.namespace_group_use_kind;
4239             Self::syntax_to_list_no_separators(clauses)
4240                 .filter(|x| Self::is_invalid_group_use_clause(kind, x))
4241                 .for_each(|clause| {
4242                     self.errors
4243                         .push(Self::make_error_from_node(clause, errors::error2049))
4244                 });
4245             self.produce_error(
4246                 |_, x| Self::is_invalid_group_use_prefix(&x),
4247                 prefix,
4248                 || errors::error2048,
4249                 prefix,
4250             )
4251         }
4252     }
4254     fn use_class_or_namespace_clause_errors(
4255         &mut self,
4256         namespace_prefix: Option<&str>,
4258         kind: &'a Syntax<Token, Value>,
4259         cl: &'a Syntax<Token, Value>,
4260     ) {
4261         match &cl.syntax {
4262             NamespaceUseClause(x) if !&x.namespace_use_name.is_missing() => {
4263                 let name = &x.namespace_use_name;
4265                 let kind = if kind.is_missing() {
4266                     &x.namespace_use_clause_kind
4267                 } else {
4268                     kind
4269                 };
4271                 let name_text = self.text(name);
4272                 let qualified_name = match namespace_prefix {
4273                     None => combine_names(GLOBAL_NAMESPACE_NAME, name_text),
4274                     Some(p) => combine_names(p, name_text),
4275                 };
4276                 let short_name = Self::get_short_name_from_qualified_name(
4277                     name_text,
4278                     self.text(&x.namespace_use_alias),
4279                 );
4281                 let do_check =
4282                     |self_: &mut Self,
4283                      error_on_global_redefinition,
4284                      get_names: &dyn Fn(&mut UsedNames) -> &mut Strmap<FirstUseOrDef>,
4285                      report_error| {
4286                         let is_global_namespace = self_.is_global_namespace();
4287                         let names = get_names(&mut self_.names);
4288                         match names.get(&short_name) {
4289                             Some(FirstUseOrDef {
4290                                 location,
4291                                 kind,
4292                                 global,
4293                                 ..
4294                             }) => {
4295                                 if *kind != NameDef
4296                                     || error_on_global_redefinition
4297                                         && (is_global_namespace || *global)
4298                                 {
4299                                     self_.errors.push(Self::make_name_already_used_error(
4300                                         name,
4301                                         name_text,
4302                                         &short_name,
4303                                         location,
4304                                         report_error,
4305                                     ))
4306                                 }
4307                             }
4308                             None => {
4309                                 let new_use = make_first_use_or_def(
4310                                     false,
4311                                     NameUse,
4312                                     Self::make_location_of_node(name),
4313                                     GLOBAL_NAMESPACE_NAME,
4314                                     &qualified_name,
4315                                 );
4316                                 names.add(&short_name, new_use)
4317                             }
4318                         }
4319                     };
4321                 match &kind.syntax {
4322                     Token(token) => match token.kind() {
4323                         TokenKind::Namespace => do_check(
4324                             self,
4325                             false,
4326                             &|x: &mut UsedNames| &mut x.namespaces,
4327                             &errors::namespace_name_is_already_in_use,
4328                         ),
4330                         TokenKind::Type => do_check(
4331                             self,
4332                             false,
4333                             &|x: &mut UsedNames| &mut x.classes,
4334                             &errors::type_name_is_already_in_use,
4335                         ),
4337                         TokenKind::Function => do_check(
4338                             self,
4339                             true,
4340                             &|x: &mut UsedNames| &mut x.functions,
4341                             &errors::function_name_is_already_in_use,
4342                         ),
4344                         TokenKind::Const => do_check(
4345                             self,
4346                             true,
4347                             &|x: &mut UsedNames| &mut x.constants,
4348                             &errors::const_name_is_already_in_use,
4349                         ),
4350                         _ => {}
4351                     },
4352                     Missing => {
4353                         if name_text == "strict" {
4354                             self.errors.push(Self::make_error_from_node(
4355                                 name,
4356                                 errors::strict_namespace_hh,
4357                             ))
4358                         }
4359                         let location = Self::make_location_of_node(name);
4361                         match self.names.classes.get(&short_name) {
4362                             Some(FirstUseOrDef {
4363                                 location: loc,
4364                                 name: def_name,
4365                                 kind,
4366                                 ..
4367                             }) => {
4368                                 if &qualified_name != def_name || kind != &NameDef {
4369                                     let (line_num, _) =
4370                                         self.env.text.offset_to_position(loc.start_offset as isize);
4371                                     let err_msg = |x: &str, y: &str| -> Error {
4372                                         if kind != &NameDef {
4373                                             if kind == &NameImplicitUse {
4374                                                 errors::name_is_already_in_use_implicit_hh(
4375                                                     line_num, x, y,
4376                                                 )
4377                                             } else {
4378                                                 errors::name_is_already_in_use_hh(line_num, x, y)
4379                                             }
4380                                         } else {
4381                                             errors::name_is_already_in_use_php(x, y)
4382                                         }
4383                                     };
4385                                     self.errors.push(Self::make_name_already_used_error(
4386                                         name,
4387                                         name_text,
4388                                         &short_name,
4389                                         loc,
4390                                         &err_msg,
4391                                     ))
4392                                 }
4393                             }
4394                             None => {
4395                                 let new_use = make_first_use_or_def(
4396                                     false,
4397                                     NameUse,
4398                                     location,
4399                                     GLOBAL_NAMESPACE_NAME,
4400                                     &qualified_name,
4401                                 );
4403                                 if !self.names.namespaces.mem(&short_name) {
4404                                     self.names.namespaces.add(&short_name, new_use.clone());
4405                                     self.names.classes.add(&short_name, new_use);
4406                                 } else {
4407                                     self.names.classes.add(&short_name, new_use);
4408                                 }
4409                             }
4410                         }
4411                     }
4412                     _ => {}
4413                 }
4414             }
4416             _ => {}
4417         }
4418     }
4420     fn is_global_in_const_decl(&self, init: &'a Syntax<Token, Value>) -> bool {
4421         if let SimpleInitializer(x) = &init.syntax {
4422             if let VariableExpression(x) = &x.simple_initializer_value.syntax {
4423                 return sn::superglobals::is_any_global(self.text(&x.variable_expression));
4424             }
4425         }
4426         false
4427     }
4429     fn namespace_use_declaration_errors(&mut self, node: &'a Syntax<Token, Value>) {
4430         match &node.syntax {
4431             NamespaceUseDeclaration(x) => {
4432                 Self::syntax_to_list_no_separators(&x.namespace_use_clauses).for_each(|clause| {
4433                     self.use_class_or_namespace_clause_errors(None, &x.namespace_use_kind, clause)
4434                 })
4435             }
4436             NamespaceGroupUseDeclaration(x) => {
4437                 Self::syntax_to_list_no_separators(&x.namespace_group_use_clauses).for_each(
4438                     |clause| {
4439                         match &clause.syntax {
4440                             NamespaceUseClause(x) if !x.namespace_use_name.is_missing() => self
4441                                 .check_preceding_backslashes_qualified_name(&x.namespace_use_name),
4442                             _ => (),
4443                         }
4444                         self.use_class_or_namespace_clause_errors(
4445                             Some(self.text(&x.namespace_group_use_prefix)),
4446                             &x.namespace_group_use_kind,
4447                             clause,
4448                         )
4449                     },
4450                 )
4451             }
4452             _ => {}
4453         }
4454     }
4456     fn token_text<'b>(&'b self, token: &Token) -> &'b str {
4457         self.env.text.source_text().sub_as_str(
4458             token.leading_start_offset().unwrap() + token.leading_width(),
4459             token.width(),
4460         )
4461     }
4463     fn check_constant_expression(&mut self, node: &'a Syntax<Token, Value>) {
4464         // __FUNCTION_CREDENTIAL__ emits an object,
4465         // so it cannot be used in a constant expression
4466         let not_function_credential = |self_: &Self, token: &Token| {
4467             !self_
4468                 .token_text(token)
4469                 .eq_ignore_ascii_case("__FUNCTION_CREDENTIAL__")
4470         };
4472         let is_whitelisted_function = |self_: &Self, receiver_token| {
4473             let text = self_.text(receiver_token);
4475             (!self_.env.parser_options.po_disallow_func_ptrs_in_constants
4476                 && (text == Self::strip_hh_ns(sn::autoimported_functions::FUN_)
4477                     || text == Self::strip_hh_ns(sn::autoimported_functions::CLASS_METH)))
4478                 || (text == sn::std_lib_functions::ARRAY_MARK_LEGACY)
4479                 || (text == Self::strip_ns(sn::std_lib_functions::ARRAY_MARK_LEGACY))
4480         };
4482         let is_namey = |self_: &Self, token: &Token| -> bool {
4483             token.kind() == TokenKind::Name && not_function_credential(self_, token)
4484         };
4486         let is_good_scope_resolution_name = |node: &'a Syntax<Token, Value>| match &node.syntax {
4487             QualifiedName(_) => true,
4488             Token(token) => {
4489                 use TokenKind::*;
4490                 match token.kind() {
4491                     Name | Trait | Extends | Implements | Static | Abstract | Final | Private
4492                     | Protected | Public | Global | Goto | Instanceof | Insteadof | Interface
4493                     | Namespace | New | Try | Use | Var | List | Clone | Include | Include_once
4494                     | Throw | Array | Tuple | Print | Echo | Require | Require_once | Return
4495                     | Else | Elseif | Default | Break | Continue | Switch | Yield | Function
4496                     | If | Finally | For | Foreach | Case | Do | While | As | Catch | Empty
4497                     | Using | Class | NullLiteral | Super | Where => true,
4498                     _ => false,
4499                 }
4500             }
4501             _ => false,
4502         };
4504         let default = |self_: &mut Self| {
4505             self_.errors.push(Self::make_error_from_node(
4506                 node,
4507                 errors::invalid_constant_initializer,
4508             ))
4509         };
4511         let check_type_specifier = |self_: &mut Self, x: &'a Syntax<Token, Value>, initializer| {
4512             if let Token(token) = &x.syntax {
4513                 if is_namey(self_, &token) {
4514                     return Self::syntax_to_list_no_separators(initializer)
4515                         .for_each(|x| self_.check_constant_expression(x));
4516                 }
4517             };
4518             default(self_)
4519         };
4521         let check_collection_members = |self_: &mut Self, x| {
4522             Self::syntax_to_list_no_separators(x).for_each(|x| self_.check_constant_expression(&x))
4523         };
4524         match &node.syntax {
4525             Missing | QualifiedName(_) | LiteralExpression(_) => {}
4526             Token(token) => {
4527                 if !is_namey(self, token) {
4528                     default(self)
4529                 }
4530             }
4531             PrefixUnaryExpression(x) => {
4532                 if let Token(token) = &x.prefix_unary_operator.syntax {
4533                     use TokenKind::*;
4534                     match token.kind() {
4535                         Exclamation | Plus | Minus | Tilde => {
4536                             self.check_constant_expression(&x.prefix_unary_operand)
4537                         }
4538                         _ => default(self),
4539                     }
4540                 } else {
4541                     default(self)
4542                 }
4543             }
4544             BinaryExpression(x) => {
4545                 if let Token(token) = &x.binary_operator.syntax {
4546                     use TokenKind::*;
4547                     match token.kind() {
4548                         BarBar
4549                         | AmpersandAmpersand
4550                         | Carat
4551                         | Bar
4552                         | Ampersand
4553                         | Dot
4554                         | Plus
4555                         | Minus
4556                         | Star
4557                         | Slash
4558                         | Percent
4559                         | LessThanLessThan
4560                         | GreaterThanGreaterThan
4561                         | StarStar
4562                         | EqualEqual
4563                         | EqualEqualEqual
4564                         | ExclamationEqual
4565                         | ExclamationEqualEqual
4566                         | GreaterThan
4567                         | GreaterThanEqual
4568                         | LessThan
4569                         | LessThanEqual
4570                         | LessThanEqualGreaterThan
4571                         | QuestionColon => {
4572                             self.check_constant_expression(&x.binary_left_operand);
4573                             self.check_constant_expression(&x.binary_right_operand);
4574                         }
4575                         _ => default(self),
4576                     }
4577                 } else {
4578                     default(self)
4579                 }
4580             }
4581             ConditionalExpression(x) => {
4582                 self.check_constant_expression(&x.conditional_test);
4583                 self.check_constant_expression(&x.conditional_consequence);
4584                 self.check_constant_expression(&x.conditional_alternative);
4585             }
4586             SimpleInitializer(x) => {
4587                 if let LiteralExpression(y) = &x.simple_initializer_value.syntax {
4588                     if let SyntaxList(_) = &y.literal_expression.syntax {
4589                         self.errors.push(Self::make_error_from_node(
4590                             node,
4591                             errors::invalid_constant_initializer,
4592                         ))
4593                     }
4594                     self.check_constant_expression(&x.simple_initializer_value)
4595                 } else {
4596                     self.check_constant_expression(&x.simple_initializer_value)
4597                 }
4598             }
4600             ParenthesizedExpression(x) => {
4601                 self.check_constant_expression(&x.parenthesized_expression_expression)
4602             }
4603             CollectionLiteralExpression(x) => {
4604                 if let SimpleTypeSpecifier(y) = &x.collection_literal_name.syntax {
4605                     check_type_specifier(
4606                         self,
4607                         &y.simple_type_specifier,
4608                         &x.collection_literal_initializers,
4609                     )
4610                 } else if let GenericTypeSpecifier(y) = &x.collection_literal_name.syntax {
4611                     check_type_specifier(
4612                         self,
4613                         &y.generic_class_type,
4614                         &x.collection_literal_initializers,
4615                     )
4616                 } else {
4617                     default(self)
4618                 };
4619             }
4621             TupleExpression(x) => check_collection_members(self, &x.tuple_expression_items),
4622             KeysetIntrinsicExpression(x) => {
4623                 check_collection_members(self, &x.keyset_intrinsic_members)
4624             }
4625             VarrayIntrinsicExpression(x) => {
4626                 check_collection_members(self, &x.varray_intrinsic_members)
4627             }
4628             DarrayIntrinsicExpression(x) => {
4629                 check_collection_members(self, &x.darray_intrinsic_members)
4630             }
4631             VectorIntrinsicExpression(x) => {
4632                 check_collection_members(self, &x.vector_intrinsic_members)
4633             }
4634             DictionaryIntrinsicExpression(x) => {
4635                 check_collection_members(self, &x.dictionary_intrinsic_members)
4636             }
4637             ArrayIntrinsicExpression(x) => {
4638                 check_collection_members(self, &x.array_intrinsic_members)
4639             }
4640             ShapeExpression(x) => check_collection_members(self, &x.shape_expression_fields),
4641             ElementInitializer(x) => {
4642                 self.check_constant_expression(&x.element_key);
4643                 self.check_constant_expression(&x.element_value);
4644             }
4645             FieldInitializer(x) => {
4646                 self.check_constant_expression(&x.field_initializer_name);
4647                 self.check_constant_expression(&x.field_initializer_value);
4648             }
4649             ScopeResolutionExpression(x)
4650                 if Self::is_good_scope_resolution_qualifier(&x.scope_resolution_qualifier)
4651                     && is_good_scope_resolution_name(&x.scope_resolution_name) => {}
4652             AsExpression(x) => match &x.as_right_operand.syntax {
4653                 LikeTypeSpecifier(_) => self.check_constant_expression(&x.as_left_operand),
4654                 GenericTypeSpecifier(y)
4655                     if self.text(&y.generic_class_type) == sn::fb::INCORRECT_TYPE
4656                         || self.text(&y.generic_class_type)
4657                             == Self::strip_ns(sn::fb::INCORRECT_TYPE) =>
4658                 {
4659                     self.check_constant_expression(&x.as_left_operand)
4660                 }
4661                 _ => default(self),
4662             },
4663             FunctionCallExpression(x) => {
4664                 let mut check_receiver_and_arguments = |receiver| {
4665                     if is_whitelisted_function(self, receiver) {
4666                         for node in
4667                             Self::syntax_to_list_no_separators(&x.function_call_argument_list)
4668                         {
4669                             self.check_constant_expression(node)
4670                         }
4671                     } else {
4672                         default(self)
4673                     }
4674                 };
4676                 match &x.function_call_receiver.syntax {
4677                     Token(tok) if tok.kind() == TokenKind::Name => {
4678                         check_receiver_and_arguments(&x.function_call_receiver)
4679                     }
4680                     QualifiedName(_) => check_receiver_and_arguments(&x.function_call_receiver),
4681                     _ => default(self),
4682                 }
4683             }
4684             FunctionPointerExpression(_) => {
4685                 // Bans the equivalent of inst_meth as well as class_meth and fun
4686                 if self.env.parser_options.po_disallow_func_ptrs_in_constants {
4687                     default(self)
4688                 }
4689             }
4690             _ => default(self),
4691         }
4692     }
4694     fn check_static_in_initializer(&mut self, initializer: &'a Syntax<Token, Value>) -> bool {
4695         if let SimpleInitializer(x) = &initializer.syntax {
4696             if let ScopeResolutionExpression(x) = &x.simple_initializer_value.syntax {
4697                 if let Token(t) = &x.scope_resolution_qualifier.syntax {
4698                     match t.kind() {
4699                         TokenKind::Static => return true,
4700                         TokenKind::Parent => {
4701                             return self
4702                                 .text(&x.scope_resolution_name)
4703                                 .eq_ignore_ascii_case("class")
4704                         }
4705                         _ => return false,
4706                     }
4707                 }
4708             }
4709         };
4710         false
4711     }
4713     fn const_decl_errors(&mut self, node: &'a Syntax<Token, Value>) {
4714         if let ConstantDeclarator(cd) = &node.syntax {
4715             self.produce_error(
4716                 |self_, x| self_.constant_abstract_with_initializer(x),
4717                 &cd.constant_declarator_initializer,
4718                 || errors::error2051,
4719                 &cd.constant_declarator_initializer,
4720             );
4722             self.produce_error(
4723                 |self_, x| self_.constant_concrete_without_initializer(x),
4724                 &cd.constant_declarator_initializer,
4725                 || errors::error2050,
4726                 &cd.constant_declarator_initializer,
4727             );
4729             self.produce_error(
4730                 |self_, x| self_.is_global_in_const_decl(x),
4731                 &cd.constant_declarator_initializer,
4732                 || errors::global_in_const_decl,
4733                 &cd.constant_declarator_initializer,
4734             );
4735             self.check_constant_expression(&cd.constant_declarator_initializer);
4737             self.produce_error(
4738                 |self_, x| self_.check_static_in_initializer(x),
4739                 &cd.constant_declarator_initializer,
4740                 || errors::parent_static_const_decl,
4741                 &cd.constant_declarator_initializer,
4742             );
4744             if !cd.constant_declarator_name.is_missing() {
4745                 let constant_name = self.text(&cd.constant_declarator_name);
4746                 let location = Self::make_location_of_node(&cd.constant_declarator_name);
4747                 let def = make_first_use_or_def(
4748                     false,
4749                     NameDef,
4750                     location,
4751                     &self.namespace_name,
4752                     constant_name,
4753                 );
4755                 match (
4756                     self.names.constants.get(constant_name),
4757                     self.first_parent_class_name(),
4758                 ) {
4759                     // Only error if this is inside a class
4760                     (Some(_), Some(class_name)) => {
4761                         let full_name = class_name.to_string() + "::" + constant_name;
4762                         self.errors.push(Self::make_error_from_node(
4763                             node,
4764                             errors::redeclaration_error(&full_name),
4765                         ))
4766                     }
4767                     (Some(prev_def), None) if prev_def.kind != NameDef => {
4768                         let (line_num, _) = self
4769                             .env
4770                             .text
4771                             .offset_to_position(prev_def.location.start_offset as isize);
4772                         let line_num = line_num as usize;
4774                         self.errors.push(Self::make_name_already_used_error(
4775                             &cd.constant_declarator_name,
4776                             &combine_names(&self.namespace_name, &constant_name),
4777                             &constant_name,
4778                             &def.location,
4779                             &|x, y| errors::declared_name_is_already_in_use(line_num, x, y),
4780                         ))
4781                     }
4782                     _ => (),
4783                 }
4784                 self.names.constants.add(constant_name, def)
4785             }
4786         }
4787     }
4789     fn class_property_modifiers_errors(&mut self, node: &'a Syntax<Token, Value>) {
4790         if let PropertyDeclaration(x) = &node.syntax {
4791             let property_modifiers = &x.property_modifiers;
4793             let abstract_static_props = self.env.parser_options.po_abstract_static_props;
4794             self.invalid_modifier_errors("Properties", node, |kind| {
4795                 if kind == TokenKind::Abstract {
4796                     return abstract_static_props;
4797                 }
4798                 kind == TokenKind::Static
4799                     || kind == TokenKind::Private
4800                     || kind == TokenKind::Protected
4801                     || kind == TokenKind::Public
4802             });
4804             self.produce_error(
4805                 |_, x| Self::is_empty_list_or_missing(x),
4806                 property_modifiers,
4807                 || errors::property_requires_visibility,
4808                 node,
4809             );
4811             if self.env.parser_options.po_abstract_static_props {
4812                 self.produce_error(
4813                     |_, n| Self::has_modifier_abstract(n) && !Self::has_modifier_static(n),
4814                     node,
4815                     || errors::abstract_instance_property,
4816                     node,
4817                 );
4818             }
4820             if Self::has_modifier_abstract(node) && Self::has_modifier_private(node) {
4821                 self.errors.push(Self::make_error_from_node(
4822                     node,
4823                     errors::elt_abstract_private("properties"),
4824                 ));
4825             }
4826         }
4827     }
4829     fn class_property_const_errors(&mut self, node: &'a Syntax<Token, Value>) {
4830         if let PropertyDeclaration(x) = &node.syntax {
4831             if self.attr_spec_contains_const(&x.property_attribute_spec)
4832                 && self.attribute_specification_contains(
4833                     &x.property_attribute_spec,
4834                     sn::user_attributes::LATE_INIT,
4835                 )
4836             {
4837                 // __LateInit together with const just doesn't make sense.
4838                 self.errors.push(Self::make_error_from_node(
4839                     node,
4840                     errors::no_const_late_init_props,
4841                 ))
4842             }
4843         }
4844     }
4846     fn class_property_declarator_errors(&mut self, node: &'a Syntax<Token, Value>) {
4847         let check_decls = |self_: &mut Self,
4848                            f: &dyn Fn(&'a Syntax<Token, Value>) -> bool,
4849                            error: errors::Error,
4850                            property_declarators| {
4851             Self::syntax_to_list_no_separators(property_declarators).for_each(|decl| {
4852                 if let PropertyDeclarator(x) = &decl.syntax {
4853                     if f(&x.property_initializer) {
4854                         self_
4855                             .errors
4856                             .push(Self::make_error_from_node(node, error.clone()))
4857                     }
4858                 }
4859             })
4860         };
4861         if let PropertyDeclaration(x) = &node.syntax {
4862             if self.env.parser_options.tco_const_static_props && Self::has_modifier_static(node) {
4863                 if self.env.parser_options.po_abstract_static_props
4864                     && Self::has_modifier_abstract(node)
4865                 {
4866                     check_decls(
4867                         self,
4868                         &|n| !n.is_missing(),
4869                         errors::abstract_prop_init,
4870                         &x.property_declarators,
4871                     )
4872                 } else if self.attr_spec_contains_const(&x.property_attribute_spec) {
4873                     check_decls(
4874                         self,
4875                         &|n| n.is_missing(),
4876                         errors::const_static_prop_init,
4877                         &x.property_declarators,
4878                     )
4879                 }
4880             }
4881         }
4882     }
4884     fn trait_use_alias_item_modifier_errors(&mut self, node: &'a Syntax<Token, Value>) {
4885         self.invalid_modifier_errors("Trait use aliases", node, |kind| {
4886             kind == TokenKind::Final
4887                 || kind == TokenKind::Private
4888                 || kind == TokenKind::Protected
4889                 || kind == TokenKind::Public
4890         });
4891     }
4893     fn mixed_namespace_errors(&mut self, node: &'a Syntax<Token, Value>) {
4894         match &node.syntax {
4895             NamespaceBody(x) => {
4896                 let s = Self::start_offset(&x.namespace_left_brace);
4897                 let e = Self::end_offset(&x.namespace_right_brace);
4898                 if let NamespaceType::Unbracketed(Location {
4899                     start_offset,
4900                     end_offset,
4901                 }) = self.namespace_type
4902                 {
4903                     let child = Some(SyntaxError::make(
4904                         start_offset,
4905                         end_offset,
4906                         errors::error2057,
4907                     ));
4908                     self.errors.push(SyntaxError::make_with_child_and_type(
4909                         child,
4910                         s,
4911                         e,
4912                         ErrorType::ParseError,
4913                         errors::error2052,
4914                     ))
4915                 }
4916             }
4917             NamespaceEmptyBody(x) => {
4918                 let s = Self::start_offset(&x.namespace_semicolon);
4919                 let e = Self::end_offset(&x.namespace_semicolon);
4920                 if let NamespaceType::Bracketed(Location {
4921                     start_offset,
4922                     end_offset,
4923                 }) = self.namespace_type
4924                 {
4925                     let child = Some(SyntaxError::make(
4926                         start_offset,
4927                         end_offset,
4928                         errors::error2056,
4929                     ));
4930                     self.errors.push(SyntaxError::make_with_child_and_type(
4931                         child,
4932                         s,
4933                         e,
4934                         ErrorType::ParseError,
4935                         errors::error2052,
4936                     ))
4937                 }
4938             }
4939             NamespaceDeclaration(x) => {
4940                 let mut is_first_decl = true;
4941                 let mut has_code_outside_namespace = false;
4943                 if let [Syntax {
4944                     syntax: Script(_), ..
4945                 }, syntax_list] = self.parents.as_slice()
4946                 {
4947                     if let SyntaxList(_) = syntax_list.syntax {
4948                         is_first_decl = false;
4949                         for decl in Self::syntax_to_list_no_separators(syntax_list) {
4950                             match &decl.syntax {
4951                                 MarkupSection(x) => {
4952                                     if x.markup_text.width() == 0
4953                                         || self.is_hashbang(&x.markup_text)
4954                                     {
4955                                         continue;
4956                                     } else {
4957                                         break;
4958                                     }
4959                                 }
4960                                 NamespaceUseDeclaration(_) | FileAttributeSpecification(_) => (),
4961                                 NamespaceDeclaration(_) => {
4962                                     is_first_decl = true;
4963                                     break;
4964                                 }
4965                                 _ => break,
4966                             }
4967                         }
4969                         has_code_outside_namespace = !(x.namespace_body.is_namespace_empty_body())
4970                             && Self::syntax_to_list_no_separators(syntax_list).any(|decl| {
4971                                 match &decl.syntax {
4972                                     MarkupSection(x) => {
4973                                         !(x.markup_text.width() == 0
4974                                             || self.is_hashbang(&x.markup_text))
4975                                     }
4976                                     NamespaceDeclaration(_)
4977                                     | FileAttributeSpecification(_)
4978                                     | EndOfFile(_)
4979                                     | NamespaceUseDeclaration(_) => false,
4980                                     _ => true,
4981                                 }
4982                             })
4983                     }
4984                 }
4986                 if !is_first_decl {
4987                     self.errors.push(Self::make_error_from_node(
4988                         node,
4989                         errors::namespace_decl_first_statement,
4990                     ))
4991                 }
4992                 if has_code_outside_namespace {
4993                     self.errors.push(Self::make_error_from_node(
4994                         node,
4995                         errors::code_outside_namespace,
4996                     ))
4997                 }
4998             }
4999             _ => (),
5000         }
5001     }
5003     fn enumerator_errors(&mut self, node: &'a Syntax<Token, Value>) {
5004         if let Enumerator(x) = &node.syntax {
5005             if self.text(&x.enumerator_name).eq_ignore_ascii_case("class") {
5006                 self.errors.push(Self::make_error_from_node(
5007                     node,
5008                     errors::enum_elem_name_is_class,
5009                 ))
5010             }
5011             self.check_constant_expression(&x.enumerator_value)
5012         }
5013     }
5015     fn enum_decl_errors(&mut self, node: &'a Syntax<Token, Value>) {
5016         if let EnumDeclaration(x) = &node.syntax {
5017             let attrs = &x.enum_attribute_spec;
5018             if self.attr_spec_contains_sealed(attrs) {
5019                 self.errors
5020                     .push(Self::make_error_from_node(node, errors::sealed_enum))
5021             } else if self.attr_spec_contains_const(attrs) {
5022                 self.errors.push(Self::make_error_from_node(
5023                     node,
5024                     errors::no_const_interfaces_traits_enums,
5025                 ))
5026             }
5028             if !x.enum_name.is_missing() {
5029                 let name = self.text(&x.enum_name);
5030                 let location = Self::make_location_of_node(&x.enum_name);
5031                 self.check_type_name(&x.enum_name, name, location)
5032             }
5033         }
5034     }
5036     fn check_lvalue(&mut self, allow_reassign: bool, loperand: &'a Syntax<Token, Value>) {
5037         let append_errors = |self_: &mut Self, node, error| {
5038             self_.errors.push(Self::make_error_from_node(node, error))
5039         };
5041         let err = |self_: &mut Self, error| append_errors(self_, loperand, error);
5043         let check_unary_expression = |self_: &mut Self, op| match Self::token_kind(op) {
5044             Some(TokenKind::At) | Some(TokenKind::Dollar) => {}
5045             _ => err(self_, errors::not_allowed_in_write("Unary expression")),
5046         };
5048         match &loperand.syntax {
5049             ListExpression(x) => Self::syntax_to_list_no_separators(&x.list_members)
5050                 .for_each(|n| self.check_lvalue(false, n)),
5051             SafeMemberSelectionExpression(_) => {
5052                 err(self, errors::not_allowed_in_write("?-> operator"))
5053             }
5054             MemberSelectionExpression(x) => {
5055                 if Self::token_kind(&x.member_name) == Some(TokenKind::XHPClassName) {
5056                     err(self, errors::not_allowed_in_write("->: operator"))
5057                 }
5058             }
5059             VariableExpression(x) => {
5060                 if !allow_reassign {
5061                     let text = self.text(&x.variable_expression);
5062                     if text == sn::special_idents::THIS {
5063                         err(self, errors::reassign_this)
5064                     } else if text == sn::superglobals::GLOBALS {
5065                         err(self, errors::not_allowed_in_write("$GLOBALS"))
5066                     }
5067                 }
5068             }
5069             DecoratedExpression(x) => match Self::token_kind(&x.decorated_expression_decorator) {
5070                 Some(TokenKind::Clone) => err(self, errors::not_allowed_in_write("Clone")),
5071                 Some(TokenKind::Await) => err(self, errors::not_allowed_in_write("Await")),
5072                 Some(TokenKind::Suspend) => err(self, errors::not_allowed_in_write("Suspend")),
5073                 Some(TokenKind::QuestionQuestion) => {
5074                     err(self, errors::not_allowed_in_write("?? operator"))
5075                 }
5076                 Some(TokenKind::BarGreaterThan) => {
5077                     err(self, errors::not_allowed_in_write("|> operator"))
5078                 }
5079                 Some(TokenKind::Inout) => err(self, errors::not_allowed_in_write("Inout")),
5080                 _ => {}
5081             },
5082             ParenthesizedExpression(x) => {
5083                 self.check_lvalue(allow_reassign, &x.parenthesized_expression_expression)
5084             }
5085             SubscriptExpression(x) => self.check_lvalue(true, &x.subscript_receiver),
5086             LambdaExpression(_)
5087             | AnonymousFunction(_)
5088             | AwaitableCreationExpression(_)
5089             | ArrayIntrinsicExpression(_)
5090             | DarrayIntrinsicExpression(_)
5091             | VarrayIntrinsicExpression(_)
5092             | ShapeExpression(_)
5093             | CollectionLiteralExpression(_)
5094             | GenericTypeSpecifier(_)
5095             | YieldExpression(_)
5096             | CastExpression(_)
5097             | BinaryExpression(_)
5098             | ConditionalExpression(_)
5099             | IsExpression(_)
5100             | AsExpression(_)
5101             | NullableAsExpression(_)
5102             | ConstructorCall(_)
5103             | AnonymousClass(_)
5104             | XHPExpression(_)
5105             | InclusionExpression(_)
5106             | TupleExpression(_)
5107             | LiteralExpression(_) => err(
5108                 self,
5109                 errors::not_allowed_in_write(loperand.kind().to_string()),
5110             ),
5111             PrefixUnaryExpression(x) => check_unary_expression(self, &x.prefix_unary_operator),
5112             PostfixUnaryExpression(x) => check_unary_expression(self, &x.postfix_unary_operator),
5114             // FIXME: Array_get ((_, Class_const _), _) is not a valid lvalue. *)
5115             _ => {} // Ideally we should put all the rest of the syntax here so everytime
5116                     // a new syntax is added people need to consider whether the syntax
5117                     // can be a valid lvalue or not. However, there are too many of them.
5118         }
5119     }
5121     fn assignment_errors(&mut self, node: &'a Syntax<Token, Value>) {
5122         let check_rvalue = |self_: &mut Self, roperand: &'a Syntax<Token, Value>| {
5123             let append_errors = |self_: &mut Self, node, error| {
5124                 self_.errors.push(Self::make_error_from_node(node, error))
5125             };
5126             match &roperand.syntax {
5127                 VariableExpression(x)
5128                     if self_.text(&x.variable_expression) == sn::superglobals::GLOBALS =>
5129                 {
5130                     append_errors(self_, roperand, errors::globals_without_subscript)
5131                 }
5133                 _ => (),
5134             }
5135         };
5137         let check_unary_expression = |self_: &mut Self, op, loperand: &'a Syntax<Token, Value>| {
5138             if Self::does_unop_create_write(Self::token_kind(op)) {
5139                 self_.check_lvalue(true, loperand)
5140             }
5141         };
5142         match &node.syntax {
5143             PrefixUnaryExpression(x) => {
5144                 check_unary_expression(self, &x.prefix_unary_operator, &x.prefix_unary_operand)
5145             }
5146             PostfixUnaryExpression(x) => {
5147                 check_unary_expression(self, &x.postfix_unary_operator, &x.postfix_unary_operand)
5148             }
5149             DecoratedExpression(x) => {
5150                 let loperand = &x.decorated_expression_expression;
5151                 if Self::does_decorator_create_write(Self::token_kind(
5152                     &x.decorated_expression_decorator,
5153                 )) {
5154                     self.check_lvalue(true, &loperand)
5155                 }
5156             }
5157             BinaryExpression(x) => {
5158                 let loperand = &x.binary_left_operand;
5159                 let roperand = &x.binary_right_operand;
5160                 if Self::does_binop_create_write_on_left(Self::token_kind(&x.binary_operator)) {
5161                     self.check_lvalue(false, &loperand);
5162                     check_rvalue(self, &roperand);
5163                 }
5164             }
5165             ForeachStatement(x) => {
5166                 self.check_lvalue(false, &x.foreach_value);
5167                 self.check_lvalue(false, &x.foreach_key);
5168                 check_rvalue(self, &x.foreach_collection);
5169             }
5170             _ => {}
5171         }
5172     }
5174     fn dynamic_method_call_errors(&mut self, node: &'a Syntax<Token, Value>) {
5175         match &node.syntax {
5176             FunctionCallExpression(x) if !x.function_call_type_args.is_missing() => {
5177                 let is_variable = |x| Self::is_token_kind(x, TokenKind::Variable);
5178                 let is_dynamic = match &x.function_call_receiver.syntax {
5179                     ScopeResolutionExpression(x) => is_variable(&x.scope_resolution_name),
5180                     MemberSelectionExpression(x) => is_variable(&x.member_name),
5181                     SafeMemberSelectionExpression(x) => is_variable(&x.safe_member_name),
5182                     _ => false,
5183                 };
5184                 if is_dynamic {
5185                     self.errors.push(Self::make_error_from_node(
5186                         node,
5187                         errors::no_type_parameters_on_dynamic_method_calls,
5188                     ))
5189                 }
5190             }
5191             _ => (),
5192         }
5193     }
5195     fn get_namespace_name(&self) -> String {
5196         if let Some(node) = self.nested_namespaces.last() {
5197             if let NamespaceDeclaration(x) = &node.syntax {
5198                 if let NamespaceDeclarationHeader(x) = &x.namespace_header.syntax {
5199                     let ns = &x.namespace_name;
5200                     if !ns.is_missing() {
5201                         return combine_names(&self.namespace_name, self.text(ns));
5202                     }
5203                 }
5204             }
5205         }
5206         return self.namespace_name.clone();
5207     }
5209     fn is_invalid_hack_mode(&mut self) {
5210         if self.env.syntax_tree.mode().is_none() {
5211             let root = self.env.syntax_tree.root();
5212             let e = Self::make_error_from_node(root, errors::invalid_hack_mode);
5213             self.errors.push(e);
5214         }
5215     }
5217     fn disabled_legacy_soft_typehint_errors(&mut self, node: &'a Syntax<Token, Value>) {
5218         if let SoftTypeSpecifier(_) = node.syntax {
5219             if self.env.parser_options.po_disable_legacy_soft_typehints {
5220                 self.errors.push(Self::make_error_from_node(
5221                     node,
5222                     errors::no_legacy_soft_typehints,
5223                 ))
5224             }
5225         }
5226     }
5228     fn disabled_legacy_attribute_syntax_errors(&mut self, node: &'a Syntax<Token, Value>) {
5229         match node.syntax {
5230             OldAttributeSpecification(_)
5231                 if self.env.parser_options.po_disable_legacy_attribute_syntax =>
5232             {
5233                 self.errors.push(Self::make_error_from_node(
5234                     node,
5235                     errors::no_legacy_attribute_syntax,
5236                 ))
5237             }
5238             _ => {}
5239         }
5240     }
5242     fn param_default_decl_errors(&mut self, node: &'a Syntax<Token, Value>) {
5243         if let ParameterDeclaration(x) = &node.syntax {
5244             if self.env.parser_options.po_const_default_lambda_args {
5245                 match self.env.context.active_callable {
5246                     Some(node) => match node.syntax {
5247                         AnonymousFunction(_) | LambdaExpression(_) => {
5248                             self.check_constant_expression(&x.parameter_default_value);
5249                         }
5250                         _ => {}
5251                     },
5252                     _ => {}
5253                 }
5254             }
5255             if self.env.parser_options.po_const_default_func_args {
5256                 self.check_constant_expression(&x.parameter_default_value)
5257             }
5258         }
5259     }
5261     fn concurrent_statement_errors(&mut self, node: &'a Syntax<Token, Value>) {
5262         if let ConcurrentStatement(x) = &node.syntax {
5263             // issue error if concurrent blocks are nested
5264             if self.is_in_concurrent_block {
5265                 self.errors.push(Self::make_error_from_node(
5266                     node,
5267                     errors::nested_concurrent_blocks,
5268                 ))
5269             };
5270             if let CompoundStatement(x) = &x.concurrent_statement.syntax {
5271                 let statement_list = || Self::syntax_to_list_no_separators(&x.compound_statements);
5272                 if statement_list().nth(1).is_none() {
5273                     self.errors.push(Self::make_error_from_node(
5274                         node,
5275                         errors::fewer_than_two_statements_in_concurrent_block,
5276                     ))
5277                 }
5278                 for n in statement_list() {
5279                     if let ExpressionStatement(x) = &n.syntax {
5280                         if !self.node_has_await_child(&x.expression_statement_expression) {
5281                             self.errors.push(Self::make_error_from_node(
5282                                 n,
5283                                 errors::statement_without_await_in_concurrent_block,
5284                             ))
5285                         }
5286                     } else {
5287                         self.errors.push(Self::make_error_from_node(
5288                             n,
5289                             errors::invalid_syntax_concurrent_block,
5290                         ))
5291                     }
5292                 }
5293                 for n in statement_list() {
5294                     for error in self.find_invalid_lval_usage(n) {
5295                         self.errors.push(error)
5296                     }
5297                 }
5298             } else {
5299                 self.errors.push(Self::make_error_from_node(
5300                     node,
5301                     errors::invalid_syntax_concurrent_block,
5302                 ))
5303             }
5304         }
5305     }
5307     fn disabled_function_pointer_expression_error(&mut self, node: &'a Syntax<Token, Value>) {
5308         if let FunctionPointerExpression(_) = &node.syntax {
5309             if !self
5310                 .env
5311                 .parser_options
5312                 .po_enable_first_class_function_pointers
5313             {
5314                 self.errors.push(Self::make_error_from_node(
5315                     node,
5316                     errors::function_pointers_disabled,
5317                 ))
5318             }
5319         }
5320     }
5322     fn check_qualified_name(&mut self, node: &'a Syntax<Token, Value>) {
5323         // The last segment in a qualified name should not have a trailing backslash
5324         // i.e. `Foospace\Bar\` except as the prefix of a GroupUseClause
5325         if let Some(Syntax {
5326             syntax: NamespaceGroupUseDeclaration(_),
5327             ..
5328         }) = self.parents.last()
5329         {
5330         } else {
5331             if let QualifiedName(x) = &node.syntax {
5332                 let name_parts = &x.qualified_name_parts;
5333                 let mut parts = Self::syntax_to_list_with_separators(name_parts);
5334                 let last_part = parts.nth_back(0);
5335                 match last_part {
5336                     Some(t) if Self::token_kind(t) == Some(TokenKind::Backslash) => self
5337                         .errors
5338                         .push(Self::make_error_from_node(t, errors::error0008)),
5339                     _ => (),
5340                 }
5341             }
5342         }
5343     }
5345     fn check_preceding_backslashes_qualified_name(&mut self, node: &'a Syntax<Token, Value>) {
5346         // Qualified names as part of file level declarations
5347         // (group use, namespace use, namespace declarations) should not have preceding backslashes
5348         // `use namespace A\{\B}` will throw this error.
5349         if let QualifiedName(x) = &node.syntax {
5350             let name_parts = &x.qualified_name_parts;
5351             let mut parts = Self::syntax_to_list_with_separators(name_parts);
5352             let first_part = parts.find(|x| !x.is_missing());
5354             match first_part {
5355                 Some(t) if Self::token_kind(t) == Some(TokenKind::Backslash) => self.errors.push(
5356                     Self::make_error_from_node(node, errors::preceding_backslash),
5357                 ),
5358                 _ => (),
5359             }
5360         }
5361     }
5363     fn strip_ns(name: &str) -> &str {
5364         match name.chars().next() {
5365             Some('\\') => &name[1..],
5366             _ => name,
5367         }
5368     }
5370     fn strip_hh_ns(name: &str) -> &str {
5371         name.trim_start_matches("\\HH\\")
5372     }
5374     fn is_global_namespace(&self) -> bool {
5375         self.namespace_name == GLOBAL_NAMESPACE_NAME
5376     }
5378     fn folder(&mut self, node: &'a Syntax<Token, Value>) {
5379         let has_rx_attr_mutable_hack = |self_: &mut Self, attrs| {
5380             self_
5381                 .attribute_first_reactivity_annotation(attrs)
5382                 .map_or(false, |node| {
5383                     self_.attr_name(node) != Some(sn::user_attributes::NON_RX)
5384                 })
5385         };
5386         let mut prev_context = None;
5387         let mut pushed_nested_namespace = false;
5389         let named_function_context =
5390             |self_: &mut Self, node, s, prev_context: &mut Option<Context<'a, _>>| {
5391                 *prev_context = Some(self_.env.context.clone());
5392                 // a _single_ variable suffices as they cannot be nested
5393                 self_.env.context.active_methodish = Some(node);
5394                 // inspect the rx attribute directly.
5395                 self_.env.context.active_is_rx_or_enclosing_for_lambdas =
5396                     has_rx_attr_mutable_hack(self_, s);
5397                 self_.env.context.active_callable = Some(node);
5398                 self_.env.context.active_callable_attr_spec = Some(s);
5399             };
5401         let lambda_context =
5402             |self_: &mut Self, node, s, prev_context: &mut Option<Context<'a, _>>| {
5403                 *prev_context = Some(self_.env.context.clone());
5404                 //preserve context when entering lambdas (and anonymous functions)
5405                 self_.env.context.active_callable = Some(node);
5406                 self_.env.context.active_callable_attr_spec = Some(s);
5407             };
5409         match &node.syntax {
5410             ConstDeclaration(_) => {
5411                 prev_context = Some(self.env.context.clone());
5412                 self.env.context.active_const = Some(node)
5413             }
5414             FunctionDeclaration(x) => {
5415                 named_function_context(self, node, &x.function_attribute_spec, &mut prev_context)
5416             }
5417             MethodishDeclaration(x) => {
5418                 named_function_context(self, node, &x.methodish_attribute, &mut prev_context)
5419             }
5420             NamespaceDeclaration(x) => {
5421                 if let NamespaceDeclarationHeader(x) = &x.namespace_header.syntax {
5422                     let namespace_name = &x.namespace_name;
5423                     if !namespace_name.is_missing() && !self.text(namespace_name).is_empty() {
5424                         pushed_nested_namespace = true;
5425                         self.nested_namespaces.push(node)
5426                     }
5427                 }
5428             }
5429             AnonymousFunction(x) => {
5430                 lambda_context(self, node, &x.anonymous_attribute_spec, &mut prev_context)
5431             }
5432             LambdaExpression(x) => {
5433                 lambda_context(self, node, &x.lambda_attribute_spec, &mut prev_context)
5434             }
5435             AwaitableCreationExpression(x) => {
5436                 lambda_context(self, node, &x.awaitable_attribute_spec, &mut prev_context)
5437             }
5438             ClassishDeclaration(_) => {
5439                 prev_context = Some(self.env.context.clone());
5440                 self.env.context.active_classish = Some(node)
5441             }
5442             FileAttributeSpecification(_) => Self::attr_spec_to_node_list(node).for_each(|node| {
5443                 if self.attr_name(node).as_deref()
5444                     == Some(sn::user_attributes::ENABLE_UNSTABLE_FEATURES)
5445                 {
5446                     if !self.env.parser_options.po_allow_unstable_features {
5447                         self.errors.push(Self::make_error_from_node(
5448                             node,
5449                             errors::invalid_use_of_enable_unstable_feature(
5450                                 "unstable features are disabled",
5451                             ),
5452                         ))
5453                     } else if let Some(args) = self.attr_args(node) {
5454                         let mut args = args.peekable();
5455                         if args.peek().is_none() {
5456                             self.errors.push(Self::make_error_from_node(
5457                                 node,
5458                                 errors::invalid_use_of_enable_unstable_feature(
5459                                     format!(
5460                                         "you didn't select a feature. Available features are:\n\t{}",
5461                                         UnstableFeatures::iter().join("\n\t")
5462                                     )
5463                                     .as_str(),
5464                                 ),
5465                             ))
5466                         } else {
5467                             args.for_each(|arg| self.enable_unstable_feature(node, arg))
5468                         }
5469                     } else {
5470                     }
5471                 }
5472             }),
5473             _ => (),
5474         };
5476         self.parameter_errors(node);
5478         match &node.syntax {
5479             TryStatement(_)
5480             | UsingStatementFunctionScoped(_)
5481             | ForStatement(_)
5482             | CaseLabel(_)
5483             | DefaultLabel(_) => self.statement_errors(node),
5484             MethodishDeclaration(_) | FunctionDeclaration(_) | FunctionDeclarationHeader(_) => {
5485                 self.reified_parameter_errors(node);
5486                 self.redeclaration_errors(node);
5487                 self.multiple_entrypoint_attribute_errors(node);
5488                 self.methodish_errors(node);
5489             }
5491             ArrayIntrinsicExpression(_) => self.expression_errors(node),
5492             LiteralExpression(_)
5493             | SafeMemberSelectionExpression(_)
5494             | FunctionCallExpression(_)
5495             | ListExpression(_)
5496             | ShapeExpression(_)
5497             | DecoratedExpression(_)
5498             | VectorIntrinsicExpression(_)
5499             | DictionaryIntrinsicExpression(_)
5500             | KeysetIntrinsicExpression(_)
5501             | VarrayIntrinsicExpression(_)
5502             | DarrayIntrinsicExpression(_)
5503             | YieldExpression(_)
5504             | ScopeResolutionExpression(_)
5505             | PrefixUnaryExpression(_)
5506             | LambdaExpression(_)
5507             | IsExpression(_)
5508             | AsExpression(_)
5509             | AnonymousFunction(_)
5510             | SubscriptExpression(_)
5511             | ConstructorCall(_)
5512             | AwaitableCreationExpression(_)
5513             | PipeVariableExpression(_)
5514             | ConditionalExpression(_)
5515             | CollectionLiteralExpression(_)
5516             | VariableExpression(_) => {
5517                 self.dynamic_method_call_errors(node);
5518                 self.expression_errors(node);
5519                 self.check_nonrx_annotation(node);
5520                 self.assignment_errors(node);
5521             }
5523             ParameterDeclaration(_) => self.param_default_decl_errors(node),
5524             RequireClause(_) => self.require_errors(node),
5525             ClassishDeclaration(_) => {
5526                 self.classish_errors(node);
5527                 self.class_reified_param_errors(node);
5528             }
5530             ConstDeclaration(_) => self.class_constant_modifier_errors(node),
5532             TypeConstDeclaration(_) => self.type_const_modifier_errors(node),
5534             AliasDeclaration(_) => self.alias_errors(node),
5535             ConstantDeclarator(_) => self.const_decl_errors(node),
5536             NamespaceBody(_) | NamespaceEmptyBody(_) | NamespaceDeclaration(_) => {
5537                 self.mixed_namespace_errors(node)
5538             }
5539             NamespaceUseDeclaration(_) | NamespaceGroupUseDeclaration(_) => {
5540                 self.group_use_errors(node);
5541                 self.namespace_use_declaration_errors(node);
5542             }
5543             PropertyDeclaration(_) => {
5544                 self.class_property_modifiers_errors(node);
5545                 self.class_reified_param_errors(node);
5546                 self.class_property_const_errors(node);
5547                 self.class_property_declarator_errors(node);
5548             }
5549             TraitUseAliasItem(_) => self.trait_use_alias_item_modifier_errors(node),
5550             EnumDeclaration(_) => self.enum_decl_errors(node),
5551             Enumerator(_) => self.enumerator_errors(node),
5552             PostfixUnaryExpression(_) | BinaryExpression(_) | ForeachStatement(_) => {
5553                 self.assignment_errors(node)
5554             }
5555             XHPEnumType(_) | XHPExpression(_) => self.xhp_errors(node),
5556             PropertyDeclarator(x) => {
5557                 let init = &x.property_initializer;
5559                 self.produce_error(
5560                     |self_, x| self_.check_static_in_initializer(x),
5561                     &init,
5562                     || errors::parent_static_prop_decl,
5563                     &init,
5564                 );
5565                 self.check_constant_expression(&init)
5566             }
5567             RecordField(x) => self.check_constant_expression(&x.record_field_init),
5568             XHPClassAttribute(x) => {
5569                 self.check_constant_expression(&x.xhp_attribute_decl_initializer)
5570             }
5571             OldAttributeSpecification(_) => self.disabled_legacy_attribute_syntax_errors(node),
5572             SoftTypeSpecifier(_) => self.disabled_legacy_soft_typehint_errors(node),
5573             FunctionPointerExpression(_) => self.disabled_function_pointer_expression_error(node),
5574             QualifiedName(_) => self.check_qualified_name(node),
5575             _ => {}
5576         }
5577         self.lval_errors(node);
5579         match &node.syntax {
5580             LambdaExpression(_) | AwaitableCreationExpression(_) | AnonymousFunction(_) => {
5581                 let prev_is_in_concurrent_block = self.is_in_concurrent_block;
5582                 // reset is_in_concurrent_block for functions
5583                 self.is_in_concurrent_block = false;
5584                 // analyze the body of lambda block
5585                 self.fold_child_nodes(node);
5586                 // adjust is_in_concurrent_block in final result
5587                 self.is_in_concurrent_block = prev_is_in_concurrent_block;
5588             }
5590             ConcurrentStatement(_) => {
5591                 self.concurrent_statement_errors(node);
5592                 // adjust is_in_concurrent_block in accumulator to dive into the
5593                 let prev_is_in_concurrent_block = self.is_in_concurrent_block;
5594                 self.is_in_concurrent_block = true;
5595                 // analyze the body of concurrent block
5596                 self.fold_child_nodes(node);
5597                 // adjust is_in_concurrent_block in final result
5598                 self.is_in_concurrent_block = prev_is_in_concurrent_block;
5599             }
5601             NamespaceBody(x) => {
5602                 if self.namespace_type == Unspecified {
5603                     self.namespace_type = Bracketed(Self::make_location(
5604                         &x.namespace_left_brace,
5605                         &x.namespace_right_brace,
5606                     ))
5607                 }
5609                 let old_namespace_name = self.namespace_name.clone();
5610                 let mut old_names = self.names.clone();
5611                 // reset names before diving into namespace body,
5612                 // keeping global function names
5613                 self.namespace_name = self.get_namespace_name();
5614                 let names_copy = std::mem::replace(&mut self.names, UsedNames::empty());
5615                 self.names.functions = names_copy.functions.filter(|x| x.global);
5616                 self.fold_child_nodes(node);
5618                 // add newly declared global functions to the old set of names
5619                 let names_copy = std::mem::replace(&mut self.names, UsedNames::empty());
5620                 for (k, v) in names_copy.functions.into_iter().filter(|(_, x)| x.global) {
5621                     old_names.functions.add(&k, v)
5622                 }
5623                 // resume with old set of names and pull back
5624                 // accumulated errors/last seen namespace type
5625                 self.names = old_names;
5626                 self.namespace_name = old_namespace_name;
5627             }
5628             NamespaceEmptyBody(x) => {
5629                 if self.namespace_type == Unspecified {
5630                     self.namespace_type =
5631                         Unbracketed(Self::make_location_of_node(&x.namespace_semicolon))
5632                 }
5633                 self.namespace_name = self.get_namespace_name();
5634                 self.names = UsedNames::empty();
5635                 self.fold_child_nodes(node);
5636             }
5637             ClassishDeclaration(_) | AnonymousClass(_) => {
5638                 // Reset the trait require clauses
5639                 // Reset the const declarations
5640                 // Reset the function declarations
5642                 let constants =
5643                     std::mem::replace(&mut self.names.constants, YesCase(HashMap::new()));
5644                 let functions =
5645                     std::mem::replace(&mut self.names.functions, NoCase(HashMap::new()));
5646                 let trait_require_clauses = std::mem::replace(
5647                     &mut self.trait_require_clauses,
5648                     empty_trait_require_clauses(),
5649                 );
5651                 self.fold_child_nodes(node);
5653                 self.trait_require_clauses = trait_require_clauses;
5654                 self.names.functions = functions;
5655                 self.names.constants = constants;
5656             }
5657             _ => self.fold_child_nodes(node),
5658         }
5660         match &node.syntax {
5661             UnionTypeSpecifier(_) | IntersectionTypeSpecifier(_) => {
5662                 self.check_can_use_feature(node, &UnstableFeatures::UnionIntersectionTypeHints)
5663             }
5664             ClassishDeclaration(x) => match &x.classish_where_clause.syntax {
5665                 WhereClause(_) => self.check_can_use_feature(
5666                     &x.classish_where_clause,
5667                     &UnstableFeatures::ClassLevelWhere,
5668                 ),
5669                 _ => (),
5670             },
5671             _ => (),
5672         }
5674         if let Some(prev_context) = prev_context {
5675             self.env.context = prev_context;
5676         }
5677         if pushed_nested_namespace {
5678             assert_eq!(
5679                 self.nested_namespaces.pop().map(|x| x as *const _),
5680                 Some(node as *const _)
5681             );
5682         }
5683     }
5685     fn fold_child_nodes(&mut self, node: &'a Syntax<Token, Value>) {
5686         self.parents.push(node);
5687         for c in node.iter_children() {
5688             self.folder(c)
5689         }
5690         assert_eq!(
5691             self.parents.pop().map(|x| x as *const _),
5692             Some(node as *const _)
5693         );
5694     }
5696     fn parse_errors_impl(mut self) -> Vec<SyntaxError> {
5697         if self.env.is_typechecker() && !self.env.parser_options.po_disable_modes {
5698             self.is_invalid_hack_mode();
5699         }
5700         self.fold_child_nodes(self.env.syntax_tree.root());
5701         self.errors.reverse();
5702         self.errors
5703     }
5705     fn parse_errors(
5706         tree: &'a SyntaxTree<'a, Syntax<Token, Value>, State>,
5707         text: IndexedSourceText<'a>,
5708         parser_options: ParserOptions,
5709         hhvm_compat_mode: bool,
5710         hhi_mode: bool,
5711         codegen: bool,
5712     ) -> Vec<SyntaxError> {
5713         let env = Env {
5714             parser_options,
5715             syntax_tree: tree,
5716             text,
5717             context: Context {
5718                 active_classish: None,
5719                 active_methodish: None,
5720                 active_callable: None,
5721                 active_callable_attr_spec: None,
5722                 active_is_rx_or_enclosing_for_lambdas: false,
5723                 active_const: None,
5724                 active_unstable_features: HashSet::new(),
5725             },
5726             hhvm_compat_mode,
5727             hhi_mode,
5728             codegen,
5729         };
5731         match tree.required_stack_size() {
5732             None => Self::new(env).parse_errors_impl(),
5733             Some(stack_size) => {
5734                 // We want to use new thread ONLY for it's capability of adjustable stack size.
5735                 // Rust is against it because SyntaxTree is not a thread safe structure. Moreover,
5736                 // spawned thread could outlive the 'a lifetime.
5737                 // Since the only thing the main thread will do after spawning the child is to wait
5738                 // for it to finish, there will be no actual concurrency, and we can "safely" unsafe
5739                 // it. The usize cast is to fool the borrow checker about the thread lifetime and 'a.
5740                 let raw_pointer = Box::leak(Box::new(Self::new(env))) as *mut Self as usize;
5741                 std::thread::Builder::new()
5742                     .stack_size(stack_size)
5743                     .spawn(move || {
5744                         let self_ = unsafe { Box::from_raw(raw_pointer as *mut Self) };
5745                         self_.parse_errors_impl()
5746                     })
5747                     .expect("ERROR: thread::spawn")
5748                     .join()
5749                     .expect("ERROR: failed to wait on new thread")
5750             }
5751         }
5752     }
5755 pub fn parse_errors<'a>(
5756     tree: &'a SyntaxTree<'a, PositionedSyntax, ()>,
5757     parser_options: ParserOptions,
5758     hhvm_compat_mode: bool,
5759     hhi_mode: bool,
5760     codegen: bool,
5761 ) -> Vec<SyntaxError> {
5762     ParserErrors::parse_errors(
5763         tree,
5764         IndexedSourceText::new(tree.text().clone()),
5765         parser_options,
5766         hhvm_compat_mode,
5767         hhi_mode,
5768         codegen,
5769     )
5772 pub fn parse_errors_with_text<'a>(
5773     tree: &'a SyntaxTree<'a, PositionedSyntax, ()>,
5774     text: IndexedSourceText<'a>,
5775     parser_options: ParserOptions,
5776     hhvm_compat_mode: bool,
5777     hhi_mode: bool,
5778     codegen: bool,
5779 ) -> Vec<SyntaxError> {
5780     ParserErrors::parse_errors(
5781         tree,
5782         text,
5783         parser_options,
5784         hhvm_compat_mode,
5785         hhi_mode,
5786         codegen,
5787     )