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