Fix bug in hack codegen for sets
[hiphop-php.git] / hphp / hack / src / parser / mode_parser.rs
blobe1f7af5fbfd528f83bf9c72f798c25e92cbe3a05
1 // Copyright (c) 2019, Facebook, Inc.
2 // All rights reserved.
3 //
4 // This source code is licensed under the MIT license found in the
5 // LICENSE file in the "hack" directory of this source tree.
7 use bumpalo::Bump;
8 use parser_core_types::parser_env::ParserEnv;
9 use parser_core_types::source_text::SourceText;
10 use parser_core_types::syntax_by_ref::syntax::Syntax;
11 use parser_core_types::syntax_by_ref::syntax_variant_generated::SyntaxVariant;
12 use parser_core_types::syntax_by_ref::syntax_variant_generated::{self as syntax};
13 use parser_core_types::syntax_tree::FileMode;
15 pub enum Language {
16     Hack,
17     PHP,
20 // Returns Language::PHP if text is a PHP file (has .php extension and starts
21 // with anything other than <?hh). Correctly recognizing PHP files is important
22 // for open-source projects, which may need Hack and PHP files to coexist in the
23 // same directory.
24 pub fn parse_mode(text: &SourceText<'_>) -> (Language, Option<FileMode>) {
25     let bump = Bump::new();
26     if let Some(header) =
27         positioned_by_ref_parser::parse_header_only(ParserEnv::default(), &bump, text)
28     {
29         match header.children {
30             SyntaxVariant::MarkupSection(section_children) => {
31                 match section_children {
32                     syntax::MarkupSectionChildren {
33                         suffix:
34                             Syntax {
35                                 children: SyntaxVariant::MarkupSuffix(suffix_children),
36                                 ..
37                             },
38                         ..
39                     } => {
40                         let syntax::MarkupSuffixChildren { name, .. } = *suffix_children;
41                         match &name.children {
42                             // <?, <?php or <?anything_else except <?hh
43                             SyntaxVariant::Missing => (Language::PHP, None),
44                             // <?hh
45                             _ => {
46                                 if text.file_path().has_extension("hhi") {
47                                     (Language::Hack, Some(FileMode::Hhi))
48                                 } else {
49                                     (Language::Hack, Some(FileMode::Strict))
50                                 }
51                             }
52                         }
53                     }
54                     _ => {
55                         // unreachable (parser either returns a value that matches
56                         // the above expressions, or None)
57                         (Language::Hack, Some(FileMode::Strict))
58                     }
59                 }
60             }
61             // unreachable (parser either returns a value that matches
62             // the above expression, or None)
63             _ => (Language::Hack, Some(FileMode::Strict)),
64         }
65     } else {
66         (Language::Hack, Some(FileMode::Strict))
67     }