mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-08-04 00:49:17 +00:00
DFS with repeats + cycle detection
This commit is contained in:
parent
ef72db8b6e
commit
0028e0ac9a
6 changed files with 304 additions and 53 deletions
37
server/Cargo.lock
generated
37
server/Cargo.lock
generated
|
@ -23,6 +23,19 @@ name = "base64"
|
|||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -329,6 +342,24 @@ dependencies = [
|
|||
"remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
|
@ -379,6 +410,7 @@ name = "vscode-mc-shader"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chan 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -389,6 +421,7 @@ dependencies = [
|
|||
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -435,6 +468,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
|
||||
"checksum bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
|
||||
"checksum bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum chan 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "d14956a3dae065ffaa0d92ece848ab4ced88d32361e7fdfbfd653a5c454a1ed8"
|
||||
|
@ -475,6 +510,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
||||
"checksum syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
|
||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
|
||||
"checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
|
||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
"checksum tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
|
|
|
@ -6,8 +6,8 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
rust_lsp = { git = "https://github.com/Strum355/RustLSP", branch = "master" }
|
||||
serde_json = "1.0.55"
|
||||
serde = "1.0.111"
|
||||
serde_json = "1.0.56"
|
||||
serde = "1.0.114"
|
||||
walkdir = "2.3.1"
|
||||
petgraph = "0.5.1"
|
||||
lazy_static = "1.4.0"
|
||||
|
@ -16,6 +16,8 @@ chan = "0.1.23"
|
|||
url = "2.1.1"
|
||||
percent-encoding = "2.1.0"
|
||||
anyhow = "1.0.31"
|
||||
bit-set = "0.5.2"
|
||||
thiserror = "1.0.20"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3.7"
|
||||
|
|
|
@ -1,17 +1,104 @@
|
|||
use petgraph::stable_graph::NodeIndex;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::graph::CachedStableGraph;
|
||||
|
||||
use anyhow::{Result, Context, format_err};
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
/// Performs a depth-first search with duplicates
|
||||
pub struct Dfs<'a> {
|
||||
stack: Vec<NodeIndex>,
|
||||
graph: &'a CachedStableGraph
|
||||
graph: &'a CachedStableGraph,
|
||||
cycle: Vec<NodeIndex>
|
||||
}
|
||||
|
||||
impl <'a> Dfs<'a> {
|
||||
pub fn new(graph: &'a CachedStableGraph, start: NodeIndex) -> Self {
|
||||
Dfs {
|
||||
stack: vec![start],
|
||||
graph
|
||||
graph,
|
||||
cycle: Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Option<Result<NodeIndex>> {
|
||||
if let Some(node) = self.stack.pop() {
|
||||
self.cycle.push(node);
|
||||
|
||||
let mut children = self.graph.child_node_indexes(node);
|
||||
|
||||
if !children.is_empty() {
|
||||
// sort by line number in parent
|
||||
children.sort_by(|x, y| {
|
||||
let graph = &self.graph.graph;
|
||||
let edge1 = graph.edge_weight(graph.find_edge(node, *x).unwrap()).unwrap();
|
||||
let edge2 = graph.edge_weight(graph.find_edge(node, *y).unwrap()).unwrap();
|
||||
|
||||
edge2.line.cmp(&edge1.line)
|
||||
});
|
||||
|
||||
match self.check_for_cycle(&children) {
|
||||
Ok(_) => {}
|
||||
Err(e) => return Some(Err(e)),
|
||||
};
|
||||
|
||||
for child in children {
|
||||
self.stack.push(child);
|
||||
}
|
||||
} else {
|
||||
self.cycle.pop();
|
||||
}
|
||||
return Some(Ok(node));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn check_for_cycle(&self, children: &[NodeIndex]) -> Result<()> {
|
||||
for prev in &self.cycle {
|
||||
for child in children {
|
||||
if *prev == *child {
|
||||
return Err(
|
||||
format_err!("cycle detected")
|
||||
).with_context(||
|
||||
CycleError::new(&self.cycle, *child, self.graph)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub struct CycleError(Vec<String>);
|
||||
|
||||
impl CycleError {
|
||||
fn new(nodes: &[NodeIndex], current_node: NodeIndex, graph: &CachedStableGraph) -> Self {
|
||||
let mut resolved_nodes: Vec<String> = nodes.iter().map(|i| graph.get_node(*i).clone()).collect();
|
||||
resolved_nodes.push(graph.get_node(current_node).clone());
|
||||
CycleError(resolved_nodes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CycleError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
eprintln!("cycle path {:?}", self.0);
|
||||
let mut disp = String::new();
|
||||
disp.push_str(format!("Include cycle detected:\n{} imports ", self.0[0]).as_str());
|
||||
for p in &self.0[1..self.0.len()-1] {
|
||||
disp.push_str(format!("\n{}, which imports ", *p).as_str());
|
||||
}
|
||||
disp.push_str(format!("\n{}", self.0[self.0.len()-1]).as_str());
|
||||
f.write_str(disp.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for CycleError {
|
||||
fn into(self) -> String {
|
||||
format!("{}", self)
|
||||
}
|
||||
|
||||
}
|
|
@ -50,9 +50,9 @@ impl CachedStableGraph {
|
|||
}
|
||||
}
|
||||
|
||||
/* pub fn get_node(&self, node: NodeIndex) -> &IncludePosition {
|
||||
self.graph.node_weight(node).expect("node index not found in graph")
|
||||
} */
|
||||
pub fn get_node(&self, node: NodeIndex) -> &String {
|
||||
&self.graph[node]
|
||||
}
|
||||
|
||||
pub fn remove_node(&mut self, name: impl Into<String>) {
|
||||
let idx = self.cache.remove(&name.into());
|
||||
|
@ -100,7 +100,6 @@ impl CachedStableGraph {
|
|||
|
||||
pub fn collect_root_ancestors(&self, node: NodeIndex) -> Vec<NodeIndex> {
|
||||
let mut visited = HashSet::new();
|
||||
//visited.insert(node);
|
||||
self.get_root_ancestors(node, node, &mut visited)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ use std::ops::Add;
|
|||
use std::process;
|
||||
use std::rc::Rc;
|
||||
|
||||
use core::cmp::{Ordering, PartialOrd, PartialEq, Ord, Eq};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use chan::WaitGroup;
|
||||
|
@ -84,29 +82,16 @@ struct MinecraftShaderLanguageServer {
|
|||
|
||||
struct Configuration {
|
||||
glslang_validator_path: String,
|
||||
shaderpacks_path: String,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
let shaderpacks_path = std::env::var("HOME").unwrap() + "/.minecraft/shaderpacks";
|
||||
Configuration{
|
||||
glslang_validator_path: "glslangValidator".into(),
|
||||
shaderpacks_path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Configuration {
|
||||
fn validate(&self) -> bool {
|
||||
if self.glslang_validator_path == "" || self.shaderpacks_path == "" {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct IncludePosition {
|
||||
filepath: String,
|
||||
|
@ -121,26 +106,16 @@ impl Display for IncludePosition {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for IncludePosition {
|
||||
#[allow(clippy::comparison_chain)]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
if self.line < other.line { Some(Ordering::Less) }
|
||||
else if self.line > other.line { Some(Ordering::Greater) }
|
||||
else { Some(Ordering::Equal) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for IncludePosition {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct GLSLFile {
|
||||
idx: petgraph::graph::NodeIndex,
|
||||
includes: Vec<IncludePosition>,
|
||||
}
|
||||
|
||||
struct MergeMeta {
|
||||
node: NodeIndex,
|
||||
last_slice: u64
|
||||
}
|
||||
|
||||
impl MinecraftShaderLanguageServer {
|
||||
pub fn error_not_available<DATA>(data: DATA) -> MethodError<DATA> {
|
||||
let msg = "Functionality not implemented.".to_string();
|
||||
|
@ -279,8 +254,22 @@ impl MinecraftShaderLanguageServer {
|
|||
} else {
|
||||
let mut lists = Vec::with_capacity(file_ancestors.len());
|
||||
for root in file_ancestors {
|
||||
let (_, views) = self.generate_merge_list(root);
|
||||
lists.push(views);
|
||||
match self.generate_merge_list(root) {
|
||||
Ok((sources, views)) => lists.push(views),
|
||||
Err(e) => {
|
||||
eprintln!("cycle detected");
|
||||
let e = e.downcast::<dfs::CycleError>().unwrap();
|
||||
return Ok(vec![Diagnostic{
|
||||
severity: Some(DiagnosticSeverity::Error),
|
||||
range: Range::new(Position::new(0, 0), Position::new(0, 500)),
|
||||
source: Some(SOURCE.into()),
|
||||
message: e.into(),
|
||||
code: None,
|
||||
tags: None,
|
||||
related_information: None,
|
||||
}])
|
||||
}
|
||||
}
|
||||
}
|
||||
lists
|
||||
};
|
||||
|
@ -361,11 +350,25 @@ impl MinecraftShaderLanguageServer {
|
|||
Ok(Some(roots))
|
||||
}
|
||||
|
||||
fn generate_merge_list(&self, root: NodeIndex) -> (LinkedList<String>, LinkedList<&str>) {
|
||||
fn generate_merge_list(&self, root: NodeIndex) -> Result<(LinkedList<String>, LinkedList<&str>)> {
|
||||
let mut merge_list = LinkedList::new();
|
||||
// need to return all sources along with the views to appease the lifetime god
|
||||
let mut all_sources = LinkedList::new();
|
||||
|
||||
let graph_ref = self.graph.borrow();
|
||||
|
||||
let mut dfs = dfs::Dfs::new(&graph_ref, root);
|
||||
|
||||
//let slice_stack = Vec::new();
|
||||
|
||||
while let Some(n) = dfs.next() {
|
||||
if n.is_err() {
|
||||
return Err(n.err().unwrap());
|
||||
}
|
||||
/* let path = self.graph.borrow().get_node(n);
|
||||
let file_content = String::from_utf8(std::fs::read(path).unwrap()); */
|
||||
}
|
||||
|
||||
/* let children = self.graph.borrow().child_node_indexes(root);
|
||||
|
||||
// include positions sorted by earliest in file
|
||||
|
@ -373,7 +376,7 @@ impl MinecraftShaderLanguageServer {
|
|||
all_edges.sort();
|
||||
eprintln!("include positions for {:?}: {:?} {:?}", self.graph.borrow().graph.node_weight(root).unwrap(), all_edges, children); */
|
||||
|
||||
(all_sources, merge_list)
|
||||
Ok((all_sources, merge_list))
|
||||
}
|
||||
|
||||
fn invoke_validator(&self, source: &str) -> Result<String> {
|
||||
|
@ -495,13 +498,6 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
|
|||
.as_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
self.config.shaderpacks_path = config.get("shaderpacksPath").unwrap().as_str().unwrap().into();
|
||||
|
||||
if !self.config.validate() {
|
||||
self.endpoint
|
||||
.send_notification("badConfig", None::<()>)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
eprintln!("{:?}", params.settings.as_object().unwrap());
|
||||
|
||||
|
|
|
@ -143,10 +143,8 @@ fn test_01_initialize() {
|
|||
fn test_graph_two_connected_nodes() {
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
graph.add_node("sample");
|
||||
graph.add_node("banana");
|
||||
let idx1 = graph.find_node("sample").unwrap();
|
||||
let idx2 = graph.find_node("banana").unwrap();
|
||||
let idx1 = graph.add_node("sample");
|
||||
let idx2 = graph.add_node("banana");
|
||||
graph.add_edge(idx1, idx2, 3, 10, 50);
|
||||
|
||||
let children = graph.child_node_names(idx1);
|
||||
|
@ -181,3 +179,135 @@ fn test_graph_two_connected_nodes() {
|
|||
let neighbors = graph.child_node_names(idx2);
|
||||
assert_eq!(neighbors.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect_root_ancestors() {
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
let idx0 = graph.add_node("0");
|
||||
let idx1 = graph.add_node("1");
|
||||
let idx2 = graph.add_node("2");
|
||||
|
||||
graph.add_edge(idx0, idx1, 2, 0, 0);
|
||||
graph.add_edge(idx1, idx2, 3, 0, 0);
|
||||
graph.add_edge(idx2, idx0, 5, 0, 0);
|
||||
|
||||
let roots = graph.collect_root_ancestors(idx0);
|
||||
assert_eq!(roots, vec![idx2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_graph_dfs() {
|
||||
{
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
let idx0 = graph.add_node("0");
|
||||
let idx1 = graph.add_node("1");
|
||||
let idx2 = graph.add_node("2");
|
||||
let idx3 = graph.add_node("3");
|
||||
let idx4 = graph.add_node("4");
|
||||
let idx5 = graph.add_node("5");
|
||||
let idx6 = graph.add_node("6");
|
||||
let idx7 = graph.add_node("7");
|
||||
|
||||
graph.add_edge(idx0, idx1, 2, 0, 0);
|
||||
graph.add_edge(idx0, idx2, 3, 0, 0);
|
||||
graph.add_edge(idx1, idx3, 5, 0, 0);
|
||||
graph.add_edge(idx1, idx4, 6, 0, 0);
|
||||
graph.add_edge(idx2, idx4, 5, 0, 0);
|
||||
graph.add_edge(idx2, idx5, 4, 0, 0);
|
||||
graph.add_edge(idx3, idx6, 4, 0, 0);
|
||||
graph.add_edge(idx4, idx6, 4, 0, 0);
|
||||
graph.add_edge(idx6, idx7, 4, 0, 0);
|
||||
|
||||
let mut dfs = dfs::Dfs::new(&graph, idx0);
|
||||
|
||||
let mut collection = Vec::new();
|
||||
|
||||
while let Some(i) = dfs.next() {
|
||||
assert_eq!(i.is_ok(), true);
|
||||
collection.push(i.unwrap());
|
||||
}
|
||||
|
||||
// 0
|
||||
// / \
|
||||
// 1 2
|
||||
// / \ / \
|
||||
// 3 4 5
|
||||
// \ /
|
||||
// 6 - 7
|
||||
let expected = vec![idx0, idx1, idx3, idx6, idx7, idx4, idx6, idx7, idx2, idx5, idx4, idx6, idx7];
|
||||
println!("{:?}\n{:?}", expected, collection);
|
||||
|
||||
collection.reverse();
|
||||
for i in expected {
|
||||
assert_eq!(i, collection.pop().unwrap());
|
||||
}
|
||||
|
||||
assert!(!is_cyclic_directed(&graph.graph));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_graph_dfs_cycle() {
|
||||
{
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
let idx0 = graph.add_node("0");
|
||||
let idx1 = graph.add_node("1");
|
||||
let idx2 = graph.add_node("2");
|
||||
let idx3 = graph.add_node("3");
|
||||
let idx4 = graph.add_node("4");
|
||||
let idx5 = graph.add_node("5");
|
||||
let idx6 = graph.add_node("6");
|
||||
let idx7 = graph.add_node("7");
|
||||
|
||||
graph.add_edge(idx0, idx1, 2, 0, 0);
|
||||
graph.add_edge(idx0, idx2, 3, 0, 0);
|
||||
graph.add_edge(idx1, idx3, 5, 0, 0);
|
||||
graph.add_edge(idx1, idx4, 6, 0, 0);
|
||||
graph.add_edge(idx2, idx4, 5, 0, 0);
|
||||
graph.add_edge(idx2, idx5, 4, 0, 0);
|
||||
graph.add_edge(idx3, idx6, 4, 0, 0);
|
||||
graph.add_edge(idx4, idx6, 4, 0, 0);
|
||||
graph.add_edge(idx6, idx7, 4, 0, 0);
|
||||
graph.add_edge(idx7, idx4, 4, 0, 0);
|
||||
|
||||
let mut dfs = dfs::Dfs::new(&graph, idx0);
|
||||
|
||||
for _ in 0..5 {
|
||||
if let Some(i) = dfs.next() {
|
||||
assert_eq!(i.is_ok(), true);
|
||||
}
|
||||
}
|
||||
|
||||
// 0
|
||||
// / \
|
||||
// 1 2
|
||||
// / \ / \
|
||||
// 3 4 5
|
||||
// \ / \
|
||||
// 6 - 7
|
||||
|
||||
assert!(is_cyclic_directed(&graph.graph));
|
||||
|
||||
let next = dfs.next().unwrap();
|
||||
assert_eq!(next.is_err(), true);
|
||||
}
|
||||
|
||||
{
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
let idx0 = graph.add_node("0");
|
||||
let idx1 = graph.add_node("1");
|
||||
|
||||
graph.add_edge(idx0, idx1, 2, 0, 0);
|
||||
graph.add_edge(idx1, idx0, 2, 0, 0);
|
||||
|
||||
let mut dfs = dfs::Dfs::new(&graph, idx1);
|
||||
|
||||
println!("{:?}", dfs.next());
|
||||
println!("{:?}", dfs.next());
|
||||
println!("{:?}", dfs.next());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue