Document links handler: first revision

Doesnt differentiate between absolute and relative links yet
Needs tests smh
Move graph.get_includes out of graph.rs?
Finally make graph generic???
Move IncludePosition out of main.rs?
Hotel? Trivago
This commit is contained in:
Noah Santschi-Cooney 2020-06-11 01:58:21 +01:00
parent f65208b657
commit 1abc8c4832
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
6 changed files with 98 additions and 53 deletions

52
server/Cargo.lock generated
View file

@ -112,8 +112,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -135,7 +135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "petgraph"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -202,18 +202,18 @@ dependencies = [
[[package]]
name = "regex"
version = "1.3.7"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -233,8 +233,8 @@ dependencies = [
"lsp-types 0.74.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustdt-json_rpc 0.3.0 (git+https://github.com/strager/rustdt-json_rpc?branch=serde-1.0)",
"rustdt_util 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -245,8 +245,8 @@ dependencies = [
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustdt_util 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -269,15 +269,15 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.110"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.110"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -287,12 +287,12 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.53"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -366,7 +366,7 @@ dependencies = [
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -376,11 +376,11 @@ 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)",
"petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rust_lsp 0.6.0 (git+https://github.com/Strum355/RustLSP)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.55 (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)",
]
@ -444,7 +444,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum petgraph 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29c127eea4a29ec6c85d153c59dc1213f33ec74cead30fe4730aecc88cc1fd92"
"checksum petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
"checksum proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
"checksum quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
@ -452,17 +452,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
"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 regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
"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"
"checksum ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
"checksum serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
"checksum serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)" = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
"checksum serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
"checksum serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
"checksum serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
"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"

View file

@ -6,8 +6,8 @@ edition = "2018"
[dependencies]
rust_lsp = { git = "https://github.com/Strum355/RustLSP" }
serde_json = "1.0.53"
serde = "1.0.110"
serde_json = "1.0.55"
serde = "1.0.111"
walkdir = "2.3.1"
petgraph = "0.5.1"
lazy_static = "1.4.0"

View file

@ -1,4 +1,7 @@
.PHONY: watchtest
.PHONY: watchtest build
watchtest:
RUST_BACKTRACE=0 cargo watch -x test -i Makefile
RUST_BACKTRACE=0 cargo watch -x test -i Makefile
build:
cargo build --release

View file

@ -2,6 +2,7 @@ use petgraph::stable_graph::StableDiGraph;
use petgraph::stable_graph::NodeIndex;
use petgraph::stable_graph::EdgeIndex;
use std::collections::HashMap;
use super::IncludePosition;
/// Wraps a `StableDiGraph` with caching behaviour for node search by maintaining
/// an index for node value to node index and a reverse index.
@ -9,7 +10,7 @@ use std::collections::HashMap;
pub struct CachedStableGraph {
// StableDiGraph is used as it allows for String node values, essential for
// generating the GraphViz DOT render.
pub graph: StableDiGraph<String, String>,
pub graph: StableDiGraph<String, IncludePosition>,
cache: HashMap<String, NodeIndex>,
// Maps a node index to its abstracted string representation.
// Mainly used as the graph is based on NodeIndex and
@ -51,7 +52,7 @@ impl CachedStableGraph {
}
}
pub fn add_node<S: Into<String>>(&mut self, name: S) -> NodeIndex {
pub fn add_node(&mut self, name: impl Into<String>) -> NodeIndex {
let name_str = name.into();
let idx = self.graph.add_node(name_str.clone());
self.cache.insert(name_str.clone(), idx);
@ -59,12 +60,17 @@ impl CachedStableGraph {
idx
}
pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex) -> EdgeIndex {
self.graph.add_edge(a, b, String::from("includes"))
pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, line: u64, start: u64, end: u64) -> EdgeIndex {
let child_path = self.reverse_index.get(&b).unwrap().clone();
self.graph.add_edge(a, b, IncludePosition{filepath: child_path, line, start, end})
}
/// Returns the filepaths of the neighbors for the given `NodeIndex`
pub fn neighbors(&self, node: NodeIndex) -> Vec<String> {
self.graph.neighbors(node).map(|n| self.reverse_index.get(&n).unwrap().clone()).collect()
}
pub fn get_includes(&self, node: NodeIndex) -> Vec<IncludePosition> {
self.graph.edges(node).into_iter().map(|e| e.weight().clone()).collect()
}
}

View file

@ -1,3 +1,5 @@
#![feature(str_strip)]
use rust_lsp::lsp::*;
use rust_lsp::lsp_types::*;
use rust_lsp::jsonrpc::*;
@ -12,6 +14,9 @@ use std::io::{BufReader, BufRead};
use std::process;
use std::collections::HashMap;
use std::io;
use std::fmt::Display;
use std::fmt::Formatter;
use std::convert::TryFrom;
use chan::WaitGroup;
@ -86,7 +91,21 @@ impl Configuration {
struct GLSLFile {
idx: petgraph::graph::NodeIndex,
includes: Vec<String>,
includes: Vec<IncludePosition>,
}
#[derive(Clone)]
pub struct IncludePosition {
filepath: String,
line: u64,
start: u64,
end: u64,
}
impl Display for IncludePosition {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{{{}, l {}, s, {}, e {}}}", self.filepath, self.line, self.start, self.end)
}
}
impl MinecraftShaderLanguageServer {
@ -113,7 +132,13 @@ impl MinecraftShaderLanguageServer {
return None;
}
let ext = path.extension().unwrap().to_str().unwrap();
let ext = match path.extension() {
Some(e) => e,
None => {
eprintln!("filepath {} had no extension", path.to_str().unwrap());
return None
},
};
if ext != "vsh" && ext != "fsh" && ext != "glsl" && ext != "inc" {
return None;
}
@ -137,13 +162,14 @@ impl MinecraftShaderLanguageServer {
for (_, v) in files.into_iter() {
for file in v.includes {
//eprintln!("searching for {}", file);
let idx = self.graph.borrow_mut().find_node(file.clone());
let idx = self.graph.borrow_mut().find_node(file.filepath.clone());
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);
self.graph.borrow_mut().graph.add_edge(v.idx, idx.unwrap(), String::from("includes"));
self.graph.borrow_mut().add_edge(v.idx, idx.unwrap(), file.line, file.start, file.end);
//self.graph.borrow_mut().graph.add_edge(v.idx, idx.unwrap(), String::from("includes"));
}
}
@ -154,22 +180,28 @@ impl MinecraftShaderLanguageServer {
self.endpoint.send_notification("clearStatus", None::<()>).unwrap();
}
pub fn find_includes(&self, root: &str, file: &str) -> Vec<String> {
pub fn find_includes(&self, root: &str, file: &str) -> Vec<IncludePosition> {
let mut includes = Vec::default();
let buf = BufReader::new(std::fs::File::open(file).unwrap());
buf.lines()
.filter_map(|line| line.ok())
.filter(|line| RE_INCLUDE.is_match(line.as_str()))
buf.lines().enumerate()
.filter_map(|line| match line.1 {
Ok(t) => Some((line.0, t)),
Err(_e) => None }
)
.filter(|line| RE_INCLUDE.is_match(line.1.as_str()))
.for_each(|line| {
let caps = RE_INCLUDE.captures(line.as_str()).unwrap();
let cap = RE_INCLUDE.captures(line.1.as_str()).unwrap().get(1).unwrap();
//eprintln!("{:?}", caps);
let mut path: String = String::from(caps.get(1).unwrap().as_str());
let start = u64::try_from(cap.start()).unwrap();
let end = u64::try_from(cap.end()).unwrap();
let mut path: String = String::from(cap.as_str());
if !path.starts_with("/") {
path.insert(0, '/');
}
let full_include = String::from(root).add("/shaders").add(path.as_str());
includes.push(full_include.clone());
includes.push(IncludePosition{filepath: full_include.clone(), line: u64::try_from(line.0).unwrap(), start, end});
//eprintln!("{} includes {}", file, full_include);
});
@ -186,7 +218,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
self.wait.add(1);
let mut capabilities = ServerCapabilities::default();
capabilities.hover_provider = Some(true);
capabilities.hover_provider = Some(false);
capabilities.document_link_provider = Some(DocumentLinkOptions{
resolve_provider: None,
work_done_progress_options: WorkDoneProgressOptions{
@ -266,16 +298,17 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
fn resolve_completion_item(&mut self, _: CompletionItem, completable: LSCompletable<CompletionItem>) {
completable.complete(Err(Self::error_not_available(())));
}
fn hover(&mut self, _: TextDocumentPositionParams, completable: LSCompletable<Hover>) {
self.wait.wait();
self.endpoint.send_notification("sampleText", vec![1,2,3]).unwrap();
completable.complete(Ok(Hover{
/* completable.complete(Ok(Hover{
contents: HoverContents::Markup(MarkupContent{
kind: MarkupKind::Markdown,
value: String::from("# Hello World"),
}),
range: None,
}));
})); */
}
fn execute_command(&mut self, mut params: ExecuteCommandParams, completable: LSCompletable<WorkspaceEdit>) {
@ -327,13 +360,14 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
fn document_link(&mut self, params: DocumentLinkParams, completable: LSCompletable<Vec<DocumentLink>>) {
eprintln!("document link file: {:?}", params.text_document.uri.to_file_path().unwrap());
// node for current document
let node = match self.graph.borrow_mut().find_node(params.text_document.uri.to_file_path().unwrap().as_os_str().to_str().unwrap().to_string()) {
Some(n) => n,
None => return,
};
let edges: Vec<DocumentLink> = self.graph.borrow().neighbors(node).into_iter().filter_map(|value| {
let path = std::path::Path::new(&value);
let edges: Vec<DocumentLink> = self.graph.borrow().get_includes(node).into_iter().filter_map(|value| {
let path = std::path::Path::new(&value.filepath);
let url = match Url::from_file_path(path) {
Ok(url) => url,
Err(e) => {
@ -341,9 +375,11 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
return None;
}
};
Some(DocumentLink{
range: Range::new(Position::new(18, 0), Position::new(18, 20)),
target: url,
range: Range::new(Position::new(value.line, value.start), Position::new(value.line, value.end)),
target: url.clone(),
//tooltip: Some(url.path().to_string().strip_prefix(self.root.clone().unwrap().as_str()).unwrap().to_string()),
tooltip: None,
})
}).collect();

View file

@ -147,7 +147,7 @@ fn test_graph_two_connected_nodes() {
graph.add_node("banana");
let idx1 = graph.find_node("sample").unwrap();
let idx2 = graph.find_node("banana").unwrap();
graph.add_edge(idx1, idx2);
graph.add_edge(idx1, idx2, 3, 10, 50);
let neighbors = graph.neighbors(idx1);
assert_eq!(neighbors.len(), 1);