@@ -479,7 +479,7 @@ pub mod scope_data {}
479479/// Note, it's common to create new scopes for each variable definition like this.
480480///
481481/// A rough approximation of a program which would have such a scope structure would be:
482- /// ```rust, no_run
482+ /// ```ignore
483483/// // in the global scope
484484/// let bar = 3;
485485/// fn foo() {
@@ -513,7 +513,7 @@ pub mod scope_data {}
513513///
514514/// Let's go for the simple case first. Let's say we now write the following example:
515515///
516- /// ```rust, no_run
516+ /// ```ignore
517517/// // in the global scope
518518/// let bar = 3;
519519/// fn foo() {
@@ -528,10 +528,83 @@ pub mod scope_data {}
528528/// So first, we look in the current scope: `foo`'s scope. We immediately find a `Definition`
529529/// edge which brings us to a variable definition with the name `baz`. So we're done!
530530///
531+ /// ```rust
532+ /// # use scopegraphs::*;
533+ /// # use completeness::{UncheckedCompleteness};
534+ /// # use resolve::{DataWellformedness, Resolve, ResolvedPath};
535+ /// # use render::{RenderSettings, RenderScopeData, RenderScopeLabel};
536+ /// #
537+ /// # #[derive(Label, Hash, PartialEq, Eq, Debug, Clone, Copy)]
538+ /// # enum Lbl {
539+ /// # Lexical,
540+ /// # Definition,
541+ /// # }
542+ /// #
543+ /// # #[derive(Hash, PartialEq, Eq, Debug, Default, Clone)]
544+ /// # enum Data<'a> {
545+ /// # #[default]
546+ /// # NoData,
547+ /// # Variable {
548+ /// # name: &'a str,
549+ /// # },
550+ /// # }
551+ /// #
552+ /// # impl RenderScopeData for Data<'_> {
553+ /// # fn render_node(&self) -> Option<String> {
554+ /// # match self {
555+ /// # Self::Variable {..} => Some(format!("{self:?}")),
556+ /// # _ => None,
557+ /// # }
558+ /// # }
559+ /// #
560+ /// # fn definition(&self) -> bool {
561+ /// # matches!(self, Self::Variable {..})
562+ /// # }
563+ /// # }
564+ /// #
565+ /// # impl RenderScopeLabel for Lbl {
566+ /// # fn render(&self) -> String {
567+ /// # match self {
568+ /// # Self::Lexical => "lexical",
569+ /// # Self::Definition => "definition",
570+ /// # }.to_string()
571+ /// # }
572+ /// # }
573+ /// #
574+ /// # let storage = Storage::new();
575+ /// # let sg: ScopeGraph<Lbl, Data, UncheckedCompleteness> =
576+ /// # unsafe { ScopeGraph::raw(&storage) };
577+ /// #
578+ /// # let global = sg.add_scope_default();
579+ /// # let fn_foo = sg.add_scope_default();
580+ /// #
581+ /// # // create a scope in which the variable `bar` is defined
582+ /// # let declares_a_global = sg.add_scope(Data::Variable {name: "bar"});
583+ /// #
584+ /// # // create another scope in which the variable `bar` is defined inside foo
585+ /// # let declares_a_local_in_foo = sg.add_scope(Data::Variable {name: "baz"});
586+ /// #
587+ /// # // Add some edges
588+ /// # sg.add_edge(fn_foo, Lbl::Lexical, global);
589+ /// #
590+ /// # sg.add_edge(global, Lbl::Definition, declares_a_global);
591+ /// # sg.add_edge(fn_foo, Lbl::Definition, declares_a_local_in_foo);
592+ /// #
593+ /// # let res = sg.query()
594+ /// # .with_path_wellformedness(query_regex!(Lbl: Lexical* Definition))
595+ /// # .with_data_wellformedness(|a: &Data| matches!(a, Data::Variable {name: "baz"}))
596+ /// # .resolve(fn_foo);
597+ /// #
598+ /// # sg.render_to("output.mmd", RenderSettings {
599+ /// # path: Some(res.get_only_item().unwrap()),
600+ /// # ..Default::default()
601+ /// # }).unwrap()
602+ /// ```
603+ ///
531604/// ## Example 2: in the enclosing (global) scope
532605/// Alright, now for a slightly more complicated example:
533606///
534- /// ```rust, no_run
607+ /// ```ignore
535608/// // in the global scope
536609/// let bar = 3;
537610/// fn foo() {
@@ -546,12 +619,85 @@ pub mod scope_data {}
546619/// So, we can choose to instead traverse the `Lexical` edge to look in the global scope.
547620/// Now we *can* find a definition of `bar` (using a `Definition` edge), so we're done.
548621///
622+ /// ```rust
623+ /// # use scopegraphs::*;
624+ /// # use completeness::{UncheckedCompleteness};
625+ /// # use resolve::{DataWellformedness, Resolve, ResolvedPath};
626+ /// # use render::{RenderSettings, RenderScopeData, RenderScopeLabel};
627+ /// #
628+ /// # #[derive(Label, Hash, PartialEq, Eq, Debug, Clone, Copy)]
629+ /// # enum Lbl {
630+ /// # Lexical,
631+ /// # Definition,
632+ /// # }
633+ /// #
634+ /// # #[derive(Hash, PartialEq, Eq, Debug, Default, Clone)]
635+ /// # enum Data<'a> {
636+ /// # #[default]
637+ /// # NoData,
638+ /// # Variable {
639+ /// # name: &'a str,
640+ /// # },
641+ /// # }
642+ /// #
643+ /// # impl RenderScopeData for Data<'_> {
644+ /// # fn render_node(&self) -> Option<String> {
645+ /// # match self {
646+ /// # Self::Variable {..} => Some(format!("{self:?}")),
647+ /// # _ => None,
648+ /// # }
649+ /// # }
650+ /// #
651+ /// # fn definition(&self) -> bool {
652+ /// # matches!(self, Self::Variable {..})
653+ /// # }
654+ /// # }
655+ /// #
656+ /// # impl RenderScopeLabel for Lbl {
657+ /// # fn render(&self) -> String {
658+ /// # match self {
659+ /// # Self::Lexical => "lexical",
660+ /// # Self::Definition => "definition",
661+ /// # }.to_string()
662+ /// # }
663+ /// # }
664+ /// #
665+ /// # let storage = Storage::new();
666+ /// # let sg: ScopeGraph<Lbl, Data, UncheckedCompleteness> =
667+ /// # unsafe { ScopeGraph::raw(&storage) };
668+ /// #
669+ /// # let global = sg.add_scope_default();
670+ /// # let fn_foo = sg.add_scope_default();
671+ /// #
672+ /// # // create a scope in which the variable `bar` is defined
673+ /// # let declares_a_global = sg.add_scope(Data::Variable {name: "bar"});
674+ /// #
675+ /// # // create another scope in which the variable `bar` is defined inside foo
676+ /// # let declares_a_local_in_foo = sg.add_scope(Data::Variable {name: "baz"});
677+ /// #
678+ /// # // Add some edges
679+ /// # sg.add_edge(fn_foo, Lbl::Lexical, global);
680+ /// #
681+ /// # sg.add_edge(global, Lbl::Definition, declares_a_global);
682+ /// # sg.add_edge(fn_foo, Lbl::Definition, declares_a_local_in_foo);
683+ /// #
684+ /// # let res = sg.query()
685+ /// # .with_path_wellformedness(query_regex!(Lbl: Lexical* Definition))
686+ /// # .with_data_wellformedness(|a: &Data| matches!(a, Data::Variable {name: "bar"}))
687+ /// # .resolve(fn_foo);
688+ /// #
689+ /// # sg.render_to("output.mmd", RenderSettings {
690+ /// # path: Some(res.get_only_item().unwrap()),
691+ /// # ..Default::default()
692+ /// # }).unwrap()
693+ /// ```
694+ ///
549695/// ## Example 3: when name resolution fails
550696///
551697/// Finally, let's look at an example in which name resolution should obviously fail,
552698/// and discuss why it does, using the scope graph we constructed.
553699///
554- /// ```rust, no_run
700+ /// ```ignore
555701/// // in the global scope
556702/// let bar = 3;
557703/// fn foo() {
0 commit comments