1use rowan::TextRange;
2use salsa::Database as Db;
3use squawk_syntax::SyntaxNode;
4use squawk_syntax::ast::AstNode;
5
6use crate::{
7 classify::classify_def_node,
8 db::{File, parse},
9};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum LocationKind {
13 AccessMethod,
14 Aggregate,
15 CaseExpr,
16 Channel,
17 Collation,
18 Column,
19 CommitBegin,
20 CommitEnd,
21 Constraint,
22 Conversion,
23 Cursor,
24 Database,
25 EventTrigger,
26 Extension,
27 ElementTable,
28 ForeignDataWrapper,
29 Function,
30 Index,
31 JsonPath,
32 Label,
33 Language,
34 NamedArgParameter,
35 Operator,
36 OperatorClass,
37 OperatorFamily,
38 Policy,
39 PreparedStatement,
40 PreparedTransaction,
41 Procedure,
42 Property,
43 PropertyGraph,
44 Publication,
45 Role,
46 Rule,
47 Savepoint,
48 Schema,
49 Sequence,
50 Server,
51 Statistics,
52 Subscription,
53 Table,
54 Tablespace,
55 TextSearchConfiguration,
56 TextSearchDictionary,
57 TextSearchParser,
58 TextSearchTemplate,
59 Trigger,
60 Type,
61 View,
62 Window,
63}
64
65#[derive(Clone, Copy, PartialEq, Eq)]
66pub struct Location {
67 pub file: File,
68 pub range: TextRange,
69 pub kind: LocationKind,
70}
71
72impl Location {
73 pub(crate) fn new(file: File, range: TextRange, kind: LocationKind) -> Location {
74 Location { file, range, kind }
75 }
76
77 pub(crate) fn from_node(file: File, node: &SyntaxNode) -> Option<Location> {
78 let kind = classify_def_node(node)?;
79 Some(Location::new(file, node.text_range(), kind))
80 }
81
82 pub(crate) fn to_node(self, db: &dyn Db) -> Option<SyntaxNode> {
83 let tree = parse(db, self.file).tree();
84 match tree.syntax().covering_element(self.range) {
85 rowan::NodeOrToken::Token(token) => token.parent(),
86 rowan::NodeOrToken::Node(node) => Some(node.clone()),
87 }
88 }
89}