use std::sync::Arc;
use uuid::Uuid;
use crate::base::FileId;
use crate::parser::{DefinitionKind, Direction, Multiplicity, ValueExpression};
use rowan::TextRange;
#[derive(Debug, Clone)]
pub(crate) struct FeatureChain {
pub parts: Vec<FeatureChainPart>,
#[allow(dead_code)]
pub range: Option<TextRange>,
}
#[derive(Debug, Clone)]
pub(crate) struct FeatureChainPart {
pub name: String,
pub range: Option<TextRange>,
}
impl FeatureChain {
pub fn as_dotted_string(&self) -> String {
self.parts
.iter()
.map(|p| p.name.as_str())
.collect::<Vec<_>>()
.join(".")
}
}
#[derive(Debug, Clone)]
pub(crate) enum RelTarget {
Simple(String),
Chain(FeatureChain),
}
impl RelTarget {
pub fn as_str(&self) -> std::borrow::Cow<'_, str> {
match self {
RelTarget::Simple(s) => std::borrow::Cow::Borrowed(s),
RelTarget::Chain(chain) => std::borrow::Cow::Owned(chain.as_dotted_string()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub(crate) enum RelKind {
Specializes,
Redefines,
Subsets,
TypedBy,
References,
Conjugates,
FeatureChain,
Expression,
TransitionSource,
TransitionTarget,
SuccessionSource,
SuccessionTarget,
AcceptedMessage,
AcceptVia,
SentMessage,
SendVia,
SendTo,
MessageSource,
MessageTarget,
Satisfies,
Verifies,
Asserts,
Assumes,
Requires,
AllocateSource,
AllocateTo,
BindSource,
BindTarget,
ConnectSource,
ConnectTarget,
FlowItem,
FlowSource,
FlowTarget,
InterfaceEnd,
Performs,
Exhibits,
Includes,
About,
Meta,
Exposes,
Renders,
Filters,
DependencySource,
DependencyTarget,
Crosses,
}
#[derive(Debug, Clone)]
pub(crate) struct ExtractedRel {
pub kind: RelKind,
pub target: RelTarget,
pub range: Option<TextRange>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub(crate) enum InternalUsageKind {
Part,
Item,
Action,
Port,
Attribute,
Connection,
Interface,
Allocation,
Requirement,
Constraint,
State,
Calculation,
Reference,
Occurrence,
Flow,
Transition,
Accept,
End,
Fork,
Join,
Merge,
Decide,
View,
Viewpoint,
Rendering,
Feature,
Other,
}
pub fn new_element_id() -> Arc<str> {
Uuid::new_v4().to_string().into()
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RefKind {
TypedBy,
Specializes,
Redefines,
Subsets,
References,
Expression,
Other,
}
impl RefKind {
pub fn is_type_reference(&self) -> bool {
matches!(self, RefKind::TypedBy | RefKind::Specializes)
}
pub fn is_feature_reference(&self) -> bool {
matches!(
self,
RefKind::Redefines | RefKind::Subsets | RefKind::References
)
}
pub(crate) fn from_rel_kind(kind: RelKind) -> Self {
match kind {
RelKind::TypedBy => RefKind::TypedBy,
RelKind::Specializes => RefKind::Specializes,
RelKind::Redefines => RefKind::Redefines,
RelKind::Subsets => RefKind::Subsets,
RelKind::References => RefKind::References,
RelKind::Expression => RefKind::Expression,
_ => RefKind::Other,
}
}
pub fn display(&self) -> &'static str {
match self {
RefKind::TypedBy => "typed by",
RefKind::Specializes => "specializes",
RefKind::Redefines => "redefines",
RefKind::Subsets => "subsets",
RefKind::References => "references",
RefKind::Expression => "expression",
RefKind::Other => "other",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RelationshipKind {
Specializes,
TypedBy,
Redefines,
Subsets,
References,
Satisfies,
Performs,
Exhibits,
Includes,
Asserts,
Verifies,
}
impl RelationshipKind {
pub(crate) fn from_rel_kind(kind: RelKind) -> Option<Self> {
match kind {
RelKind::Specializes => Some(RelationshipKind::Specializes),
RelKind::TypedBy => Some(RelationshipKind::TypedBy),
RelKind::Redefines => Some(RelationshipKind::Redefines),
RelKind::Subsets => Some(RelationshipKind::Subsets),
RelKind::References => Some(RelationshipKind::References),
RelKind::Satisfies => Some(RelationshipKind::Satisfies),
RelKind::Performs => Some(RelationshipKind::Performs),
RelKind::Exhibits => Some(RelationshipKind::Exhibits),
RelKind::Includes => Some(RelationshipKind::Includes),
RelKind::Asserts => Some(RelationshipKind::Asserts),
RelKind::Verifies => Some(RelationshipKind::Verifies),
_ => None,
}
}
pub fn display(&self) -> &'static str {
match self {
RelationshipKind::Specializes => "Specializes",
RelationshipKind::TypedBy => "Typed by",
RelationshipKind::Redefines => "Redefines",
RelationshipKind::Subsets => "Subsets",
RelationshipKind::References => "References",
RelationshipKind::Satisfies => "Satisfies",
RelationshipKind::Performs => "Performs",
RelationshipKind::Exhibits => "Exhibits",
RelationshipKind::Includes => "Includes",
RelationshipKind::Asserts => "Asserts",
RelationshipKind::Verifies => "Verifies",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct HirRelationship {
pub kind: RelationshipKind,
pub target: Arc<str>,
pub resolved_target: Option<Arc<str>>,
pub start_line: u32,
pub start_col: u32,
pub end_line: u32,
pub end_col: u32,
}
impl HirRelationship {
pub fn new(kind: RelationshipKind, target: impl Into<Arc<str>>) -> Self {
Self {
kind,
target: target.into(),
resolved_target: None,
start_line: 0,
start_col: 0,
end_line: 0,
end_col: 0,
}
}
pub fn with_span(
kind: RelationshipKind,
target: impl Into<Arc<str>>,
start_line: u32,
start_col: u32,
end_line: u32,
end_col: u32,
) -> Self {
Self {
kind,
target: target.into(),
resolved_target: None,
start_line,
start_col,
end_line,
end_col,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TypeRef {
pub target: Arc<str>,
pub resolved_target: Option<Arc<str>>,
pub kind: RefKind,
pub start_line: u32,
pub start_col: u32,
pub end_line: u32,
pub end_col: u32,
}
impl TypeRef {
pub fn new(
target: impl Into<Arc<str>>,
kind: RefKind,
start_line: u32,
start_col: u32,
end_line: u32,
end_col: u32,
) -> Self {
Self {
target: target.into(),
resolved_target: None,
kind,
start_line,
start_col,
end_line,
end_col,
}
}
pub fn contains(&self, line: u32, col: u32) -> bool {
let after_start =
line > self.start_line || (line == self.start_line && col >= self.start_col);
let before_end = line < self.end_line || (line == self.end_line && col <= self.end_col);
after_start && before_end
}
pub fn immediately_precedes(&self, other: &TypeRef) -> bool {
if self.end_line != other.start_line {
return false;
}
self.end_col + 1 == other.start_col
}
pub fn effective_target(&self) -> &Arc<str> {
self.resolved_target.as_ref().unwrap_or(&self.target)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TypeRefKind {
Simple(TypeRef),
Chain(TypeRefChain),
}
impl TypeRefKind {
pub fn as_refs(&self) -> Vec<&TypeRef> {
match self {
TypeRefKind::Simple(r) => vec![r],
TypeRefKind::Chain(c) => c.parts.iter().collect(),
}
}
pub fn is_chain(&self) -> bool {
matches!(self, TypeRefKind::Chain(_))
}
pub fn first_target(&self) -> &Arc<str> {
match self {
TypeRefKind::Simple(r) => &r.target,
TypeRefKind::Chain(c) => &c.parts[0].target,
}
}
pub fn contains(&self, line: u32, col: u32) -> bool {
match self {
TypeRefKind::Simple(r) => r.contains(line, col),
TypeRefKind::Chain(c) => c.parts.iter().any(|r| r.contains(line, col)),
}
}
pub fn part_at(&self, line: u32, col: u32) -> Option<(usize, &TypeRef)> {
match self {
TypeRefKind::Simple(r) if r.contains(line, col) => Some((0, r)),
TypeRefKind::Chain(c) => c
.parts
.iter()
.enumerate()
.find(|(_, r)| r.contains(line, col)),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TypeRefChain {
pub parts: Vec<TypeRef>,
}
impl TypeRefChain {
pub fn as_dotted_string(&self) -> String {
self.parts
.iter()
.map(|p| p.target.as_ref())
.collect::<Vec<_>>()
.join(".")
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct HirSymbol {
pub name: Arc<str>,
pub short_name: Option<Arc<str>>,
pub qualified_name: Arc<str>,
pub element_id: Arc<str>,
pub kind: SymbolKind,
pub file: FileId,
pub start_line: u32,
pub start_col: u32,
pub end_line: u32,
pub end_col: u32,
pub short_name_start_line: Option<u32>,
pub short_name_start_col: Option<u32>,
pub short_name_end_line: Option<u32>,
pub short_name_end_col: Option<u32>,
pub doc: Option<Arc<str>>,
pub supertypes: Vec<Arc<str>>,
pub relationships: Vec<HirRelationship>,
pub type_refs: Vec<TypeRefKind>,
pub is_public: bool,
pub view_data: Option<crate::hir::views::ViewData>,
pub metadata_annotations: Vec<Arc<str>>,
pub is_abstract: bool,
pub is_variation: bool,
pub is_readonly: bool,
pub is_derived: bool,
pub is_parallel: bool,
pub is_individual: bool,
pub is_end: bool,
pub is_default: bool,
pub is_ordered: bool,
pub is_nonunique: bool,
pub is_portion: bool,
pub direction: Option<Direction>,
pub multiplicity: Option<Multiplicity>,
pub value: Option<ValueExpression>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum SymbolKind {
Package,
PartDefinition,
ItemDefinition,
ActionDefinition,
PortDefinition,
AttributeDefinition,
ConnectionDefinition,
InterfaceDefinition,
AllocationDefinition,
RequirementDefinition,
ConstraintDefinition,
StateDefinition,
CalculationDefinition,
UseCaseDefinition,
AnalysisCaseDefinition,
ConcernDefinition,
ViewDefinition,
ViewpointDefinition,
RenderingDefinition,
ViewUsage,
ViewpointUsage,
RenderingUsage,
EnumerationDefinition,
MetadataDefinition,
Interaction,
DataType,
Class,
Structure,
Behavior,
Function,
Association,
PartUsage,
ItemUsage,
ActionUsage,
PortUsage,
AttributeUsage,
ConnectionUsage,
InterfaceUsage,
AllocationUsage,
RequirementUsage,
ConstraintUsage,
StateUsage,
TransitionUsage,
CalculationUsage,
ReferenceUsage,
OccurrenceUsage,
FlowConnectionUsage,
ExposeRelationship,
Import,
Alias,
Comment,
Dependency,
Other,
}
impl SymbolKind {
pub(crate) fn from_definition_kind(kind: Option<DefinitionKind>) -> Self {
match kind {
Some(DefinitionKind::Part) => Self::PartDefinition,
Some(DefinitionKind::Item) => Self::ItemDefinition,
Some(DefinitionKind::Action) => Self::ActionDefinition,
Some(DefinitionKind::Port) => Self::PortDefinition,
Some(DefinitionKind::Attribute) => Self::AttributeDefinition,
Some(DefinitionKind::Connection) => Self::ConnectionDefinition,
Some(DefinitionKind::Interface) => Self::InterfaceDefinition,
Some(DefinitionKind::Allocation) => Self::AllocationDefinition,
Some(DefinitionKind::Requirement) => Self::RequirementDefinition,
Some(DefinitionKind::Constraint) => Self::ConstraintDefinition,
Some(DefinitionKind::State) => Self::StateDefinition,
Some(DefinitionKind::Calc) => Self::CalculationDefinition,
Some(DefinitionKind::Case) | Some(DefinitionKind::UseCase) => Self::UseCaseDefinition,
Some(DefinitionKind::Analysis) | Some(DefinitionKind::Verification) => {
Self::AnalysisCaseDefinition
}
Some(DefinitionKind::Concern) => Self::ConcernDefinition,
Some(DefinitionKind::View) => Self::ViewDefinition,
Some(DefinitionKind::Viewpoint) => Self::ViewpointDefinition,
Some(DefinitionKind::Rendering) => Self::RenderingDefinition,
Some(DefinitionKind::Enum) => Self::EnumerationDefinition,
Some(DefinitionKind::Flow) => Self::Other,
Some(DefinitionKind::Metadata) => Self::Other,
Some(DefinitionKind::Occurrence) => Self::Other,
Some(DefinitionKind::Class) => Self::PartDefinition,
Some(DefinitionKind::Struct) => Self::PartDefinition,
Some(DefinitionKind::Datatype) => Self::AttributeDefinition,
Some(DefinitionKind::Assoc) => Self::ConnectionDefinition,
Some(DefinitionKind::Behavior) => Self::ActionDefinition,
Some(DefinitionKind::Function) => Self::CalculationDefinition,
Some(DefinitionKind::Predicate) => Self::ConstraintDefinition,
Some(DefinitionKind::Interaction) => Self::ActionDefinition,
Some(DefinitionKind::Classifier) => Self::PartDefinition,
Some(DefinitionKind::Type) => Self::Other,
Some(DefinitionKind::Metaclass) => Self::MetadataDefinition,
None => Self::Other,
}
}
pub(crate) fn from_usage_kind(kind: InternalUsageKind) -> Self {
match kind {
InternalUsageKind::Part => Self::PartUsage,
InternalUsageKind::Item => Self::ItemUsage,
InternalUsageKind::Action => Self::ActionUsage,
InternalUsageKind::Port => Self::PortUsage,
InternalUsageKind::Attribute => Self::AttributeUsage,
InternalUsageKind::Connection => Self::ConnectionUsage,
InternalUsageKind::Interface => Self::InterfaceUsage,
InternalUsageKind::Allocation => Self::AllocationUsage,
InternalUsageKind::Requirement => Self::RequirementUsage,
InternalUsageKind::Constraint => Self::ConstraintUsage,
InternalUsageKind::State => Self::StateUsage,
InternalUsageKind::Calculation => Self::CalculationUsage,
InternalUsageKind::Reference => Self::ReferenceUsage,
InternalUsageKind::Occurrence => Self::OccurrenceUsage,
InternalUsageKind::Flow => Self::FlowConnectionUsage,
InternalUsageKind::Transition => Self::TransitionUsage,
InternalUsageKind::Accept => Self::ActionUsage,
InternalUsageKind::End => Self::PortUsage,
InternalUsageKind::Fork => Self::ActionUsage,
InternalUsageKind::Join => Self::ActionUsage,
InternalUsageKind::Merge => Self::ActionUsage,
InternalUsageKind::Decide => Self::ActionUsage,
InternalUsageKind::View => Self::ViewUsage,
InternalUsageKind::Viewpoint => Self::ViewpointUsage,
InternalUsageKind::Rendering => Self::RenderingUsage,
InternalUsageKind::Feature => Self::AttributeUsage,
InternalUsageKind::Other => Self::Other,
}
}
pub fn display(&self) -> &'static str {
match self {
Self::Package => "Package",
Self::PartDefinition => "Part def",
Self::ItemDefinition => "Item def",
Self::ActionDefinition => "Action def",
Self::PortDefinition => "Port def",
Self::AttributeDefinition => "Attribute def",
Self::ConnectionDefinition => "Connection def",
Self::InterfaceDefinition => "Interface def",
Self::AllocationDefinition => "Allocation def",
Self::RequirementDefinition => "Requirement def",
Self::ConstraintDefinition => "Constraint def",
Self::StateDefinition => "State def",
Self::CalculationDefinition => "Calc def",
Self::UseCaseDefinition => "Use case def",
Self::AnalysisCaseDefinition => "Analysis case def",
Self::ConcernDefinition => "Concern def",
Self::ViewDefinition => "View def",
Self::ViewpointDefinition => "Viewpoint def",
Self::RenderingDefinition => "Rendering def",
Self::ViewUsage => "View",
Self::ViewpointUsage => "Viewpoint",
Self::RenderingUsage => "Rendering",
Self::EnumerationDefinition => "Enum def",
Self::MetadataDefinition => "Metaclass def",
Self::Interaction => "Interaction def",
Self::DataType => "Datatype",
Self::Class => "Class",
Self::Structure => "Struct",
Self::Behavior => "Behavior",
Self::Function => "Function",
Self::Association => "Assoc",
Self::PartUsage => "Part",
Self::ItemUsage => "Item",
Self::ActionUsage => "Action",
Self::PortUsage => "Port",
Self::AttributeUsage => "Attribute",
Self::ConnectionUsage => "Connection",
Self::InterfaceUsage => "Interface",
Self::AllocationUsage => "Allocation",
Self::RequirementUsage => "Requirement",
Self::ConstraintUsage => "Constraint",
Self::StateUsage => "State",
Self::TransitionUsage => "Transition",
Self::CalculationUsage => "Calc",
Self::ReferenceUsage => "Ref",
Self::OccurrenceUsage => "Occurrence",
Self::FlowConnectionUsage => "Flow",
Self::ExposeRelationship => "Expose",
Self::Import => "Import",
Self::Alias => "Alias",
Self::Comment => "Comment",
Self::Dependency => "Dependency",
Self::Other => "Element",
}
}
}
#[derive(Debug, Default)]
pub struct ExtractionResult {
pub symbols: Vec<HirSymbol>,
pub scope_filters: Vec<(Arc<str>, Vec<String>)>,
pub import_filters: Vec<(Arc<str>, Vec<String>)>,
}
#[derive(Clone, Copy, Debug, Default)]
pub(super) struct SpanInfo {
pub start_line: u32,
pub start_col: u32,
pub end_line: u32,
pub end_col: u32,
}