Caching graph datatype for faster nodeindex lookup. Basic include containing 2-node graph test

This commit is contained in:
Noah Santschi-Cooney 2020-05-12 00:12:12 +01:00
parent 85f1c8d85c
commit 375f7f45a7
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
11 changed files with 165 additions and 26 deletions

View file

@ -2,7 +2,7 @@ kind: pipeline
name: default
steps:
- name: Test Server
- name: test server
image: rust:1.43
commands:
- cd server
@ -12,4 +12,5 @@ steps:
image: node:14
commands:
- npm i
- npm run compile
- npm run lint

View file

@ -4,7 +4,7 @@
[![Marketplace Version](https://vsmarketplacebadge.apphb.com/version/strum355.vscode-mc-shader.svg)](https://marketplace.visualstudio.com/items?itemName=strum355.vscode-mc-shader) [![Installs](https://vsmarketplacebadge.apphb.com/installs/strum355.vscode-mc-shader.svg)](https://marketplace.visualstudio.com/items?itemName=strum355.vscode-mc-shader)
[![license](https://img.shields.io/github/license/Strum355/vscode-mc-shader.svg)](https://github.com/Strum355/vscode-mc-shader)
[![Issues](https://img.shields.io/github/issues-raw/Strum355/vscode-mc-shader.svg)](https://github.com/Strum355/vscode-mc-shader/issues)
[![Maintainability](https://api.codeclimate.com/v1/badges/c2c813cb0a42a8aad483/maintainability)](https://codeclimate.com/github/Strum355/vscode-mc-shader/maintainability)
[![Build Status](https://cloud.drone.io/api/badges/Strum355/vscode-mc-shader/status.svg)](https://cloud.drone.io/Strum355/vscode-mc-shader)
<!-- It doesnt seem to like these :<
[![CI](https://ci.netsoc.co/api/badges/Strum355/vscode-mc-shader/status.svg?branch=master)](https://ci.netsoc.co/Strum355/vscode-mc-shader)

27
server/Cargo.lock generated
View file

@ -41,6 +41,11 @@ name = "fixedbitset"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fs_extra"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
@ -211,6 +216,14 @@ name = "regex-syntax"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "remove_dir_all"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust_lsp"
version = "0.6.0"
@ -307,6 +320,15 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
@ -352,12 +374,14 @@ name = "vscode-mc-shader"
version = "0.1.0"
dependencies = [
"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)",
"petgraph 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rust_lsp 0.6.0 (git+https://github.com/Strum355/RustLSP)",
"serde 1.0.108 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -406,6 +430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"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"
"checksum fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
@ -429,6 +454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum rust_lsp 0.6.0 (git+https://github.com/Strum355/RustLSP)" = "<none>"
"checksum rustdt-json_rpc 0.3.0 (git+https://github.com/strager/rustdt-json_rpc?branch=serde-1.0)" = "<none>"
"checksum rustdt_util 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7cfffa8a89d8758be2dd5605c5fc62bce055af2491ebf3ce953d4d31512c59fd"
@ -440,6 +466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
"checksum smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
"checksum syn 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"

View file

@ -12,4 +12,8 @@ walkdir = "2.3.1"
petgraph = "0.5.0"
lazy_static = "1.4.0"
regex = "1.3.7"
chan = "0.1.23"
chan = "0.1.23"
[dev-dependencies]
tempdir = "0.3.7"
fs_extra = "1.1.0"

36
server/src/graph.rs Normal file
View file

@ -0,0 +1,36 @@
use petgraph::stable_graph::StableDiGraph;
use petgraph::stable_graph::NodeIndex;
use std::collections::HashMap;
pub struct CachedStableGraph {
pub graph: StableDiGraph<String, String>,
cache: HashMap<String, NodeIndex>,
}
impl CachedStableGraph {
pub fn new() -> CachedStableGraph {
CachedStableGraph{
graph: StableDiGraph::new(),
cache: HashMap::new(),
}
}
pub fn find_node(&mut self, name: String) -> Option<NodeIndex> {
match self.cache.get(&name) {
Some(n) => Some(*n),
None => {
let n = self.graph.node_indices().find(|n| self.graph[*n] == name);
if n.is_some() {
self.cache.insert(name, n.unwrap());
}
n
}
}
}
pub fn add_node(&mut self, name: String) -> NodeIndex {
let idx = self.graph.add_node(name.clone());
self.cache.insert(name, idx);
idx
}
}

View file

@ -13,8 +13,6 @@ use std::process;
use std::collections::HashMap;
use std::io;
use petgraph::graph::Graph;
use chan::WaitGroup;
use regex::Regex;
@ -22,7 +20,7 @@ use regex::Regex;
use lazy_static::lazy_static;
mod provider;
mod graph;
#[cfg(test)]
mod test;
@ -41,9 +39,11 @@ fn main() {
let endpoint_output = LSPEndpoint::create_lsp_output_with_output_stream(|| io::stdout());
let cache_graph = graph::CachedStableGraph::new();
let mut langserver = MinecraftShaderLanguageServer{
endpoint: endpoint_output.clone(),
graph: Rc::new(RefCell::new(Graph::default())),
graph: Rc::new(RefCell::new(cache_graph)),
config: Configuration::default(),
wait: WaitGroup::new(),
root: None,
@ -61,7 +61,7 @@ fn main() {
struct MinecraftShaderLanguageServer {
endpoint: Endpoint,
graph: Rc<RefCell<Graph<String, String>>>,
graph: Rc<RefCell<graph::CachedStableGraph>>,
config: Configuration,
wait: WaitGroup,
root: Option<String>,
@ -136,15 +136,14 @@ impl MinecraftShaderLanguageServer {
// Add edges between nodes, finding target nodes on weight (value)
for (_, v) in files.into_iter() {
for file in v.includes {
let mut iter = self.graph.borrow().node_indices();
//eprintln!("searching for {}", file);
let idx = iter.find(|i| self.graph.borrow_mut()[*i] == file);
let idx = self.graph.borrow_mut().find_node(file.clone());
if idx.is_none() {
eprintln!("couldn't find {} in graph", file);
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);
self.graph.borrow_mut().add_edge(v.idx, idx.unwrap(), String::from("includes"));
self.graph.borrow_mut().graph.add_edge(v.idx, idx.unwrap(), String::from("includes"));
}
}
@ -204,7 +203,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
})
}));
self.root = Some(params.root_path.unwrap());
self.root = Some(String::from(params.root_uri.unwrap().path()));
completable.complete(Ok(InitializeResult{capabilities, server_info: None}));

View file

@ -7,7 +7,8 @@ use std::io::prelude::*;
use serde_json::Value;
use petgraph::dot;
use petgraph::graph::Graph;
use crate::graph::CachedStableGraph;
pub struct CustomCommandProvider {
commands: HashMap<String, Box<dyn Invokeable>>
@ -35,7 +36,7 @@ pub trait Invokeable {
}
pub struct GraphDotCommand {
pub graph: Rc<RefCell<Graph<String, String>>>
pub graph: Rc<RefCell<CachedStableGraph>>
}
impl<'a> Invokeable for GraphDotCommand {
@ -51,7 +52,7 @@ impl<'a> Invokeable for GraphDotCommand {
let mut write_data_closure = || -> Result<(), std::io::Error> {
let graph = self.graph.as_ref();
file.seek(std::io::SeekFrom::Start(0))?;
file.write_all(dot::Dot::new(&(*(graph.borrow()))).to_string().as_bytes())?;
file.write_all(dot::Dot::new(&(graph.borrow().graph)).to_string().as_bytes())?;
file.flush()?;
file.seek(std::io::SeekFrom::Start(0))?;
Ok(())

View file

@ -1,12 +1,13 @@
use super::*;
use std::io;
use std::io::Result;
use tempdir::TempDir;
use std::fs;
use fs_extra;
use jsonrpc_common::*;
use jsonrpc_response::*;
use jsonrpc_response::*;
use serde_json::json;
struct StdoutNewline {
s: io::Stdout
@ -33,7 +34,7 @@ fn new_temp_server() -> MinecraftShaderLanguageServer {
MinecraftShaderLanguageServer{
endpoint,
graph: Rc::new(RefCell::new(Graph::default())),
graph: Rc::new(RefCell::new(graph::CachedStableGraph::new())),
config: Configuration::default(),
wait: WaitGroup::new(),
root: None,
@ -42,13 +43,17 @@ fn new_temp_server() -> MinecraftShaderLanguageServer {
}
#[test]
fn test_initialize() {
fn test_empty_initialize() {
let mut server = new_temp_server();
let tmp_dir = TempDir::new("mcshader").unwrap();
let tmp_path = tmp_dir.path().as_os_str().to_str().unwrap();
let tmp_uri = format!("{}{}", "file://", tmp_path);
let initialize_params = InitializeParams{
process_id: None,
root_path: Some(String::from("/tmp/vscodemcshader")),
root_uri: 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},
@ -68,13 +73,58 @@ fn test_initialize() {
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/vscodemcshader")));
assert_eq!(server.root, Some(String::from(tmp_path)));
assert_eq!(server.graph.borrow().edge_count(), 0);
assert_eq!(server.graph.borrow().node_count(), 0);
assert_eq!(server.graph.borrow().graph.edge_count(), 0);
assert_eq!(server.graph.borrow().graph.node_count(), 0);
assert_eq!(format!("{:?}", server.wait), "WaitGroup { count: 1 }");
server.endpoint.request_shutdown();
//std::thread::sleep(std::time::Duration::from_secs(1));
}
#[test]
fn test_01_initialize() {
let mut server = new_temp_server();
let tmp_dir = TempDir::new("mcshader").unwrap();
fs::create_dir(tmp_dir.path().join("shaders")).unwrap();
let opts = &fs_extra::dir::CopyOptions::new();
let files = fs::read_dir("./testdata/01").unwrap().map(|e| String::from(e.unwrap().path().as_os_str().to_str().unwrap())).collect::<Vec<String>>();
fs_extra::copy_items(&files, tmp_dir.path().join("shaders"), opts).unwrap();
let tmp_path = tmp_dir.path().as_os_str().to_str().unwrap();
let tmp_uri = format!("{}{}", "file://", tmp_path);
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},
trace: None,
workspace_folders: None,
};
let on_response = |resp: Option<Response>| {
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)) }
}
};
let completable = MethodCompletable::new(ResponseCompletable::new(Some(Id::Number(1)), Box::new(on_response)));
server.initialize(initialize_params, completable);
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_eq!(server.graph.borrow().graph[node1].as_str(), tmp_dir.path().join("shaders").join("final.fsh").as_os_str().to_str().unwrap());
server.endpoint.request_shutdown();
}

3
server/testdata/01/common.glsl vendored Normal file
View file

@ -0,0 +1,3 @@
float test() {
return 0.5;
}

7
server/testdata/01/final.fsh vendored Normal file
View file

@ -0,0 +1,7 @@
#version 120
#include "/common.glsl"
void main() {
gl_FragColor[0] = vec4(0.0);
}

11
server/testdata/01/final.fsh.merge vendored Normal file
View file

@ -0,0 +1,11 @@
#version 120
#line 1 1
float test() {
return 0.5;
}
#line 4 0
void main() {
gl_FragColor = vec4(0.0);
}