diff --git a/src/dreammaker/builtins.rs b/src/dreammaker/builtins.rs index 48397738..9dc233bf 100644 --- a/src/dreammaker/builtins.rs +++ b/src/dreammaker/builtins.rs @@ -2,20 +2,26 @@ use super::objtree::*; use super::ast::*; -use super::{Location, DMError}; +use super::{Location, FileId, DMError}; /// Register BYOND builtins into the specified object tree. pub fn register_builtins(tree: &mut ObjectTree) -> Result<(), DMError> { + let location = Location { + file: FileId::builtins(), + line: 1, + column: 1, + }; + macro_rules! entries { ($($($elem:ident)/ * $(= $val:expr)*;)*) => { $(loop { #![allow(unreachable_code)] let elems = [$(stringify!($elem)),*]; $( - tree.add_var(Location::default(), elems.iter().cloned(), $val)?; + tree.add_var(location, elems.iter().cloned(), $val)?; break; )* - tree.add_entry(Location::default(), elems.iter().cloned())?; + tree.add_entry(location, elems.iter().cloned())?; break; })* } diff --git a/src/dreammaker/error.rs b/src/dreammaker/error.rs index 3fabfbc1..77ee841a 100644 --- a/src/dreammaker/error.rs +++ b/src/dreammaker/error.rs @@ -8,11 +8,19 @@ use std::cell::{RefCell, Ref}; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct FileId(u32); -const BAD_FILE_ID: FileId = FileId(::std::u32::MAX); +const FILEID_BAD: FileId = FileId(::std::u32::MAX); +const FILEID_BUILTINS: FileId = FileId(0xfffffffe); impl Default for FileId { fn default() -> FileId { - BAD_FILE_ID + FILEID_BAD + } +} + +impl FileId { + #[inline] + pub fn builtins() -> FileId { + FILEID_BUILTINS } } @@ -38,9 +46,12 @@ impl Context { /// Look up a file path by its index returned from `register_file`. pub fn file_path(&self, file: FileId) -> PathBuf { + if file == FILEID_BUILTINS { + return "(builtins)".into(); + } let files = self.files.borrow(); let idx = file.0 as usize; - if idx > files.len() { // includes BAD_FILE_ID + if idx > files.len() { "(unknown)".into() } else { files[idx].to_owned() diff --git a/src/langserver/main.rs b/src/langserver/main.rs index 8e893c75..5a257c7f 100644 --- a/src/langserver/main.rs +++ b/src/langserver/main.rs @@ -133,13 +133,18 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { path_to_url(self.root.join(self.context.file_path(file))) } - fn convert_location(&self, loc: dm::Location) -> Result { + fn convert_location(&self, loc: dm::Location, one: &str, two: &str, three: &str) -> Result { let pos = langserver::Position { line: loc.line.saturating_sub(1) as u64, character: loc.column.saturating_sub(1) as u64, }; Ok(langserver::Location { - uri: self.file_url(loc.file)?, + uri: if loc.file == dm::FileId::builtins() { + Url::parse(&format!("https://secure.byond.com/docs/ref/info.html#{}{}{}", one, two, three)) + .map_err(invalid_request)? + } else { + self.file_url(loc.file)? + }, range: langserver::Range::new(pos, pos), }) } @@ -299,7 +304,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { results.push(SymbolInformation { name: name.to_owned(), kind: SymbolKind::Constant, - location: self.convert_location(location)?, + location: self.convert_location(location, "/DM", "/preprocessor/", name)?, container_name: None, }); } @@ -310,8 +315,8 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { results.push(SymbolInformation { name: ty.name.clone(), kind: SymbolKind::Class, - location: self.convert_location(ty.location)?, - container_name: Some(ty.path.clone()), + location: self.convert_location(ty.location, &ty.path, "", "")?, + container_name: Some(ty.path[..ty.path.len() - ty.name.len() - 1].to_owned()), }); } @@ -324,7 +329,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { results.push(SymbolInformation { name: var_name.clone(), kind: SymbolKind::Field, - location: self.convert_location(decl.location)?, + location: self.convert_location(decl.location, &ty.path, "/var/", var_name)?, container_name: Some(ty.path.clone()), }); } @@ -343,7 +348,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { } else { SymbolKind::Method }, - location: self.convert_location(decl.location)?, + location: self.convert_location(decl.location, &ty.path, "/proc/", proc_name)?, container_name: Some(ty.path.clone()), }); } @@ -352,10 +357,10 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { } let elapsed = start.elapsed(); eprintln!(" {} results in {}.{:03}s", results.len(), elapsed.as_secs(), elapsed.subsec_nanos() / 1_000_000); - // TODO: break if the query is too general, e.g. `obj/` on - // tgstation has 9100+ results. Search is very fast but - // serialization is very slow (30+ seconds). - results.truncate(200); + #[cfg(debug_assertions)] { + // Serializing all these to the debug log is very slow. + results.truncate(100); + } Some(results) } else { None