use crate::base::FileId;
use super::types::SpanInfo;
pub(super) struct ExtractionContext {
pub file: FileId,
pub prefix: String,
pub anon_counter: u32,
pub scope_stack: Vec<String>,
pub line_index: crate::base::LineIndex,
}
impl ExtractionContext {
pub fn qualified_name(&self, name: &str) -> String {
if self.prefix.is_empty() {
name.to_string()
} else {
format!("{}::{}", self.prefix, name)
}
}
pub fn current_scope_name(&self) -> String {
self.prefix.clone()
}
pub fn push_scope(&mut self, name: &str) {
self.scope_stack.push(name.to_string());
if self.prefix.is_empty() {
self.prefix = name.to_string();
} else {
self.prefix = format!("{}::{}", self.prefix, name);
}
}
pub fn pop_scope(&mut self) {
if let Some(popped) = self.scope_stack.pop() {
let suffix_len = if self.scope_stack.is_empty() {
popped.len()
} else {
popped.len() + 2 };
self.prefix
.truncate(self.prefix.len().saturating_sub(suffix_len));
}
}
pub fn next_anon_scope(&mut self, rel_prefix: &str, target: &str, line: u32) -> String {
self.anon_counter += 1;
format!("<{}{}#{}@L{}>", rel_prefix, target, self.anon_counter, line)
}
pub fn range_to_info(&self, range: Option<rowan::TextRange>) -> SpanInfo {
match range {
Some(r) => {
let start = self.line_index.line_col(r.start());
let end = self.line_index.line_col(r.end());
SpanInfo {
start_line: start.line,
start_col: start.col,
end_line: end.line,
end_col: end.col,
}
}
None => SpanInfo::default(),
}
}
pub fn range_to_optional(
&self,
range: Option<rowan::TextRange>,
) -> (Option<u32>, Option<u32>, Option<u32>, Option<u32>) {
match range {
Some(r) => {
let start = self.line_index.line_col(r.start());
let end = self.line_index.line_col(r.end());
(
Some(start.line),
Some(start.col),
Some(end.line),
Some(end.col),
)
}
None => (None, None, None, None),
}
}
}
pub(super) fn strip_quotes(s: &str) -> String {
if s.starts_with('\'') && s.ends_with('\'') && s.len() >= 2 {
s[1..s.len() - 1].to_string()
} else {
s.to_string()
}
}