use super::{analyze, span_contains, AnalysisResult};
use crate::ast::{Declaration, FieldType, Schema};
use crate::span::Span;
pub fn goto_definition(source: &str, offset: usize) -> Option<Span> {
let result = analyze(source);
goto_definition_with_analysis(&result, offset)
}
pub fn goto_definition_with_analysis(result: &AnalysisResult, offset: usize) -> Option<Span> {
let ast = result.ast.as_ref()?;
for decl in &ast.declarations {
match decl {
Declaration::Model(model) => {
for field in &model.fields {
if span_contains(field.span, offset) {
if let FieldType::UserType(ref name) = field.field_type {
return find_declaration_span(ast, name);
}
}
}
}
Declaration::Type(type_decl) => {
for field in &type_decl.fields {
if span_contains(field.span, offset) {
if let FieldType::UserType(ref name) = field.field_type {
return find_declaration_span(ast, name);
}
}
}
}
_ => {}
}
}
None
}
fn find_declaration_span(ast: &Schema, name: &str) -> Option<Span> {
for decl in &ast.declarations {
match decl {
Declaration::Model(m) if m.name.value == name => return Some(m.span),
Declaration::Enum(e) if e.name.value == name => return Some(e.span),
Declaration::Type(t) if t.name.value == name => return Some(t.span),
_ => {}
}
}
None
}