1 // Copyright (c) Meta Platforms, Inc. and affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
8 use direct_decl_parser::parse_decls_without_reference_text;
9 use direct_decl_parser::Decls;
10 use oxidized::decl_parser_options::DeclParserOptions;
11 use oxidized_by_ref::shallow_decl_defs::ConstDecl;
12 use oxidized_by_ref::shallow_decl_defs::FunDecl;
13 use oxidized_by_ref::shallow_decl_defs::ModuleDecl;
14 use parser_core_types::source_text::SourceText;
16 use crate::DeclProvider;
20 /// A decl provider that also provides decls found in the given file.
22 /// Checks the current file first for decls. If not found,
23 /// checks the provided decl provider for the decls next.
25 /// Useful when the file under compilation is not indexed by the HHVM autoloader
26 /// or similar circumstances.
27 pub struct SelfProvider<'d> {
28 fallback_decl_provider: Option<Arc<dyn DeclProvider<'d> + 'd>>,
32 impl<'d> SelfProvider<'d> {
34 fallback_decl_provider: Option<Arc<dyn DeclProvider<'d> + 'd>>,
35 decl_opts: DeclParserOptions,
36 source_text: SourceText<'_>,
37 arena: &'d bumpalo::Bump,
39 let parsed_file = parse_decls_without_reference_text(
41 source_text.file_path().clone(),
46 fallback_decl_provider,
47 decls: parsed_file.decls,
51 /// Currently, because decls are not on by default everywhere
52 /// only create a new SelfProvider when given a fallback provider,
53 /// which indicates that we want to compile with decls.
54 /// When decls are turned on everywhere by default and it is no longer optional
55 /// this can simply return a nonoption decl provider
56 pub fn wrap_existing_provider(
57 fallback_decl_provider: Option<Arc<dyn DeclProvider<'d> + 'd>>,
58 decl_opts: DeclParserOptions,
59 source_text: SourceText<'_>,
60 arena: &'d bumpalo::Bump,
61 ) -> Option<Arc<dyn DeclProvider<'d> + 'd>> {
62 if fallback_decl_provider.is_none() {
65 Some(Arc::new(SelfProvider::new(
66 fallback_decl_provider,
70 )) as Arc<dyn DeclProvider<'d> + 'd>)
77 get_fallback_decl: impl Fn(&Arc<dyn DeclProvider<'d> + 'd>) -> Result<T>,
80 self.fallback_decl_provider
82 .map_or(Err(crate::Error::NotFound), get_fallback_decl)
87 impl<'d> DeclProvider<'d> for SelfProvider<'d> {
88 fn type_decl(&self, symbol: &str, depth: u64) -> Result<TypeDecl<'d>> {
89 self.result_or_else(crate::find_type_decl(&self.decls, symbol), |provider| {
90 provider.type_decl(symbol, depth)
94 fn func_decl(&self, symbol: &str) -> Result<&'d FunDecl<'d>> {
95 self.result_or_else(crate::find_func_decl(&self.decls, symbol), |provider| {
96 provider.func_decl(symbol)
100 fn const_decl(&self, symbol: &str) -> Result<&'d ConstDecl<'d>> {
101 self.result_or_else(crate::find_const_decl(&self.decls, symbol), |provider| {
102 provider.const_decl(symbol)
106 fn module_decl(&self, symbol: &str) -> Result<&'d ModuleDecl<'d>> {
107 self.result_or_else(crate::find_module_decl(&self.decls, symbol), |provider| {
108 provider.module_decl(symbol)
113 impl<'d> std::fmt::Debug for SelfProvider<'d> {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 if let Some(p) = &self.fallback_decl_provider {
116 write!(f, "SelfProvider({:?})", p)
118 write!(f, "SelfProvider")