Improved generating initial include graph

This commit is contained in:
Noah Santschi-Cooney 2020-08-12 21:07:57 +01:00
parent e56d182e3c
commit b535ede737
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
3 changed files with 623 additions and 194 deletions

View file

@ -65,6 +65,9 @@ impl CachedStableGraph {
}
pub fn add_node(&mut self, name: &str) -> NodeIndex {
if let Some(idx) = self.cache.get(name) {
return *idx;
}
let name_str = name.to_string();
let idx = self.graph.add_node(name_str.clone());
self.cache.insert(name_str.clone(), idx);
@ -72,9 +75,8 @@ impl CachedStableGraph {
idx
}
pub fn add_edge(&mut self, parent: NodeIndex, child: NodeIndex, line: usize, start: usize, end: usize) -> EdgeIndex {
let child_path = self.reverse_index.get(&child).unwrap().clone();
self.graph.add_edge(parent, child, IncludePosition{filepath: child_path, line, start, end})
pub fn add_edge(&mut self, parent: NodeIndex, child: NodeIndex, meta: IncludePosition) -> EdgeIndex {
self.graph.add_edge(parent, child, meta)
}
#[allow(dead_code)]
@ -100,6 +102,7 @@ impl CachedStableGraph {
self.graph.neighbors_directed(node, Direction::Incoming).collect()
}
#[allow(dead_code)]
pub fn get_include_meta(&self, node: NodeIndex) -> Vec<IncludePosition> {
self.graph.edges(node).map(|e| e.weight().clone()).collect()
}

View file

@ -11,8 +11,8 @@ use walkdir::WalkDir;
use std::cell::RefCell;
use std::collections::{HashMap, LinkedList};
use std::convert::TryFrom;
use std::fmt::{Display, Formatter};
use std::convert::{TryFrom, TryInto};
use std::fmt::{Display, Formatter, Debug};
use std::cmp::max;
use std::io::{stdin, stdout, BufRead, BufReader, Write};
use std::ops::Add;
@ -21,7 +21,7 @@ use std::rc::Rc;
use std::fs;
use std::iter::Extend;
use anyhow::Result;
use anyhow::{Result, anyhow};
use chan::WaitGroup;
@ -61,7 +61,7 @@ fn main() {
graph: Rc::new(RefCell::new(cache_graph)),
config: Configuration::default(),
wait: WaitGroup::new(),
root: None,
root: "".to_string(),
command_provider: None,
};
@ -80,7 +80,7 @@ struct MinecraftShaderLanguageServer {
graph: Rc<RefCell<graph::CachedStableGraph>>,
config: Configuration,
wait: WaitGroup,
root: Option<String>,
root: String,
command_provider: Option<provider::CustomCommandProvider>,
}
@ -96,25 +96,26 @@ impl Default for Configuration {
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq)]
pub struct IncludePosition {
filepath: String,
line: usize,
start: usize,
end: usize,
}
impl Display for IncludePosition {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{{path: '{}', line: {}}}", self.filepath, self.line)
impl Debug for IncludePosition {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{{line: {}}}", self.line)
}
}
struct GLSLFile {
idx: petgraph::graph::NodeIndex,
includes: Vec<IncludePosition>,
impl Display for IncludePosition {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{{line: {}}}", self.line)
}
}
impl MinecraftShaderLanguageServer {
pub fn error_not_available<DATA>(data: DATA) -> MethodError<DATA> {
let msg = "Functionality not implemented.".to_string();
@ -125,13 +126,11 @@ impl MinecraftShaderLanguageServer {
}
}
pub fn gen_initial_graph(&self, root: &str) {
let mut files = HashMap::new();
eprintln!("root of project is {}", root);
pub fn gen_initial_graph(&self) {
eprintln!("root of project is {}", self.root);
// filter directories and files not ending in any of the 3 extensions
let file_iter = WalkDir::new(root)
let file_iter = WalkDir::new(&self.root)
.into_iter()
.filter_map(|entry| {
if entry.is_err() {
@ -160,33 +159,18 @@ impl MinecraftShaderLanguageServer {
// iterate all valid found files, search for includes, add a node into the graph for each
// file and add a file->includes KV into the map
for path in file_iter {
let includes = self.find_includes(root, path.as_str());
let includes = self.find_includes(path.as_str());
let idx = self.graph.borrow_mut().add_node(&path);
//eprintln!("adding {} with\n{:?}", path.clone(), includes);
files.insert(path, GLSLFile { idx, includes });
}
// Add edges between nodes, finding target nodes on weight (value)
for (_, v) in files.into_iter() {
for file in v.includes {
//eprintln!("searching for {}", file);
let idx = self.graph.borrow_mut().find_node(file.filepath.as_str());
if idx.is_none() {
eprintln!("couldn't find {} in graph for {}", file, self.graph.borrow().graph[v.idx]);
continue;
}
//eprintln!("added edge between\n\t{}\n\t{}", k, file);
for include in includes {
let child = self.graph.borrow_mut().add_node(&include.0);
self.graph.borrow_mut().add_edge(
v.idx,
idx.unwrap(),
file.line,
file.start,
file.end,
idx,
child,
include.1,
);
//self.graph.borrow_mut().graph.add_edge(v.idx, idx.unwrap(), String::from("includes"));
}
}
@ -194,7 +178,7 @@ impl MinecraftShaderLanguageServer {
std::thread::sleep(std::time::Duration::from_secs(1));
}
pub fn find_includes(&self, root: &str, file: &str) -> Vec<IncludePosition> {
pub fn find_includes(&self, file: &str) -> Vec<(String, IncludePosition)> {
let mut includes = Vec::default();
let buf = BufReader::new(std::fs::File::open(file).unwrap());
@ -219,19 +203,23 @@ impl MinecraftShaderLanguageServer {
if !path.starts_with('/') {
path.insert(0, '/');
}
let full_include = String::from(root).add("/shaders").add(path.as_str());
includes.push(IncludePosition {
filepath: full_include,
line: line.0,
start,
end,
});
let full_include = String::from(&self.root).add("/shaders").add(path.as_str());
includes.push((
full_include,
IncludePosition {
line: line.0,
start,
end,
}
));
//eprintln!("{} includes {}", file, full_include);
});
includes
}
//fn update_includes_for_node(&self, )
pub fn lint(&self, uri: &str) -> Result<HashMap<Url, Vec<Diagnostic>>> {
// get all top level ancestors of this file
let file_ancestors = match self.get_file_toplevel_ancestors(uri) {
@ -399,7 +387,7 @@ impl MinecraftShaderLanguageServer {
continue;
}
let source = String::from_utf8(fs::read(path)?)?;
let source = fs::read_to_string(path)?;
sources.insert(path.clone(), source);
}
@ -409,7 +397,7 @@ impl MinecraftShaderLanguageServer {
fn get_file_toplevel_ancestors(&self, uri: &str) -> Result<Option<Vec<petgraph::stable_graph::NodeIndex>>> {
let curr_node = match self.graph.borrow_mut().find_node(uri) {
Some(n) => n,
None => return Err(anyhow::format_err!("node not found")),
None => return Err(anyhow!("node not found")),
};
let roots = self.graph.borrow().collect_root_ancestors(curr_node);
if roots.is_empty() {
@ -521,9 +509,9 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
},
};
self.root = Some(root);
self.root = root;
self.gen_initial_graph(self.root.as_ref().unwrap());
self.gen_initial_graph();
self.set_status("ready", "Project initialized", "$(check)");
}
@ -606,7 +594,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
fn execute_command(&mut self, mut params: ExecuteCommandParams, completable: LSCompletable<WorkspaceEdit>) {
params
.arguments
.push(serde_json::Value::String(self.root.as_ref().unwrap().into()));
.push(serde_json::Value::String(self.root.clone()));
match self
.command_provider
.as_ref()
@ -694,10 +682,13 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
let edges: Vec<DocumentLink> = self
.graph
.borrow()
.get_include_meta(node)
.child_node_indexes(node)
.into_iter()
.filter_map(|value| {
let path = std::path::Path::new(&value.filepath);
.filter_map(|child| {
let graph = self.graph.borrow();
let value = graph.get_edge_meta(node, child);
let path: std::ffi::OsString = graph.get_node(child).try_into().unwrap();
let path = std::path::Path::new(&path);
let url = match Url::from_file_path(path) {
Ok(url) => url,
Err(e) => {

View file

@ -1,7 +1,7 @@
use super::*;
use std::fs;
use std::io;
use std::io::Result;
use std::fs;
use hamcrest2::prelude::*;
@ -9,19 +9,19 @@ use tempdir::TempDir;
use petgraph::algo::is_cyclic_directed;
use fs_extra::{dir, copy_items};
use fs_extra::{copy_items, dir};
use jsonrpc_common::*;
use jsonrpc_response::*;
struct StdoutNewline {
s: io::Stdout
s: Box<dyn io::Write>,
}
impl io::Write for StdoutNewline {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let res = self.s.write(buf);
if buf[buf.len()-1] == b"}"[0] {
if buf[buf.len() - 1] == b"}"[0] {
#[allow(unused_variables)]
let res = self.s.write(b"\n\n");
}
@ -34,28 +34,36 @@ impl io::Write for StdoutNewline {
}
fn new_temp_server() -> MinecraftShaderLanguageServer {
let endpoint = LSPEndpoint::create_lsp_output_with_output_stream(|| StdoutNewline{s: io::stdout()});
let endpoint = LSPEndpoint::create_lsp_output_with_output_stream(|| StdoutNewline {
s: Box::new(io::sink()),
});
MinecraftShaderLanguageServer{
MinecraftShaderLanguageServer {
endpoint,
graph: Rc::new(RefCell::new(graph::CachedStableGraph::new())),
config: Configuration::default(),
wait: WaitGroup::new(),
root: None,
root: "".to_string(),
command_provider: None,
}
}
fn copy_files(files: &str, dest: &TempDir) {
let opts = &dir::CopyOptions::new();
let files = fs::read_dir(files).unwrap().map(|e| String::from(e.unwrap().path().as_os_str().to_str().unwrap())).collect::<Vec<String>>();
let files = fs::read_dir(files)
.unwrap()
.map(|e| String::from(e.unwrap().path().as_os_str().to_str().unwrap()))
.collect::<Vec<String>>();
copy_items(&files, dest.path().join("shaders"), opts).unwrap();
}
fn copy_to_and_set_root(test_path: &str, server: &mut MinecraftShaderLanguageServer) -> (Rc<TempDir>, String) {
fn copy_to_and_set_root(
test_path: &str,
server: &mut MinecraftShaderLanguageServer,
) -> (Rc<TempDir>, String) {
let (_tmp_dir, tmp_path) = copy_to_tmp_dir(test_path);
server.root = Some(format!("{}{}", "file://", tmp_path));
server.root = format!("{}{}", "file://", tmp_path);
(_tmp_dir, tmp_path)
}
@ -81,13 +89,18 @@ fn test_empty_initialize() {
let tmp_path = tmp_dir.path().as_os_str().to_str().unwrap();
let tmp_uri = format!("{}{}", "file://", tmp_path);
let initialize_params = InitializeParams{
let initialize_params = InitializeParams {
process_id: None,
root_path: None,
root_uri: Some(Url::parse(tmp_uri.as_str()).unwrap()),
client_info: None,
initialization_options: None,
capabilities: ClientCapabilities{workspace: None, text_document: None, experimental: None, window: None},
capabilities: ClientCapabilities {
workspace: None,
text_document: None,
experimental: None,
window: None,
},
trace: None,
workspace_folders: None,
};
@ -96,15 +109,20 @@ fn test_empty_initialize() {
assert!(resp.is_some());
let respu = resp.unwrap();
match respu.result_or_error {
ResponseResult::Result(_) => {},
ResponseResult::Error(e) => { panic!(format!("expected ResponseResult::Result(..), got {:?}", e)) }
ResponseResult::Result(_) => {}
ResponseResult::Error(e) => {
panic!(format!("expected ResponseResult::Result(..), got {:?}", e))
}
}
};
let completable = MethodCompletable::new(ResponseCompletable::new(Some(Id::Number(1)), Box::new(on_response)));
let completable = MethodCompletable::new(ResponseCompletable::new(
Some(Id::Number(1)),
Box::new(on_response),
));
server.initialize(initialize_params, completable);
assert_eq!(server.root, Some(String::from(tmp_path)));
assert_eq!(server.root, String::from(tmp_path));
assert_eq!(server.graph.borrow().graph.edge_count(), 0);
assert_eq!(server.graph.borrow().graph.node_count(), 0);
@ -121,13 +139,18 @@ fn test_01_initialize() {
let (_tmp_dir, tmp_path) = copy_to_tmp_dir("./testdata/01");
let initialize_params = InitializeParams{
let initialize_params = InitializeParams {
process_id: None,
root_path: None,
root_uri: Some(Url::parse(format!("{}{}", "file://", tmp_path).as_str()).unwrap()),
client_info: None,
initialization_options: None,
capabilities: ClientCapabilities{workspace: None, text_document: None, experimental: None, window: None},
capabilities: ClientCapabilities {
workspace: None,
text_document: None,
experimental: None,
window: None,
},
trace: None,
workspace_folders: None,
};
@ -136,25 +159,39 @@ fn test_01_initialize() {
assert!(resp.is_some());
let respu = resp.unwrap();
match respu.result_or_error {
ResponseResult::Result(_) => {},
ResponseResult::Error(e) => { panic!(format!("expected ResponseResult::Result(..), got {:?}", e)) }
ResponseResult::Result(_) => {}
ResponseResult::Error(e) => {
panic!(format!("expected ResponseResult::Result(..), got {:?}", e))
}
}
};
let completable = MethodCompletable::new(ResponseCompletable::new(Some(Id::Number(1)), Box::new(on_response)));
let completable = MethodCompletable::new(ResponseCompletable::new(
Some(Id::Number(1)),
Box::new(on_response),
));
server.initialize(initialize_params, completable);
// Assert there is one edge between two nodes
assert_eq!(server.graph.borrow().graph.edge_count(), 1);
let edge = server.graph.borrow().graph.edge_indices().next().unwrap();
let (node1, node2) = server.graph.borrow().graph.edge_endpoints(edge).unwrap();
// Assert the values of the two nodes in the tree
assert_eq!(server.graph.borrow().graph[node1], format!("{}/{}/{}", tmp_path, "shaders", "final.fsh"));
assert_eq!(server.graph.borrow().graph[node2], format!("{}/{}/{}", tmp_path, "shaders", "common.glsl"));
assert_eq!(server.graph.borrow().graph.edge_weight(edge).unwrap().line, 2);
// Assert the values of the two nodes in the tree
assert_eq!(
server.graph.borrow().graph[node1],
format!("{}/{}/{}", tmp_path, "shaders", "final.fsh")
);
assert_eq!(
server.graph.borrow().graph[node2],
format!("{}/{}/{}", tmp_path, "shaders", "common.glsl")
);
assert_eq!(
server.graph.borrow().graph.edge_weight(edge).unwrap().line,
2
);
server.endpoint.request_shutdown();
}
@ -165,7 +202,15 @@ fn test_graph_two_connected_nodes() {
let idx1 = graph.add_node("sample");
let idx2 = graph.add_node("banana");
graph.add_edge(idx1, idx2, 3, 10, 50);
graph.add_edge(
idx1,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
let children = graph.child_node_names(idx1);
assert_eq!(children.len(), 1);
@ -177,7 +222,7 @@ fn test_graph_two_connected_nodes() {
let parents = graph.parent_node_names(idx1);
assert_eq!(parents.len(), 0);
let parents = graph.parent_node_names(idx2);
assert_eq!(parents.len(), 1);
assert_eq!(parents[0], "sample");
@ -210,13 +255,37 @@ fn test_collect_root_ancestors() {
let idx2 = graph.add_node("2");
let idx3 = graph.add_node("3");
graph.add_edge(idx0, idx1, 2, 0, 0);
graph.add_edge(idx1, idx2, 3, 0, 0);
graph.add_edge(idx3, idx1, 4, 0, 0);
graph.add_edge(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx3,
idx1,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
// 0 3
// |/
// 1
// |/
// 1
// |
// 2
@ -240,14 +309,38 @@ fn test_collect_root_ancestors() {
let idx2 = graph.add_node("2");
let idx3 = graph.add_node("3");
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(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx0,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
// 0
// / \
// / \
// 1 2
// /
// /
// 3
let roots = graph.collect_root_ancestors(idx3);
@ -270,15 +363,39 @@ fn test_collect_root_ancestors() {
let idx2 = graph.add_node("2");
let idx3 = graph.add_node("3");
graph.add_edge(idx0, idx1, 2, 0, 0);
graph.add_edge(idx2, idx3, 3, 0, 0);
graph.add_edge(idx1, idx3, 5, 0, 0);
graph.add_edge(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx2,
idx3,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
// 0
// |
// 1
// |
// 1
// \
// 2 \
// 2 \
// \ /
// 3
@ -302,13 +419,37 @@ fn test_collect_root_ancestors() {
let idx2 = graph.add_node("2");
let idx3 = graph.add_node("3");
graph.add_edge(idx0, idx1, 2, 0, 0);
graph.add_edge(idx1, idx2, 4, 0, 0);
graph.add_edge(idx1, idx3, 6, 0, 0);
graph.add_edge(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx2,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 6,
start: 0,
end: 0,
},
);
// 0
// |
// 1
// |
// 1
// / \
// 2 3
@ -336,9 +477,33 @@ fn test_graph_dfs() {
let idx2 = graph.add_node("2");
let idx3 = graph.add_node("3");
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(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx0,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
let dfs = dfs::Dfs::new(&graph, idx0);
@ -348,16 +513,16 @@ fn test_graph_dfs() {
assert_that!(&i, ok());
collection.push(i.unwrap());
}
let nodes: Vec<NodeIndex> = collection.iter().map(|n| n.0).collect();
let parents: Vec<Option<NodeIndex>> = collection.iter().map(|n| n.1).collect();
// 0
// / \
// 1 2
// /
// 3
// 3
let expected_nodes = vec![idx0, idx1, idx3, idx2];
assert_eq!(expected_nodes, nodes);
let expected_parents = vec![None, Some(idx0), Some(idx1), Some(idx0)];
@ -378,15 +543,87 @@ fn test_graph_dfs() {
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(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx0,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx4,
IncludePosition {
line: 6,
start: 0,
end: 0,
},
);
graph.add_edge(
idx2,
idx4,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
graph.add_edge(
idx2,
idx5,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx3,
idx6,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx4,
idx6,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx6,
idx7,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
let dfs = dfs::Dfs::new(&graph, idx0);
@ -396,7 +633,7 @@ fn test_graph_dfs() {
assert_that!(&i, ok());
collection.push(i.unwrap());
}
let nodes: Vec<NodeIndex> = collection.iter().map(|n| n.0).collect();
let parents: Vec<Option<NodeIndex>> = collection.iter().map(|n| n.1).collect();
// 0
@ -404,13 +641,29 @@ fn test_graph_dfs() {
// 1 2
// / \ / \
// 3 4 5
// \ /
// \ /
// 6 - 7
let expected_nodes = vec![idx0, idx1, idx3, idx6, idx7, idx4, idx6, idx7, idx2, idx5, idx4, idx6, idx7];
let expected_nodes = vec![
idx0, idx1, idx3, idx6, idx7, idx4, idx6, idx7, idx2, idx5, idx4, idx6, idx7,
];
assert_eq!(expected_nodes, nodes);
let expected_parents = vec![None, Some(idx0), Some(idx1), Some(idx3), Some(idx6), Some(idx1), Some(idx4), Some(idx6), Some(idx0), Some(idx2), Some(idx2), Some(idx4), Some(idx6)];
let expected_parents = vec![
None,
Some(idx0),
Some(idx1),
Some(idx3),
Some(idx6),
Some(idx1),
Some(idx4),
Some(idx6),
Some(idx0),
Some(idx2),
Some(idx2),
Some(idx4),
Some(idx6),
];
assert_eq!(expected_parents, parents);
@ -432,16 +685,96 @@ fn test_graph_dfs_cycle() {
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);
graph.add_edge(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx0,
idx2,
IncludePosition {
line: 3,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx3,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx4,
IncludePosition {
line: 6,
start: 0,
end: 0,
},
);
graph.add_edge(
idx2,
idx4,
IncludePosition {
line: 5,
start: 0,
end: 0,
},
);
graph.add_edge(
idx2,
idx5,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx3,
idx6,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx4,
idx6,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx6,
idx7,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
graph.add_edge(
idx7,
idx4,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
let mut dfs = dfs::Dfs::new(&graph, idx0);
@ -450,7 +783,7 @@ fn test_graph_dfs_cycle() {
assert_that!(&i, ok());
}
}
// 0
// / \
// 1 2
@ -470,8 +803,24 @@ fn test_graph_dfs_cycle() {
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);
graph.add_edge(
idx0,
idx1,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
graph.add_edge(
idx1,
idx0,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
let mut dfs = dfs::Dfs::new(&graph, idx1);
@ -487,11 +836,25 @@ fn test_generate_merge_list_01() {
let (_tmp_dir, tmp_path) = copy_to_and_set_root("./testdata/01", &mut server);
let final_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let common_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/{}", tmp_path, "common.glsl"));
let final_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let common_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/{}", tmp_path, "common.glsl"));
server.graph.borrow_mut().add_edge(
final_idx,
common_idx,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(final_idx, common_idx, 2, 0, 0);
let nodes = server.get_dfs_for_node(final_idx).unwrap();
let mut sources = server.load_sources(&nodes).unwrap();
@ -500,19 +863,15 @@ fn test_generate_merge_list_01() {
let result = merger.generate_merge_list(&nodes);
let total: String = result
.iter()
.map(|s| &**s)
.collect::<Vec<&str>>()
.join("");
let total: String = result.iter().map(|s| &**s).collect::<Vec<&str>>().join("");
let merge_file = tmp_path.clone() + "/shaders/final.fsh.merge";
let mut truth = String::from_utf8(fs::read::<String>(merge_file).unwrap()).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone()+"/shaders/final.fsh"), 1);
truth = truth.replacen("!!", &(tmp_path.clone()+"/shaders/"+"common.glsl"), 1);
truth = truth.replace("!!", &(tmp_path+"/shaders/"+"final.fsh"));
let mut truth = fs::read_to_string::<String>(merge_file).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone() + "/shaders/final.fsh"), 1);
truth = truth.replacen("!!", &(tmp_path.clone() + "/shaders/" + "common.glsl"), 1);
truth = truth.replace("!!", &(tmp_path + "/shaders/" + "final.fsh"));
assert_that!(total, eq(truth));
server.endpoint.request_shutdown();
@ -524,15 +883,51 @@ fn test_generate_merge_list_02() {
let (_tmp_dir, tmp_path) = copy_to_and_set_root("./testdata/02", &mut server);
let final_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let test_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "test.glsl"));
let burger_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "burger.glsl"));
let sample_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "sample.glsl"));
let final_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let test_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "test.glsl"));
let burger_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "burger.glsl"));
let sample_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "sample.glsl"));
server.graph.borrow_mut().add_edge(
final_idx,
sample_idx,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(
sample_idx,
burger_idx,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(
sample_idx,
test_idx,
IncludePosition {
line: 6,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(final_idx, sample_idx, 2, 0, 0);
server.graph.borrow_mut().add_edge(sample_idx, burger_idx, 4, 0, 0);
server.graph.borrow_mut().add_edge(sample_idx, test_idx, 6, 0, 0);
let nodes = server.get_dfs_for_node(final_idx).unwrap();
let mut sources = server.load_sources(&nodes).unwrap();
@ -541,22 +936,24 @@ fn test_generate_merge_list_02() {
let result = merger.generate_merge_list(&nodes);
let total: String = result
.iter()
.map(|s| &**s)
.collect::<Vec<&str>>()
.join("");
let total: String = result.iter().map(|s| &**s).collect::<Vec<&str>>().join("");
let merge_file = tmp_path.clone() + "/shaders/final.fsh.merge";
let mut truth = String::from_utf8(fs::read::<String>(merge_file).unwrap()).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone()+"/shaders/final.fsh"), 1);
for file in &["sample.glsl", "burger.glsl", "sample.glsl", "test.glsl", "sample.glsl"] {
let mut truth = fs::read_to_string::<String>(merge_file).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone() + "/shaders/final.fsh"), 1);
for file in &[
"sample.glsl",
"burger.glsl",
"sample.glsl",
"test.glsl",
"sample.glsl",
] {
let path = tmp_path.clone();
truth = truth.replacen("!!", &format!("{}/shaders/utils/{}", path, file), 1);
}
truth = truth.replacen("!!", &(tmp_path+"/shaders/final.fsh"), 1);
truth = truth.replacen("!!", &(tmp_path + "/shaders/final.fsh"), 1);
assert_that!(total, eq(truth));
@ -569,15 +966,51 @@ fn test_generate_merge_list_03() {
let (_tmp_dir, tmp_path) = copy_to_and_set_root("./testdata/03", &mut server);
let final_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let test_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "test.glsl"));
let burger_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "burger.glsl"));
let sample_idx = server.graph.borrow_mut().add_node(&format!("{}/shaders/utils/{}", tmp_path, "sample.glsl"));
let final_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/{}", tmp_path, "final.fsh"));
let test_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "test.glsl"));
let burger_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "burger.glsl"));
let sample_idx = server
.graph
.borrow_mut()
.add_node(&format!("{}/shaders/utils/{}", tmp_path, "sample.glsl"));
server.graph.borrow_mut().add_edge(
final_idx,
sample_idx,
IncludePosition {
line: 2,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(
sample_idx,
burger_idx,
IncludePosition {
line: 4,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(
sample_idx,
test_idx,
IncludePosition {
line: 6,
start: 0,
end: 0,
},
);
server.graph.borrow_mut().add_edge(final_idx, sample_idx, 2, 0, 0);
server.graph.borrow_mut().add_edge(sample_idx, burger_idx, 4, 0, 0);
server.graph.borrow_mut().add_edge(sample_idx, test_idx, 6, 0, 0);
let nodes = server.get_dfs_for_node(final_idx).unwrap();
let mut sources = server.load_sources(&nodes).unwrap();
@ -586,24 +1019,26 @@ fn test_generate_merge_list_03() {
let result = merger.generate_merge_list(&nodes);
let total: String = result
.iter()
.map(|s| &**s)
.collect::<Vec<&str>>()
.join("");
let total: String = result.iter().map(|s| &**s).collect::<Vec<&str>>().join("");
let merge_file = tmp_path.clone() + "/shaders/final.fsh.merge";
let mut truth = String::from_utf8(fs::read::<String>(merge_file).unwrap()).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone()+"/shaders/final.fsh"), 1);
for file in &["sample.glsl", "burger.glsl", "sample.glsl", "test.glsl", "sample.glsl"] {
let mut truth = fs::read_to_string::<String>(merge_file).unwrap();
truth = truth.replacen("!!", &(tmp_path.clone() + "/shaders/final.fsh"), 1);
for file in &[
"sample.glsl",
"burger.glsl",
"sample.glsl",
"test.glsl",
"sample.glsl",
] {
let path = tmp_path.clone();
truth = truth.replacen("!!", &format!("{}/shaders/utils/{}", path, file), 1);
}
truth = truth.replacen("!!", &(tmp_path+"/shaders/final.fsh"), 1);
truth = truth.replacen("!!", &(tmp_path + "/shaders/final.fsh"), 1);
assert_that!(total, eq(truth));
server.endpoint.request_shutdown();
}
}