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 Procedure,
41 Property,
42 PropertyGraph,
43 Publication,
44 Role,
45 Rule,
46 Savepoint,
47 Schema,
48 Sequence,
49 Server,
50 Statistics,
51 Subscription,
52 Table,
53 Tablespace,
54 TextSearchConfiguration,
55 TextSearchDictionary,
56 TextSearchParser,
57 TextSearchTemplate,
58 Trigger,
59 Type,
60 View,
61 Window,
62}
63
64#[derive(Clone, Copy, PartialEq, Eq)]
65pub struct Location {
66 pub file: File,
67 pub range: TextRange,
68 pub kind: LocationKind,
69}
70
71impl Location {
72 pub(crate) fn new(file: File, range: TextRange, kind: LocationKind) -> Location {
73 Location { file, range, kind }
74 }
75
76 pub(crate) fn from_node(file: File, node: &SyntaxNode) -> Option<Location> {
77 let kind = classify_def_node(node)?;
78 Some(Location::new(file, node.text_range(), kind))
79 }
80
81 pub(crate) fn to_node(self, db: &dyn Db) -> Option<SyntaxNode> {
82 let tree = parse(db, self.file).tree();
83 match tree.syntax().covering_element(self.range) {
84 rowan::NodeOrToken::Token(token) => token.parent(),
85 rowan::NodeOrToken::Node(node) => Some(node.clone()),
86 }
87 }
88}