use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
use ecow::EcoString;
use crate::ast::{BindingId as AstBindingId, Pattern, RestPattern, Span};
use crate::types::Type;
use super::{Definition, File, ModuleInfo};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct ReceiverId(Span);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReceiverCoercion {
AutoAddress,
AutoDeref,
}
#[derive(Debug, Clone, Default)]
pub struct CoercionInfo {
receivers: HashMap<ReceiverId, ReceiverCoercion>,
}
impl CoercionInfo {
pub fn mark_coercion(&mut self, span: Span, coercion: ReceiverCoercion) {
self.receivers.insert(ReceiverId(span), coercion);
}
pub fn get_coercion(&self, span: Span) -> Option<ReceiverCoercion> {
self.receivers.get(&ReceiverId(span)).copied()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct BindingId(Span);
#[derive(Debug, Clone, Default)]
pub struct UnusedInfo {
bindings: HashSet<BindingId>,
definitions: HashSet<BindingId>,
pub imports_by_module: HashMap<EcoString, HashSet<EcoString>>,
}
impl UnusedInfo {
pub fn mark_binding_unused(&mut self, span: Span) {
self.bindings.insert(BindingId(span));
}
pub fn is_unused_binding(&self, pattern: &Pattern) -> bool {
match pattern {
Pattern::Identifier { span, .. } => self.bindings.contains(&BindingId(*span)),
_ => false,
}
}
pub fn is_unused_rest_binding(&self, rest: &RestPattern) -> bool {
match rest {
RestPattern::Bind { span, .. } => self.bindings.contains(&BindingId(*span)),
_ => false,
}
}
pub fn mark_definition_unused(&mut self, span: Span) {
self.definitions.insert(BindingId(span));
}
pub fn is_unused_definition(&self, span: &Span) -> bool {
self.definitions.contains(&BindingId(*span))
}
}
#[derive(Debug, Clone, Default)]
pub struct MutationInfo {
bindings: HashSet<AstBindingId>,
}
impl MutationInfo {
pub fn mark_binding_mutated(&mut self, id: AstBindingId) {
self.bindings.insert(id);
}
pub fn is_mutated(&self, id: AstBindingId) -> bool {
self.bindings.contains(&id)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DotAccessKind {
StructField { is_exported: bool },
TupleStructField { is_newtype: bool },
TupleElement,
ModuleMember,
ValueEnumVariant,
EnumVariant,
InstanceMethod { is_exported: bool },
InstanceMethodValue {
is_exported: bool,
is_pointer_receiver: bool,
},
StaticMethod { is_exported: bool },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NativeTypeKind {
Slice,
EnumeratedSlice,
Map,
Channel,
Sender,
Receiver,
String,
}
impl NativeTypeKind {
pub fn from_type(ty: &Type) -> Option<Self> {
let resolved = ty.resolve().strip_refs();
if let Type::Constructor { ref id, .. } = resolved
&& (id.starts_with("@import/go:") || id.starts_with("go:"))
{
return None;
}
let name = resolved.get_name()?;
Self::from_name(name)
}
pub fn from_name(name: &str) -> Option<Self> {
match name {
"Slice" => Some(Self::Slice),
"EnumeratedSlice" => Some(Self::EnumeratedSlice),
"Map" => Some(Self::Map),
"Channel" => Some(Self::Channel),
"Sender" => Some(Self::Sender),
"Receiver" => Some(Self::Receiver),
"string" => Some(Self::String),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CallKind {
Regular,
TupleStructConstructor,
AssertType,
UfcsMethod,
NativeConstructor(NativeTypeKind),
NativeMethod(NativeTypeKind),
NativeMethodIdentifier(NativeTypeKind),
ReceiverMethodUfcs { is_public: bool },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct ResolutionId(Span);
#[derive(Debug, Clone, Default)]
pub struct ResolutionInfo {
dot_accesses: HashMap<ResolutionId, DotAccessKind>,
calls: HashMap<ResolutionId, CallKind>,
}
impl ResolutionInfo {
pub fn mark_dot_access(&mut self, span: Span, kind: DotAccessKind) {
self.dot_accesses.insert(ResolutionId(span), kind);
}
pub fn get_dot_access(&self, span: Span) -> Option<DotAccessKind> {
self.dot_accesses.get(&ResolutionId(span)).copied()
}
pub fn mark_call(&mut self, span: Span, meta: CallKind) {
self.calls.insert(ResolutionId(span), meta);
}
pub fn get_call(&self, span: Span) -> Option<CallKind> {
self.calls.get(&ResolutionId(span)).copied()
}
}
pub struct EmitInput {
pub files: HashMap<u32, File>,
pub definitions: HashMap<EcoString, Definition>,
pub modules: HashMap<String, ModuleInfo>,
pub entry_module_id: String,
pub unused: UnusedInfo,
pub mutations: MutationInfo,
pub coercions: CoercionInfo,
pub resolutions: ResolutionInfo,
pub cached_modules: HashSet<String>,
pub ufcs_methods: HashSet<(String, String)>,
pub go_package_names: HashMap<String, String>,
}