Skip to content
18 changes: 9 additions & 9 deletions rust/rubydex-mcp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ fn format_ancestors(graph: &Graph, ancestors: &Ancestors) -> Vec<serde_json::Val
let ancestor_decl = graph.declarations().get(id)?;
Some(serde_json::json!({
"name": ancestor_decl.name(),
"kind": ancestor_decl.kind(),
"kind": ancestor_decl.kind().as_api_str(),
}))
}
Ancestor::Partial(name_id) => {
Expand Down Expand Up @@ -265,7 +265,7 @@ impl RubydexServer {

Some(serde_json::json!({
"name": decl.name(),
"kind": decl.kind(),
"kind": decl.kind().as_api_str(),
"locations": locations,
}))
},
Expand Down Expand Up @@ -333,7 +333,7 @@ impl RubydexServer {

let mut member = serde_json::json!({
"name": member_decl.name(),
"kind": member_decl.kind(),
"kind": member_decl.kind().as_api_str(),
});

if let Some(def) = member_def
Expand All @@ -354,7 +354,7 @@ impl RubydexServer {

let result = serde_json::json!({
"name": decl.name(),
"kind": decl.kind(),
"kind": decl.kind().as_api_str(),
"definitions": definitions,
"ancestors": ancestors,
"members": members,
Expand Down Expand Up @@ -384,7 +384,7 @@ impl RubydexServer {
let desc_decl = graph.declarations().get(id)?;
Some(serde_json::json!({
"name": desc_decl.name(),
"kind": desc_decl.kind(),
"kind": desc_decl.kind().as_api_str(),
}))
},
);
Expand Down Expand Up @@ -484,7 +484,7 @@ impl RubydexServer {
let decl_name = graph
.definition_id_to_declaration_id(*def_id)
.and_then(|decl_id| graph.declarations().get(decl_id))
.map(|decl| (decl.name().to_string(), decl.kind()));
.map(|decl| (decl.name().to_string(), decl.kind().as_api_str()));

if let Some((name, kind)) = decl_name {
declarations.push(serde_json::json!({
Expand All @@ -510,14 +510,14 @@ impl RubydexServer {
let state = ensure_graph_ready!(self);
let graph = state.graph.as_ref().unwrap();

let mut breakdown: HashMap<&str, usize> = HashMap::new();
let mut breakdown: HashMap<&'static str, usize> = HashMap::new();
for decl in graph.declarations().values() {
*breakdown.entry(decl.kind()).or_default() += 1;
*breakdown.entry(decl.kind().as_api_str()).or_default() += 1;
}

let breakdown_json: serde_json::Value = breakdown
.iter()
.map(|(k, v)| (k.to_string(), serde_json::json!(v)))
.map(|(k, v)| ((*k).to_string(), serde_json::json!(v)))
.collect();

let result = serde_json::json!({
Expand Down
6 changes: 6 additions & 0 deletions rust/rubydex/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ rules! {
TopLevelMixinSelf;

// Resolution
KindRedefinition;
ParentRedefinition;
NonClassSuperclass;
CircularDependency;
NonModuleMixin;
UnresolvedConstantReference;
}
104 changes: 91 additions & 13 deletions rust/rubydex/src/model/declaration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::assert_mem_size;
use crate::diagnostic::Diagnostic;
use crate::model::{
definitions::DefinitionKind,
identity_maps::{IdentityHashMap, IdentityHashSet},
ids::{DeclarationId, DefinitionId, NameId, ReferenceId, StringId},
};
Expand Down Expand Up @@ -54,6 +55,75 @@ impl<'a> IntoIterator for &'a Ancestors {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeclarationKind {
Class,
SingletonClass,
Module,
Todo,
Constant,
ConstantAlias,
Method,
GlobalVariable,
InstanceVariable,
ClassVariable,
}

impl DeclarationKind {
/// Returns the canonical `PascalCase` name used in external APIs and serialization.
#[must_use]
pub fn as_api_str(self) -> &'static str {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we name this as_str instead?

match self {
DeclarationKind::Class => "Class",
DeclarationKind::SingletonClass => "SingletonClass",
DeclarationKind::Module => "Module",
DeclarationKind::Constant => "Constant",
DeclarationKind::ConstantAlias => "ConstantAlias",
DeclarationKind::Method => "Method",
DeclarationKind::GlobalVariable => "GlobalVariable",
DeclarationKind::InstanceVariable => "InstanceVariable",
DeclarationKind::ClassVariable => "ClassVariable",
DeclarationKind::Todo => "<TODO>",
}
}

#[must_use]
pub fn from_definition_kind(definition_kind: DefinitionKind) -> Self {
match definition_kind {
DefinitionKind::Class => DeclarationKind::Class,
DefinitionKind::SingletonClass => DeclarationKind::SingletonClass,
DefinitionKind::Module => DeclarationKind::Module,
DefinitionKind::Constant => DeclarationKind::Constant,
DefinitionKind::ConstantAlias => DeclarationKind::ConstantAlias,
DefinitionKind::Method
| DefinitionKind::MethodAlias
| DefinitionKind::AttrAccessor
| DefinitionKind::AttrReader
| DefinitionKind::AttrWriter => DeclarationKind::Method,
DefinitionKind::InstanceVariable => DeclarationKind::InstanceVariable,
DefinitionKind::ClassVariable => DeclarationKind::ClassVariable,
DefinitionKind::GlobalVariable | DefinitionKind::GlobalVariableAlias => DeclarationKind::GlobalVariable,
}
}
}

impl std::fmt::Display for DeclarationKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DeclarationKind::Class => write!(f, "class"),
DeclarationKind::SingletonClass => write!(f, "singleton class"),
DeclarationKind::Module => write!(f, "module"),
DeclarationKind::Todo => write!(f, "<TODO>"),
DeclarationKind::Constant => write!(f, "constant"),
DeclarationKind::ConstantAlias => write!(f, "constant alias"),
DeclarationKind::Method => write!(f, "method"),
DeclarationKind::GlobalVariable => write!(f, "global variable"),
DeclarationKind::InstanceVariable => write!(f, "instance variable"),
DeclarationKind::ClassVariable => write!(f, "class variable"),
}
}
}

macro_rules! all_declarations {
($value:expr, $var:ident => $expr:expr) => {
match $value {
Expand Down Expand Up @@ -264,15 +334,15 @@ impl Declaration {
}

#[must_use]
pub fn kind(&self) -> &'static str {
pub fn kind(&self) -> DeclarationKind {
match self {
Declaration::Namespace(namespace) => namespace.kind(),
Declaration::Constant(_) => "Constant",
Declaration::ConstantAlias(_) => "ConstantAlias",
Declaration::Method(_) => "Method",
Declaration::GlobalVariable(_) => "GlobalVariable",
Declaration::InstanceVariable(_) => "InstanceVariable",
Declaration::ClassVariable(_) => "ClassVariable",
Declaration::Constant(_) => DeclarationKind::Constant,
Declaration::ConstantAlias(_) => DeclarationKind::ConstantAlias,
Declaration::Method(_) => DeclarationKind::Method,
Declaration::GlobalVariable(_) => DeclarationKind::GlobalVariable,
Declaration::InstanceVariable(_) => DeclarationKind::InstanceVariable,
Declaration::ClassVariable(_) => DeclarationKind::ClassVariable,
}
}

Expand Down Expand Up @@ -362,12 +432,20 @@ impl Declaration {
all_declarations!(self, it => &it.diagnostics)
}

pub fn diagnostics_mut(&mut self) -> &mut Vec<Diagnostic> {
all_declarations!(self, it => &mut it.diagnostics)
}

pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
all_declarations!(self, it => std::mem::take(&mut it.diagnostics))
}

pub fn add_diagnostic(&mut self, diagnostic: Diagnostic) {
all_declarations!(self, it => it.diagnostics.push(diagnostic));
all_declarations!(self, it => {
if !it.diagnostics.iter().any(|d| d.rule() == diagnostic.rule() && d.uri_id() == diagnostic.uri_id() && d.offset() == diagnostic.offset()) {
it.diagnostics.push(diagnostic);
}
Comment on lines +445 to +447
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a separate PR, but I wonder if we should use a set here to avoid the duplicate check.

});
}

pub fn clear_diagnostics(&mut self) {
Expand All @@ -386,12 +464,12 @@ assert_mem_size!(Namespace, 16);

impl Namespace {
#[must_use]
pub fn kind(&self) -> &'static str {
pub fn kind(&self) -> DeclarationKind {
match self {
Namespace::Class(_) => "Class",
Namespace::SingletonClass(_) => "SingletonClass",
Namespace::Module(_) => "Module",
Namespace::Todo(_) => "<TODO>",
Namespace::Class(_) => DeclarationKind::Class,
Namespace::SingletonClass(_) => DeclarationKind::SingletonClass,
Namespace::Module(_) => DeclarationKind::Module,
Namespace::Todo(_) => DeclarationKind::Todo,
}
}

Expand Down
69 changes: 54 additions & 15 deletions rust/rubydex/src/model/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,45 @@ impl DefinitionFlags {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum DefinitionKind {
Class,
SingletonClass,
Module,
Constant,
ConstantAlias,
GlobalVariable,
InstanceVariable,
ClassVariable,
AttrAccessor,
AttrReader,
AttrWriter,
Method,
MethodAlias,
GlobalVariableAlias,
}

impl std::fmt::Display for DefinitionKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DefinitionKind::Class => write!(f, "class"),
DefinitionKind::SingletonClass => write!(f, "singleton class"),
DefinitionKind::Module => write!(f, "module"),
DefinitionKind::Constant => write!(f, "constant"),
DefinitionKind::ConstantAlias => write!(f, "constant alias"),
DefinitionKind::Method => write!(f, "method"),
DefinitionKind::AttrAccessor => write!(f, "attr_accessor"),
DefinitionKind::AttrReader => write!(f, "attr_reader"),
DefinitionKind::AttrWriter => write!(f, "attr_writer"),
DefinitionKind::GlobalVariable => write!(f, "global variable"),
DefinitionKind::InstanceVariable => write!(f, "instance variable"),
DefinitionKind::ClassVariable => write!(f, "class variable"),
DefinitionKind::MethodAlias => write!(f, "method alias"),
DefinitionKind::GlobalVariableAlias => write!(f, "global variable alias"),
}
}
}

#[derive(Debug)]
pub enum Definition {
Class(Box<ClassDefinition>),
Expand Down Expand Up @@ -122,22 +161,22 @@ impl Definition {
}

#[must_use]
pub fn kind(&self) -> &'static str {
pub fn kind(&self) -> DefinitionKind {
match self {
Definition::Class(_) => "Class",
Definition::SingletonClass(_) => "SingletonClass",
Definition::Module(_) => "Module",
Definition::Constant(_) => "Constant",
Definition::ConstantAlias(_) => "ConstantAlias",
Definition::Method(_) => "Method",
Definition::AttrAccessor(_) => "AttrAccessor",
Definition::AttrReader(_) => "AttrReader",
Definition::AttrWriter(_) => "AttrWriter",
Definition::GlobalVariable(_) => "GlobalVariable",
Definition::InstanceVariable(_) => "InstanceVariable",
Definition::ClassVariable(_) => "ClassVariable",
Definition::MethodAlias(_) => "AliasMethod",
Definition::GlobalVariableAlias(_) => "GlobalVariableAlias",
Definition::Class(_) => DefinitionKind::Class,
Definition::SingletonClass(_) => DefinitionKind::SingletonClass,
Definition::Module(_) => DefinitionKind::Module,
Definition::Constant(_) => DefinitionKind::Constant,
Definition::ConstantAlias(_) => DefinitionKind::ConstantAlias,
Definition::Method(_) => DefinitionKind::Method,
Definition::AttrAccessor(_) => DefinitionKind::AttrAccessor,
Definition::AttrReader(_) => DefinitionKind::AttrReader,
Definition::AttrWriter(_) => DefinitionKind::AttrWriter,
Definition::GlobalVariable(_) => DefinitionKind::GlobalVariable,
Definition::InstanceVariable(_) => DefinitionKind::InstanceVariable,
Definition::ClassVariable(_) => DefinitionKind::ClassVariable,
Definition::MethodAlias(_) => DefinitionKind::MethodAlias,
Definition::GlobalVariableAlias(_) => DefinitionKind::GlobalVariableAlias,
}
}

Expand Down
Loading
Loading