1use perl_ast::ast::Node;
7use std::ops::Range;
8
9mod args;
10mod conditional;
11mod features;
12mod map;
13mod range_builder;
14mod version;
15
16pub use map::{
17 CompileTimePragmaEnvironment, PragmaEntry, PragmaMap, PragmaQueryCursor, PragmaStateQuery,
18};
19pub use version::{
20 PerlVersion, features_enabled_by_version, parse_perl_version, version_implies_strict,
21 version_implies_warnings,
22};
23
24pub(crate) use args::{
25 add_disabled_warning_category, apply_builtin_imports, builtin_import_names,
26 normalized_pragma_token, pragma_arg_items, remove_builtin_imports,
27};
28pub(crate) use conditional::conditional_pragma_target;
29pub(crate) use features::{apply_feature_state, canonical_feature_query};
30pub(crate) use map::normalize_state;
31pub(crate) use version::enable_effective_version_semantics;
32
33#[derive(Debug, Clone, Default, PartialEq)]
35pub struct PragmaState {
36 pub strict_vars: bool,
38 pub strict_subs: bool,
40 pub strict_refs: bool,
42 pub warnings: bool,
44 pub utf8: bool,
46 pub encoding: Option<String>,
48 pub unicode_strings: bool,
50 pub locale: bool,
52 pub locale_scope: Option<String>,
54 pub disabled_warning_categories: Vec<String>,
61 pub signatures_strict: bool,
67 pub features: Vec<&'static str>,
72 pub builtin_imports: Vec<String>,
74}
75
76#[derive(Debug, Clone, Default, PartialEq)]
81pub struct PragmaSnapshot {
82 state: PragmaState,
83}
84
85impl PragmaSnapshot {
86 #[must_use]
88 pub fn from_state(state: PragmaState) -> Self {
89 Self { state }
90 }
91
92 #[must_use]
94 pub fn state(&self) -> &PragmaState {
95 &self.state
96 }
97
98 #[must_use]
100 pub fn strict_enabled(&self) -> bool {
101 self.state.strict_vars && self.state.strict_subs && self.state.strict_refs
102 }
103
104 #[must_use]
106 pub fn warnings_enabled(&self) -> bool {
107 self.state.warnings
108 }
109
110 #[must_use]
112 pub fn has_feature(&self, feature: &str) -> bool {
113 self.state.has_feature(feature)
114 }
115
116 #[must_use]
118 pub fn is_warning_active(&self, category: &str) -> bool {
119 self.state.is_warning_active(category)
120 }
121}
122
123impl From<PragmaState> for PragmaSnapshot {
124 fn from(state: PragmaState) -> Self {
125 Self::from_state(state)
126 }
127}
128
129impl From<PragmaSnapshot> for PragmaState {
130 fn from(snapshot: PragmaSnapshot) -> Self {
131 snapshot.state
132 }
133}
134
135impl PragmaState {
136 pub fn all_strict() -> Self {
138 Self {
139 strict_vars: true,
140 strict_subs: true,
141 strict_refs: true,
142 warnings: false,
143 utf8: false,
144 encoding: None,
145 unicode_strings: false,
146 locale: false,
147 locale_scope: None,
148 disabled_warning_categories: Vec::new(),
149 signatures_strict: false,
150 features: Vec::new(),
151 builtin_imports: Vec::new(),
152 }
153 }
154
155 #[must_use]
165 pub fn is_warning_active(&self, category: &str) -> bool {
166 self.warnings && !self.disabled_warning_categories.iter().any(|c| c == category)
167 }
168
169 #[must_use]
171 pub fn has_feature(&self, feature: &str) -> bool {
172 let feature = canonical_feature_query(feature);
173 self.features.contains(&feature)
174 }
175
176 #[must_use]
178 pub fn has_builtin_import(&self, name: &str) -> bool {
179 self.builtin_imports.iter().any(|import| import == name)
180 }
181}
182
183pub struct PragmaTracker;
185
186impl PragmaTracker {
187 pub fn build(ast: &Node) -> Vec<(Range<usize>, PragmaState)> {
189 CompileTimePragmaEnvironment::build(ast)
190 .as_map()
191 .iter()
192 .map(|(range, snapshot)| (range.clone(), snapshot.clone().into()))
193 .collect()
194 }
195
196 pub fn state_for_offset(
198 pragma_map: &[(Range<usize>, PragmaState)],
199 offset: usize,
200 ) -> PragmaState {
201 let idx = pragma_map.partition_point(|(range, _)| range.start <= offset);
202 let state = if idx > 0 { pragma_map[idx - 1].1.clone() } else { PragmaState::default() };
203
204 normalize_state(state)
205 }
206
207 #[must_use]
209 pub fn final_state(pragma_map: &[(Range<usize>, PragmaState)]) -> PragmaState {
210 let state = pragma_map.last().map_or_else(PragmaState::default, |(_, s)| s.clone());
211
212 normalize_state(state)
213 }
214}