use constructor::ConstructorDefinition;
use contract::ContractDefinition;
use derive_more::{Display, From, IsVariant, TryInto};
use enumeration::EnumDefinition;
use error::ErrorDefinition;
use event::EventDefinition;
use function::FunctionDefinition;
use lintspec_macros::AsToVariant;
use modifier::ModifierDefinition;
use serde::{Deserialize, Serialize};
use structure::StructDefinition;
use variable::VariableDeclaration;
use crate::{
definitions::{interface::InterfaceDefinition, library::LibraryDefinition},
error::Error,
lint::{Diagnostic, ItemDiagnostics, Validate, ValidationOptions},
textindex::TextRange,
};
pub mod constructor;
pub mod contract;
pub mod enumeration;
pub mod error;
pub mod event;
pub mod function;
pub mod interface;
pub mod library;
pub mod modifier;
pub mod structure;
pub mod variable;
pub trait SourceItem {
fn item_type(&self) -> ItemType;
fn parent(&self) -> Option<Parent>;
fn name(&self) -> String;
fn span(&self) -> TextRange;
}
#[derive(Debug, Clone, bon::Builder)]
#[builder(on(String, into))]
pub struct Identifier {
pub name: Option<String>,
pub span: TextRange,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum Visibility {
External,
#[default]
Internal,
Private,
Public,
}
#[derive(Debug, Clone, Copy, Default, bon::Builder)]
#[non_exhaustive]
pub struct Attributes {
pub visibility: Visibility,
pub r#override: bool,
}
#[derive(Debug, Clone, Display, Serialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum Parent {
Contract(String),
Interface(String),
Library(String),
}
#[derive(Debug, From, TryInto, IsVariant, AsToVariant)]
pub enum Definition {
Contract(ContractDefinition),
Interface(InterfaceDefinition),
Library(LibraryDefinition),
Constructor(ConstructorDefinition),
Enumeration(EnumDefinition),
Error(ErrorDefinition),
Event(EventDefinition),
Function(FunctionDefinition),
Modifier(ModifierDefinition),
Struct(StructDefinition),
Variable(VariableDeclaration),
NatspecParsingError(Error),
}
impl PartialEq for Definition {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Contract(a), Self::Contract(b)) => a.span.start == b.span.start,
(Self::Interface(a), Self::Interface(b)) => a.span.start == b.span.start,
(Self::Library(a), Self::Library(b)) => a.span.start == b.span.start,
(Self::Constructor(a), Self::Constructor(b)) => a.span.start == b.span.start,
(Self::Enumeration(a), Self::Enumeration(b)) => a.span.start == b.span.start,
(Self::Error(a), Self::Error(b)) => a.span.start == b.span.start,
(Self::Event(a), Self::Event(b)) => a.span.start == b.span.start,
(Self::Function(a), Self::Function(b)) => a.span.start == b.span.start,
(Self::Modifier(a), Self::Modifier(b)) => a.span.start == b.span.start,
(Self::Struct(a), Self::Struct(b)) => a.span.start == b.span.start,
(Self::Variable(a), Self::Variable(b)) => a.span.start == b.span.start,
(
Self::NatspecParsingError(Error::NatspecParsingError { span: span_a, .. }),
Self::NatspecParsingError(Error::NatspecParsingError { span: span_b, .. }),
) => span_a.start == span_b.start,
(Self::NatspecParsingError(a), Self::NatspecParsingError(b)) => {
a.to_string() == b.to_string() }
_ => false,
}
}
}
impl Definition {
#[must_use]
pub fn span(&self) -> Option<TextRange> {
match self {
Definition::Contract(d) => Some(d.span()),
Definition::Interface(d) => Some(d.span()),
Definition::Library(d) => Some(d.span()),
Definition::Constructor(d) => Some(d.span()),
Definition::Enumeration(d) => Some(d.span()),
Definition::Error(d) => Some(d.span()),
Definition::Event(d) => Some(d.span()),
Definition::Function(d) => Some(d.span()),
Definition::Modifier(d) => Some(d.span()),
Definition::Struct(d) => Some(d.span()),
Definition::Variable(d) => Some(d.span()),
Definition::NatspecParsingError(Error::NatspecParsingError { span, .. }) => {
Some(span.clone())
}
Definition::NatspecParsingError(_) => None,
}
}
pub fn span_mut(&mut self) -> Option<&mut TextRange> {
match self {
Definition::Contract(d) => Some(&mut d.span),
Definition::Interface(d) => Some(&mut d.span),
Definition::Library(d) => Some(&mut d.span),
Definition::Constructor(d) => Some(&mut d.span),
Definition::Enumeration(d) => Some(&mut d.span),
Definition::Error(d) => Some(&mut d.span),
Definition::Event(d) => Some(&mut d.span),
Definition::Function(d) => Some(&mut d.span),
Definition::Modifier(d) => Some(&mut d.span),
Definition::Struct(d) => Some(&mut d.span),
Definition::Variable(d) => Some(&mut d.span),
Definition::NatspecParsingError(Error::NatspecParsingError { span, .. }) => Some(span),
Definition::NatspecParsingError(_) => None,
}
}
}
impl Validate for Definition {
fn validate(&self, options: &ValidationOptions) -> ItemDiagnostics {
match self {
Definition::NatspecParsingError(error) => {
let (parent, span, message) = match error {
Error::NatspecParsingError {
parent,
span,
message,
} => (parent.clone(), span.clone(), message.clone()),
_ => (None, TextRange::default(), error.to_string()),
};
ItemDiagnostics {
parent,
item_type: ItemType::ParsingError,
name: String::new(),
span: span.clone(),
diags: vec![Diagnostic { span, message }],
}
}
Definition::Contract(def) => def.validate(options),
Definition::Interface(def) => def.validate(options),
Definition::Library(def) => def.validate(options),
Definition::Constructor(def) => def.validate(options),
Definition::Enumeration(def) => def.validate(options),
Definition::Error(def) => def.validate(options),
Definition::Event(def) => def.validate(options),
Definition::Function(def) => def.validate(options),
Definition::Modifier(def) => def.validate(options),
Definition::Struct(def) => def.validate(options),
Definition::Variable(def) => def.validate(options),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
#[serde(rename_all = "lowercase")]
pub enum ContractType {
#[display("contract")]
Contract,
#[display("interface")]
Interface,
#[display("library")]
Library,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
#[serde(rename_all = "lowercase")]
pub enum ItemType {
#[display("contract")]
Contract,
#[display("interface")]
Interface,
#[display("library")]
Library,
#[display("constructor")]
Constructor,
#[display("enum")]
Enum,
#[display("error")]
Error,
#[display("event")]
Event,
#[display("function")]
PrivateFunction,
#[display("function")]
InternalFunction,
#[display("function")]
PublicFunction,
#[display("function")]
ExternalFunction,
#[display("modifier")]
Modifier,
#[cfg_attr(feature = "cli", value(skip))]
ParsingError,
#[display("struct")]
Struct,
#[display("variable")]
PrivateVariable,
#[display("variable")]
InternalVariable,
#[display("variable")]
PublicVariable,
}