deno_doc/
node.rs

1// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2
3use crate::js_doc::JsDoc;
4use serde::Deserialize;
5use serde::Serialize;
6use std::sync::Arc;
7
8#[derive(Debug, Serialize, Deserialize, Clone)]
9pub struct NamespaceDef {
10  pub elements: Vec<Arc<DocNode>>,
11}
12
13#[derive(
14  Debug,
15  PartialEq,
16  Eq,
17  PartialOrd,
18  Ord,
19  Hash,
20  Serialize,
21  Deserialize,
22  Clone,
23  Copy,
24)]
25#[serde(rename_all = "camelCase")]
26pub enum DocNodeKind {
27  // NOTE(bartlomieju): Because of `derive(Ord), we must keep the variants
28  // in an alphabetical order.
29  Class,
30  Enum,
31  Function,
32  Import,
33  Interface,
34  ModuleDoc,
35  Namespace,
36  Reference,
37  TypeAlias,
38  Variable,
39}
40
41#[derive(
42  Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default,
43)]
44#[serde(rename_all = "camelCase")]
45pub struct Location {
46  pub filename: Box<str>,
47  /// The 1-indexed display line.
48  /// todo(#150): why is one of these 0-indexed and the other 1-indexed?
49  pub line: usize,
50  /// The 0-indexed display column.
51  pub col: usize,
52  #[serde(default)]
53  /// The 0-indexed byte offset in the source text.
54  pub byte_index: usize,
55}
56
57impl Ord for Location {
58  fn cmp(&self, other: &Self) -> std::cmp::Ordering {
59    match self.filename.cmp(&other.filename) {
60      core::cmp::Ordering::Equal => match self.line.cmp(&other.line) {
61        core::cmp::Ordering::Equal => self.col.cmp(&other.col),
62        ord => ord,
63      },
64      ord => ord,
65    }
66  }
67}
68
69impl PartialOrd for Location {
70  fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
71    Some(self.cmp(other))
72  }
73}
74
75#[derive(Debug, Serialize, Deserialize, Clone)]
76#[serde(rename_all = "camelCase")]
77pub struct ImportDef {
78  pub src: String,
79  pub imported: Option<String>,
80}
81
82#[derive(Debug, Serialize, Deserialize, Clone)]
83#[serde(rename_all = "camelCase")]
84pub struct ReferenceDef {
85  pub target: Location,
86}
87
88#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
89#[serde(rename_all = "camelCase")]
90pub enum DeclarationKind {
91  Private,
92  Declare,
93  Export,
94}
95
96#[derive(Debug, Serialize, Deserialize, Clone)]
97#[serde(rename_all = "camelCase")]
98pub struct DocNode {
99  pub name: Box<str>,
100  #[serde(skip_serializing_if = "Option::is_none", default)]
101  pub is_default: Option<bool>,
102  pub location: Location,
103  pub declaration_kind: DeclarationKind,
104  #[serde(skip_serializing_if = "JsDoc::is_empty", default)]
105  pub js_doc: JsDoc,
106  #[serde(flatten)]
107  pub def: DocNodeDef,
108}
109
110#[derive(Debug, Serialize, Deserialize, Clone)]
111#[serde(tag = "kind", rename_all = "camelCase")]
112pub enum DocNodeDef {
113  #[serde(rename_all = "camelCase")]
114  Function {
115    function_def: super::function::FunctionDef,
116  },
117  #[serde(rename_all = "camelCase")]
118  Variable {
119    variable_def: super::variable::VariableDef,
120  },
121  #[serde(rename_all = "camelCase")]
122  Enum {
123    enum_def: super::r#enum::EnumDef,
124  },
125  #[serde(rename_all = "camelCase")]
126  Class {
127    class_def: super::class::ClassDef,
128  },
129  #[serde(rename_all = "camelCase")]
130  TypeAlias {
131    type_alias_def: super::type_alias::TypeAliasDef,
132  },
133  #[serde(rename_all = "camelCase")]
134  Namespace {
135    namespace_def: NamespaceDef,
136  },
137  #[serde(rename_all = "camelCase")]
138  Interface {
139    interface_def: super::interface::InterfaceDef,
140  },
141  #[serde(rename_all = "camelCase")]
142  Import {
143    import_def: ImportDef,
144  },
145  ModuleDoc,
146  Reference {
147    reference_def: ReferenceDef,
148  },
149}
150
151impl Default for DocNode {
152  fn default() -> Self {
153    Self {
154      is_default: None,
155      name: "".into(),
156      declaration_kind: DeclarationKind::Private,
157      location: Location::default(),
158      js_doc: JsDoc::default(),
159      def: DocNodeDef::ModuleDoc,
160    }
161  }
162}
163
164impl DocNode {
165  pub fn module_doc(location: Location, js_doc: JsDoc) -> Self {
166    Self {
167      name: "".into(),
168      is_default: None,
169      location,
170      declaration_kind: DeclarationKind::Export,
171      js_doc,
172      def: DocNodeDef::ModuleDoc,
173    }
174  }
175
176  pub fn function(
177    name: Box<str>,
178    is_default: bool,
179    location: Location,
180    declaration_kind: DeclarationKind,
181    js_doc: JsDoc,
182    fn_def: super::function::FunctionDef,
183  ) -> Self {
184    Self {
185      name,
186      is_default: Some(is_default),
187      location,
188      declaration_kind,
189      js_doc,
190      def: DocNodeDef::Function {
191        function_def: fn_def,
192      },
193    }
194  }
195
196  pub fn variable(
197    name: Box<str>,
198    is_default: bool,
199    location: Location,
200    declaration_kind: DeclarationKind,
201    js_doc: JsDoc,
202    var_def: super::variable::VariableDef,
203  ) -> Self {
204    Self {
205      name,
206      is_default: Some(is_default),
207      declaration_kind,
208      location,
209      js_doc,
210      def: DocNodeDef::Variable {
211        variable_def: var_def,
212      },
213    }
214  }
215
216  pub fn r#enum(
217    name: Box<str>,
218    is_default: bool,
219    location: Location,
220    declaration_kind: DeclarationKind,
221    js_doc: JsDoc,
222    enum_def: super::r#enum::EnumDef,
223  ) -> Self {
224    Self {
225      name,
226      is_default: Some(is_default),
227      declaration_kind,
228      location,
229      js_doc,
230      def: DocNodeDef::Enum { enum_def },
231    }
232  }
233
234  pub fn class(
235    name: Box<str>,
236    is_default: bool,
237    location: Location,
238    declaration_kind: DeclarationKind,
239    js_doc: JsDoc,
240    class_def: super::class::ClassDef,
241  ) -> Self {
242    Self {
243      name,
244      is_default: Some(is_default),
245      declaration_kind,
246      location,
247      js_doc,
248      def: DocNodeDef::Class { class_def },
249    }
250  }
251
252  pub fn type_alias(
253    name: Box<str>,
254    is_default: bool,
255    location: Location,
256    declaration_kind: DeclarationKind,
257    js_doc: JsDoc,
258    type_alias_def: super::type_alias::TypeAliasDef,
259  ) -> Self {
260    Self {
261      name,
262      is_default: Some(is_default),
263      declaration_kind,
264      location,
265      js_doc,
266      def: DocNodeDef::TypeAlias { type_alias_def },
267    }
268  }
269
270  pub fn namespace(
271    name: Box<str>,
272    is_default: bool,
273    location: Location,
274    declaration_kind: DeclarationKind,
275    js_doc: JsDoc,
276    namespace_def: NamespaceDef,
277  ) -> Self {
278    Self {
279      name,
280      is_default: Some(is_default),
281      declaration_kind,
282      location,
283      js_doc,
284      def: DocNodeDef::Namespace { namespace_def },
285    }
286  }
287
288  pub fn interface(
289    name: Box<str>,
290    is_default: bool,
291    location: Location,
292    declaration_kind: DeclarationKind,
293    js_doc: JsDoc,
294    interface_def: super::interface::InterfaceDef,
295  ) -> Self {
296    Self {
297      name,
298      is_default: Some(is_default),
299      declaration_kind,
300      location,
301      js_doc,
302      def: DocNodeDef::Interface { interface_def },
303    }
304  }
305
306  pub fn import(
307    name: Box<str>,
308    location: Location,
309    js_doc: JsDoc,
310    import_def: ImportDef,
311  ) -> Self {
312    Self {
313      name,
314      is_default: None,
315      declaration_kind: DeclarationKind::Private,
316      location,
317      js_doc,
318      def: DocNodeDef::Import { import_def },
319    }
320  }
321
322  pub fn reference(
323    name: Box<str>,
324    location: Location,
325    js_doc: JsDoc,
326    reference_def: ReferenceDef,
327  ) -> Self {
328    Self {
329      name,
330      is_default: None,
331      declaration_kind: DeclarationKind::Private,
332      location,
333      js_doc,
334      def: DocNodeDef::Reference { reference_def },
335    }
336  }
337
338  pub fn get_name(&self) -> &str {
339    let default_name = match &self.def {
340      DocNodeDef::Class { class_def } => class_def.def_name.as_deref(),
341      DocNodeDef::Function { function_def } => function_def.def_name.as_deref(),
342      DocNodeDef::Interface { interface_def } => {
343        interface_def.def_name.as_deref()
344      }
345      DocNodeDef::Enum { .. }
346      | DocNodeDef::Import { .. }
347      | DocNodeDef::ModuleDoc { .. }
348      | DocNodeDef::Namespace { .. }
349      | DocNodeDef::TypeAlias { .. }
350      | DocNodeDef::Variable { .. }
351      | DocNodeDef::Reference { .. } => None,
352    };
353
354    default_name.unwrap_or(&self.name)
355  }
356
357  pub fn class_def(&self) -> Option<&super::class::ClassDef> {
358    match &self.def {
359      DocNodeDef::Class { class_def } => Some(class_def),
360      _ => None,
361    }
362  }
363
364  pub fn function_def(&self) -> Option<&super::function::FunctionDef> {
365    match &self.def {
366      DocNodeDef::Function { function_def } => Some(function_def),
367      _ => None,
368    }
369  }
370
371  pub fn variable_def(&self) -> Option<&super::variable::VariableDef> {
372    match &self.def {
373      DocNodeDef::Variable { variable_def } => Some(variable_def),
374      _ => None,
375    }
376  }
377
378  pub fn enum_def(&self) -> Option<&super::r#enum::EnumDef> {
379    match &self.def {
380      DocNodeDef::Enum { enum_def } => Some(enum_def),
381      _ => None,
382    }
383  }
384
385  pub fn type_alias_def(&self) -> Option<&super::type_alias::TypeAliasDef> {
386    match &self.def {
387      DocNodeDef::TypeAlias { type_alias_def } => Some(type_alias_def),
388      _ => None,
389    }
390  }
391
392  pub fn namespace_def(&self) -> Option<&NamespaceDef> {
393    match &self.def {
394      DocNodeDef::Namespace { namespace_def } => Some(namespace_def),
395      _ => None,
396    }
397  }
398
399  pub fn interface_def(&self) -> Option<&super::interface::InterfaceDef> {
400    match &self.def {
401      DocNodeDef::Interface { interface_def } => Some(interface_def),
402      _ => None,
403    }
404  }
405
406  pub fn import_def(&self) -> Option<&ImportDef> {
407    match &self.def {
408      DocNodeDef::Import { import_def } => Some(import_def),
409      _ => None,
410    }
411  }
412
413  pub fn reference_def(&self) -> Option<&ReferenceDef> {
414    match &self.def {
415      DocNodeDef::Reference { reference_def } => Some(reference_def),
416      _ => None,
417    }
418  }
419}