#![allow(clippy::needless_lifetimes)]
mod map;
pub use map::*;
use marker_api::{
common::{ExpnId, ExprId, SpanId, SymbolId},
context::{MarkerContextCallbacks, MarkerContextData},
diagnostic::Diagnostic,
ffi::{self, FfiOption},
prelude::*,
span::{ExpnInfo, FileInfo, FilePos, SpanPos, SpanSource},
};
#[repr(C)]
pub struct MarkerContextWrapper<'ast> {
driver: &'ast dyn MarkerContextDriver<'ast>,
}
impl<'ast> MarkerContextWrapper<'ast> {
pub fn new(driver: &'ast dyn MarkerContextDriver<'ast>) -> Self {
Self { driver }
}
#[must_use]
pub fn create_callbacks(&'ast self) -> MarkerContextCallbacks<'ast> {
MarkerContextCallbacks {
data: unsafe { &*(self as *const MarkerContextWrapper).cast::<MarkerContextData>() },
emit_diag,
resolve_ty_ids,
expr_ty,
span,
span_snippet,
span_source,
span_pos_to_file_loc,
span_expn_info,
symbol_str,
resolve_method_target,
}
}
}
pub trait MarkerContextDriver<'ast> {
fn emit_diag(&'ast self, diag: &Diagnostic<'_, 'ast>);
fn resolve_ty_ids(&'ast self, path: &str) -> &'ast [TyDefId];
fn expr_ty(&'ast self, expr: ExprId) -> marker_api::sem::TyKind<'ast>;
fn span(&'ast self, owner: SpanId) -> &'ast Span<'ast>;
fn span_snippet(&'ast self, span: &Span<'_>) -> Option<&'ast str>;
fn span_source(&'ast self, span: &Span<'_>) -> SpanSource<'ast>;
fn span_expn_info(&'ast self, expn_id: ExpnId) -> Option<&'ast ExpnInfo<'ast>>;
fn span_pos_to_file_loc(&'ast self, file: &FileInfo<'ast>, pos: SpanPos) -> Option<FilePos<'ast>>;
fn symbol_str(&'ast self, api_id: SymbolId) -> &'ast str;
fn resolve_method_target(&'ast self, id: ExprId) -> ItemId;
}
extern "C" fn emit_diag<'a, 'ast>(data: &'ast MarkerContextData, diag: &Diagnostic<'a, 'ast>) {
unsafe { as_driver(data) }.emit_diag(diag);
}
extern "C" fn resolve_ty_ids<'ast>(
data: &'ast MarkerContextData,
path: ffi::FfiStr<'_>,
) -> ffi::FfiSlice<'ast, TyDefId> {
unsafe { as_driver(data) }.resolve_ty_ids((&path).into()).into()
}
#[allow(improper_ctypes_definitions)]
extern "C" fn expr_ty<'ast>(data: &'ast MarkerContextData, expr: ExprId) -> marker_api::sem::TyKind<'ast> {
unsafe { as_driver(data) }.expr_ty(expr)
}
extern "C" fn span<'ast>(data: &'ast MarkerContextData, span_id: SpanId) -> &'ast Span<'ast> {
unsafe { as_driver(data) }.span(span_id)
}
extern "C" fn span_snippet<'ast>(
data: &'ast MarkerContextData,
span: &Span<'ast>,
) -> ffi::FfiOption<ffi::FfiStr<'ast>> {
unsafe { as_driver(data) }.span_snippet(span).map(Into::into).into()
}
#[allow(improper_ctypes_definitions)]
extern "C" fn span_source<'ast>(data: &'ast MarkerContextData, span: &Span<'_>) -> SpanSource<'ast> {
unsafe { as_driver(data) }.span_source(span)
}
extern "C" fn span_pos_to_file_loc<'ast>(
data: &'ast MarkerContextData,
file: &FileInfo<'ast>,
pos: SpanPos,
) -> ffi::FfiOption<FilePos<'ast>> {
unsafe { as_driver(data) }.span_pos_to_file_loc(file, pos).into()
}
extern "C" fn span_expn_info<'ast>(data: &'ast MarkerContextData, expn_id: ExpnId) -> FfiOption<&'ast ExpnInfo<'ast>> {
unsafe { as_driver(data) }.span_expn_info(expn_id).into()
}
extern "C" fn symbol_str<'ast>(data: &'ast MarkerContextData, sym: SymbolId) -> ffi::FfiStr<'ast> {
unsafe { as_driver(data) }.symbol_str(sym).into()
}
extern "C" fn resolve_method_target<'ast>(data: &'ast MarkerContextData, id: ExprId) -> ItemId {
unsafe { as_driver(data) }.resolve_method_target(id)
}
unsafe fn as_driver<'ast>(data: &'ast MarkerContextData) -> &'ast dyn MarkerContextDriver<'ast> {
let wrapper = &*(data as *const MarkerContextData).cast::<MarkerContextWrapper>();
wrapper.driver
}