mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-08-03 16:39:16 +00:00
Fixed cycle path rewinding
This commit is contained in:
parent
1250c81365
commit
d80adf83a3
4 changed files with 122 additions and 21 deletions
|
@ -4,7 +4,7 @@ watchtest:
|
|||
RUST_BACKTRACE=0 cargo watch -x test -i Makefile
|
||||
|
||||
test:
|
||||
RUST_LIB_BACKTRACE=0 cargo test
|
||||
RUST_LIB_BACKTRACE=0 RUST_BACKTRACE=0 cargo test
|
||||
|
||||
build:
|
||||
cargo build --release
|
|
@ -7,11 +7,17 @@ use crate::graph::CachedStableGraph;
|
|||
use anyhow::{Result, Error};
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
struct VisitCount {
|
||||
node: NodeIndex,
|
||||
touch: usize,
|
||||
children: usize,
|
||||
}
|
||||
|
||||
/// Performs a depth-first search with duplicates
|
||||
pub struct Dfs<'a> {
|
||||
stack: Vec<NodeIndex>,
|
||||
graph: &'a CachedStableGraph,
|
||||
cycle: Vec<NodeIndex>
|
||||
cycle: Vec<VisitCount>
|
||||
}
|
||||
|
||||
impl <'a> Dfs<'a> {
|
||||
|
@ -24,9 +30,11 @@ impl <'a> Dfs<'a> {
|
|||
}
|
||||
|
||||
fn reset_path_to_branch(&mut self) {
|
||||
while let Some(par) = self.cycle.pop() {
|
||||
if self.graph.graph.edges(par).count() > 0 {
|
||||
while let Some(par) = self.cycle.last_mut() {
|
||||
par.touch += 1;
|
||||
if par.touch > par.children {
|
||||
self.cycle.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -35,10 +43,11 @@ impl <'a> Dfs<'a> {
|
|||
fn check_for_cycle(&self, children: &[NodeIndex]) -> Result<()> {
|
||||
for prev in &self.cycle {
|
||||
for child in children {
|
||||
if *prev == *child {
|
||||
if prev.node == *child {
|
||||
let cycle_nodes: Vec<NodeIndex> = self.cycle.iter().map(|n| n.node).collect();
|
||||
return Err(
|
||||
Error::new(
|
||||
CycleError::new(&self.cycle, *child, self.graph)
|
||||
CycleError::new(&cycle_nodes, *child, self.graph)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -49,11 +58,20 @@ impl <'a> Dfs<'a> {
|
|||
}
|
||||
|
||||
impl <'a> Iterator for Dfs<'a> {
|
||||
type Item = Result<NodeIndex>;
|
||||
type Item = Result<(NodeIndex, Option<NodeIndex>)>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<(NodeIndex, Option<NodeIndex>)>> {
|
||||
let parent = match self.cycle.last() {
|
||||
Some(p) => Some(p.node),
|
||||
None => None,
|
||||
};
|
||||
|
||||
fn next(&mut self) -> Option<Result<NodeIndex>> {
|
||||
if let Some(node) = self.stack.pop() {
|
||||
self.cycle.push(node);
|
||||
self.cycle.push(VisitCount{
|
||||
node,
|
||||
children: self.graph.graph.edges(node).count(),
|
||||
touch: 1,
|
||||
});
|
||||
|
||||
let mut children = self.graph.child_node_indexes(node);
|
||||
|
||||
|
@ -78,7 +96,8 @@ impl <'a> Iterator for Dfs<'a> {
|
|||
} else {
|
||||
self.reset_path_to_branch();
|
||||
}
|
||||
return Some(Ok(node));
|
||||
|
||||
return Some(Ok((node, parent)));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -97,7 +116,6 @@ impl CycleError {
|
|||
|
||||
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] {
|
||||
|
@ -112,5 +130,4 @@ impl Into<String> for CycleError {
|
|||
fn into(self) -> String {
|
||||
format!("{}", self)
|
||||
}
|
||||
|
||||
}
|
|
@ -14,6 +14,7 @@ use std::io::{stdin, stdout, BufRead, BufReader, Write};
|
|||
use std::ops::Add;
|
||||
use std::process;
|
||||
use std::rc::Rc;
|
||||
use std::fs;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
|
@ -257,7 +258,6 @@ impl MinecraftShaderLanguageServer {
|
|||
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),
|
||||
|
@ -350,7 +350,7 @@ impl MinecraftShaderLanguageServer {
|
|||
Ok(Some(roots))
|
||||
}
|
||||
|
||||
fn generate_merge_list(&self, root: NodeIndex) -> Result<(LinkedList<String>, LinkedList<&str>)> {
|
||||
pub 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();
|
||||
|
@ -362,15 +362,16 @@ impl MinecraftShaderLanguageServer {
|
|||
//let slice_stack = Vec::new();
|
||||
|
||||
let iteration_order: Vec<_> = dfs.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
|
||||
for n in dfs {
|
||||
|
||||
|
||||
/* for n in dfs {
|
||||
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);
|
||||
|
||||
|
@ -530,7 +531,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
|
|||
|
||||
let path: String = percent_encoding::percent_decode_str(params.text_document.uri.path()).decode_utf8().unwrap().into();
|
||||
|
||||
let file_content = std::fs::read(path).unwrap();
|
||||
let file_content = fs::read(path).unwrap();
|
||||
match self.lint(params.text_document.uri.path(), String::from_utf8(file_content).unwrap()) {
|
||||
Ok(diagnostics) => self.publish_diagnostic(diagnostics, params.text_document.uri, None),
|
||||
Err(e) => eprintln!("error linting: {}", e),
|
||||
|
|
|
@ -203,6 +203,44 @@ fn test_collect_root_ancestors() {
|
|||
|
||||
#[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");
|
||||
|
||||
graph.add_edge(idx0, idx1, 2, 0, 0);
|
||||
graph.add_edge(idx0, idx2, 3, 0, 0);
|
||||
graph.add_edge(idx1, idx3, 5, 0, 0);
|
||||
|
||||
let dfs = dfs::Dfs::new(&graph, idx0);
|
||||
|
||||
let mut collection = Vec::new();
|
||||
|
||||
for i in 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
|
||||
let expected_nodes = vec![idx0, idx1, idx3, idx2];
|
||||
|
||||
assert_eq!(expected_nodes, nodes);
|
||||
|
||||
let expected_parents = vec![None, Some(idx0), Some(idx1), Some(idx0)];
|
||||
|
||||
assert_eq!(expected_parents, parents);
|
||||
|
||||
assert!(!is_cyclic_directed(&graph.graph));
|
||||
}
|
||||
{
|
||||
let mut graph = graph::CachedStableGraph::new();
|
||||
|
||||
|
@ -233,7 +271,9 @@ 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
|
||||
|
@ -241,9 +281,13 @@ fn test_graph_dfs() {
|
|||
// 3 4 5
|
||||
// \ /
|
||||
// 6 - 7
|
||||
let expected = 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, collection);
|
||||
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)];
|
||||
|
||||
assert_eq!(expected_parents, parents);
|
||||
|
||||
assert!(!is_cyclic_directed(&graph.graph));
|
||||
}
|
||||
|
@ -311,4 +355,43 @@ fn test_graph_dfs_cycle() {
|
|||
println!("{:?}", dfs.next());
|
||||
println!("{:?}", dfs.next());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_merge_list() {
|
||||
let mut server = new_temp_server();
|
||||
|
||||
let tmp_dir = TempDir::new("mcshader").unwrap();
|
||||
fs::create_dir(tmp_dir.path().join("shaders")).unwrap();
|
||||
|
||||
copy_files("./testdata/01", &tmp_dir);
|
||||
|
||||
let tmp_path = tmp_dir.path().as_os_str().to_str().unwrap();
|
||||
let tmp_uri = format!("{}{}/shaders", "file://", tmp_path);
|
||||
|
||||
server.root = Some(tmp_uri);
|
||||
|
||||
let final_idx = server.graph.borrow_mut().add_node(format!("{}/{}", tmp_path, "final.fsh"));
|
||||
let common_idx = server.graph.borrow_mut().add_node(format!("{}/{}", tmp_path, "common.glsl"));
|
||||
|
||||
server.graph.borrow_mut().add_edge(final_idx, common_idx, 2, 0, 0);
|
||||
|
||||
let result = server.generate_merge_list(final_idx);
|
||||
|
||||
assert_that!(&result, ok());
|
||||
|
||||
let total: String = result
|
||||
.unwrap().1
|
||||
.iter()
|
||||
.map(|s| &**s)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("");
|
||||
|
||||
let merge_file = String::from(tmp_path) + "/shaders/final.fsh.merge";
|
||||
|
||||
let truth = String::from_utf8(fs::read::<String>(merge_file).unwrap()).unwrap();
|
||||
|
||||
assert_that!(total, eq(truth));
|
||||
|
||||
server.endpoint.request_shutdown();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue